2012-12-30 12 views
1

OpenGL 사양에 여러 번 (예 : 프레임 당 한 번) 호출하는 것이 불법이라는 제안이있는 내용이 있습니까? 나는 '을 사용하지 않으면 성능에 영향을주지 않는다고 가정 할 때 '비효율적 일뿐만 아니라'잘못된 결과를 낼 수도 있습니다 '와 같이 불법을 의미합니다.OpenGL이 glTexImage2D 및 알파 블렌딩을 반복적으로 호출합니다.

내가 묻는 이유는 glTexImage2D (첨부 된 그림 참조)을 사용하여 매 프레임마다 한 번로드되는 부분적으로 투명한 텍스처를 사용하는 겹쳐진 텍스처 매핑 된 프리미티브를 그릴 때 매우 이상한 아티팩트를 발견했다는 것입니다. 몇 초 (즉, 수백 프레임), 작은 직사각형 검은 색 패치가 화면에 나타납니다 (실제로는 연속하는 프레임 사이에서 검정과 보통 사이를 뒤집습니다). 나는 간단한 예제 코드 아래에 부착하고있어

Artifacts

그 문제를 전시 작성할 수 있습니다.

#include <stdio.h> 

#ifndef __APPLE__ 
# include <SDL/SDL.h> 
# include <SDL/SDL_opengl.h> 
#else 
# include <SDL.h> 
# include <SDL_opengl.h> 
#endif 

/* some constants and variables that several functions use */ 
const int width = 640; 
const int height = 480; 
#define texSize 64 

GLuint vbo; 
GLuint tex; 

/* forward declaration, creates a random texture; uses glTexSubImage2D if 
    update is non-zero (otherwise glTexImage2D) */ 
void createTexture(GLuint label, int update); 

int init() 
{ 
    /* SDL initialization */ 
    if (SDL_Init(SDL_INIT_VIDEO) < 0) 
    return 0; 

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
    if (!SDL_SetVideoMode(width, height, 0, SDL_OPENGL)) { 
    fprintf(stderr, "Couldn't initialize OpenGL"); 
    return 0; 
    } 

    /* OpenGL initialization */ 
    glClearColor(0, 0, 0, 0); 
    glEnable(GL_TEXTURE_2D); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

    glViewport(0, 0, width, height); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0, width, height, 0, -1, 1); 
    glMatrixMode(GL_MODELVIEW); 

    /* creating the VBO and the textures */ 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, 1024, 0, GL_DYNAMIC_DRAW); 

    glGenTextures(1, &tex); 
    createTexture(tex, 0); 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

    return 1; 
} 

/* draw a triangle at the specified point */ 
void drawTriangle(GLfloat x, GLfloat y) 
{ 
    GLfloat coords1[12] = {0, 0, 0, 0, /**/200, 0, 1, 0, /**/200, 150, 1, 1}; 

    glLoadIdentity(); 
    glTranslatef(x, y, 0); 

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(coords1), coords1); 
    glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), (void*)0); 
    glTexCoordPointer(2, GL_FLOAT, 4*sizeof(GLfloat), 
    (char*)0 + 2*sizeof(GLfloat)); 

    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

void render() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    drawTriangle(250, 50); 

    createTexture(tex, 0); 
    drawTriangle(260, 120); 

    SDL_GL_SwapBuffers(); 
} 

void cleanup() 
{ 
    glDeleteTextures(1, &tex); 
    glDeleteBuffers(1, &vbo); 

    SDL_Quit(); 
} 

int main(int argc, char* argv[]) 
{ 
    SDL_Event event; 

    if (!init()) return 1; 

    while (1) { 
    while (SDL_PollEvent(&event)) 
     if (event.type == SDL_QUIT) 
     return 0; 

    render(); 
    } 

    cleanup(); 

    return 0; 
} 

void createTexture(GLuint label, int update) 
{ 
    GLubyte data[texSize*texSize*4]; 
    GLubyte* p; 
    int i, j; 

    glBindTexture(GL_TEXTURE_2D, label); 

    for (i = 0; i < texSize; ++i) { 
    for (j = 0; j < texSize; ++j) { 
     p = data + (i + j*texSize)*4; 
     p[0] = ((i % 8) > 4?255:0); 
     p[1] = ((j % 8) > 4?255:0); 
     p[2] = ((i % 8) > 4?255:0); 
     p[3] = 255 - i*3; 
    } 
    } 

    if (!update) 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texSize, texSize, 0, GL_RGBA, 
     GL_UNSIGNED_BYTE, data); 
    else 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texSize, texSize, GL_RGBA, 
     GL_UNSIGNED_BYTE, data); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
} 

주 :

  1. 내가 SDL을 사용하고 있습니다,하지만 난 wxWidgets에에서 같은 해프닝을 본 적이, 그래서는 SDL 관련 문제가 아니다.

  2. 모든 프레임 (createTextureupdate = 1 사용) 대신에 glTexSubImage2D을 사용하면 아티팩트가 사라집니다.

  3. 블렌드를 사용하지 않으면 더 이상 아티팩트가 없습니다.

  4. 필자는 2010 년 말 MacBook Air에서이를 테스트 해왔다.

+0

흥미로운 점 ... createTexture를 처음 drawTriangles로 이동하면 ... 작동합니까? (나는 드라이버의 텍스쳐 싱크 경로에있는 버그를 의심한다.) – Goz

+0

@Goz'createTexture'를'drawTriangle' 둘 다에 옮기면 이슈가 사라진다. 나는 정말로 운전수에서 벌레를 고려하지 않았다고 생각한다. 나는 기회가 생길 때 두 개의 다른 시스템에서이 코드를 시도 할 것이다. – Legendre17

+0

기본적으로 이전 그리기 호출에서 시스템이 여전히 사용 중일 때 시스템이 텍스처를 업데이트하는 것처럼 보입니다. 나는 알파 블렌드를 끄면 이전 드로잉이 진행되는 동안 텍스쳐 변경이 일어나지 않는 지점으로 렌더 경로에 영향을 미친다는 것을 알 수 있습니다. 과거에 운전사를 썼다는 것은 꽤 초보적인 (그리고 정말로 쉽게) 실수였습니다. 최선의 방법은 그 문제를 해결하고 통제에서 벗어나는 것입니다. 그들이 드라이버를 고쳐 줄 것을 희망하면서 사과에 버그를 게시 할 가치가 있습니다! – Goz

답변

1

이것은 분명히 OpenGL 구현 버그입니다. 루프에서 glTexImage2D를 호출하면이 문제가 발생하지 않아야합니다.

+0

좋은 지적입니다, 이것은 버그 일 수 있습니다. 대부분의 어플리케이션이'glTexImage2D'를 한 프레임보다 훨씬 덜 자주 호출하기 때문에 눈치 채기가 어려울 것입니다 ... 이것을 몇 가지 시스템에서 재현 할 수 있는지 살펴 보겠습니다. – Legendre17

+0

이것은 아마도 올바른 대답 일 것입니다. 이를 지원하기 위해 우분투 리눅스를 실행하는 다른 컴퓨터에서이 프로그램을 시도했지만 유물을 볼 수 없었습니다. 더욱이, 유물은 Macbook Air (Ubuntu Linux를 실행하는 가상 머신)의 가상 박스에서 프로그램을 실행하는 경우에도 사라집니다. – Legendre17

+0

@ Legendre17 : 머리를 주셔서 감사합니다. – datenwolf