1

我正在尝试将 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 纹理。但是我的纹理单元被正确地(至少在外观上)传递给了着色器。有什么线索吗?

4

4 回答 4

1

你得到黑色的原因仅仅是你没有设置适当的统一变量。

# 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”,因此将访问绑定了 3d 纹理的纹理单元 0 - 因此您正在尝试使用 2d texcoords 访问 3d 纹理,这很可能会返回全黑。您需要使用 查询纹理的统一位置,glGetUniformLocation然后使用 .将它们设置为正确的纹理单位(分别为 0/1)glUniform1i

编辑:另外,您正在使用已弃用的功能,因此您的着色器版本指令应更改为#version 420 compatibility- 默认为core

于 2013-05-21T07:52:03.817 回答
1
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。它不会神奇地结合test1and test2。它们是单独的值,因此,除非您明确组合它们,否则它们将保持独立。

就像你的片段着色器一样。

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

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

你如何做到这一点完全取决于你。也许您的 2D 纹理有一些 alpha 表示要显示多少 2D 纹理。我不知道; 你没有描述你的纹理是什么样的,或者你打算如何在某些地方而不是在其他地方展示道路。

于 2013-05-21T07:08:48.680 回答
0

glEnableClientState(GL_TEXTURE_COORD_ARRAY);激活第二个纹理单元后,您需要再次调用glClientActiveTexture(GL_TEXTURE1);

来自http://www.opengl.org/sdk/docs/man2/xhtml/glEnableClientState.xml

启用和禁用 GL_TEXTURE_COORD_ARRAY 会影响活动的客户端纹理单元。

于 2013-05-21T13:47:18.130 回答
0

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

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);

谢谢阅读。

于 2013-05-21T19:37:55.917 回答