2014-08-29 5 views
0

OpenGL을 처음 사용했습니다. 저는 iPad에서 페인팅 응용 프로그램을 제작하고 있으며 Apple의 GLPaint 예제를 약간 따르고 있습니다. 기본적으로 터치가 이동 될 때마다 터치 위치에 텍스처를 그립니다.OpenGL ES 2D 텍스처 회전

초기화 GL :

- (BOOL)initGL { 

glGenFramebuffers(1, &viewFramebuffer); 
glGenRenderbuffers(1, &viewRenderbuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer); 
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); 
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(id<EAGLDrawable>)self.layer]; 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer); 
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth); 
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight); 

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{ 
    NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); 
    return NO; 
} 

glViewport(0, 0, backingWidth, backingHeight); 

glGenBuffers(1, &vboId); 

brushTexture = [self textureFromName:@"Brush2.png"]; 

[self setupShaders]; 

glEnable(GL_BLEND); 
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

return YES; 
} 

로드 질감 :

- (textureInfo_t)textureFromName:(NSString *)name { 
CGImageRef  brushImage; 
CGContextRef brushContext; 
GLubyte   *brushData; 
size_t   width, height; 
GLuint   texId; 
textureInfo_t texture; 

brushImage = [UIImage imageNamed:name].CGImage; 

width = CGImageGetWidth(brushImage); 
height = CGImageGetHeight(brushImage); 

if(brushImage) { 
    brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte)); 
    brushContext = CGBitmapContextCreate(brushData, width, height, 8, width * 4, CGImageGetColorSpace(brushImage), kCGImageAlphaPremultipliedLast); 
    CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushImage); 

    CGContextRelease(brushContext); 
    glGenTextures(1, &texId); 
    glBindTexture(GL_TEXTURE_2D, texId); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData); 

    free(brushData); 

    texture.id = texId; 
    texture.width = (int)width; 
    texture.height = (int)height; 
} 

return texture; 
} 

쉐이더 :

- (void)setupShaders { 
for (int i = 0; i < NUM_PROGRAMS; i++) 
{ 
    char *vsrc = readFile(pathForResource(program[i].vert)); 
    char *fsrc = readFile(pathForResource(program[i].frag)); 
    GLsizei attribCt = 0; 
    GLchar *attribUsed[NUM_ATTRIBS]; 
    GLint attrib[NUM_ATTRIBS]; 
    GLchar *attribName[NUM_ATTRIBS] = { 
     "inVertex", 
    }; 
    const GLchar *uniformName[NUM_UNIFORMS] = { 
     "MVP", "pointSize", "vertexColor", "texture", 
    }; 

    for (int j = 0; j < NUM_ATTRIBS; j++) 
    { 
     if (strstr(vsrc, attribName[j])) 
     { 
      attrib[attribCt] = j; 
      attribUsed[attribCt++] = attribName[j]; 
     } 
    } 

    glueCreateProgram(vsrc, fsrc, 
         attribCt, (const GLchar **)&attribUsed[0], attrib, 
         NUM_UNIFORMS, &uniformName[0], program[i].uniform, 
         &program[i].id); 
    free(vsrc); 
    free(fsrc); 

    if (i == PROGRAM_POINT) 
    { 
     glUseProgram(program[PROGRAM_POINT].id); 

     glUniform1i(program[PROGRAM_POINT].uniform[UNIFORM_TEXTURE], 0); 

     GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, backingWidth, 0, backingHeight, -1, 1); 
     GLKMatrix4 modelViewMatrix = GLKMatrix4Identity; // this sample uses a constant identity modelView matrix 
     GLKMatrix4 MVPMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); 

     glUniformMatrix4fv(program[PROGRAM_POINT].uniform[UNIFORM_MVP], 1, GL_FALSE, MVPMatrix.m); 

     glUniform1f(program[PROGRAM_POINT].uniform[UNIFORM_POINT_SIZE], brushTexture.width/kBrushScale); 

     glUniform4fv(program[PROGRAM_POINT].uniform[UNIFORM_VERTEX_COLOR], 1, brushColor); 
    } 
} 

glError(); 
다음 코드를 사용하여 볼 수있는 이미지에서 텍스처를로드하고 그것을 그릴 수 있었다

}

그리기 :

- (void)renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end { 
static GLfloat*  vertexBuffer = NULL; 
static NSUInteger vertexMax = 64; 
NSUInteger   vertexCount = 0, 
        count, 
        i; 

[EAGLContext setCurrentContext:context]; 

glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer); 

CGFloat scale = self.contentScaleFactor; 
start.x *= scale; 
start.y *= scale; 
end.x *= scale; 
end.y *= scale; 

if(vertexBuffer == NULL) 
    vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat)); 

count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y))/kBrushPixelStep), 1); 
for(i = 0; i < count; ++i) { 
    if(vertexCount == vertexMax) { 
     vertexMax = 2 * vertexMax; 
     vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat)); 
    } 

    vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i/(GLfloat)count); 
    vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i/(GLfloat)count); 
    vertexCount += 1; 
} 

glBindBuffer(GL_ARRAY_BUFFER, vboId); 
glBufferData(GL_ARRAY_BUFFER, vertexCount*2*sizeof(GLfloat), vertexBuffer, GL_DYNAMIC_DRAW); 

glEnableVertexAttribArray(ATTRIB_VERTEX); 
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0); 

glUseProgram(program[PROGRAM_POINT].id); 
glDrawArrays(GL_POINTS, 0, (int)vertexCount); 

glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer); 
[context presentRenderbuffer:GL_RENDERBUFFER]; 

}

은 내가 놓친 것은이 그려됩니다 때마다 전에 텍스처를 회전하는 방법이다. 회전 된 CGContext로 텍스처를 초기화하려고 시도했지만 포인트가 그려 질 때마다 호출하기에는 너무 많은 처리가 필요합니다. 누군가가 감촉을 회전시키는 더 좋은 방법을 보여줄 수 있습니까? 나는 OpenGL에 대해 매우 익숙하다.

답변

2

GL_TEXTURE 매트릭스 모드를 사용하여 텍스처 좌표에 변환을 적용 할 수 있습니다. 예를 들어, Z 축 주위에 90도 반 시계 방향으로 텍스처 좌표를 회전 :

glMatrixMode(GL_TEXTURE); 
glTranslatef(1.0f, 0.0f, 0.0f); 
glRotatef(90.0f, 0.0f, 0.0f, 1.0f); 
glMatrixMode(GL_MODELVIEW); 

주 번역은 감촉이 [0.0, 1.0] 내에 범위 좌표 원점 주위 회전 이후 범위 유지. 여기에 비슷한 질문에 대한 나의 이전 대답이 좀 더 자세히 설명되어 있습니다 : gluCylinder with rotated texture.

나는 일반적으로 포스터가 묻는 것보다 다른 기술을 권장하지는 않지만이 경우에는 도움이되지 않습니다. OpenGL ES를 처음 사용하는 경우 ES 1.x를 건너 뛰는 것이 좋습니다. 나는 대부분의 사람들이 현재 쓸모없는 API라고 생각할 것입니다. 예를 들어 www.khronos.com (https://www.khronos.org/opengles/sdk/docs/)의 Man Pages로 이동하면 ES 1.x에 대한 링크가 더 이상 없음을 알 수 있습니다. 콘텐츠는 더 이상 탐색 할 때 당연히 주위에 있지만, 요즘 ES 2.0이 기준선으로 간주된다는 것은 분명한 힌트입니다.

+0

답변을 게시 해 주셔서 감사합니다. 그러나 조금 위의 코드에 대한 혼란. glDrawArrays 함수 바로 앞에 넣으려고했지만 결과가 없습니다. 텍스처는 여전히 원래 방향으로 그려집니다. 코드가 다른 곳으로 가야하나요? – Amendale

+0

흠, 어디에도 명시 적으로 텍스처 좌표를 설정하지 않은 것처럼 보입니다. 그것들을 생성하는'GL_POINT_SPRITE_OES' 물건이어야합니다. 텍스처 변환이 생성 된 텍스처 좌표에 적용되지 않을 가능성이 있습니다. –

+0

http://www.khronos.org/registry/gles/extensions/OES/OES_point_sprite.txt 문서에 따라 점 스프라이트는 항상 창 좌표에서 축 정렬됩니다. 포스터는 파티클을위한 확장이 아닌 실제 지오메트리 사용으로 전환해야합니다. – Tommy