C++ 带有多个着色器程序的OpenGL多重纹理
我试图在OpenGL中制作一个场景,从太空模拟地球。我现在有两个球体,一个是地球,另一个稍大一点的是云层。地球和云球体对象有自己的着色器程序来保持简单。地球着色器程序采用4种纹理(白天、夜晚、specmap和normalmap),云着色器程序采用2种纹理(cloudmap和normalmap)。我有一个对象类,它有一个渲染函数,在该函数中我使用以下逻辑:C++ 带有多个着色器程序的OpenGL多重纹理,c++,opengl,opengl-es,glsl,shader,C++,Opengl,Opengl Es,Glsl,Shader,我试图在OpenGL中制作一个场景,从太空模拟地球。我现在有两个球体,一个是地球,另一个稍大一点的是云层。地球和云球体对象有自己的着色器程序来保持简单。地球着色器程序采用4种纹理(白天、夜晚、specmap和normalmap),云着色器程序采用2种纹理(cloudmap和normalmap)。我有一个对象类,它有一个渲染函数,在该函数中我使用以下逻辑: //bind the current object's texture for (GLuint i = 0; i < texIDs.si
//bind the current object's texture
for (GLuint i = 0; i < texIDs.size(); i++){
glActiveTexture(GL_TEXTURE0 + i);
if (cubemap)
glBindTexture(GL_TEXTURE_CUBE_MAP, texIDs[i]);
else
glBindTexture(GL_TEXTURE_2D, texIDs[i]);
}
if (samplers.size()){
for (GLuint i = 0; i < samplers.size(); i++){
glUniform1i(glGetUniformLocation(program, samplers[i]), i);
}
}
//绑定当前对象的纹理
对于(GLuint i=0;i
它从第0个纹理单元开始,并将N个纹理绑定到从GL_TEXTURE0开始的N个纹理单元。然后在着色器程序中从0到N绑定采样器。采样器由我在加载纹理时提供:
void Object::loadTexture(const char* filename, const GLchar* sampler){
int texID;
texID = SOIL_load_OGL_texture(filename, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS);
if(texID == 0){
cerr << "SOIL error: " << SOIL_last_result();
}
cout << filename << " Tex ID: " << texID << endl;
texIDs.push_back(texID);
samplers.push_back(sampler);
//glBindTexture(GL_TEXTURE_2D, texID);
}
void Object::loadTexture(常量字符*文件名,常量GLchar*采样器){
int-texID;
texID=土壤加载纹理(文件名、土壤加载自动、土壤创建新ID、土壤标志mipmap、土壤标志纹理重复);
如果(texID==0){
cerr据我所知,您将所有纹理绑定为单独的纹理单元
- 这是错误的
- 如果你有100个对象,每个都有4个纹理
- 我强烈怀疑你是否有400个纹理单位可供你使用
- 纹理ID(名称)不是纹理单位…
我像这样渲染空间体:
- 我有特定任务的特定纹理单位
// texture units:
// 0 - texture0 map 2D rgba (surface)
// 1 - texture1 map 2D rgba (clouds blend)
// 2 - normal map 2D xyz (normal/bump mapping)
// 3 - specular map 2D i (reflection shininess)
// 4 - light map 2D rgb rgb (night lights)
// 5 - enviroment/skybox cube map 3D rgb
- 请参见该链接中的着色器(它也是为太阳系可视化而编写的)
- 在每次渲染单个实体之前,仅绑定该实体的纹理
- (绑定着色器后)
- 不要更改纹理单元的含义(如果您这样做,着色器如何知道哪个纹理是什么?)
- 没有使用纹理
- 它只是一个覆盖整个屏幕的透明四边形
[edit1]多文本的示例
// init shader once per render all geometries
GLint prog_id; // shader program ID;
GLint txrskybox; // global skybox environment cube map
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr_texture0"); glUniform1i(id,0); //uniform sampler2D txr_texture0;
id=glGetUniformLocation(prog_id,"txr_texture1"); glUniform1i(id,1); //uniform sampler2D txr_texture1;
id=glGetUniformLocation(prog_id,"txr_normal"); glUniform1i(id,2); //uniform sampler2D txr_normal;
id=glGetUniformLocation(prog_id,"txr_specular"); glUniform1i(id,3); //uniform sampler2D txr_specular;
id=glGetUniformLocation(prog_id,"txr_light"); glUniform1i(id,4); //uniform sampler2D txr_light;
id=glGetUniformLocation(prog_id,"txr_skybox"); glUniform1i(id,5); //uniform samplerCube txr_skybox;
// add here all uniforms you need ...
glActiveTexture(GL_TEXTURE0+5); glEnable(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP,txrskybox);
for (i=0;i<all_objects;i++)
{
// add here all uniforms you need ...
// pass textures once per any object render
// obj::(GLint) txr0,txr1,txrnor,txrspec,txrlight; // object local textures
glActiveTexture(GL_TEXTURE0+0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr0);
glActiveTexture(GL_TEXTURE0+1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr1);
glActiveTexture(GL_TEXTURE0+2); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrnor);
glActiveTexture(GL_TEXTURE0+3); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrspec);
glActiveTexture(GL_TEXTURE0+4); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrlight);
// here render the geometry of obj[i]
}
// unbind textures and shaders
glActiveTexture(GL_TEXTURE0+5); glBindTexture(GL_TEXTURE_CUBE_MAP,0); glDisable(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE0+4); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+3); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+2); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+1); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+0); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D); // unit0 at last so it stays active ...
glUseProgram(0);
//每次渲染所有几何体时初始化着色器一次
闪烁程序id;//着色器程序id;
闪烁txrskybox;//全局skybox环境立方体贴图
闪烁id;
glUseProgram(程序id);
id=glGetUniformLocation(prog_id,“txr_texture0”);glUniform1i(id,0);//统一采样器2D txr_texture0;
id=glGetUniformLocation(prog_id,“txr_texture1”);glUniform1i(id,1);//统一采样器2D txr_texture1;
id=glGetUniformLocation(prog_id,“txr_normal”);glUniform1i(id,2);//统一采样器2D txr_normal;
id=glGetUniformLocation(prog_id,“txr_镜面反射”);glUniform1i(id,3);//统一采样器2D txr_镜面反射;
id=glGetUniformLocation(prog_id,“txr_light”);glUniform1i(id,4);//统一采样器2D txr_light;
id=glGetUniformLocation(prog_id,“txr_skybox”);glUniform1i(id,5);//统一采样器立方体txr_skybox;
//在这里添加您需要的所有制服。。。
glActiveTexture(GL_纹理0+5);glEnable(GL_纹理_立方体_贴图);glBindTexture(GL_纹理_立方体_贴图,txrskybox);
对于(i=0;你能演示如何使用GLASTeTeTeXION和GLBDIN纹理调用绑定纹理到C++的着色器吗?@ PSLAYR89+添加示例,我今天晚些时候再试试。结果我还在研究它,我在上面,我意识到了一些我不确定的东西。你读到纹理的顺序是什么?从file matter?据我所知,它不应该。只是想有人确认…@pslayer89它不重要唯一的区别是,如果你按顺序添加纹理,那么不同的顺序有时在OpenGL中意味着不同的TextureID
,但这与渲染本身无关,除非你不通过<代码>纹理ID
但改为一些索引(但这毕竟是代码中的bug…)