• IOS摄像头采和显示


    1该博客采集后置摄像头,然后直接转UIimage显示;通过OpenGLES显示 两种

    博客参考:简书loyinlin 和 IOS 官方demo:https://developer.apple.com/library/archive/samplecode/GLCameraRipple/Introduction/Intro.html

    #import <UIKit/UIKit.h>
    #import <GLKit/GLKit.h>
    @interface ViewController : UIViewController
    
    @end
    //-----------------------------------------
    
    
    #import "ViewController.h"
    #import "CapAndRender.h"
    #import "CapFromCamera.h"
    #import <AVFoundation/AVFoundation.h>
    @interface ViewController ()<CapDelegate>
    // OpenGL ES
    @property (nonatomic, strong) CapAndRender *mGLView;
    @property (nonatomic, strong) CapCamera *mCamera;
    @property(nonatomic,strong)IBOutlet UIView *view1;
    @property(nonatomic,strong)IBOutlet UIView *RenderView;
    @end
    
    @implementation ViewController
    {
         dispatch_queue_t mProcessQueue;
    }
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.mGLView = [[CapAndRender alloc] initWithFrame:self.RenderView.bounds];
        [self.RenderView addSubview:self.mGLView];
        [self.mGLView setupGL];//着色器相关设置
        //相机
        self.mCamera = [[CapCamera alloc]init];
        [self.mCamera InitCap];
        self.mCamera.delegate = self;
        [self.mCamera StartCap];
        
       
        __weak typeof(self) weakSelf = self;
        //注册回调;定义回调函数的实现
        self.mCamera.cameraCB = ^(UIImage *image) {
            
            weakSelf.view1.layer.contents = (__bridge id)(image.CGImage);
        };
    
    }
    
    
    
    #pragma mark - Simple Editor
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
    }
    //代理方法
    - (void)RenderPixelBuf:(CVPixelBufferRef *)pixelBuf {
        
        [self.mGLView displayPixelBuffer:*pixelBuf];
    }
    
    
    @end

    appdelegate:

    @property (strong, nonatomic) UIWindow *window;

    info.plist:添加属性

    Privacy - Camera Usage Description

    摄像头采集//CapFromCamera.h
    
    #import <Foundation/Foundation.h>
    #include <AVFoundation/AVFoundation.h>
    #import <UIKit/UIKit.h>
    #import <GLKit/GLKit.h>
    
    @protocol CapDelegate<NSObject>
    
    - (void)RenderPixelBuf:(CVPixelBufferRef*)pixelBuf;
    
    @end
    
    @interface CapCamera :NSObject
    
    @property (nonatomic, weak) id<CapDelegate>delegate;//渲染显示
    
    //block
    @property (nonatomic, copy) void(^cameraCB)(UIImage *image);//直接显示采集数据
    
    -(void)InitCap;  //写在这才能在其他的.m使用的时候被找到
    -(void)StartCap;
    -(void)StopCap;
    
    @end
    #include "CapFromCamera.h"
    @interface CapCamera()<AVCaptureVideoDataOutputSampleBufferDelegate>
    
    @property (nonatomic, strong) AVCaptureSession *mCaptureSession;
    @property (nonatomic, strong) AVCaptureDeviceInput *mCaptureDeviceInput;
    @property (nonatomic, strong) AVCaptureVideoDataOutput *mCaptureDeviceOutput;
    
    @end
    
    @implementation CapCamera
    
    -(void)InitCap{
        
        self.mCaptureSession = [[AVCaptureSession alloc] init];
         //AVCaptureSessionPreset1920x1080
         self.mCaptureSession.sessionPreset = AVCaptureSessionPreset640x480;
         
         AVCaptureDevice *inputCamera = nil;
         NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
         for (AVCaptureDevice *device in devices)
         {
             if ([device position] == AVCaptureDevicePositionBack)
             {
                 inputCamera = device;
             }
         }
         
         self.mCaptureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:inputCamera error:nil];
         
         if ([self.mCaptureSession canAddInput:self.mCaptureDeviceInput]) {
             [self.mCaptureSession addInput:self.mCaptureDeviceInput];
         }
    
         
         self.mCaptureDeviceOutput = [[AVCaptureVideoDataOutput alloc] init];
         [self.mCaptureDeviceOutput setAlwaysDiscardsLateVideoFrames:NO];
         
        
         [self.mCaptureDeviceOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
         [self.mCaptureDeviceOutput setSampleBufferDelegate:self queue:dispatch_queue_create("mProcessQueue", DISPATCH_QUEUE_SERIAL)];
         if ([self.mCaptureSession canAddOutput:self.mCaptureDeviceOutput]) {
             [self.mCaptureSession addOutput:self.mCaptureDeviceOutput];
         }
         
         AVCaptureConnection *connection = [self.mCaptureDeviceOutput connectionWithMediaType:AVMediaTypeVideo];
         [connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
        
         
    }
    -(void)StartCap
    {
         [self.mCaptureSession startRunning];
    }
    -(void)StopCap{
         [self.mCaptureSession stopRunning];
    }
    
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
       
        CFRetain(sampleBuffer);
        dispatch_async(dispatch_get_main_queue(), ^{
            CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
            //------------------采集画面直接显示----------------
        CIImage* ciImage = [CIImage imageWithCVPixelBuffer :(CVPixelBufferRef)pixelBuffer  options:nil];
         
            CIContext* context = [CIContext contextWithOptions : @{kCIContextUseSoftwareRenderer : @(YES)
        }];
         
            CGRect rect = CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer));
         
            CGImageRef videoImage = [context createCGImage : ciImage fromRect : rect];
         
            UIImage* image = [UIImage imageWithCGImage : videoImage];
            //触发回调,直接显示采集数据
            if (self.cameraCB) {
                self.cameraCB(image);
            }
            
            CGImageRelease(videoImage);
           //-------------------------------------------------------
            //-----------------------渲染------------------------------
            if(self.delegate && [self.delegate respondsToSelector:@selector(RenderPixelBuf:)])
            {
                [self.delegate RenderPixelBuf:&pixelBuffer];
            }
            //------------------------------------------------------
           
            CFRelease(sampleBuffer);
        });
    }
    
    @end

    //渲染类
    #import <UIKit/UIKit.h> #import <OpenGLES/ES2/gl.h> #import <OpenGLES/ES2/glext.h> @interface CapAndRender : UIView - (void)setupGL; - (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer; @end
    #import <Foundation/Foundation.h>
    #import <QuartzCore/QuartzCore.h>
    #import <AVFoundation/AVUtilities.h>
    #import <mach/mach_time.h>
    #import <GLKit/GLKit.h>
    #include "CapAndRender.h"
    // Uniform index.
    enum
    {
        UNIFORM_Y,
        UNIFORM_UV,
        UNIFORM_COLOR_CONVERSION_MATRIX,
        NUM_UNIFORMS
    };
    GLint uniforms[NUM_UNIFORMS];
    
    // Attribute index.
    enum
    {
        ATTRIB_VERTEX,
        ATTRIB_TEXCOORD,
        NUM_ATTRIBUTES
    };
    //YUV 转 RGB
    // BT.601 full range (ref: http://www.equasys.de/colorconversion.html)
    const GLfloat kColorConversion601FullRange[] = {
        1.0,    1.0,    1.0,
        0.0,    -0.343, 1.765,
        1.4,    -0.711, 0.0,
    };
    static const GLfloat kColorConversion709[] = {
            1.164,  1.164, 1.164,
              0.0, -0.213, 2.112,
            1.793, -0.533,   0.0,
    };
    static const GLfloat kColorConversion601[] = {
            1.164,  1.164, 1.164,
              0.0, -0.392, 2.017,
            1.596, -0.813,   0.0,
    };
    
    @interface CapAndRender()
    {
           GLuint _program;
           
           GLuint _screenWidth;//必须是int,float会导致获取宽高的时候异常
           GLuint _screenHeight;
           unsigned int _meshFactor;
           
           EAGLContext *_context;
           
           CVOpenGLESTextureRef _lumaTexture;
           CVOpenGLESTextureRef _chromaTexture;
           
           CVOpenGLESTextureCacheRef _videoTextureCache;
           const GLfloat *_preferredConversion;
           
           GLuint _frameBufferHandle;
           GLuint _colorBufferHandle;
    }
    
    
    - (void)cleanUpTextures;
    - (void)setupAVCapture;
    - (void)tearDownAVCapture;
    
    - (void)setupBuffers;
    - (void)setupGL;
    - (void)tearDownGL;
    
    - (BOOL)loadShaders;
    - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
    - (BOOL)linkProgram:(GLuint)prog;
    @end
    
    @implementation CapAndRender
    
    + (Class)layerClass
    {
        return [CAEAGLLayer class];
    }
    //滑屏,旋转屏幕触发
    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
    }
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame])
        {
    
            self.contentScaleFactor = 2.0;
           // int w = frame.size.width;
           // int H = frame.size.height;
            _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
            
            
            [EAGLContext setCurrentContext:_context];
           
            CAEAGLLayer *CaeaglLayer = (CAEAGLLayer *)self.layer;
            
            CaeaglLayer.opaque = YES;
            CaeaglLayer.contentsScale = [UIScreen mainScreen].scale;
            CaeaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking :[NSNumber numberWithBool:YES ],
            kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8};
            
    //        CaeaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking:[NSNumber numberWithBool:YES]};
            
            
            glGenFramebuffers(1, &_frameBufferHandle);
            glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
            
            glGenRenderbuffers(1, &_colorBufferHandle);
            glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle);
            
            [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)CaeaglLayer];
            
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorBufferHandle);
           // NSLog(@" %ld ",glGetError());
            glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_screenWidth);//宽高类型不能float否则会获取不到正确的宽高,进而无法渲染
            //NSLog(@" %ld ",glGetError());
            glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_screenHeight);
            //NSLog(@" %ld ",glGetError());
            glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,_screenWidth, _screenHeight);
          
            
            glViewport(0, 0,_screenHeight, _screenHeight);
            //-----
            //_preferredConversion = kColorConversion709;
            
        }
        return self;
    }
    
    //支持Xib,Xib中加载UIView,会调用initWithCoder
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        if ((self = [super initWithCoder:aDecoder]))//导入头文件,否则会出现root没有super
        {
            self.contentScaleFactor = [[UIScreen mainScreen] scale];
    
            CAEAGLLayer *CaeaglLayer = (CAEAGLLayer *)self.layer;
    
            CaeaglLayer.opaque = TRUE;
            CaeaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking :[NSNumber numberWithBool:NO],
                                              kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8};
    
            _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
            if (!_context || ![EAGLContext setCurrentContext:_context] || ![self loadShaders]) {
                return nil;
            }
            
        }
        return self;
    }
    
    
    
    # pragma mark - OpenGL setup
    - (void)setupGL
    {
        [EAGLContext setCurrentContext:_context];
        // [self setupBuffers];
        [self loadShaders];
        
        glUseProgram(_program);
        
        glUniform1i(uniforms[UNIFORM_Y], 0);
        glUniform1i(uniforms[UNIFORM_UV], 1);
        
        //glUniformMatrix3fv(uniforms[UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion);
        
        // Create CVOpenGLESTextureCacheRef for optimal CVPixelBufferRef to GLES texture conversion.
        if (!_videoTextureCache) {
            CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _context, NULL, &_videoTextureCache);
            if (err != noErr) {
                NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
                return;
            }
        }
    }
    
    #pragma mark - Utilities
    
    - (void)setupBuffers
    {
        
        _screenWidth = 0;
        _screenHeight = 0;
        glDisable(GL_DEPTH_TEST);
        
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
        
        glEnableVertexAttribArray(ATTRIB_TEXCOORD);
        glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
        
        glGenFramebuffers(1, &_frameBufferHandle);
        glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
        
        glGenRenderbuffers(1, &_colorBufferHandle);
        glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle);
        
        [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_screenWidth);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_screenHeight);
        
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorBufferHandle);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
            NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
        }
    }
    
    - (void)cleanUpTextures
    {
        if (_lumaTexture) {
            CFRelease(_lumaTexture);
            _lumaTexture = NULL;
        }
        
        if (_chromaTexture) {
            CFRelease(_chromaTexture);
            _chromaTexture = NULL;
        }
        
        // Periodic texture cache flush every frame
        CVOpenGLESTextureCacheFlush(_videoTextureCache, 0);
    }
    
    - (void)dealloc
    {
        [self cleanUpTextures];
        
        if(_videoTextureCache) {
            CFRelease(_videoTextureCache);
        }
    }
    
    #pragma mark - OpenGLES drawing
    
    - (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer
    {
        CVReturn err;
        if (pixelBuffer != NULL) {
            int frameWidth = (int)CVPixelBufferGetWidth(pixelBuffer);
            int frameHeight = (int)CVPixelBufferGetHeight(pixelBuffer);
            
            if (!_videoTextureCache) {
                NSLog(@"No video texture cache");
                return;
            }
            if ([EAGLContext currentContext] != _context) {
                [EAGLContext setCurrentContext:_context]; // 非常重要的一行代码
            }
            [self cleanUpTextures];
            
            
            //通过CVBufferGetAttachment获取pixelBuffer的颜色空间格式,决定使用的颜色转换矩阵,用于下一步的YUV到RGB颜色空间的转换;
            CFTypeRef colorAttachments = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL);
            
            if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_601_4) {
                
                if (1) {
                    _preferredConversion = kColorConversion601FullRange;
                }
                else {
                    _preferredConversion = kColorConversion601;
                }
            }
            else {
                _preferredConversion = kColorConversion709;
            }
            
            
            /*
             CVOpenGLESTextureCacheCreateTextureFromImage will create GLES texture optimally from CVPixelBufferRef.
             */
            
            /*
             Create Y and UV textures from the pixel buffer. These textures will be drawn on the frame buffer Y-plane.
             */
            glActiveTexture(GL_TEXTURE0);
            err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                               _videoTextureCache,
                                                               pixelBuffer,
                                                               NULL,
                                                               GL_TEXTURE_2D,
                                                               GL_LUMINANCE,
                                                               frameWidth,
                                                               frameHeight,
                                                               GL_LUMINANCE,
                                                               GL_UNSIGNED_BYTE,
                                                               0,
                                                               &_lumaTexture);
            if (err) {
                NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
            }
            
            glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture));
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            
            // UV-plane.
            glActiveTexture(GL_TEXTURE1);
            err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                               _videoTextureCache,
                                                               pixelBuffer,
                                                               NULL,
                                                               GL_TEXTURE_2D,
                                                               GL_LUMINANCE_ALPHA,
                                                               frameWidth / 2,
                                                               frameHeight / 2,
                                                               GL_LUMINANCE_ALPHA,
                                                               GL_UNSIGNED_BYTE,
                                                               1,
                                                               &_chromaTexture);
            if (err) {
                NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
            }
            
            glBindTexture(CVOpenGLESTextureGetTarget(_chromaTexture), CVOpenGLESTextureGetName(_chromaTexture));
            //        NSLog(@"id %d", CVOpenGLESTextureGetName(_chromaTexture));
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            
            glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
            
            // Set the view port to the entire view.
            glViewport(0, 0, _screenWidth, _screenHeight);
        }
        
        glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        // Use shader program.
        glUseProgram(_program);
        glUniformMatrix3fv(uniforms[UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion);
        
        // Set up the quad vertices with respect to the orientation and aspect ratio of the video.
        CGRect vertexSamplingRect = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(_screenWidth, _screenHeight), self.layer.bounds);
        
        // Compute normalized quad coordinates to draw the frame into.
        CGSize normalizedSamplingSize = CGSizeMake(0.0, 0.0);
        CGSize cropScaleAmount = CGSizeMake(vertexSamplingRect.size.width/self.layer.bounds.size.width, vertexSamplingRect.size.height/self.layer.bounds.size.height);
        
        // Normalize the quad vertices.
        if (cropScaleAmount.width > cropScaleAmount.height) {
            normalizedSamplingSize.width = 1.0;
            normalizedSamplingSize.height = cropScaleAmount.height/cropScaleAmount.width;
        }
        else {
            normalizedSamplingSize.width = 1.0;
            normalizedSamplingSize.height = cropScaleAmount.width/cropScaleAmount.height;
        }
        
        /*
         The quad vertex data defines the region of 2D plane onto which we draw our pixel buffers.
         Vertex data formed using (-1,-1) and (1,1) as the bottom left and top right coordinates respectively, covers the entire screen.
         */
        GLfloat quadVertexData [] = {
            -1 * normalizedSamplingSize.width, -1 * normalizedSamplingSize.height,
            normalizedSamplingSize.width, -1 * normalizedSamplingSize.height,
            -1 * normalizedSamplingSize.width, normalizedSamplingSize.height,
            normalizedSamplingSize.width, normalizedSamplingSize.height,
        };
        
        // 更新顶点数据
        glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, quadVertexData);
        glEnableVertexAttribArray(ATTRIB_VERTEX);
        
        GLfloat quadTextureData[] =  { // 正常坐标
            0, 0,
            1, 0,
            0, 1,
            1, 1
        };
        
        glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, 0, quadTextureData);
        glEnableVertexAttribArray(ATTRIB_TEXCOORD);
        
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
        glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle);
        
        if ([EAGLContext currentContext] == _context) {
            [_context presentRenderbuffer:GL_RENDERBUFFER];
        }
        
    }
    
    #pragma mark -  OpenGL ES 2 shader compilation
    //
    - (BOOL)loadShaders
    {
        GLuint vertShader, fragShader;
        NSURL *vertShaderURL, *fragShaderURL;
        
        
        _program = glCreateProgram();
        
        // Create and compile the vertex shader.
        vertShaderURL = [[NSBundle mainBundle] URLForResource:@"Shader" withExtension:@"vsh"];
        if (![self compileShader:&vertShader type:GL_VERTEX_SHADER URL:vertShaderURL]) {
            NSLog(@"Failed to compile vertex shader");
            return NO;
        }
        
        // Create and compile fragment shader.
        fragShaderURL = [[NSBundle mainBundle] URLForResource:@"Shader" withExtension:@"fsh"];
        if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER URL:fragShaderURL]) {
            NSLog(@"Failed to compile fragment shader");
            return NO;
        }
        
        // Attach vertex shader to program.
        glAttachShader(_program, vertShader);
        
        // Attach fragment shader to program.
        glAttachShader(_program, fragShader);
        
        // Bind attribute locations. This needs to be done prior to linking.
        glBindAttribLocation(_program, ATTRIB_VERTEX, "position");
        glBindAttribLocation(_program, ATTRIB_TEXCOORD, "texCoord");
        
        // Link the program.
        if (![self linkProgram:_program]) {
            NSLog(@"Failed to link program: %d", _program);
            
            if (vertShader) {
                glDeleteShader(vertShader);
                vertShader = 0;
            }
            if (fragShader) {
                glDeleteShader(fragShader);
                fragShader = 0;
            }
            if (_program) {
                glDeleteProgram(_program);
                _program = 0;
            }
            
            return NO;
        }
        
        // Get uniform locations.
        uniforms[UNIFORM_Y] = glGetUniformLocation(_program, "SamplerY");
        uniforms[UNIFORM_UV] = glGetUniformLocation(_program, "SamplerUV");
        uniforms[UNIFORM_COLOR_CONVERSION_MATRIX] = glGetUniformLocation(_program, "colorConversionMatrix");
        
        // Release vertex and fragment shaders.
        if (vertShader) {
            glDetachShader(_program, vertShader);
            glDeleteShader(vertShader);
        }
        if (fragShader) {
            glDetachShader(_program, fragShader);
            glDeleteShader(fragShader);
        }
        
        return YES;
    }
    
    - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type URL:(NSURL *)URL
    {
        NSError *error;
        NSString *sourceString = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
        if (sourceString == nil) {
            NSLog(@"Failed to load vertex shader: %@", [error localizedDescription]);
            return NO;
        }
        
        GLint status;
        const GLchar *source;
        source = (GLchar *)[sourceString UTF8String];
        
        *shader = glCreateShader(type);
        glShaderSource(*shader, 1, &source, NULL);
        glCompileShader(*shader);
        
    #if defined(DEBUG)
        GLint logLength;
        glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0) {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetShaderInfoLog(*shader, logLength, &logLength, log);
            NSLog(@"Shader compile log:\n%s", log);
            free(log);
        }
    #endif
        
        glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
        if (status == 0) {
            glDeleteShader(*shader);
            return NO;
        }
        
        return YES;
    }
    
    - (BOOL)linkProgram:(GLuint)prog
    {
        GLint status;
        glLinkProgram(prog);
        
    #if defined(DEBUG)
        GLint logLength;
        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0) {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetProgramInfoLog(prog, logLength, &logLength, log);
            NSLog(@"Program link log:\n%s", log);
            free(log);
        }
    #endif
        
        glGetProgramiv(prog, GL_LINK_STATUS, &status);
        if (status == 0) {
            return NO;
        }
        
        return YES;
    }
    
    - (BOOL)validateProgram:(GLuint)prog
    {
        GLint logLength, status;
        
        glValidateProgram(prog);
        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0) {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetProgramInfoLog(prog, logLength, &logLength, log);
            NSLog(@"Program validate log:\n%s", log);
            free(log);
        }
        
        glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
        if (status == 0) {
            return NO;
        }
        
        return YES;
    }
    
    
    @end
  • 相关阅读:
    C语言学习019:函数指针
    C语言学习018:strdup复制字符串数组
    C语言学习017:malloc和free
    C语言学习016:单链表
    C语言学习015:联合(union)与枚举(enum)
    C语言学习014:结构化数据类型
    C语言学习013:通过make编译C源代码
    C语言学习012:将代码文件分成多个文件
    C语言学习011:带参数的main函数
    C语言学习010:fopen读写文件
  • 原文地址:https://www.cnblogs.com/8335IT/p/16383518.html
Copyright © 2020-2023  润新知