FUOpenGLView.m 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. //
  2. // FUOpenGLView.m
  3. // FULiveDemo
  4. //
  5. // Created by 刘洋 on 2017/8/15.
  6. // Copyright © 2017年 刘洋. All rights reserved.
  7. //
  8. #import "FUOpenGLView.h"
  9. #import <CoreVideo/CoreVideo.h>
  10. #import <OpenGLES/ES3/gl.h>
  11. #import <OpenGLES/ES3/glext.h>
  12. //#define use_capture
  13. #ifdef use_capture
  14. #import <libCNamaSDK/FURenderer.h>
  15. #else
  16. #endif
  17. #define STRINGIZE(x) #x
  18. #define STRINGIZE2(x) STRINGIZE(x)
  19. #define SHADER_STRING(text) @ STRINGIZE2(text)
  20. NSString *const FUYUVToRGBAFragmentShaderString = SHADER_STRING
  21. (
  22. varying highp vec2 textureCoordinate;
  23. uniform sampler2D luminanceTexture;
  24. uniform sampler2D chrominanceTexture;
  25. uniform mediump mat3 colorConversionMatrix;
  26. void main()
  27. {
  28. mediump vec3 yuv;
  29. lowp vec3 rgb;
  30. yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
  31. yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
  32. rgb = colorConversionMatrix * yuv;
  33. gl_FragColor = vec4(rgb, 1.0);
  34. }
  35. );
  36. NSString *const FURGBAFragmentShaderString = SHADER_STRING
  37. (
  38. uniform sampler2D inputImageTexture;
  39. varying highp vec2 textureCoordinate;
  40. void main()
  41. {
  42. gl_FragColor = vec4(texture2D(inputImageTexture, textureCoordinate).rgb,1.0);
  43. }
  44. );
  45. NSString *const FUVertexShaderString = SHADER_STRING
  46. (
  47. attribute vec4 position;
  48. attribute vec4 inputTextureCoordinate;
  49. varying vec2 textureCoordinate;
  50. void main()
  51. {
  52. gl_Position = position;
  53. textureCoordinate = inputTextureCoordinate.xy;
  54. }
  55. );
  56. NSString *const FUPointsFrgShaderString = SHADER_STRING
  57. (
  58. precision mediump float;
  59. varying highp vec4 fragmentColor;
  60. void main()
  61. {
  62. if (-smoothstep(0.48, 0.5, length(gl_PointCoord - vec2(0.5))) + 1.0 == 0.0) {
  63. discard;
  64. }
  65. gl_FragColor = fragmentColor;
  66. }
  67. );
  68. NSString *const FUPointsVtxShaderString = SHADER_STRING
  69. (
  70. attribute vec4 position;
  71. attribute float point_size;
  72. attribute vec4 inputColor;
  73. varying vec4 fragmentColor;
  74. void main()
  75. {
  76. gl_Position = position;
  77. gl_PointSize = point_size;
  78. fragmentColor = inputColor;
  79. }
  80. );
  81. enum
  82. {
  83. furgbaPositionAttribute,
  84. furgbaTextureCoordinateAttribute,
  85. fuPointSize,
  86. fuPointColor,
  87. };
  88. enum
  89. {
  90. fuyuvConversionPositionAttribute,
  91. fuyuvConversionTextureCoordinateAttribute
  92. };
  93. @interface FUOpenGLView(){
  94. dispatch_semaphore_t semaphore;
  95. }
  96. @property (nonatomic, strong) EAGLContext *glContext;
  97. @property(nonatomic) dispatch_queue_t contextQueue;
  98. @end
  99. @implementation FUOpenGLView
  100. {
  101. GLuint rgbaProgram;
  102. GLuint rgbaToYuvProgram;
  103. GLuint pointProgram;
  104. CVOpenGLESTextureCacheRef videoTextureCache;
  105. GLuint frameBufferHandle;
  106. GLuint renderBufferHandle;
  107. GLint yuvConversionLuminanceTextureUniform, yuvConversionChrominanceTextureUniform;
  108. GLint yuvConversionMatrixUniform;
  109. GLint displayInputTextureUniform;
  110. GLfloat vertices[8];
  111. int frameWidth;
  112. int frameHeight;
  113. int backingWidth;
  114. int backingHeight;
  115. CGSize boundsSizeAtFrameBufferEpoch;
  116. GLuint texture;
  117. }
  118. + (Class)layerClass
  119. {
  120. return [CAEAGLLayer class];
  121. }
  122. - (instancetype)initWithCoder:(NSCoder *)aDecoder
  123. {
  124. if (self = [super initWithCoder:aDecoder]) {
  125. self.disapplePointIndex = -1 ;
  126. _contextQueue = dispatch_queue_create("com.faceunity.contextQueue", DISPATCH_QUEUE_SERIAL);
  127. self.contentScaleFactor = [[UIScreen mainScreen] scale];
  128. CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
  129. eaglLayer.opaque = TRUE;
  130. eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking :[NSNumber numberWithBool:NO],
  131. kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8};
  132. #ifdef use_capture
  133. [[FURenderer shareRenderer] setUpCurrentContext];
  134. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
  135. _glContext = [EAGLContext currentContext];
  136. #else
  137. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
  138. if (!_glContext) {
  139. NSLog(@"This devicde is not support OpenGLES3,try to create OpenGLES2");
  140. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  141. }
  142. if (!self.glContext) {
  143. NSLog(@"failed to create context");
  144. }
  145. #endif
  146. if (!videoTextureCache) {
  147. CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, self.glContext, NULL, &videoTextureCache);
  148. if (err != noErr) {
  149. NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
  150. }
  151. }
  152. self.origintation = FUOpenGLViewOrientationPortrait ;
  153. self.contentMode = FUOpenGLViewContentModeScaleAspectFill;
  154. }
  155. return self;
  156. }
  157. - (instancetype)initWithFrame:(CGRect)frame{
  158. if (self = [super initWithFrame:frame] ) {
  159. self.disapplePointIndex = -1 ;
  160. _contextQueue = dispatch_queue_create("com.faceunity.contextQueue", DISPATCH_QUEUE_SERIAL);
  161. self.contentScaleFactor = [[UIScreen mainScreen] scale];
  162. CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
  163. eaglLayer.opaque = TRUE;
  164. eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking :[NSNumber numberWithBool:NO],
  165. kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8};
  166. #ifdef use_capture
  167. [[FURenderer shareRenderer] setUpCurrentContext];
  168. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
  169. _glContext = [EAGLContext currentContext];
  170. #else
  171. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
  172. if (!_glContext) {
  173. NSLog(@"This devicde is not support OpenGLES3,try to create OpenGLES2");
  174. _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
  175. }
  176. if (!self.glContext) {
  177. NSLog(@"failed to create context");
  178. }
  179. #endif
  180. if (!videoTextureCache) {
  181. CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, self.glContext, NULL, &videoTextureCache);
  182. if (err != noErr) {
  183. NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
  184. }
  185. }
  186. self.origintation = FUOpenGLViewOrientationPortrait ;
  187. self.contentMode = FUOpenGLViewContentModeScaleAspectFill;
  188. }
  189. return self;
  190. }
  191. - (void)layoutSubviews{
  192. [super layoutSubviews];
  193. // The frame buffer needs to be trashed and re-created when the view size changes.
  194. if (!CGSizeEqualToSize(self.bounds.size, boundsSizeAtFrameBufferEpoch) &&
  195. !CGSizeEqualToSize(self.bounds.size, CGSizeZero)) {
  196. boundsSizeAtFrameBufferEpoch = self.bounds.size;
  197. dispatch_async(_contextQueue, ^{
  198. [self destroyDisplayFramebuffer];
  199. [self createDisplayFramebuffer];
  200. [self updateVertices];
  201. });
  202. }
  203. }
  204. - (void)dealloc
  205. {
  206. dispatch_sync(_contextQueue, ^{
  207. [self destroyDisplayFramebuffer];
  208. [self destoryProgram];
  209. if(self->videoTextureCache) {
  210. CVOpenGLESTextureCacheFlush(self->videoTextureCache, 0);
  211. CFRelease(self->videoTextureCache);
  212. self->videoTextureCache = NULL;
  213. }
  214. });
  215. }
  216. - (void)createDisplayFramebuffer
  217. {
  218. NSLog(@"createDisplayFramebuffer -----");
  219. [EAGLContext setCurrentContext:self.glContext];
  220. glDisable(GL_DEPTH_TEST);
  221. glGenFramebuffers(1, &frameBufferHandle);
  222. glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);
  223. glGenRenderbuffers(1, &renderBufferHandle);
  224. glBindRenderbuffer(GL_RENDERBUFFER, renderBufferHandle);
  225. dispatch_sync(dispatch_get_main_queue(), ^{
  226. [self.glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
  227. });
  228. glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
  229. glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
  230. if ( (backingWidth == 0) || (backingHeight == 0) )
  231. {
  232. [self destroyDisplayFramebuffer];
  233. return;
  234. }
  235. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferHandle);
  236. if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  237. NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
  238. }
  239. }
  240. - (void)destroyDisplayFramebuffer;
  241. {
  242. [EAGLContext setCurrentContext:self.glContext];
  243. if (frameBufferHandle)
  244. {
  245. glDeleteFramebuffers(1, &frameBufferHandle);
  246. frameBufferHandle = 0;
  247. }
  248. if (renderBufferHandle)
  249. {
  250. glDeleteRenderbuffers(1, &renderBufferHandle);
  251. renderBufferHandle = 0;
  252. }
  253. }
  254. - (void)setDisplayFramebuffer;
  255. {
  256. if (!frameBufferHandle)
  257. {
  258. [self createDisplayFramebuffer];
  259. }
  260. glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);
  261. glViewport(0, 0, (GLint)backingWidth, (GLint)backingHeight);
  262. }
  263. - (void)setImageDisplayFramebuffer;
  264. {
  265. if (!frameBufferHandle)
  266. {
  267. [self createDisplayFramebuffer];
  268. }
  269. glBindFramebuffer(GL_FRAMEBUFFER, frameBufferHandle);
  270. float bw = self.frame.size.width * [UIScreen mainScreen].scale ;
  271. float bh = self.frame.size.height * [UIScreen mainScreen].scale ;
  272. glViewport(0, 0, (GLint)bw, (GLint)bh);
  273. }
  274. - (void)destoryProgram{
  275. if (rgbaProgram) {
  276. glDeleteProgram(rgbaProgram);
  277. rgbaProgram = 0;
  278. }
  279. if (rgbaToYuvProgram) {
  280. glDeleteProgram(rgbaToYuvProgram);
  281. rgbaToYuvProgram = 0;
  282. }
  283. if (pointProgram) {
  284. glDeleteProgram(pointProgram);
  285. pointProgram = 0;
  286. }
  287. }
  288. - (void)presentFramebuffer;
  289. {
  290. glBindRenderbuffer(GL_RENDERBUFFER, renderBufferHandle);
  291. [self.glContext presentRenderbuffer:GL_RENDERBUFFER];
  292. // glFinish();
  293. }
  294. - (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer
  295. {
  296. [self displayPixelBuffer:pixelBuffer withLandmarks:NULL count:0 MAX:NO];
  297. }
  298. - (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer withLandmarks:(float *)landmarks count:(int)count MAX:(BOOL)max
  299. {
  300. #ifdef use_capture
  301. if (pixelBuffer == NULL) return;
  302. CVPixelBufferRetain(pixelBuffer);
  303. CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  304. // dispatch_async(_contextQueue, ^{ //dispatch_sync iphone8p 可能死锁
  305. self->frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
  306. self->frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
  307. if ([EAGLContext currentContext] != self.glContext) {
  308. if (![EAGLContext setCurrentContext:self.glContext]) {
  309. NSLog(@"fail to setCurrentContext");
  310. }
  311. }
  312. [self setDisplayFramebuffer];
  313. OSType type = CVPixelBufferGetPixelFormatType(pixelBuffer);
  314. if (type == kCVPixelFormatType_32BGRA)
  315. {
  316. [self prepareToDrawBGRAPixelBuffer:pixelBuffer];
  317. }else{
  318. [self prepareToDrawYUVPixelBuffer:pixelBuffer];
  319. }
  320. if (landmarks) {
  321. [self prepareToDrawLandmarks:landmarks count:count MAX:max zoomScale:1];
  322. }
  323. [self presentFramebuffer];
  324. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  325. CVPixelBufferRelease(pixelBuffer);
  326. // });
  327. #else
  328. if (pixelBuffer == NULL) return;
  329. CVPixelBufferRetain(pixelBuffer);
  330. CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  331. dispatch_async(_contextQueue, ^{ //dispatch_sync iphone8p 可能死锁
  332. self->frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
  333. self->frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
  334. if ([EAGLContext currentContext] != self.glContext) {
  335. if (![EAGLContext setCurrentContext:self.glContext]) {
  336. NSLog(@"fail to setCurrentContext");
  337. }
  338. }
  339. [self setDisplayFramebuffer];
  340. OSType type = CVPixelBufferGetPixelFormatType(pixelBuffer);
  341. if (type == kCVPixelFormatType_32BGRA)
  342. {
  343. [self prepareToDrawBGRAPixelBuffer:pixelBuffer];
  344. }else{
  345. [self prepareToDrawYUVPixelBuffer:pixelBuffer];
  346. }
  347. if (landmarks) {
  348. [self prepareToDrawLandmarks:landmarks count:count MAX:max zoomScale:1];
  349. }
  350. [self presentFramebuffer];
  351. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  352. CVPixelBufferRelease(pixelBuffer);
  353. });
  354. #endif
  355. }
  356. - (void)displaySyncPixelBuffer:(CVPixelBufferRef)pixelBuffer
  357. {
  358. if (pixelBuffer == NULL) return;
  359. CVPixelBufferRetain(pixelBuffer);
  360. CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  361. // dispatch_async(_contextQueue, ^{ //dispatch_sync iphone8p 可能死锁
  362. self->frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
  363. self->frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
  364. if ([EAGLContext currentContext] != self.glContext) {
  365. if (![EAGLContext setCurrentContext:self.glContext]) {
  366. NSLog(@"fail to setCurrentContext");
  367. }
  368. }
  369. [self setDisplayFramebuffer];
  370. OSType type = CVPixelBufferGetPixelFormatType(pixelBuffer);
  371. if (type == kCVPixelFormatType_32BGRA)
  372. {
  373. [self prepareToDrawBGRAPixelBuffer:pixelBuffer];
  374. }else{
  375. [self prepareToDrawYUVPixelBuffer:pixelBuffer];
  376. }
  377. [self presentFramebuffer];
  378. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  379. CVPixelBufferRelease(pixelBuffer);
  380. // });
  381. }
  382. - (void)displayImageData:(void *)imageData withSize:(CGSize)size{
  383. frameWidth = (int)size.width;
  384. frameHeight = (int)size.height;
  385. if ([EAGLContext currentContext] != self.glContext) {
  386. if (![EAGLContext setCurrentContext:self.glContext]) {
  387. NSLog(@"fail to setCurrentContext");
  388. }
  389. }
  390. [self setDisplayFramebuffer];
  391. if (!rgbaProgram) {
  392. [self loadShadersRGBA];
  393. }
  394. if (texture == 0) {
  395. glGenTextures(1, &texture);
  396. }
  397. glBindTexture(GL_TEXTURE_2D, texture);
  398. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  399. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  400. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  401. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  402. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  403. glUseProgram(rgbaProgram);
  404. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  405. glClear(GL_COLOR_BUFFER_BIT);
  406. glActiveTexture(GL_TEXTURE1);
  407. glBindTexture(GL_TEXTURE_2D, texture);
  408. glUniform1i(displayInputTextureUniform, 1);
  409. [self updateVertices];
  410. // 更新顶点数据
  411. glVertexAttribPointer(furgbaPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  412. glEnableVertexAttribArray(furgbaPositionAttribute);
  413. GLfloat quadTextureData[] = {
  414. 0.0f, 1.0f,
  415. 1.0f, 1.0f,
  416. 0.0f, 0.0f,
  417. 1.0f, 0.0f,
  418. };
  419. glVertexAttribPointer(furgbaTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  420. glEnableVertexAttribArray(furgbaTextureCoordinateAttribute);
  421. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  422. [self presentFramebuffer];
  423. }
  424. - (void)displayImageData:(void *)imageData withSize:(CGSize)size Center:(CGPoint)center Landmarks:(float *)landmarks count:(int)count {
  425. frameWidth = (int)size.width;
  426. frameHeight = (int)size.height;
  427. if ([EAGLContext currentContext] != self.glContext) {
  428. if (![EAGLContext setCurrentContext:self.glContext]) {
  429. NSLog(@"fail to setCurrentContext");
  430. }
  431. }
  432. [self setImageDisplayFramebuffer];
  433. if (!rgbaProgram) {
  434. [self loadShadersRGBA];
  435. }
  436. if (texture == 0) {
  437. glGenTextures(1, &texture);
  438. }
  439. glBindTexture(GL_TEXTURE_2D, texture);
  440. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  441. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  442. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  443. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  444. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  445. glUseProgram(rgbaProgram);
  446. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);;
  447. glClear(GL_COLOR_BUFFER_BIT);
  448. glActiveTexture(GL_TEXTURE1);
  449. glBindTexture(GL_TEXTURE_2D, texture);
  450. glUniform1i(displayInputTextureUniform, 1);
  451. [self updateVertices];
  452. // 更新顶点数据
  453. glVertexAttribPointer(furgbaPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  454. glEnableVertexAttribArray(furgbaPositionAttribute);
  455. GLfloat quadTextureData[] = {
  456. center.x - 0.1, center.y + 0.1,
  457. center.x + 0.1, center.y + 0.1,
  458. center.x - 0.1, center.y - 0.1,
  459. center.x + 0.1, center.y - 0.1,
  460. };
  461. glVertexAttribPointer(furgbaTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  462. glEnableVertexAttribArray(furgbaTextureCoordinateAttribute);
  463. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  464. if (landmarks) {
  465. [self drawImageLandmarks:landmarks count:count center:center];
  466. }
  467. [self presentFramebuffer];
  468. }
  469. - (void)drawImageLandmarks:(float *)landmarks count:(int)count center:(CGPoint)center
  470. {
  471. if (!pointProgram) {
  472. [self loadPointsShaders];
  473. }
  474. glUseProgram(pointProgram);
  475. count = count;
  476. float sizeData[count];
  477. float colorData[count * 4];
  478. float newLandmarks[count *2];
  479. float bw = self.frame.size.width * [UIScreen mainScreen].scale ;
  480. float bh = self.frame.size.height * [UIScreen mainScreen].scale ;
  481. const float width = frameWidth;
  482. const float height = frameHeight;
  483. const float dH = bh / height;
  484. const float dW = bw / width;
  485. const float dd = MAX(dH, dW);
  486. const float h = (height * dd / (float)bw) * 10/2;
  487. const float w = (width * dd / (float)bw) * 10/2;
  488. for (int i = 0; i < count/2; i++)
  489. {
  490. if (self.disapplePointIndex == i) {
  491. continue ;
  492. }
  493. //点的大小
  494. sizeData[i] = [UIScreen mainScreen].scale * 5;
  495. //点的颜色
  496. colorData[4 * i] = 1.0;
  497. colorData[4 * i + 1] = .0;
  498. colorData[4 * i + 2] = .0;
  499. colorData[4 * i + 3] = .0;
  500. //转化坐标
  501. newLandmarks[2 * i] = (float)((2 * landmarks[2 * i] / frameWidth - 1)) * w - (center.x - 0.5) * 2 * w;
  502. newLandmarks[2 * i + 1] = (float)(1 - 2 * landmarks[2 * i + 1] / frameHeight ) * h - (0.5 - center.y) * 2 * h;
  503. }
  504. for (int i = count/2; i < count; i++)
  505. {
  506. sizeData[i] = [UIScreen mainScreen].scale * 3;
  507. colorData[4 * i ] = 1.0;
  508. colorData[4 * i + 1] = 1.0;
  509. colorData[4 * i + 2] = 1.0;
  510. colorData[4 * i + 3] = 1.0;
  511. newLandmarks[2 * i] = (float)((2 * landmarks[2 * i - count] / frameWidth - 1)) * w - (center.x - 0.5) * 2 * w;
  512. newLandmarks[2 * i + 1] = (float)(1 - 2 * landmarks[2 * i + 1 - count] / frameHeight ) * h - (0.5 - center.y) * 2 * h;
  513. }
  514. glEnableVertexAttribArray(fuPointSize);
  515. glVertexAttribPointer(fuPointSize, 1, GL_FLOAT, GL_FALSE, 0, sizeData);
  516. glEnableVertexAttribArray(GLKVertexAttribPosition);
  517. glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, (GLfloat *)newLandmarks);
  518. glEnableVertexAttribArray(fuPointColor);
  519. glVertexAttribPointer(fuPointColor, 4, GL_FLOAT, GL_FALSE, 0, colorData);
  520. glDrawArrays(GL_POINTS, 0, count);
  521. }
  522. - (void)displayImageData:(void *)imageData Size:(CGSize)size Landmarks:(float *)landmarks count:(int)count zoomScale:(float)zoomScale{
  523. frameWidth = (int)size.width;
  524. frameHeight = (int)size.height;
  525. if ([EAGLContext currentContext] != self.glContext) {
  526. if (![EAGLContext setCurrentContext:self.glContext]) {
  527. NSLog(@"fail to setCurrentContext");
  528. }
  529. }
  530. [self setDisplayFramebuffer];
  531. if (!rgbaProgram) {
  532. [self loadShadersRGBA];
  533. }
  534. if (texture == 0) {
  535. glGenTextures(1, &texture);
  536. }
  537. glBindTexture(GL_TEXTURE_2D, texture);
  538. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  539. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  540. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  541. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  542. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  543. glUseProgram(rgbaProgram);
  544. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);;
  545. glClear(GL_COLOR_BUFFER_BIT);
  546. glActiveTexture(GL_TEXTURE1);
  547. glBindTexture(GL_TEXTURE_2D, texture);
  548. glUniform1i(displayInputTextureUniform, 1);
  549. [self updateVertices];
  550. // 更新顶点数据
  551. glVertexAttribPointer(furgbaPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  552. glEnableVertexAttribArray(furgbaPositionAttribute);
  553. GLfloat quadTextureData[] = {
  554. 0.0f, 1.0f,
  555. 1.0f, 1.0f,
  556. 0.0f, 0.0f,
  557. 1.0f, 0.0f,
  558. };
  559. glVertexAttribPointer(furgbaTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  560. glEnableVertexAttribArray(furgbaTextureCoordinateAttribute);
  561. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  562. if (landmarks) {
  563. [self prepareToDrawLandmarks:landmarks count:count MAX:NO zoomScale:zoomScale];
  564. }
  565. [self presentFramebuffer];
  566. }
  567. //- (void)updateVerticesRenderImage
  568. //{
  569. // const float width = frameWidth;
  570. // const float height = frameHeight;
  571. // const float dH = (float)backingHeight / height;
  572. // const float dW = (float)backingWidth / width;
  573. // const float dd = MIN(dH, dW);
  574. // const float h = (height * dd / (float)backingHeight);
  575. // const float w = (width * dd / (float)backingWidth );
  576. //
  577. // imageVertices[0] = - w;
  578. // imageVertices[1] = - h;
  579. // imageVertices[2] = w;
  580. // imageVertices[3] = - h;
  581. // imageVertices[4] = - w;
  582. // imageVertices[5] = h;
  583. // imageVertices[6] = w;
  584. // imageVertices[7] = h;
  585. //}
  586. - (void)prepareToDrawLandmarks:(float *)landmarks count:(int)count MAX:(BOOL)max zoomScale:(float)zoomScale
  587. {
  588. if (!pointProgram) {
  589. [self loadPointsShaders];
  590. }
  591. glUseProgram(pointProgram);
  592. count = count;
  593. float sizeData[count];
  594. float colorData[count * 4];
  595. float newLandmarks[count * 2];
  596. float width = frameWidth;
  597. float height = frameHeight;
  598. float dH = (float)backingHeight / height;
  599. float dW = (float)backingWidth / width;
  600. float dd = 0;
  601. if (max) {
  602. dd = MAX(dH, dW);
  603. }else {
  604. dd = MIN(dH, dW) ;
  605. }
  606. float h = (height * dd / (float)backingHeight);
  607. float w = (width * dd / (float)backingWidth );
  608. for (int i = 0; i < count / 2; i++)
  609. {
  610. //点的大小
  611. sizeData[i] = [UIScreen mainScreen].scale * 2 / zoomScale;
  612. colorData[4 * i ] = 1.0;
  613. colorData[4 * i + 1] = 0.0;
  614. colorData[4 * i + 2] = 0.0;
  615. colorData[4 * i + 3] = 0.0;
  616. //转化坐标
  617. newLandmarks[2 * i] = (float)((2 * landmarks[2 * i] / frameWidth - 1))*w;
  618. newLandmarks[2 * i + 1] = (float)(1 - 2 * landmarks[2 * i + 1] / frameHeight)*h;
  619. }
  620. for (int i = count/2; i < count; i++)
  621. {
  622. sizeData[i] = [UIScreen mainScreen].scale / zoomScale;
  623. colorData[4 * i ] = 1.0;
  624. colorData[4 * i + 1] = 1.0;
  625. colorData[4 * i + 2] = 1.0;
  626. colorData[4 * i + 3] = 1.0;
  627. newLandmarks[2 * i] = (float)((2 * landmarks[2 * i - count] / frameWidth - 1))*w;
  628. newLandmarks[2 * i + 1] = (float)(1 - 2 * landmarks[2 * i + 1 - count] / frameHeight)*h;
  629. }
  630. glEnableVertexAttribArray(fuPointSize);
  631. glVertexAttribPointer(fuPointSize, 1, GL_FLOAT, GL_FALSE, 0, sizeData);
  632. glEnableVertexAttribArray(GLKVertexAttribPosition);
  633. glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, (GLfloat *)newLandmarks);
  634. glEnableVertexAttribArray(fuPointColor);
  635. glVertexAttribPointer(fuPointColor, 4, GL_FLOAT, GL_FALSE, 0, colorData);
  636. glDrawArrays(GL_POINTS, 0, count);
  637. }
  638. - (void)prepareToDrawBGRAPixelBuffer:(CVPixelBufferRef)pixelBuffer
  639. {
  640. if (!rgbaProgram) {
  641. [self loadShadersRGBA];
  642. }
  643. CVOpenGLESTextureRef rgbaTexture = NULL;
  644. CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, videoTextureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, frameWidth, frameHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &rgbaTexture);
  645. if (!rgbaTexture || err) {
  646. NSLog(@"Camera CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
  647. return;
  648. }
  649. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(rgbaTexture));
  650. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  651. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  652. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  653. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  654. glUseProgram(rgbaProgram);
  655. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  656. glClear(GL_COLOR_BUFFER_BIT);
  657. glActiveTexture(GL_TEXTURE4);
  658. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(rgbaTexture));
  659. glUniform1i(displayInputTextureUniform, 4);
  660. [self updateVertices];
  661. // 更新顶点数据
  662. glVertexAttribPointer(furgbaPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  663. glEnableVertexAttribArray(furgbaPositionAttribute);
  664. GLfloat quadTextureData[] = {
  665. 0.0f, 1.0f,
  666. 1.0f, 1.0f,
  667. 0.0f, 0.0f,
  668. 1.0f, 0.0f,
  669. };
  670. if (_origintation == FUOpenGLViewOrientationPortrait) {
  671. float quadTextureData0[] = {
  672. 0.0f, 1.0f,
  673. 1.0f, 1.0f,
  674. 0.0f, 0.0f,
  675. 1.0f, 0.0f,
  676. };
  677. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  678. }
  679. if (_origintation == FUOpenGLViewOrientationLandscapeRight) {
  680. float quadTextureData0[] = {
  681. 1.0f, 1.0f,
  682. 1.0f, 0.0f,
  683. 0.0f, 1.0f,
  684. 0.0f, 0.0f,
  685. };
  686. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  687. }
  688. if (_origintation == FUOpenGLViewOrientationPortraitUpsideDown) {
  689. float quadTextureData0[] = {
  690. 1.0f, 0.0f,
  691. 0.0f, 0.0f,
  692. 1.0f, 1.0f,
  693. 0.0f, 1.0f,
  694. };
  695. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  696. }
  697. if (_origintation == FUOpenGLViewOrientationLandscapeLeft) {
  698. float quadTextureData0[] = {
  699. 0.0f, 0.0f,
  700. 0.0f, 1.0f,
  701. 1.0f, 0.0f,
  702. 1.0f, 1.0f,
  703. };
  704. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  705. }
  706. glVertexAttribPointer(furgbaTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  707. glEnableVertexAttribArray(furgbaTextureCoordinateAttribute);
  708. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  709. if (rgbaTexture) {
  710. CFRelease(rgbaTexture);
  711. rgbaTexture = NULL;
  712. }
  713. }
  714. - (void)prepareToDrawYUVPixelBuffer:(CVPixelBufferRef)pixelBuffer
  715. {
  716. if (!rgbaToYuvProgram) {
  717. [self loadShadersYUV];
  718. }
  719. CVReturn err;
  720. CVOpenGLESTextureRef luminanceTextureRef = NULL;
  721. CVOpenGLESTextureRef chrominanceTextureRef = NULL;
  722. /*
  723. CVOpenGLESTextureCacheCreateTextureFromImage will create GLES texture optimally from CVPixelBufferRef.
  724. */
  725. /*
  726. Create Y and UV textures from the pixel buffer. These textures will be drawn on the frame buffer Y-plane.
  727. */
  728. glActiveTexture(GL_TEXTURE0);
  729. err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
  730. videoTextureCache,
  731. pixelBuffer,
  732. NULL,
  733. GL_TEXTURE_2D,
  734. GL_LUMINANCE,
  735. frameWidth,
  736. frameHeight,
  737. GL_LUMINANCE,
  738. GL_UNSIGNED_BYTE,
  739. 0,
  740. &luminanceTextureRef);
  741. if (err) {
  742. NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
  743. }
  744. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(luminanceTextureRef));
  745. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  746. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  747. // UV-plane.
  748. glActiveTexture(GL_TEXTURE1);
  749. err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
  750. videoTextureCache,
  751. pixelBuffer,
  752. NULL,
  753. GL_TEXTURE_2D,
  754. GL_LUMINANCE_ALPHA,
  755. frameWidth / 2,
  756. frameHeight / 2,
  757. GL_LUMINANCE_ALPHA,
  758. GL_UNSIGNED_BYTE,
  759. 1,
  760. &chrominanceTextureRef);
  761. if (err) {
  762. NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
  763. }
  764. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(chrominanceTextureRef));
  765. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  766. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  767. glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
  768. glClear(GL_COLOR_BUFFER_BIT);
  769. // Use shader program.
  770. glUseProgram(rgbaToYuvProgram);
  771. glActiveTexture(GL_TEXTURE0);
  772. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(luminanceTextureRef));
  773. glUniform1i(yuvConversionLuminanceTextureUniform, 0);
  774. glActiveTexture(GL_TEXTURE1);
  775. glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(chrominanceTextureRef));
  776. glUniform1i(yuvConversionChrominanceTextureUniform, 1);
  777. GLfloat kColorConversion601FullRange[] = {
  778. 1.0, 1.0, 1.0,
  779. 0.0, -0.343, 1.765,
  780. 1.4, -0.711, 0.0,
  781. };
  782. glUniformMatrix3fv(yuvConversionMatrixUniform, 1, GL_FALSE, kColorConversion601FullRange);
  783. // 更新顶点数据
  784. [self updateVertices];
  785. glVertexAttribPointer(fuyuvConversionPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
  786. glEnableVertexAttribArray(fuyuvConversionPositionAttribute);
  787. GLfloat quadTextureData[] = {
  788. 0.0f, 1.0f,
  789. 1.0f, 1.0f,
  790. 0.0f, 0.0f,
  791. 1.0f, 0.0f,
  792. };
  793. if (_origintation == FUOpenGLViewOrientationPortrait) {
  794. float quadTextureData0[] = {
  795. 0.0f, 1.0f,
  796. 1.0f, 1.0f,
  797. 0.0f, 0.0f,
  798. 1.0f, 0.0f,
  799. };
  800. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  801. }
  802. if (_origintation == FUOpenGLViewOrientationLandscapeRight) {
  803. float quadTextureData0[] = {
  804. 1.0f, 1.0f,
  805. 1.0f, 0.0f,
  806. 0.0f, 1.0f,
  807. 0.0f, 0.0f,
  808. };
  809. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  810. }
  811. if (_origintation == FUOpenGLViewOrientationPortraitUpsideDown) {
  812. float quadTextureData0[] = {
  813. 1.0f, 0.0f,
  814. 0.0f, 0.0f,
  815. 1.0f, 1.0f,
  816. 0.0f, 1.0f,
  817. };
  818. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  819. }
  820. if (_origintation == FUOpenGLViewOrientationLandscapeLeft) {
  821. float quadTextureData0[] = {
  822. 0.0f, 0.0f,
  823. 0.0f, 1.0f,
  824. 1.0f, 0.0f,
  825. 1.0f, 1.0f,
  826. };
  827. memcpy(quadTextureData, quadTextureData0, sizeof(quadTextureData));
  828. }
  829. glVertexAttribPointer(fuyuvConversionTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, quadTextureData);
  830. glEnableVertexAttribArray(fuyuvConversionTextureCoordinateAttribute);
  831. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  832. if (luminanceTextureRef) {
  833. CFRelease(luminanceTextureRef);
  834. luminanceTextureRef = NULL;
  835. }
  836. if (chrominanceTextureRef) {
  837. CFRelease(chrominanceTextureRef);
  838. chrominanceTextureRef = NULL;
  839. }
  840. }
  841. - (void)updateVertices
  842. {
  843. float height = frameHeight;
  844. float width = frameWidth;
  845. if (_origintation == FUOpenGLViewOrientationLandscapeRight || _origintation == FUOpenGLViewOrientationLandscapeLeft) {
  846. height = frameWidth;
  847. width = frameHeight;
  848. }
  849. float dH = (float)backingHeight / height;
  850. float dW = (float)backingWidth / width;
  851. if(_contentMode == FUOpenGLViewContentModeScaleToFill){
  852. vertices[0] = - 1;
  853. vertices[1] = - 1;
  854. vertices[2] = 1;
  855. vertices[3] = - 1;
  856. vertices[4] = - 1;
  857. vertices[5] = 1;
  858. vertices[6] = 1;
  859. vertices[7] = 1;
  860. }
  861. if (_contentMode == FUOpenGLViewContentModeScaleAspectFill) {
  862. float dd = MAX(dH, dW) ;
  863. float h = (height * dd / (float)backingHeight);
  864. float w = (width * dd / (float)backingWidth );
  865. vertices[0] = - w;
  866. vertices[1] = - h;
  867. vertices[2] = w;
  868. vertices[3] = - h;
  869. vertices[4] = - w;
  870. vertices[5] = h;
  871. vertices[6] = w;
  872. vertices[7] = h;
  873. }
  874. if (_contentMode == FUOpenGLViewContentModeScaleAspectFit) {
  875. float dd = MIN(dH, dW) ;
  876. float h = (height * dd / (float)backingHeight);
  877. float w = (width * dd / (float)backingWidth );
  878. vertices[0] = - w;
  879. vertices[1] = - h;
  880. vertices[2] = w;
  881. vertices[3] = - h;
  882. vertices[4] = - w;
  883. vertices[5] = h;
  884. vertices[6] = w;
  885. vertices[7] = h;
  886. }
  887. }
  888. #pragma mark - OpenGL ES 2 shader compilation
  889. - (BOOL)loadShadersRGBA
  890. {
  891. GLuint vertShader, fragShader;
  892. if (!rgbaProgram) {
  893. rgbaProgram = glCreateProgram();
  894. }
  895. // Create and compile the vertex shader.
  896. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:FUVertexShaderString]) {
  897. NSLog(@"Failed to compile vertex shader");
  898. return NO;
  899. }
  900. // Create and compile fragment shader.
  901. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:FURGBAFragmentShaderString]) {
  902. NSLog(@"Failed to compile fragment shader");
  903. return NO;
  904. }
  905. // Attach vertex shader to program.
  906. glAttachShader(rgbaProgram, vertShader);
  907. // Attach fragment shader to program.
  908. glAttachShader(rgbaProgram, fragShader);
  909. // Bind attribute locations. This needs to be done prior to linking.
  910. glBindAttribLocation(rgbaProgram, furgbaPositionAttribute, "position");
  911. glBindAttribLocation(rgbaProgram, furgbaTextureCoordinateAttribute, "inputTextureCoordinate");
  912. // Link the program.
  913. if (![self linkProgram:rgbaProgram]) {
  914. NSLog(@"Failed to link program: %d", rgbaProgram);
  915. if (vertShader) {
  916. glDeleteShader(vertShader);
  917. vertShader = 0;
  918. }
  919. if (fragShader) {
  920. glDeleteShader(fragShader);
  921. fragShader = 0;
  922. }
  923. if (rgbaProgram) {
  924. glDeleteProgram(rgbaProgram);
  925. rgbaProgram = 0;
  926. }
  927. return NO;
  928. }
  929. // Get uniform locations.
  930. displayInputTextureUniform = glGetUniformLocation(rgbaProgram, "inputImageTexture");
  931. // Release vertex and fragment shaders.
  932. if (vertShader) {
  933. glDetachShader(rgbaProgram, vertShader);
  934. glDeleteShader(vertShader);
  935. }
  936. if (fragShader) {
  937. glDetachShader(rgbaProgram, fragShader);
  938. glDeleteShader(fragShader);
  939. }
  940. return YES;
  941. }
  942. - (BOOL)loadShadersYUV
  943. {
  944. GLuint vertShader, fragShader;
  945. if (!rgbaToYuvProgram) {
  946. rgbaToYuvProgram = glCreateProgram();
  947. }
  948. // Create and compile the vertex shader.
  949. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:FUVertexShaderString]) {
  950. NSLog(@"Failed to compile vertex shader");
  951. return NO;
  952. }
  953. // Create and compile fragment shader.
  954. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:FUYUVToRGBAFragmentShaderString]) {
  955. NSLog(@"Failed to compile fragment shader");
  956. return NO;
  957. }
  958. // Attach vertex shader to rgbaToYuvProgram.
  959. glAttachShader(rgbaToYuvProgram, vertShader);
  960. // Attach fragment shader to rgbaToYuvProgram.
  961. glAttachShader(rgbaToYuvProgram, fragShader);
  962. // Bind attribute locations. This needs to be done prior to linking.
  963. glBindAttribLocation(rgbaToYuvProgram, fuyuvConversionPositionAttribute, "position");
  964. glBindAttribLocation(rgbaToYuvProgram, fuyuvConversionTextureCoordinateAttribute, "inputTextureCoordinate");
  965. // Link the rgbaToYuvProgram.
  966. if (![self linkProgram:rgbaToYuvProgram]) {
  967. NSLog(@"Failed to link program: %d", rgbaToYuvProgram);
  968. if (vertShader) {
  969. glDeleteShader(vertShader);
  970. vertShader = 0;
  971. }
  972. if (fragShader) {
  973. glDeleteShader(fragShader);
  974. fragShader = 0;
  975. }
  976. if (rgbaToYuvProgram) {
  977. glDeleteProgram(rgbaToYuvProgram);
  978. rgbaToYuvProgram = 0;
  979. }
  980. return NO;
  981. }
  982. // Get uniform locations.
  983. yuvConversionLuminanceTextureUniform = glGetUniformLocation(rgbaToYuvProgram, "luminanceTexture");
  984. yuvConversionChrominanceTextureUniform = glGetUniformLocation(rgbaToYuvProgram, "chrominanceTexture");
  985. yuvConversionMatrixUniform = glGetUniformLocation(rgbaToYuvProgram, "colorConversionMatrix");
  986. // Release vertex and fragment shaders.
  987. if (vertShader) {
  988. glDetachShader(rgbaToYuvProgram, vertShader);
  989. glDeleteShader(vertShader);
  990. }
  991. if (fragShader) {
  992. glDetachShader(rgbaToYuvProgram, fragShader);
  993. glDeleteShader(fragShader);
  994. }
  995. glUseProgram(rgbaToYuvProgram);
  996. return YES;
  997. }
  998. - (BOOL)loadPointsShaders
  999. {
  1000. GLuint vertShader, fragShader;
  1001. pointProgram = glCreateProgram();
  1002. // Create and compile the vertex shader.
  1003. if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:FUPointsVtxShaderString]) {
  1004. NSLog(@"Failed to compile vertex shader");
  1005. return NO;
  1006. }
  1007. // Create and compile fragment shader.
  1008. if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:FUPointsFrgShaderString]) {
  1009. NSLog(@"Failed to compile fragment shader");
  1010. return NO;
  1011. }
  1012. // Attach vertex shader to program.
  1013. glAttachShader(pointProgram, vertShader);
  1014. // Attach fragment shader to program.
  1015. glAttachShader(pointProgram, fragShader);
  1016. // Bind attribute locations. This needs to be done prior to linking.
  1017. glBindAttribLocation(pointProgram, fuPointSize, "point_size");
  1018. glBindAttribLocation(pointProgram, fuPointColor, "inputColor");
  1019. // Link the program.
  1020. if (![self linkProgram:pointProgram]) {
  1021. NSLog(@"Failed to link program: %d", pointProgram);
  1022. if (vertShader) {
  1023. glDeleteShader(vertShader);
  1024. vertShader = 0;
  1025. }
  1026. if (fragShader) {
  1027. glDeleteShader(fragShader);
  1028. fragShader = 0;
  1029. }
  1030. if (pointProgram) {
  1031. glDeleteProgram(pointProgram);
  1032. pointProgram = 0;
  1033. }
  1034. return NO;
  1035. }
  1036. // Release vertex and fragment shaders.
  1037. if (vertShader) {
  1038. glDetachShader(pointProgram, vertShader);
  1039. glDeleteShader(vertShader);
  1040. }
  1041. if (fragShader) {
  1042. glDetachShader(pointProgram, fragShader);
  1043. glDeleteShader(fragShader);
  1044. }
  1045. return YES;
  1046. }
  1047. - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString
  1048. {
  1049. GLint status;
  1050. const GLchar *source;
  1051. source = (GLchar *)[shaderString UTF8String];
  1052. *shader = glCreateShader(type);
  1053. glShaderSource(*shader, 1, &source, NULL);
  1054. glCompileShader(*shader);
  1055. #if defined(DEBUG)
  1056. GLint logLength;
  1057. glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
  1058. if (logLength > 0) {
  1059. GLchar *log = (GLchar *)malloc(logLength);
  1060. glGetShaderInfoLog(*shader, logLength, &logLength, log);
  1061. NSLog(@"Shader compile log:\n%s", log);
  1062. free(log);
  1063. }
  1064. #endif
  1065. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
  1066. if (status == 0) {
  1067. glDeleteShader(*shader);
  1068. return NO;
  1069. }
  1070. return YES;
  1071. }
  1072. - (BOOL)linkProgram:(GLuint)prog
  1073. {
  1074. GLint status;
  1075. glLinkProgram(prog);
  1076. #if defined(DEBUG)
  1077. GLint logLength;
  1078. glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
  1079. if (logLength > 0) {
  1080. GLchar *log = (GLchar *)malloc(logLength);
  1081. glGetProgramInfoLog(prog, logLength, &logLength, log);
  1082. NSLog(@"Program link log:\n%s", log);
  1083. free(log);
  1084. }
  1085. #endif
  1086. glGetProgramiv(prog, GL_LINK_STATUS, &status);
  1087. if (status == 0) {
  1088. return NO;
  1089. }
  1090. return YES;
  1091. }
  1092. - (BOOL)validateProgram:(GLuint)prog
  1093. {
  1094. GLint logLength, status;
  1095. glValidateProgram(prog);
  1096. glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
  1097. if (logLength > 0) {
  1098. GLchar *log = (GLchar *)malloc(logLength);
  1099. glGetProgramInfoLog(prog, logLength, &logLength, log);
  1100. NSLog(@"Program validate log:\n%s", log);
  1101. free(log);
  1102. }
  1103. glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
  1104. if (status == 0) {
  1105. return NO;
  1106. }
  1107. return YES;
  1108. }
  1109. - (UIColor*)getColorWithPoint:(CGPoint)point{
  1110. __block UIColor *color = nil;
  1111. semaphore = dispatch_semaphore_create(0);
  1112. float imageW = frameWidth;
  1113. float imageH = frameHeight;
  1114. point = CGPointMake(point.x/self.bounds.size.width,point.y/self.bounds.size.height);
  1115. point.x = point.x * backingWidth;
  1116. point.y = (1- point.y)* backingHeight;
  1117. dispatch_async(_contextQueue, ^{
  1118. if ([EAGLContext currentContext] != self.glContext) {
  1119. if (![EAGLContext setCurrentContext:self.glContext]) {
  1120. NSLog(@"fail to setCurrentContext");
  1121. }
  1122. }
  1123. [self setDisplayFramebuffer];
  1124. GLubyte aa[4] = {0};
  1125. GLint aaa = (GLint)point.x;
  1126. GLint bb = (GLint)point.y;
  1127. glReadPixels(aaa,bb,1, 1, GL_BGRA, GL_UNSIGNED_BYTE, aa);
  1128. color = [UIColor colorWithRed:(aa[2]/255.0f) green:(aa[1]/255.0f) blue:(aa[0]/255.0f) alpha:(aa[3]/255.0f)];
  1129. dispatch_semaphore_signal(semaphore);
  1130. });
  1131. dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  1132. return color;
  1133. }
  1134. @end