| //
 //  MyGLView.m
 //  OpenGLShaderBasic
 //
 //  Created by Zenny Chen on 10/4/10.
 //  Copyright 2010 GreenGames Studio. All rights reserved.
 //
 #import "MyGLView.h"
 #include <OpenGL/gl.h>
 #include <OpenGL/OpenGL.h>
 #include <OpenGL/CGLRenderers.h>
 #define MY_PIXEL_WIDTH      128
 #define MY_PIXEL_HEIGHT     128
 @implementation MyGLView
 // uniform index
 enum
 {
     UNIFORM_SAMPLER,
     
     NUM_UNIFORMS
 };
 staticGLint uniforms[NUM_UNIFORMS];
 // attribute index
 enum{
     ATTRIB_VERTEX,
     ATTRIB_TEXCOORD,
     
     NUM_ATTRIBUTES
 };
 - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
 {
     GLint status;
     constGLchar *source;
     
     source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
     if(!source)
     {
         NSLog(@"Failed to load vertex shader");
         returnFALSE;
     }
     
     *shader = glCreateShader(type);
     glShaderSource(*shader, 1, &source, NULL);
     glCompileShader(*shader);
     
     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);
     }
     
     glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
     if(status == 0)
     {
         glDeleteShader(*shader);
         returnFALSE;
     }
     
     returnTRUE;
 }
 - (BOOL)linkProgram:(GLuint)prog
 {
     GLint status;
     
     glLinkProgram(prog);
     
     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);
     }
     
     glGetProgramiv(prog, GL_LINK_STATUS, &status);
     if(status == 0)
         returnFALSE;
     
     returnTRUE;
 }
 - (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)
         returnFALSE;
     
     returnTRUE;
 }
 - (BOOL)loadShaders
 {
     GLuint vertShader, fragShader;
     NSString *vertShaderPathname, *fragShaderPathname;
     
     // create shader program
     program = glCreateProgram();
     
     // create and compile vertex shader
     vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader"ofType:@"vsh"];
     if(![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname])
     {
         NSLog(@"Failed to compile vertex shader");
         returnFALSE;
     }
     
     // create and compile fragment shader
     fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader"ofType:@"fsh"];
     if(![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname])
     {
         NSLog(@"Failed to compile fragment shader");
         returnFALSE;
     }
     
     // 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, "texCoords");
     //glBindFragDataLocationEXT(program, 0, "myFragColor");
     
     // link program
     if(![self linkProgram:program])
     {
         NSLog(@"Failed to link program: %d", program);
         returnFALSE;
     }
     
     // get uniform locations
     uniforms[UNIFORM_SAMPLER] = glGetUniformLocation(program, "sampler");
     
     // release vertex and fragment shaders
     if(vertShader)
         glDeleteShader(vertShader);
     if(fragShader)
         glDeleteShader(fragShader);
     
     returnTRUE;
 }
 - (void)dealloc
 {
     if(texName != 0)
         glDeleteTextures(1, &texName);
     
     if(framebufferID != 0)
         glDeleteFramebuffers(1, &framebufferID);
     
     if(glContext != nil)
     {
         [glContext release];
         glContext = nil;
     }
     
     [super dealloc];
 }
 staticGLfloat __attribute__((aligned(16))) my_buffer[MY_PIXEL_WIDTH * MY_PIXEL_HEIGHT * 4];
 staticGLfloat __attribute__((aligned(16))) checkImage[MY_PIXEL_WIDTH * MY_PIXEL_HEIGHT * 4];
 staticvoidinitCheckImage(void)
 {
     for(introw = 0; row < MY_PIXEL_HEIGHT; row++)
     {        
         for(intcol = 0; col < MY_PIXEL_WIDTH; col++)
         {
             checkImage[row * MY_PIXEL_WIDTH * 4 + col * 4 + 0] = 0.1f;
             checkImage[row * MY_PIXEL_WIDTH * 4 + col * 4 + 1] = 0.2f;
             checkImage[row * MY_PIXEL_WIDTH * 4 + col * 4 + 2] = 0.3f;
             checkImage[row * MY_PIXEL_WIDTH * 4 + col * 4 + 3] = 0.4f;
         }
     }
 }
 - (void)prepareOpenGL
 {
     if(glContext != nil)
         return;
     
 #if 0
     CGLPixelFormatObj pixObj = NULL;
     GLint nPix = 0;
     CGLChoosePixelFormat((constCGLPixelFormatAttribute[]){kCGLPFAOpenGLProfile, kCGLOGLPVersion_3_2_Core, 0}, &pixObj, &nPix);
     NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithCGLPixelFormatObj:pixObj];
     CGLReleasePixelFormat(pixObj);
     
 #else
     
     // 创建pixel format,设置离屏渲染
     NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:(constNSOpenGLPixelFormatAttribute[]){NSOpenGLPFAAllRenderers, NSOpenGLPFAOffScreen, NSOpenGLPFAAllowOfflineRenderers, 0}];
 #endif
     
     // 创建OpenGL上下文
     glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
     [pixelFormat release];<br>
     // 将此上下文作为当前上下文
     [glContext makeCurrentContext];
     
     if(![self loadShaders])
         return;
     
     glGenFramebuffers(1, &framebufferID);
     glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
     
     glViewport(0, 0, MY_PIXEL_WIDTH, MY_PIXEL_HEIGHT);
     glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
     
     // Use shader program
     glUseProgram(program);
     
     // Drawing code here.
     staticconstGLfloat squareVertices[] = {
         -1.0f, -1.0f, 0.0f,
         1.0f, -1.0f, 0.0f,
         -1.0f,  1.0f, 0.0f,
         1.0f,  1.0f, 0.0f
     };
     
     staticconstGLfloat texCoords[] = {
         0.0f, 0.0f,     // left lower
         1.0f, 0.0f,     // right lower
         0.0f, 1.0f,     // left upper
         1.0f, 1.0f      // right upper
     };
     
     glEnable(GL_CULL_FACE);
     
     // 初始化纹理数据
     initCheckImage();
     
     glClampColorARB(GL_RGBA_FLOAT_MODE_ARB, GL_TRUE);
     glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
     glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
     
     // 初始化纹理
     glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
     glActiveTexture(GL_TEXTURE0);
     glGenTextures(1, &texName);
     glBindTexture(GL_TEXTURE_2D, texName);
     
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MY_PIXEL_WIDTH, MY_PIXEL_HEIGHT, 0, GL_RGBA, GL_FLOAT, checkImage);
     
     // 将纹理绑定到帧缓存
     glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texName, 0);
     glUniform1i(uniforms[UNIFORM_SAMPLER], 0);      // Set the sampler value
     
     // Update attribute values
     glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, squareVertices);
     glEnableVertexAttribArray(ATTRIB_VERTEX);
     glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, 0, 0, texCoords);
     glEnableVertexAttribArray(ATTRIB_TEXCOORD);
 }
 - (void)compute
 {
     glClear(GL_COLOR_BUFFER_BIT);
     
     // Draw
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     
     glFlush();
     
     glReadPixels(0, 0, MY_PIXEL_WIDTH, MY_PIXEL_HEIGHT, GL_RGBA, GL_FLOAT, my_buffer);
     NSLog(@"R:%f, G:%f, B:%f, A:%f", my_buffer[0], my_buffer[1], my_buffer[2], my_buffer[3]);
 }
 @end
 |