Java OpenGL размером с экран с отображением текстуры Quad

У меня есть приложение Java OpenGL (JOGL), и я пытаюсь создать четырехугольник с отображением текстуры, который покрывает весь экран. Нарисуйте несколько пикселей в буфер, а затем я хочу прочитать эти пиксели в текстуре и перерисовать их на экране (с применением фрагментного шейдера). Мой код для сопоставления текстуры с окном просмотра:

        gl.glMatrixMode(GL.GL_PROJECTION);                                        
        gl.glPushMatrix();                                                 
        gl.glLoadIdentity();                                               
        gl.glOrtho( 0, width, height, 0, -1, 1 );                          
        gl.glMatrixMode(GL.GL_MODELVIEW);                                  
        gl.glPushMatrix();                                                 
        gl.glLoadIdentity();
        IntBuffer ib = IntBuffer.allocate(1);
        gl.glEnable(GL.GL_TEXTURE_2D);
        gl.glGenTextures(1, ib);
        gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
        //buff contains pixels read from glReadPixels
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);
        gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));
        gl.glBegin(GL.GL_QUADS);
        gl.glTexCoord2f(0,1);
        gl.glVertex2f(0,0); 
        gl.glTexCoord2f(0,0);
        gl.glVertex2f(0,height);
        gl.glTexCoord2f(1,0);   
        gl.glVertex2f(width,height);
        gl.glTexCoord2f(1,1);      
        gl.glVertex2f(width,0);
        gl.glEnd();
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
        gl.glPopMatrix();
        gl.glPopMatrix();

Конечным результатом является четырехугольник, который не покрывает всю область просмотра (частично включен) и не содержит пикселей из буфера. Что я здесь неправильно делаю?

спасибо Джефф


person Jeff Storey    schedule 10.06.2011    source источник
comment
Вы также должны иметь в виду, что вертикальное переворачивание экрана (в вашем glOrtho вызове) эффективно меняет ориентацию ваших лиц. Но поскольку вы хоть что-то видите, это не будет вашей проблемой, так как при отбраковке вы вообще ничего не увидите.   -  person Christian Rau    schedule 11.06.2011


Ответы (3)


Во-первых, вы должны создавать текстуру только в коде инициализации. Вы не должны вызывать glTexImage2D каждый кадр. Только вызовите glTexImage2D снова, если размер текстуры изменится; glTexSubImage2D можно использовать для загрузки данных в текстуру. Считайте glTexImage2D «новым», а glTexSubImage2D - копией памяти.

Сделайте это один раз после инициализации OpenGL.

IntBuffer ib = IntBuffer.allocate(1);  //Store this in your object
gl.glGenTextures(1, ib);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
//buff contains pixels read from glReadPixels
gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

Затем в каждом кадре проделайте следующее:

gl.glMatrixMode(GL.GL_PROJECTION);                                        
gl.glPushMatrix();                                                 
gl.glLoadIdentity();                                               
gl.glMatrixMode(GL.GL_MODELVIEW);                                  
gl.glPushMatrix();                                                 
gl.glLoadIdentity();

gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));  //Retrieved from your object
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);

gl.glBegin(GL.GL_QUADS);
    gl.glTexCoord2f(0,1);
    gl.glVertex2f(-1, -1); 
    gl.glTexCoord2f(0, 0);
    gl.glVertex2f(-1, 1);
    gl.glTexCoord2f(1, 0);   
    gl.glVertex2f(1, 1);
    gl.glTexCoord2f(1, 1);      
    gl.glVertex2f(1, -1);
gl.glEnd();

gl.glMatrixMode(GL.GL_MODELVIEW);                                  
gl.glPopMatrix();   
gl.glMatrixMode(GL.GL_PROJECTION);                                        
gl.glPopMatrix();   
gl.glMatrixMode(GL.GL_MODELVIEW);                                  

Используя идентичность для проекции и просмотра модели, мы можем предоставить координаты вершин непосредственно в пространстве отсечения. Диапазон [-1, 1] в пространстве клипа отображается на [0, ширина / высота] в пространстве окна. Таким образом, нам не нужно знать или заботиться о том, насколько велико окно; Пока glViewport настроен правильно, это должно работать.

person Nicol Bolas    schedule 10.06.2011

Возможно, это не проблема, но это не поможет: вы дважды открываете матрицу просмотра модели для одного нажатия. Вы вообще не выскакиваете матрицу проекции.

Я бы порекомендовал настроить матрицу проекции один раз при запуске, без каких-либо толчков или хлопков. Вам также не нужно толкать и выталкивать матрицу просмотра модели. (Вы также можете настроить текстуру один раз при запуске.)

person Martin Stone    schedule 10.06.2011
comment
это не было проблемой, но это все еще хорошие предложения и исправления, так что +1. - person Jeff Storey; 10.06.2011

Я бы начал с проверки glError с помощью кода, подобного приведенному ниже. Обратите внимание, что я использовал объект GL2, потому что были некоторые проблемы со старыми версиями JOGL и объекта GL, а таких глупостей, как GL_QUADS, там не было.

Если у вас включен шейдер с приведенным выше кодом, вам необходимо выполнить текстурирование, прочитав семплер. Если да, приложите код шейдера, который вы используете с этим кодом отрисовки.

private static void checkForGLErrors(GL2 gl) {
    int errno = gl.glGetError();
    switch (errno) {
        case GL2.GL_INVALID_ENUM:
            System.err.println("OpenGL Error: Invalid ENUM");
            break;
        case GL2.GL_INVALID_VALUE:
            System.err.println("OpenGL Error: Invalid Value");
            break;
        case GL2.GL_INVALID_OPERATION:
            System.err.println("OpenGL Error: Invalid Operation");
            break;
        case GL2.GL_STACK_OVERFLOW:
            System.err.println("OpenGL Error: Stack Overflow");
            break;
        case GL2.GL_STACK_UNDERFLOW:
            System.err.println("OpenGL Error: Stack Underflow");
            break;
        case GL2.GL_OUT_OF_MEMORY:
            System.err.println("OpenGL Error: Out of Memory");
            break;
        default:
            return;
    }
}

Я бы также попытался избежать создания текстуры каждый кадр, если она не меняется. Вы можете сохранить textureId и привязать его позже.

person EnabrenTane    schedule 10.06.2011
comment
Код ошибки GL возвращает 0, поэтому на данный момент ошибок нет. - person Jeff Storey; 10.06.2011