Подтвердить что ты не робот

Как передать несколько текстур в один шейдер?

Я использую freeglut, GLEW и DevIL для визуализировать текстурированный чайник, используя вершинный и фрагментарный шейдер, Все это отлично работает в OpenGL 2.0 и GLSL 1.2 на Ubuntu 14.04.

Теперь я хочу применить карту рельефа к чайнику. Мой лектор, очевидно, не brew собственного чая, и поэтому не знает, что они должны быть гладкими. Во всяком случае, я нашел красиво выглядящий учебник по сопоставлению башен старой школы, который включает в себя фрагментарный шейдер, который начинается:

uniform sampler2D DecalTex; //The texture
uniform sampler2D BumpTex; //The bump-map 

То, что они не упоминают, - это как передать две текстуры шейдеру в первую очередь.

Раньше я

//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);

//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

//Fragment shader
gl_FragColor = color * texture2D(DecalTex,gl_TexCoord[0].xy);

так что теперь I

//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);
glBindTexture(GL_TEXTURE_2D, bumpHandle);

//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;

//Fragment shader
gl_FragColor = color * texture2D(BumpTex,gl_TexCoord[0].xy);
//no bump logic yet, just testing I can use texture 1 instead of texture 0

но это не работает. Текстура полностью исчезает (фактически, чайник белый). Я пробовал GL_TEXTURE_2D_ARRAY, glActiveTexture и несколько других, вероятно, кажущихся, но бесплодных вариантов.

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

(Это домашнее задание, поэтому, пожалуйста, ответьте с минимальными фрагментами кода (если вообще). Спасибо!)

В противном случае, у кого-нибудь есть чайная уютная сетка?

4b9b3361

Ответ 1

Это очень просто, на самом деле. Все, что вам нужно, - привязать пробоотборник к некоторой текстурной единице с помощью glUniform1i. Итак, для вашего примера кода, предполагая два одинаковых сэмплера:

uniform sampler2D DecalTex;  // The texture  (we'll bind to texture unit 0)
uniform sampler2D BumpTex;   // The bump-map (we'll bind to texture unit 1)

В коде инициализации:

// Get the uniform variables location. You've probably already done that before...
decalTexLocation = glGetUniformLocation(shader_program, "DecalTex");
bumpTexLocation  = glGetUniformLocation(shader_program, "BumpTex");

// Then bind the uniform samplers to texture units:
glUseProgram(shader_program);
glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation,  1);

ОК, шейдерная униформа, теперь мы визуализируем. Для этого вам понадобится обычный glBindTexture плюс glActiveTexture:

glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
glBindTexture(GL_TEXTURE_2D, decalTexHandle);

glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1
glBindTexture(GL_TEXTURE_2D, bumpHandle);

// Done! Now you render normally.

И в шейдере вы будете использовать образцы текстур точно так же, как вы уже делали:

vec4 a = texture2D(DecalTex, tc);
vec4 b = texture2D(BumpTex,  tc);

Примечание. Для таких методов, как bump-mapping, вам нужен только один набор текстурных координат, так как текстуры одинаковы, только содержащие разные данные. Поэтому вы должны, вероятно, передать координаты текстуры как атрибут vertex.

Ответ 2

вместо использования:

glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation,  1);

в вашем коде, вы можете:

layout(location=0) uniform sampler2D DecalTex;  
// The texture  (we'll bind to texture unit 0)
layout(location=1)uniform sampler2D BumpTex;   
// The bump-map (we'll bind to texture unit 1)

в вашем шейдере. Это также означает, что вам не нужно запрашивать местоположение.