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

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

uniform int myArray[300];

и заполнение его вне шейдера glUniform1iv.

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

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

1 ответов


это должно заставить вас начать использовать единый объект буфера для хранения массива. Обратите внимание, что GL требует, чтобы UBOs имел минимальную емкость 16 Кб, максимальная емкость может быть запрошена через GL_MAX_UNIFORM_BLOCK_SIZE.

образец шейдера фрагментов (UBOs требует 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 layout, это означает, что вы можете использовать этот UBO в любой программе GLSL, где вы привязываете один из его однородных блоков к этому месту привязки (0). Это на самом деле очень удобно, когда вы хотите поделиться чем - то вроде ваших матриц ModelView и Projection между десятками разных Программы на GLSL.