繁体   English   中英

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

[英]GLSL, combining 2D and 3D textures

我正在尝试将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纹理的纹理坐标正确地发送到了片段着色器(我知道这一点是因为我使用了它们为测试进行着色,并从绿色到红色获得平滑的渐变(仅使用前两个坐标就可以实现)。 我还检查了传递给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的值。 它不会神奇地组合test1test2 它们是独立的值,因此除非您明确组合它们,否则它们将保持独立。

就像片段着色器一样。

着色器不是魔术。 他们正在编程。 他们只会按照您的指示去做。 因此,如果您说“从纹理获取值,然后不对其进行任何处理”,它将完全按照自己的意愿行事。 尽管很有可能编译器会完全优化纹理获取。

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

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

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

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

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

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

刚刚解决了这个问题。 Apprently你仍然需要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);

谢谢阅读。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM