2016-11-30 3 views
0

Для gui для моей игры у меня есть собственный объект текстуры, который хранит данные rgba для текстуры. Каждый элемент GUI, зарегистрированный в моей игре, добавляет к окончательной текстуре графического интерфейса, а затем эта текстура накладывается на фреймбуфер после постобработки.rgba массивы для текстуры OpenGL

У меня возникли проблемы с преобразованием объекта Texture в текстуру openGL.

Сначала я создаю целочисленный массив 1D, который идет rgbargbargba... etc.

public int[] toIntArray(){ 
    int[] colors = new int[(width*height)*4]; 

    int i = 0; 
    for(int y = 0; y < height; ++y){ 
     for(int x = 0; x < width; ++x){ 

      colors[i] = r[x][y]; 
      colors[i+1] = g[x][y]; 
      colors[i+2] = b[x][y]; 
      colors[i+3] = a[x][y]; 

      i += 4; 
     } 
    } 
    return colors; 
} 

Где r, g, b и a являются зубчатыми ИНТ массивы от 0 до 255. Далее я создаю ИНТ буфер и текстуру.

id = glGenTextures(); 

glBindTexture(GL_TEXTURE_2D, id); 

glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

IntBuffer iBuffer = BufferUtils.createIntBuffer(((width * height)*4)); 

int[] data = toIntArray(); 
iBuffer.put(data); 
iBuffer.rewind(); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT, iBuffer); 

glBindTexture(GL_TEXTURE_2D, 0); 

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

frameBuffer.unbind(window.getWidth(), window.getHeight()); 

postShaderProgram.bind(); 

glEnable(GL_TEXTURE_2D); 
glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, guiManager.texture()); // this gets the texture id that was created 

postShaderProgram.setUniform("gui_texture", 1); 

mesh.render(); 

postShaderProgram.unbind(); 

И тогда в моем пиксельный шейдер, я пытаюсь отображения графического интерфейса пользователя:

#version 330 

in vec2 Texcoord; 
out vec4 outColor; 

uniform sampler2D texFramebuffer; 
uniform sampler2D gui_texture; 

void main() 
{ 
    outColor = texture(gui_texture, Texcoord); 
} 

Но все это выводит это черное окно!

Я добавил красный правый прямоугольник 50x50 в верхний левый угол и подтвердил, что он существует, но по какой-то причине он не отображается в конечном выходе.

enter image description here

Это дает мне основания полагать, что я не преобразовывать свою текстуру в OpenGL текстуры с glTexImage2D правильно.

Вы видите, что я делаю неправильно?

Update 1:

Here Я видел их делать подобную вещь с помощью буев, поэтому я попытался преобразовать мой 0-255 в массив 0-1 поплавка и передачи его в качестве данных изображения, как так :

public float[] toFloatArray(){ 
    float[] colors = new float[(width*height)*4]; 

    int i = 0; 
    for(int y = 0; y < height; ++y){ 
     for(int x = 0; x < width; ++x){ 

      colors[i] = ((r[x][y] * 1.0f)/255); 
      colors[i+1] = ((g[x][y] * 1.0f)/255); 
      colors[i+2] = ((b[x][y] * 1.0f)/255); 
      colors[i+3] = ((a[x][y] * 1.0f)/255); 

      i += 4; 
     } 
    } 
    return colors; 
} 

... 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, toFloatArray()); 

И это работает!

enter image description here

Я собираюсь оставить этот вопрос открытым, однако, как я хочу, чтобы узнать, почему ИНТ буфер не работает :)

ответ

3

Когда вы определили GL_UNSIGNED_INT как тип «Host» данных, OpenGL ожидается 32 бита, выделенные для каждого цвета. Поскольку OpenGL отображает только выходные цвета в фреймбуфере по умолчанию в диапазоне [0.0f, 1.0f], он принимает ваши значения входного цвета (отображается в диапазоне [0, 255]) и делит их все на максимальный размер int (около 4,2 миллиарда), чтобы получить последний цвет отображается на экране. В качестве упражнения, используя исходный код, установите «чистый» цвет экрана на белый и посмотрите, что на экране отображается черный прямоугольник.

У вас есть два варианта.Первый заключается в преобразовании значений цвета в диапазон, заданный GL_UNSIGNED_INT, что означает для каждого значения цвета, умножьте их на Math.pow((long)2, 24) и верьте, что целочисленное переполнение умножения на это значение будет вести себя корректно (поскольку Java не имеет целого без знака типов).

Другой, гораздо более безопасным вариантом, чтобы сохранить каждый 0-255 значение в byte[] объекта (сделать не использование char. char составляет 1 байт в C/C++/OpenGL, но 2 байта в Java) и укажите тип элементов как GL_UNSIGNED_BYTE.

+1

Исправление: тип OpenGL называется GL_UNSIGNED_BYTE, а не GL_UNSIGNED_CHAR –

+0

@ Антон Решетников Отредактировано. – Xirema