Вернуться содержимое буфера в текстуру в OpenGL - PullRequest
1 голос
/ 14 февраля 2012

Чтобы ускорить мою игру типа лабиринт, я решил поместить свой нарисованный шарик в текстуру, потому что я должен нарисовать его иначе один раз для каждой комнаты, и я рисую его как вогнутый многоугольник, используя буфер трафарета, для этого требуется большевремя, чем с помощью текстуры.Проблема в том, что я правильно получаю текстуру из заднего буфера при рендеринге третьего кадра с момента запуска игры, и мой вопрос: почему это так?

КогдаЯ использую текстуру из рамки жажды, у меня есть текстура сплошного белого цвета, поэтому внутри нее ничего нет.Когда я использую текстуры из второго кадра, у меня есть только черный фон желаемой текстуры, а когда я беру текстуру из третьего кадра, то у меня есть желаемая текстура.Для подсчета кадров я использую статическую переменную «done» внутри функции «drawTexture».

Копирование из первого кадра:

enter image description here

Копирование со второго кадра:

enter image description here

Копирование изтретий кадр (желаемый результат):

enter image description here

void DrawBall::drawTexture(float imageD) {
    static int done = 0;

    if (done < 3) {
        drawToTexture(imageD);
        done++;
    }

    glEnable(GL_TEXTURE_2D);
    glBindTexture (GL_TEXTURE_2D, texture);

    glColor3f(1, 1, 1);
    glBegin (GL_QUADS);
        glTexCoord2f (0.0, 0.0); glVertex3f (0.0, 0.0, -imageD);    
        glTexCoord2f (1.0, 0.0); glVertex3f (5.0, 0.0, -imageD);
        glTexCoord2f (1.0, 1.0); glVertex3f (5.0, 5.0, -imageD);    
        glTexCoord2f (0.0, 1.0); glVertex3f (0.0, 5.0, -imageD);
    glEnd ();

    glDisable(GL_TEXTURE_2D);   
}

void DrawBall::drawToTexture(float imageD) {
    int viewport[4];
    glGetIntegerv(GL_VIEWPORT, (int*) viewport);

    int textureWidth = 64;
    int textureHeight = 64;

    texture = genEmptyTexture(textureWidth, textureHeight);

    glViewport(0, 0, textureWidth, textureHeight);
    glMatrixMode(GL_PROJECTION);                            
    glLoadIdentity();                                       
    gluPerspective(45.0f, 1, 1, 100);
    glMatrixMode(GL_MODELVIEW);                         
    glLoadIdentity();                                       

    /* 
       This function calculates the vertexes for the ball
       inside a vector<vector<float>> variable "test"
    */
    _calculateCircleVertexes(0.0f, 0.0f, -2.0f, 0.249f, &test, 20);

    _displayBall(&test, 0.0f, 0.0f, 0.5f, -2.0f, &*smallBallColor);

    glBindTexture(GL_TEXTURE_2D, texture);
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, textureWidth, textureHeight, 0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
    glMatrixMode(GL_PROJECTION);    
    glLoadIdentity();               
    gluPerspective(45.0f, (GLfloat)viewport[2] / (GLfloat)viewport[3], 1.0f, imageD + 10.0f);
    glMatrixMode(GL_MODELVIEW);     
    glLoadIdentity();   
}

GLuint DrawBall::genEmptyTexture(unsigned int width, unsigned int height) {
    GLuint txtIndex;

    glGenTextures(1, &txtIndex);                                    
    glBindTexture(GL_TEXTURE_2D, txtIndex);                         

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
    GL_RGB, GL_UNSIGNED_BYTE, NULL);                            

    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_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

    return txtIndex;
}

void DrawBall::_displayBall(vector<vector<GLfloat>> *vertexes, GLfloat x, GLfloat y
                        , GLfloat imageW, GLfloat imageD, color *color) {
    glTranslatef(x, y, imageD);

    glClearStencil(0);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NEVER, 0, 1);
    glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);

    glBegin(GL_POLYGON);
        vector<vector<GLfloat>>::iterator it = vertexes->begin();
        for (; it != vertexes->end(); it++) {
            glVertex3f((*it)[0], (*it)[1], 0.0f);
        }
    glEnd();

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glStencilFunc(GL_EQUAL, 1, 1);
    glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);

    glColor3f(color->r, color->g, color->b);
    glBegin(GL_QUADS);
        glVertex3f(-(imageW / 2.0f), -(imageW / 2.0f), 0.0f);
        glVertex3f( (imageW / 2.0f), -(imageW / 2.0f), 0.0f);
        glVertex3f( (imageW / 2.0f),  (imageW / 2.0f), 0.0f);
        glVertex3f(-(imageW / 2.0f),  (imageW / 2.0f), 0.0f);
    glEnd();

    glDisable(GL_STENCIL_TEST);

    glTranslatef(x, y, -imageD);
}

Ответы [ 2 ]

2 голосов
/ 15 февраля 2012

Вы не должны использовать оконный кадровый буфер (который включает в себя как задний, так и передний буфер) для операций рендеринга в текстуру.Это просто ломается легко (вы испытали это).Вместо этого используйте так называемый объект Framebuffer с текстурой в качестве цели рендеринга.

0 голосов
/ 26 февраля 2012

Ну, Datenwolf, спасибо за ваше предложение, вы, вероятно, правы, но я просто хочу использовать продвинутые вещи как можно меньше, и я нашел свои ошибки.Я не получил желаемого результата до второго кадра, потому что у меня еще не было теста трафарета.До первого кадра я не получил желаемого результата, потому что при создании окна Windows посылает сообщение WM_SIZE, и у меня внутри него есть сообщение отрисовки, но в то время OpenGL еще не настроен должным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...