Opengl GLSL,结合2D和3D纹理

Opengl GLSL,结合2D和3D纹理,opengl,glsl,textures,Opengl,Glsl,Textures,我正在尝试将3D纹理与2D纹理混合以生成地形。3D纹理包含苔藓、沙子、雪等,并进行插值以增强高度感。2D纹理当前只有一条橙色的线穿过,表示为“道路”。这是我的片段着色器: # version 420 uniform sampler3D mainTexture; uniform sampler2D roadTexture; void main() { vec4 diffuse3D = texture3D(mainTexture, gl_TexCoord[0].stp); vec

我正在尝试将3D纹理与2D纹理混合以生成地形。3D纹理包含苔藓、沙子、雪等,并进行插值以增强高度感。2D纹理当前只有一条橙色的线穿过,表示为“道路”。这是我的片段着色器:

# version 420

uniform sampler3D mainTexture;
uniform sampler2D roadTexture;

void main() {
    vec4 diffuse3D = texture3D(mainTexture, gl_TexCoord[0].stp);
    vec4 diffuse2D = texture2D(roadTexture, gl_TexCoord[1].st);
    // Yes, I am aware I am only returning the 2D texture value
    // However this is for testing purposes only
    // Doing gl_FragColor = diffuse3D + diffuse2D;
    // Or any other operation returns the 3D texture only
    gl_FragColor = diffuse2D; 
}
这是我的绘画号召:

void Terrain::Draw() {

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &v[0].x);
    glEnableClientState(GL_NORMAL_ARRAY); 
    glNormalPointer(GL_FLOAT, sizeof(glm::vec3), &n[0].x); 

    s.enable(); // simple glUseProgram call within my Shader object

    glClientActiveTexture(GL_TEXTURE0);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_3D);
    glBindTexture(GL_TEXTURE_3D, id_texture);
    s.setSampler("mainTexture",0); // Calls to glGetUniformLocation and glUniform1i
    glTexCoordPointer(3, GL_FLOAT, sizeof(glm::vec3), &t[0].x);

    glClientActiveTexture(GL_TEXTURE1);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, id_texture_road);
    s.setSampler("roadTexture",1); // Same as above
    glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &t2[0].x);

    glPushMatrix();
    glScalef(scalex,scaley,scalez);
    glDrawElements(GL_TRIANGLES, sizei, GL_UNSIGNED_INT, index);
    glPopMatrix();

    s.disable(); // glUseProgram(0)

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisable(GL_TEXTURE_3D);
    glDisable(GL_TEXTURE_2D);
}
以下是我的
setSampler()
方法的代码:

void Shader::setSampler(std::string name, GLint value)
{
    GLuint loc = glGetUniformLocation(program, name.c_str());
    if (loc>0)
    {
        glUniform1i(loc, value); 
    }
}
结果是整个地形上呈现纯黑颜色。遗憾的是,我无法找到有关sampler3D的信息,但是片段着色器中的diffuse3D变量确实计算出正确的纹理,并且2D纹理的纹理坐标正被正确地发送到片段着色器(我知道这一点,因为我使用它们为测试地形上色,得到了从绿色到红色的平滑渐变,这是您仅使用前2个坐标所期望的)。我还检查了传递给我的
setSampler()
方法的值,我得到了0和1,以及对应于它们的1和2个位置

在这个问题上,我能找到的所有帮助都在我已经实施的建议附近)

有人能帮忙吗

编辑:所以,为了踢,我交换了我的纹理单位,这样2D纹理变成了单位0,3D变成了单位1。现在仅渲染2D纹理。但是我的纹理单位被正确地传递(至少在外观上)到着色器。有什么线索吗

vec4 diffuse3D = texture3D(mainTexture, gl_TexCoord[0].stp);
vec4 diffuse2D = texture2D(roadTexture, gl_TexCoord[1].st);
gl_FragColor = diffuse2D;
让我们假设这不是使用着色器。让我们假设你只是在C++中写了一个函数,返回一个值。
int FuncName(int val1, int val2)
{
  int test1 = Compute(val1);
  int test2 = Compute(val2);
  return test2;
}
这个函数将返回什么?显然,它返回
Compute(val2)
,完全忽略
test1
的值。它不会神奇地结合
test1
test2
。它们是独立的值,因此,除非将它们显式组合,否则它们将保持独立

就像你的片段着色器一样

着色器不是魔法;他们正在编程。他们只做你让他们做的事。所以,如果你说,“从纹理中获取一个值,然后不要对它做任何事情”,它会尽职尽责地做到这一点。尽管编译器很可能会完全优化纹理提取

如果要“混合”两种纹理,则必须混合它们。必须从每个纹理中提取,然后使用这两个值来计算新颜色


你到底怎么做完全取决于你自己。可能您的2D纹理有一些alpha,表示要显示多少2D纹理。我不知道;你没有描述你的纹理是什么样子,或者你计划在某些地方而不是在其他地方显示道路的具体方式。

你得到黑色的原因很简单,就是你没有设置适当的均匀变量

# version 420

uniform sampler3D mainTexture;
uniform sampler2D roadTexture;

void main() {
    vec4 diffuse3D = texture3D(mainTexture, gl_TexCoord[0].stp);
    vec4 diffuse2D = texture2D(roadTexture, gl_TexCoord[1].st);
    gl_FragColor = diffuse2D;
}
该着色器所做的是查找“roadTexture”的值并显示它。不幸的是,它不知道当前绑定到哪个纹理单元“roadTexture”,因此将访问纹理单元0,即绑定3d纹理的位置-因此您正在尝试使用2d texcoords访问3d纹理,这可能会返回全部黑色。您需要使用
glGetUniformLocation
查询纹理的统一位置,然后使用
glUniform1i
将它们设置为正确的纹理单位(分别为0/1)


编辑:另外,您正在使用不推荐的功能,因此您的着色器版本指令应更改为
#version 420 compatibility
-默认值为
核心

,您需要调用
glEnableClientState(GL#u纹理\u协调\u数组)glClientActiveTexture(GL_TEXTURE1)激活第二个纹理单元后,再次执行code>

启用和禁用GL_纹理_坐标_阵列会影响活动的客户端纹理单元


刚刚解决了这个问题。显然,除了
glClientActiveTexture()
之外,您还需要
glActiveTexture()
。对于任何遇到同样问题的人来说,这就是有效的代码:

glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_3D, id_texture);
s.setSampler("mainTexture",0); // Calls to glGetUniformLocation and glUniform1i
glTexCoordPointer(3, GL_FLOAT, sizeof(glm::vec3), &t[0].x);

glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, id_texture_road);
s.setSampler("roadTexture",1); // Same as above
glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &t2[0].x);

// Drawing Calls

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY); 
glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
glActiveTexture(GL_TEXTURE0);

感谢阅读。

也许应该粘贴另一段代码……将两个值相乘或相加也不起作用。当我尝试混合它们时,我只得到3D纹理这正是我在s.setSampler(“mainTexture”,0)中所做的
s.setSampler(“道路纹理”,1)刚刚尝试此操作失败。还是一件好事。我将更新上面的代码。对不起,请重新阅读您的问题,看起来纹理坐标从来都不是问题。恐怕我被难倒了!