GLSL 中的多种纹理 - 只有一种有效 [英] Multiple textures in GLSL - only one works
问题描述
我的问题是在 GLSL 着色器中可以访问多个纹理.这是我正在做的:
My problem is getting more than one texture accessible in a GLSL shader. Here's what I'm doing:
着色器:
uniform sampler2D sampler0;
uniform sampler2D sampler1;
uniform float blend;
void main( void )
{
vec2 coords = gl_TexCoord[0];
vec4 col = texture2D(sampler0, coords);
vec4 col2 = texture2D(sampler1, coords);
if (blend > 0.5){
gl_FragColor = col;
} else {
gl_FragColor = col2;
}
};
因此,我只是根据统一变量在两个颜色值之间进行选择.很简单(这是一个测试),但是当混合 <= 0.5 时,我得到的不是预期的行为,而是全黑 .
So, I simply choose between the two color values based on a uniform variable. Simple enough (this is a test), but instead of the expected behavior, I get all black when blend <= 0.5.
OpenGL 代码:
m_sampler0location = m_shader.FindUniform("sampler0");
m_sampler1location = m_shader.FindUniform("sampler1");
m_blendlocation = m_shader.FindUniform("blend");
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler0location, 0);
glBindTexture(GL_TEXTURE_2D, Texture0.Handle);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler1location, 1);
glBindTexture(GL_TEXTURE_2D, Texture1.Handle);
glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, maxCoords0.t);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(maxCoords0.s, maxCoords0.t);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(maxCoords0.s, 0);
glVertex2f(1.0, -1.0);
glEnd()
着色器在这一切之前被编译和绑定.该过程中的所有健全性检查都表明一切正常.正如我所说,着色器程序中 根据 Bahbar 的回复修复.col
的值反映了来自纹理的片段;col2
的值为黑色.显示的纹理是最后一个活动纹理 - 如果我将最后一个 glBindTexture
更改为绑定 Texture0.Handle
,则纹理会发生变化.
The shader is compiled and bound before all this. All the sanity checks in that process indicate that it goes ok.
As I said, the value of Fixed according to Bahbar's reply.col
in the shader program reflects fragments from a texture; the value of col2
is black. The texture that is displayed is the last active texture - if I change the last glBindTexture
to bind Texture0.Handle
, the texture changes.
实际上,场景呈现全黑,即使我添加了类似 gl_FragColor.r = blend;
作为着色器的最后一行的内容.但是,如果我注释掉调用 glActiveTexture(GL_TEXTURE1);
,着色器会再次工作,并且在 sampler0 和 sampler1 中出现相同的纹理.
As it is, the scene renders all black, even if I add something like gl_FragColor.r = blend;
as the last line of the shader. But, if I comment out the call glActiveTexture(GL_TEXTURE1);
, the shader works again, and the same texture appears in both sampler0 and sampler1.
这是怎么回事?有问题的行 glActiveTexture(GL_TEXTURE1);
似乎工作得很好,随后的 glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)
证明了这一点.为什么它会如此可怕地破坏一切?我已经尝试升级我的显示驱动程序.
What's going on? The line in question, glActiveTexture(GL_TEXTURE1);
, seems to work just fine, as evidenced by a subsequent glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)
. Why does it break everything so horribly? I've already tried upgrading my display drivers.
推荐答案
这是一个基本的 GLUT 示例(在 OS X 上编写,根据需要进行调整),它生成两个棋盘格纹理,加载一个带有两个采样器的着色器,并通过给每个采样器着色来组合它们(一红一蓝)并混合.看看这是否适合您:
Here's a basic GLUT example (written on OS X, adapt as needed) that generates two checkerboard textures, loads a shader with two samplers and combines them by tinting each (one red, one blue) and blending. See if this works for you:
#include <stdio.h>
#include <stdlib.h>
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#define kTextureDim 64
GLuint t1;
GLuint t2;
/* adapted from the red book */
GLuint makeCheckTex() {
GLubyte image[kTextureDim][kTextureDim][4]; // RGBA storage
for (int i = 0; i < kTextureDim; i++) {
for (int j = 0; j < kTextureDim; j++) {
int c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0))*255;
image[i][j][0] = (GLubyte)c;
image[i][j][1] = (GLubyte)c;
image[i][j][2] = (GLubyte)c;
image[i][j][3] = (GLubyte)255;
}
}
GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureDim, kTextureDim, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
return texName;
}
void loadShader() {
#define STRINGIFY(A) #A
const GLchar* source = STRINGIFY(
uniform sampler2D tex1;
uniform sampler2D tex2;
void main() {
vec4 s1 = texture2D(tex1, gl_TexCoord[0].st);
vec4 s2 = texture2D(tex2, gl_TexCoord[0].st + vec2(0.0625, 0.0625));
gl_FragColor = mix(vec4(1, s1.g, s1.b, 0.5), vec4(s2.r, s2.g, 1, 0.5), 0.5);
}
);
GLuint program = glCreateProgram();
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar* log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(shader, logLength, &logLength, log);
printf("Shader compile log:
%s
", log);
free(log);
}
glAttachShader(program, shader);
glLinkProgram(program);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar* log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(program, logLength, &logLength, log);
printf("Program link log:
%s
", log);
free(log);
}
GLuint t1Location = glGetUniformLocation(program, "tex1");
GLuint t2Location = glGetUniformLocation(program, "tex2");
glUniform1i(t1Location, 0);
glUniform1i(t2Location, 1);
glUseProgram(program);
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);
t1 = makeCheckTex();
t2 = makeCheckTex();
loadShader();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, t1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, t2);
glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, 1.0);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(1.0, 0);
glVertex2f(1.0, -1.0);
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, -2, 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(512, 512);
glutInitWindowPosition(0, 0);
glutCreateWindow("GLSL Texture Blending");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
init();
glutMainLoop();
return 0;
}
希望结果看起来像这样(您可以注释掉 glUseProgram
调用以查看未使用着色器绘制的第一个纹理):
Hopefully the result will look something like this (you can comment out the glUseProgram
call to see the first texture drawn without the shader):
这篇关于GLSL 中的多种纹理 - 只有一种有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!