使用 GLSL 的多个着色器加载多个纹理时出现问题
Posted
技术标签:
【中文标题】使用 GLSL 的多个着色器加载多个纹理时出现问题【英文标题】:Problem Loading multiple textures using multiple shaders with GLSL 【发布时间】:2010-04-14 12:19:36 【问题描述】:我试图在同一个场景中使用多个纹理,但无论我尝试什么,都会为每个对象加载相同的纹理。所以这就是我目前正在做的事情,我初始化每个着色器:
rightWall.SendShaders("wall.vert","wall.frag","brick3.bmp", "wallTex", 0);
demoFloor.SendShaders("floor.vert","floor.frag","dirt1.bmp", "floorTex", 1);
SendShaders 中的代码是:
GLuint vert,frag;
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
char *vs = NULL,*fs = NULL;
vert = glCreateShader(GL_VERTEX_SHADER);
frag = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead(vertFile);
fs = textFileRead(fragFile);
const char * ff = fs;
const char * vv = vs;
glShaderSource(vert, 1, &vv, NULL);
glShaderSource(frag, 1, &ff, NULL);
free(vs); free(fs);
glCompileShader(vert);
glCompileShader(frag);
program = glCreateProgram();
glAttachShader(program, frag);
glAttachShader(program, vert);
glLinkProgram(program);
glUseProgram(program);
LoadGLTexture(textureImage, texture);
然后在主循环中:
rightWall.UseShader("wallTex");
rightWall.Draw();
demoFloor.UseShader("floorTex");
demoFloor.Draw();
UseShader中的代码:
void GraphicsObject::UseShader(char textureName [])
glUseProgram(program);
GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
最后,纹理加载方法:
int GraphicsObject::LoadGLTexture(const char fileName [])
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
int arraySize = strlen(fileName);
arraySize += 1;
if (TextureImage[0]=LoadBMP(fileName, arraySize))
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureImage[0]->sizeX,
TextureImage[0]->sizeY, 0, GL_RGB,
GL_UNSIGNED_BYTE, TextureImage[0]->data);
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_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
if (TextureImage[0])
if (TextureImage[0]->data)
free(TextureImage[0]->data);
free(TextureImage[0]);
return 1;
AUX_RGBImageRec* GraphicsObject::LoadBMP(const char fileName[], int arraySize)
FILE *File=NULL;
LPWSTR pwszFileName;
int lenW;
BSTR unicodestr;
lenW = MultiByteToWideChar(CP_ACP, 0, fileName, arraySize, 0,0);
DWORD bottom = GetLastError();
unicodestr = SysAllocStringLen(0, lenW);
MultiByteToWideChar(CP_ACP,0, fileName, arraySize,
unicodestr,lenW);
SysFreeString(unicodestr);
DWORD tit = GetLastError();
if (!fileName)
return NULL;
File=fopen(fileName,"r");
if (File)
fclose(File);
return auxDIBImageLoad((LPCWSTR)unicodestr);
return NULL;
最后初始化着色器的是用于两个对象的纹理。感谢您抽出宝贵时间,感谢任何 cmets。
【问题讨论】:
【参考方案1】:就像您必须在使用着色器进行渲染之前调用 glUseProgram(program) 一样,您也必须在渲染之前直接绑定正确的纹理。
代码应如下所示:
glUseProgram(program1);
glBindTexture(GL_TEXTURE_2D, texture1);
// render calls for object 1
glUseProgram(program2);
glBindTexture(GL_TEXTURE_2D, texture2);
// render calls for object 2
此外,Uniforms 必须在渲染之前直接设置,而不是在着色器初始化时设置。
所以在你的情况下,部分
GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
不属于函数SendShaders,而是属于UseShader!
【讨论】:
感谢您的意见,但是,在进行这些更改后,结果仍然相同。 我更新了我的答案,制服也必须区别对待。你能看看这个吗? 好的,现在我的 UseShader 看起来像:glUseProgram(program); GLint location = glGetUniformLocation(program, textureName); glUniform1i(位置,0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 纹理);但是结果还是和之前一模一样。 能否请您更新上面的源代码,说明整个函数 SendShader 和 UseShader LoadGLTexture(textureImage, texture)的代码;会有帮助的。 “纹理”在哪里定义? SendShader 中最后一个参数的目的是什么?请也添加这个。还有一个问题:墙壁和地板着色器是否相同?如果不是,着色器是否正确?【参考方案2】:我将指出明显的情况,以确保您可以排除它。
你的纹理图像数据真的不同吗?您是否检查了纹理加载代码以确保获得不同的纹理文件?
【讨论】:
纹理图像数据不同,它取决于哪个 SendShaders 最后声明了哪个纹理被绘制在两个对象上。以上是关于使用 GLSL 的多个着色器加载多个纹理时出现问题的主要内容,如果未能解决你的问题,请参考以下文章