Я использую следующий код для создания цели рендеринга карты куба:
glGenTextures( 1, &id );
glBindTexture( GL_TEXTURE_CUBE_MAP, id );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
// Creates a renderbuffer object to store depth info.
GLuint bufferId;
glGenRenderbuffers( 1, &bufferId );
glBindRenderbuffer( GL_RENDERBUFFER, bufferId );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height );
glBindRenderbuffer( GL_RENDERBUFFER, 0 );
glGenFramebuffers( 1, &fboId );
glBindFramebuffer( GL_FRAMEBUFFER, fboId );
const GLenum externalFormat = GL_RGBA;
const GLenum internalFormat = GL_RGBA8;
const GLenum dataType = GL_UNSIGNED_BYTE;
for (int i = 0; i < 6; ++i)
{
glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalFormat,
size, size, 0, externalFormat,
dataType, nullptr );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, id, 0 );
}
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, bufferId );
Он не генерирует никаких ошибок OpenGL в контексте OpenGL 3.2, но при запуске того же кода в контексте OpenGL 4.3 обратный вызов отладочного вывода выдает следующую ошибку на glFramebufferTexture2D:
OpenGL: Framebuffer unsupported. Attachment COLOR_ATTACHMENT0 unsupported because it uses an inconsistent texture due to invalid texture parameters.
Я использую код для Windows 8.1 с NVIDIA GeForce GT 750M, драйвер 337.88. Я неправильно создаю цель рендеринга?
Я не уверен, в чем заключается ошибка, но может быть связано с несоответствием между size
, width
а также height
,
Несмотря на это, есть несколько других проблем:
Каждая итерация цикла просто переопределяет GL_COLOR_ATTACHMENT0
, Возможно, изменить на GL_COLOR_ATTACHMENT0 + i
,
Однако это означает, что вы должны писать в каждый слой куба, когда фрагмент проходит проверку глубины.
У вас также есть один рендер-буфер с одним слоем, что означает, что для всех сторон вашего куба используется один тест глубины.
Я не думаю, что все вышесказанное — то, чего вы хотите.
Чтобы визуализировать текстуру куба, вы можете связывать каждый слой по очереди, каждый раз визуализируя всю сцену из новой проекции. Это старый способ сделать это.
Чтобы выполнить рендеринг в текстуру куба всего за один проход, вы можете привязать всю карту куба (которая на самом деле представляет собой всего 6 слоев обычной текстуры) к GL_COLOR_ATTACHMENT0
, Для глубинного тестирования вы создаете и привязываете другая текстура куба (или renderbuffer, но не уверен, что можете) GL_DEPTH_COMPONENT
в GL_DEPTH_ATTACHMENT
, Затем в геометрическом шейдере вы дублируете все 6 раз, по одному на каждую грань вашего куба. gl_Layer
в геометрическом шейдере используется для задания грани куба, к которой обращается примитив. Если подумать, вы также можете использовать инстансинг (glDrawElementsInstanced
/gl_InstanceID
) дублировать вашу геометрию 6 раз, что сместит вычисления с геометрического шейдера на вершинный шейдер и может быть немного быстрее, если ваши операции с вершинами дороги.
В обоих случаях вам понадобится матрица проекции на 90 градусов с соотношением сторон 1, и вам нужно будет повернуть вид, чтобы соответствовать граням куба (это довольно сложно, поэтому сохраните свой код для будущего использования). Поэтому создайте 6 матриц вида и передайте их либо в геометрический, либо в вершинный шейдер в зависимости от того, используете ли вы инстансинг или нет.