º£²ó¤ÏOpenGLES2¤ÇÈĥݥꥴ¥ó¤òÉÁ²è¤·¤Þ¤¹ &ref(screenshot2.PNG); º£²ó¤Î¥×¥í¥°¥é¥à°ì¼°¤Ï¤³¤Á¤é ¡¦&ref(OpenGLES2DrawQuad.zip); º£²ó°Ê¹ß¤«¤é Á°²ó¤ÎOpenGLES.framework¡¢QuartzCore.framework¤Ë²Ã¤¨¤Æ ¿ô³Ø·×»»½èÍý¤Ê¤ÉÊØÍø¤ÊAPI¤âÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç ¡¦GLKit.framework ¤ò¥×¥í¥¸¥§¥¯¥È¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤ &ref(framework.png); º£²ó¤Ï¤ä¤ë¤³¤ÈÀ¹¤ê¤À¤¯¤µ¤ó¤Ç¤¹¡£ ²èÁüÉÕ¤Èĥݥꥴ¥ó¤òÉÁ²è¤¹¤ë¤¿¤á¤Ë¤Ï °Ê²¼¤Î¼ê½ç¤¬É¬ÍפǤ¹¡£ ¡¦¡ÄºÅÀ¹½Â¤¤ÎÄêµÁ ¡¦¢¥Æ¥¯¥¹¥Á¥ã¡Ê²èÁü¡Ë¤ÎÆɤ߹þ¤ß ¡¦£ÄºÅÀ¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È(VBO)¤ÎºîÀ® ¡¦¤ÄºÅÀ¥·¥§¡¼¥À¡¢¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤ÎºîÀ®¤ª¤è¤Ó¥³¥ó¥Ñ¥¤¥ë¡õ¥ê¥ó¥¯ ¡¦¥¥·¥§¡¼¥ÀÊÑ¿ô¤ÎÀßÄê ¡¦¦ÄºÅÀ¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È¤ÎÉÁ²è ÉÁ²è¤Îή¤ì¤ÏDrawQuadView.m¤Ë¤Þ¤È¤á¤Æ¤¢¤ë¤Î¤Ç ¤½¤Á¤é¤ò³Îǧ¤·¤Æ¤¯¤À¤µ¤¤ ¡ÄºÅÀ¹½Â¤¤ÎÄêµÁ ÉÁ²èÍѤÎĺÅÀ¥Ç¡¼¥¿¤òÄêµÁ¤·¤Þ¤¹ // ĺÅÀ¹½Â¤ typedef struct { float Position[3]; // ĺÅÀºÂɸ float TexCoord[2]; // ¥Æ¥¯¥¹¥Á¥ãºÂɸ } Vertex; #define TEX_COORD_MAX 1 // ĺÅÀ¥Ç¡¼¥¿ const Vertex Vertices[] = { {{1, -1, 1}, {TEX_COORD_MAX, 0}}, {{1, 1, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}}, {{-1, 1, 1}, {0, TEX_COORD_MAX}}, {{-1, -1, 1},{0, 0}}, }; // ĺÅÀ¥¤¥ó¥Ç¥Ã¥¯¥¹ const GLubyte Indices[] = { 2, 1, 0, 0, 3, 2, }; º£²ó¤ÏĺÅÀ¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç»ØÄꤷ¤¿ÄºÅÀ¤«¤éÀ®¤ë »°³Ñ·Á¤ò£²¤Ä¹çÂΤ·¤Æ»Í³Ñ·Á¤òºîÀ®¤·¤Þ¤¹¡£ £³DÉÁ²è¤Î´ðËÜñ°Ì¤Ï»°³Ñ·Á¤Ç¤¹ ¸Þ³Ñ·Á¤Ï»°³Ñ·Á»°¸Ä¡¢ Ï»³Ñ·Á¤Ï»°³Ñ·Á»Í¸Ä¤Ëʬ³ä²Äǽ¤È¤¤¤Ã¤¿¤è¤¦¤Ë ²¿³Ñ·Á¤Ç¤â»°³Ñ·Á¤Çɽ¸½¤Ç¤¤Þ¤¹¡£ »°³Ñ·Á¤Î¤è¤¦¤ËÉÁ²è¤Î´ðËܤȤʤëñ°Ì¤ò¥×¥ê¥ß¥Æ¥£¥Ö¤È¸Æ¤Ó¤Þ¤¹¡£ ¾¤Ë¤â¡¢Àþ¤äÅÀ¤Ê¤É¤Î¥×¥ê¥ß¥Æ¥£¥Ö¤¬¤¢¤ê¤Þ¤¹¡£ ¢¥Æ¥¯¥¹¥Á¥ã¡Ê²èÁü¡Ë¤ÎÆɤ߹þ¤ß _texture = [[Texture alloc] initWithFile:[NSString stringWithUTF8String:"tile_floor.png"]]; £ÄºÅÀ¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È¡ÊVBO¡Ë¤ÎºîÀ® ĺÅÀ¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È¤Ï ÂçÎ̤ÎĺÅÀ¥Ç¡¼¥¿¤ò¸úΨ¤è¤¯ÉÁ²è¤¹¤ë¤¿¤á¤Ë ¥ª¥ó¥á¥â¥ê¤Ë¥Ç¡¼¥¿¤ò¥¥ã¥Ã¥·¥å¤¹¤ë»ÅÁȤߤǤ¹¡£ ĺÅÀ¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ëĺÅÀ¥Ð¥Ã¥Õ¥¡¤È ¤É¤ÎĺÅÀ¤ò»È¤Ã¤Æ»°³Ñ·Á¤òÉÁ²è¤¹¤ë¤Î¤«¤ò·è¤á¤ëĺÅÀ¥¤¥ó¥Ç¥Ã¥¯¥¹¤ò³ÊǼ¤¹¤ë¥¤¥ó¥Ç¥Ã¥¯¥¹¥Ð¥Ã¥Õ¥¡¤ÎºîÀ®¤ò¤·¤Þ¤¹ // ĺÅÀ¥Ð¥Ã¥Õ¥¡ºîÀ® glGenBuffers(1, &_vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); // ¥¤¥ó¥Ç¥Ã¥¯¥¹¥Ð¥Ã¥Õ¥¡ºîÀ® glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); ¤ÄºÅÀ¥·¥§¡¼¥À¡¢¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤ÎºîÀ®¤ª¤è¤Ó¥³¥ó¥Ñ¥¤¥ë¡õ¥ê¥ó¥¯ ¥·¥§¡¼¥À¤È¤ÏGPU¡Ê¥°¥é¥Õ¥£¥Ã¥¯¥Ü¡¼¥É¡Ë¤Ç¤ÎÌ¿Îá½èÍý¤Ç¤¹¡£ ½èÍý¤¬½Å¤¤¡¢ÉÁ²è½èÍý¤Ë´Ø¤·¤Æ¤ÏGPU¤ËľÀÜÌ¿Î᤹¤ë¤³¤È¤Ç¹â®²½¤¬·×¤ì¤Þ¤¹¡£ ¤Þ¤¿¡¢OpenGLES2°Ê¹ß¤«¤é¥·¥§¡¼¥À¤Ç¤ÎÌ¿Î᤬ɬ¿Ü¤Ë¤Ê¤ê¤Þ¤·¤¿¡£ ¥·¥§¡¼¥À¤ÇľÀÜÉÁ²è½èÍý¤ò»ØÄꤹ¤ë¤³¤È¤Ç¤è¤êĺÅÀ¡¦¥Ô¥¯¥»¥ëñ°Ì¤Ç¤Î ½ÀÆð¤Ç¹â®¤ÊÉÁ²è½èÍý¤ò¹Ô¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£ ¥·¥§¡¼¥À¤Ï£²¼ïÎढ¤ê¡¢ ĺÅÀ¥·¥§¡¼¥À¤ÏĺÅÀñ°Ì¤Î½èÍý¡¢¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤Ï¥Ô¥¯¥»¥ëñ°Ì¤Î½èÍý¤ò¹Ô¤¤¤Þ¤¹¡£ ÉÁ²è»þ¤Ë¤ÏĺÅÀñ°Ì¤Ë½èÍý¤ò¤µ¤ì¤¿¸å¡¢ ĺÅÀƱ»Î¤Î¥Ô¥¯¥»¥ë´Ö¤òÊä´Ö¤¹¤ë¥é¥¹¥¿¥é¥¤¥º²½¤È¸Æ¤Ð¤ì¤ë½èÍý¤¬¤µ¤ì¡¢ ¥Ô¥¯¥»¥ëñ°Ì¤Î½èÍý¤Ë°Ü¹Ô¤·¤Þ¤¹¡£ ¤½¤Î¤¿¤áξÊý¤È¤â¼ÂÁõ¤Ïɬ¿Ü¤Ç¤¹¡£ Vertex.glsl¤¬ÄºÅÀ¥·¥§¡¼¥À¤Ç¤¹¡£ // input Vertex data attribute vec3 aPosition; attribute vec2 aTexCoord; // Uniform data uniform mat4 uProjectionMatrix; uniform mat4 uModelViewMatrix; // Output Vertex data varying vec2 vTexCoord; void main(void) { gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aPosition,1.0); vTexCoord = aTexCoord; } attribute°À¤ò»ý¤ÄÊÑ¿ô¤ÏĺÅÀñ°Ì¤ÇÁ÷¤é¤ì¤Æ¤¯¤ë¥Ç¡¼¥¿¤Ç¤¹¡£ uniform°À¤ò»ý¤ÄÊÑ¿ô¤Ï³°Éô¡ÊCPU¦¤Î¥×¥í¥°¥é¥à¡Ë¤«¤éÀßÄꤵ¤ì¤ë¤É¤ÎĺÅÀ¤Ç¤â¶¦Ä̤Υǡ¼¥¿¤Ç¤¹¡£ varying°À¤ò»ý¤ÄÊÑ¿ô¤Ï¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤ËÅϤ¹¥Ç¡¼¥¿¤Ç¤¹¡£ ĺÅÀ°ÌÃ֤ϥե饰¥á¥ó¥È¥·¥§¡¼¥À¤ËÅϤ¹É¬Íפ¬¤Ê¤¤¤¿¤á gl_Position¤È¤¤¤¦Í½Ìó¸ì¤Ç½ÐÎϤ·¤Þ¤¹¡£ Fragment.glsl¤¬¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤Ç¤¹¡£ varying highp vec2 vTexCoord; uniform sampler2D ColorTextureSampler; void main(void) { gl_FragColor = texture2D(ColorTextureSampler, vTexCoord); } varying°À¤ò»ý¤ÄÊÑ¿ô¤Ï¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤ËÁ÷¤é¤ì¤Æ¤¯¤ë¥Ç¡¼¥¿¤Ç¤¹¡£ ¤Ê¤ª¡¢¥Õ¥é¥°¥á¥ó¥È¥·¥§¡¼¥À¤Ç¤Ïvec2,vec3¤Ê¤É¤Î¥Ù¥¯¥È¥ë¤ämat4¤Ê¤É¤Î¹ÔÎó¤Ê¤É ¿ôÃͤ¬Íí¤àÊÑ¿ô¤Ë¤ÏÀºÅÙ¼¨¤¹Â°À¤ò¤Ä¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£ highp°À¤Ï¹âÀºÅ٤Ǥ¢¤ë¤³¤È¤ò¼¨¤·¤Þ¤¹¡£ ÄãÀºÅÙ¤Êlowp°À¤ò»ØÄꤹ¤ë¤³¤È¤â¤Ç¤¤Þ¤¹¡£ uniform°À¤ò»ý¤ÄÊÑ¿ô¤Ï³°Éô¡ÊCPU¦¤Î¥×¥í¥°¥é¥à¡Ë¤«¤éÀßÄꤵ¤ì¤ë¤É¤Î¥Ô¥¯¥»¥ë¤Ç¤â¶¦Ä̤Υǡ¼¥¿¤Ç¤¹¡£ ¥µ¥ó¥×¥é¡Êsampler2D¡Ë¤Ë¤Ï¥é¥¹¥¿¥é¥¤¥º²½¤µ¤ì¤¿¥Æ¥¯¥¹¥Á¥ã¤Î¥Æ¥¯¥»¥ë¥Ç¡¼¥¿¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£ texture2D´Ø¿ô¤Ë¤è¤Ã¤Æ¥Æ¥¯¥¹¥Á¥ãºÂɸ¤ËÂбþ¤¹¤ë¥Æ¥¯¥»¥ë¤Î¿§¾ðÊó¤ò¼èÆÀ¤Ç¤¤Þ¤¹¡£ ºîÀ®¤·¤¿¥·¥§¡¼¥À¤Î¥³¥ó¥Ñ¥¤¥ë¡õ¥ê¥ó¥¯¤Ï ²¼µ¤Ç¹Ô¤Ã¤Æ¤¤¤Þ¤¹¡£ // ¥×¥í¥°¥é¥à¥Ö¥ë¥·¥§¡¼¥À¡¼¤Î¥³¥ó¥Ñ¥¤¥ë - (void)compileShaders { shader = [[Shader alloc] init]; [shader compileShaders:@"Vertex.glsl" fragmentShader:@"Fragment.glsl"]; ¥³¥ó¥Ñ¥¤¥ë¡õ¥ê¥ó¥¯¤Î¼ÂÁõ¤Ï Shader.h,Shader.m¤Ë¤¢¤ê¤Þ¤¹¤¬ ·è¤Þ¤ê¤¤Ã¤¿½èÍý¤Ê¤Î¤ÇÀâÌÀ¤Ï³ä°¦¤·¤Þ¤¹¡£ ¥·¥§¡¼¥À¡¼¤Î¥³¥ó¥Ñ¥¤¥ë¡õ¥ê¥ó¥¯¤¬À®¸ù¤·¤¿¤é ¥·¥§¡¼¥À¡¼ÊÑ¿ô¤Ë¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥Ï¥ó¥É¥ë¤ò¼èÆÀ¤·¤Æ¤ª¤¤Þ¤¹ ¤³¤ì¤é¤Î¥Ï¥ó¥É¥ë¤ÏÉÁ²è»þ¤Ë¥·¥§¡¼¥À¤Ë¥Ç¡¼¥¿¤òÅϤ¹¤¿¤á¤Ë»È¤¤¤Þ¤¹ // ¥·¥§¡¼¥ÀÊÑ¿ô¤Î¥Ï¥ó¥É¥ë¼èÆÀ _positionSlot = glGetAttribLocation(shader.programHandle, "Position"); _texCoordSlot = glGetAttribLocation(shader.programHandle, "TexCoordIn"); _modelViewUniform = glGetUniformLocation(shader.programHandle, "Modelview"); _projectionUniform = glGetUniformLocation(shader.programHandle, "Projection"); _textureUniform = glGetUniformLocation(shader.programHandle, "ColorTexture"); ¥¥·¥§¡¼¥ÀÊÑ¿ô¤ÎÀßÄê GLKMatrix4 modelMatrix = GLKMatrix4Make(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); // ¥Ó¥å¡¼ÊÑ´¹ GLKMatrix4 viewMatrix = [_transformations getViewMatrix]; GLKMatrix4 modelViewMatrix = GLKMatrix4Multiply(viewMatrix,modelMatrix); glUniformMatrix4fv(_modelViewUniform, 1, 0, modelViewMatrix.m); // ¼Í±ÆÊÑ´¹¹ÔÎó const GLfloat aspectRatio = (GLfloat)(self.bounds.size.width) / (GLfloat)(self.bounds.size.height); const GLfloat fieldView = GLKMathDegreesToRadians(60.0f); const GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(fieldView, aspectRatio, 0.1f, 100.0f); glUniformMatrix4fv(_projectionUniform, 1, 0, projectionMatrix.m); // ¥Ó¥å¡¼¥Ý¡¼¥ÈÊÑ´¹¤ÎÀßÄê glViewport(0, 0, self.frame.size.width, self.frame.size.height); // ÉÁ²è»þ¤Ë»ÈÍѤ¹¤ë¥·¥§¡¼¥À¤ÎÀßÄê glUseProgram(shader.programHandle); // VBO¤ÎÀßÄê glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); // ĺÅÀ¥Ç¡¼¥¿¹½Â¤¤ÎÀßÄê glEnableVertexAttribArray(_positionSlot); glEnableVertexAttribArray(_texCoordSlot); glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3)); // ¥Æ¥¯¥¹¥Á¥ã¤ÎÀßÄê glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _texture.handle); glUniform1i(_textureUniform, 0); ¦ÄºÅÀ¥Ð¥Ã¥Õ¥¡¥ª¥Ö¥¸¥§¥¯¥È¤ÎÉÁ²è // ÉÁ²è glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); Ê䡧 ÉÁ²è¤ÈľÀܤϴط¸¤¢¤ê¤Þ¤»¤ó¤¬ ¥¸¥§¥¹¥Á¥ã¡¼¤Ç²èÌ̤Υ¤¥ó¥¿¥é¥¯¥Æ¥£¥ÖÁàºî¤¬¤Ç¤¤ë¤è¤¦¤Ë¤·¤Æ¤¢¤ê¤Þ¤¹ ¥Ñ¥ó¡Ê£±Ëܻإɥé¥Ã¥°¡Ë¡§²èÌÌÊ¿¹Ô°ÜÆ° ¥Ñ¥ó¡Ê£²Ëܻإɥé¥Ã¥°¡Ë¡§²èÌ̤ÎXY¼´¤ò´ð¼´¤È¤·¤¿²óž ¥Ô¥ó¥Á¡¦¥¤¥ó¥¢¥¦¥È¡§³ÈÂç½Ì¾® ¥í¡¼¥Æ¡¼¥·¥ç¥ó¡Ê£²Ëܻزóž¡Ë¡§¸«¤Æ¤¤¤ë±ü¹Ô¤Êý¸þ(Z¼´)¤ËÂФ·¤Æ¤Î²óž ¥¸¥§¥¹¥Á¥ã¡¼ÁàºîÉôʬ¤Ï¤½¤Î¤Þ¤Þ¥Ñ¥¯¤Ã¤Æ¤¤¿¤â¤Î¤Ê¤Î¤Ç¾ÜºÙ¤Ï¥ê¥ó¥¯Àè¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤ http://www.raywenderlich.com/50398/opengl-es-transformations-gestures DrawQuadView.m¤Î ¥¸¥§¥¹¥Á¥ã¡¼¼ÂÁõÉôʬ¤òÈ´¿è¤·¤Þ¤¹ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // Begin transformations [_transformations start]; } // ¥Ñ¥ó - (IBAction)pan:(UIPanGestureRecognizer *)sender { // Pan (1 Finger) if((sender.numberOfTouches == 1) && ((_transformations.state == S_NEW) || (_transformations.state == S_TRANSLATION))) { // Ê¿¹Ô°ÜÆ° CGPoint translation = [sender translationInView:sender.view]; float x = translation.x/sender.view.frame.size.width; float y = translation.y/sender.view.frame.size.height; [_transformations translate:GLKVector2Make(x, y) withMultiplier:5.0f]; } // Pan (2 Fingers) else if((sender.numberOfTouches == 2) && ((_transformations.state == S_NEW) || (_transformations.state == S_ROTATION))) { // ²óž const float m = GLKMathDegreesToRadians(0.5f); CGPoint rotation = [sender translationInView:sender.view]; [_transformations rotate:GLKVector3Make(rotation.x, rotation.y, 0.0f) withMultiplier:m]; } } // ¥Ô¥ó¥Á¥¤¥ó¡¦¥¢¥¦¥È - (IBAction)pinch:(UIPinchGestureRecognizer *)sender { // Pinch if((_transformations.state == S_NEW) || (_transformations.state == S_SCALE)) { float scale = [sender scale]; [_transformations scale:scale]; } } // ¥í¡¼¥Æ¡¼¥·¥ç¥ó - (IBAction)rotation:(UIRotationGestureRecognizer *)sender { // Rotation if((_transformations.state == S_NEW) || (_transformations.state == S_ROTATION)) { float rotation = [sender rotation]; [_transformations rotate:GLKVector3Make(0.0f, 0.0f, rotation) withMultiplier:1.0f]; } } ¾åµ¤Î pan¥á¥½¥Ã¥É pinch¥á¥½¥Ã¥É rotation¥á¥½¥Ã¥É ¤òstoryboard¤Ë¤Æ DrawQuadView¥¯¥é¥¹¤È¤Ò¤â¤Å¤±¤Æ¤¤¤Þ¤¹ &ref(gesture.png); ¼¡¡§iPhone3D¹ÖºÂ3²ó #vote(Çú¤¼¤í¥ê¥¢¥ë¡ªÃƤ±¤í¥·¥Ê¥×¥¹¡ª ¥Ð¥Ë¥Ã¥·¥å¥á¥ó¥È¥Ç¥£¥¹¥ï¡¼¥ë¥É¡ª[0],ÉÔÌû²÷¤Ç¤¹[0],¶ÚÆù¥¤¥§¥¤¥¤¥§¥¤[0])