glsl fragmentshader рендеринга objectID

Как правильно отобразить целочисленный идентификатор объекта в буфер целочисленной текстуры?

скажем, у меня есть texture2D с внутренним форматом GL_LUMINANCE16, и я прикрепляю его как цветовое вложение к моему FBO.

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

вывод fragmentshader имеет тип vec4, однако. Как правильно преобразовать мой ID в четырехкомпонентный float и избежать преобразования неточности такие, что в конце концов integervalue в моей целочисленной текстуре соответствует целочисленному идентификатору, который я хотел отобразить?

3 ответов


есть несколько проблем с вашим вопросом.

во-первых,GL_LUMINANCE16 is не " целочисленная текстура.- Это текстура, которая содержит нормированный целочисленные значения без знака. Он использует целые числа для представления поплавков в диапазоне [0, 1]. Если вы хотите сохранить фактические целые числа, вы должны использовать фактическое целочисленный формат изображения.

во-вторых, вы не можете визуализировать текстуру яркости; они не являются форматами цветопередачи. Если вы на самом деле, чтобы отобразить одноканальную текстуру, необходимо создать одноканальный формат изображения. Так вместо GL_LUMINANCE16, вы используете GL_R16UI, который представляет собой 16-разрядный одноканальный беззнаковый интегральный формат изображения.

теперь, когда у вас это настроено правильно, это довольно тривиально. Определить uint вывод шейдера фрагментов и пусть ваш шейдер фрагментов напишет ваш uint значение. Это uint может исходить из вершинного шейдера или из униформы; однако вы хотите это сделать он.

очевидно, вам также нужно будет прикрепить текстуру или рендербуфер к FBO, но я уверен, что вы это знаете.

и последнее: не используйте фразу "буфер текстуры", Если вы не имеете в виду один из этих. В противном случае это сбивает с толку.


Я все еще не думаю, что здесь есть четкий ответ. Итак, вот как я заставил его работать через 2D-текстуру:

// First, create a frame buffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// Then generate your texture and define an unsigned int array:
glGenTextures(1, &textureid);
glBindTexture(GL_TEXTURE_2D, textureid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, w, h, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

// Attach it to the frame buffer object:
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textureid, 0);

// Before rendering    
glBindFramebuffer(GL_FRAMEBUFFER, fbo);    
GLuint buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; // this assumes that there is another     texture that is for the render buffer. Color attachment1 is preserved for the element ids.
glDrawBuffers(2, buffers);

// Clear and render here
glFlush(); // Flush after just in case
glBindFramebuffer(GL_FRAMEBUFFER, 0);

на стороне GLSL шейдер фрагментов должен иметь (код профиля ядра 4.3 здесь):

layout(location = 0) out vec4 colorOut; // The first element in 'buffers' so location 0    
layout(location = 1) out uvec4 elementID; // The second element in 'buffers' so location 1. unsigned int vector as color

// ...
void main()
{
//...

elementID = uvec4( elementid, 0, 0, 0 ); // Write the element id as integer to the red channel.

}

вы можете прочитать значения на принимающей стороне:

unsigned int* ids = new unsigned int[ w*h ];
glBindTexture(GL_TEXTURE_2D, textureid);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, ids);

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

uniform int vertedObjectId;

после рендеринга вы хотите сохранить обработку фрагмента в целое число текстуры. Обратите внимание, что целочисленные текстуры должны быть выбраны с помощью целое пробоотборники (isampler2D), которая возвращает целое векторы (т. е. ivec3).

эта текстура может быть прикреплена к объекту framebuffer (имейте в виду фреймбуфер полноты). Приложение framebuffer может быть привязан к целочисленной переменной вывода:

out int fragmentObjectId;

void main() {
    fragmentObjectId = vertedObjectId;
}

вам нужна поддержка нескольких расширений или расширенная версия OpenGL (3.2?).