Как передать несколько текстур в один шейдер?
Я использую 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 передать уже заполненные маркеры текстуры шейдеру фрагментов?
- как передать массив текстур с разными размерами в GLSL?
- передача нескольких текстур из OpenGL в GLSL shader
- несколько текстур в GLSL-работает только один
(Это домашнее задание, поэтому, пожалуйста, ответьте с минимальными фрагменты кода (если вообще). Спасибо!)
в противном случае, есть ли у кого-нибудь чайная сетка?
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)
в шейдере. Это также означает, что вам не нужно запрашивать местоположение.