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

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

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

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);

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

//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. Как именно я использую это в файле OpenGL cpp передать уже заполненные маркеры текстуры шейдеру фрагментов?

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

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

2 ответов


это очень просто. Все, что вам нужно, это привязать сэмплер к некоторому текстурному блоку с 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, вам нужен только один набор координат текстуры, так как текстуры одинаковы, только содержащие разные данные. Поэтому вы, вероятно, должны передать координаты текстуры как атрибут вершины.


вместо:

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)

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