GLSL: заменить большой равномерный массив int буфером или текстурой

Сейчас я пытаюсь передать массив int в фрагментный шейдер и делаю это через единый массив:

uniform int myArray[300];

И заполняя его вне шейдера glUniform1iv,

К сожалению, однородные массивы больше, чем ~400 потерпеть поражение. Я понимаю, что вместо этого могу использовать «единый буфер», но не могу найти полного примера передачи большого 1D-массива в фрагментный шейдер с буферами или другим способом.

Кто-нибудь может привести такой пример?

7

Решение

Это должно помочь вам начать использовать объект Uniform Buffer для хранения массива. Обратите внимание, что GL требует, чтобы UBO имели минимальную емкость 16 КиБ, максимальная емкость может быть запрошена через GL_MAX_UNIFORM_BLOCK_SIZE,

Образец шейдера фрагмента (для UBO требуется OpenGL 3.1):

#version 140 // GL 3.1

// Arrays in a UBO must use a constant expression for their size.
const int MY_ARRAY_SIZE = 512;

// The name of the block is used for finding the index location only
layout (std140) uniform myArrayBlock {
int myArray [MY_ARRAY_SIZE]; // This is the important name (in the shader).
};

void main (void) {
gl_FragColor = vec4 ((float)myArray [0] * 0.1, vec3 (1.0));
}

Код OpenGL

const int MY_ARRAY_SIZE = 512;

GLuint myArrayUBO;
glGenBuffers (1, &myArrayUBO);

// Allocate storage for the UBO
glBindBuffer (GL_UNIFORM_BUFFER, myArrayUBO);
glBufferData (GL_UNIFORM_BUFFER, sizeof (GLint) * MY_ARRAY_SIZE,
NULL, GL_DYNAMIC_DRAW);

[...]

// When you want to update the data in your UBO, you do it like you would any
//   other buffer object.
glBufferSubData (GL_UNIFORM_BUFFER, ...);

[...]

GLuint myArrayBlockIdx = glGetUniformBlockIndex (GLSLProgramID, "myArrayBlock");

glUniformBlockBinding (GLSLProgramID,     myArrayBlockIdx, 0);
glBindBufferBase      (GL_UNIFORM_BUFFER, 0,               myArrayUBO);

Я, наверное, что-то забыл, есть причина, по которой я не пишу учебники. Если у вас возникли проблемы с реализацией этого, оставьте комментарий.

ОБНОВИТЬ:

Обратите внимание, что 0 используется в glUniformBlockBinding (...) а также glBindBufferBase (...) является глобальным идентификатором для точки привязки. При использовании в сочетании с std140 компоновка, это означает, что вы можете использовать этот UBO в любой программе GLSL, где вы привязываете один из его унифицированных блоков к этому месту привязки (0). Это на самом деле очень удобно, когда вы хотите поделиться чем-то вроде ваших таблиц ModelView и Projection между десятками различных программ GLSL.

8

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]