OpenGL纹理组合不(总是)工作

Posted

技术标签:

【中文标题】OpenGL纹理组合不(总是)工作【英文标题】:OpenGL texture combining not (always) working 【发布时间】:2009-07-21 02:01:02 【问题描述】:

如果您看过我的最后几个问题,您现在应该知道我一直在使用 OpenGL 处理地形问题。我在使用顶点 alpha 和多个渲染通道将一个纹理混合到另一个平铺高度图中的纹理时失败了……所以现在我有了另一个计划。

我的 WorldQuad 对象有 'bottom' 和 'top' 变量,两者都是 Texture 类型。这是一个 JOGL 提供的封装 OpenGL 纹理的类;它会为我加载它,然后我可以调用 enable() 让它执行 glEnable(GL_TEXTURE_2D),然后调用 bind() 让它执行绑定。

它还有一个我自己类型的 alphaMap 变量,用于存储另一个纹理;但是这个是纹理内部格式 GL_ALPHA8 (换句话说,它是一个只有 alpha 值的纹理)。我目前以编程方式生成它以使其像素完美。

然后我使用 OpenGL“纹理组合”(或有时称为纹理喷溅)来根据 alpha 贴图组合底部和顶部纹理。

问题是,它在我的工作笔记本电脑上运行得非常好!!...它是带有集成 Intel 芯片(GMA950 或类似芯片)的 IBM Thinkpad T400。但当我回到我的戴尔 Inspiron E1705 时,我发现我的程序只渲染了具有“底部”纹理的四边形。就好像根本没有应用 alpha。我还在两台台式机和另一台笔记本电脑上尝试过。其中一台台式机崩溃了,另一台显示四边形全白(它是旧的 GeForce 芯片,可能不支持 OpenGL 2 或其他东西),另一台笔记本电脑的性能与我的相同;一个覆盖在底部纹理中的四边形。

我已经尝试将 alpha 贴图格式更改为 GL_RGBA,以防我的显卡由于某种原因不喜欢 GL_ALPHA8 纹理。我还验证了所有三个纹理都存在并且可以通过使用每个单独的纹理(包括 alphamap)绘制法线四边形来渲染。我还将 alphamap 输出到一个文件,所以我基本上仔细检查了它是否存在并且应该可以工作。

下面是我基于所有这些绘制一个四边形的函数。我已经添加了 cmets,希望你能跟随。请提出任何可能解决问题的建议。我难住了!为什么它可以在一个蹩脚的集成芯片上工作,而不是我的显卡?我错过了什么??

谢谢!!

编辑:好的,显然没有人可以帮助我......我现在回来工作,将我的闪存驱动器插入我的工作计算机,启动 Eclipse 并点击运行按钮......它工作了。然后我把驱动器拿出来,放入我的个人笔记本电脑(我今天带去上班)并做了完全相同的事情,它只是一个红色的斑点。但是在这里,我记录了它。首先the output from glGetString(GL_EXTENSIONS), diffed between the two computers。

接下来,screenshots of broken and working。 同样,这些都是以完全相同的方式拍摄的:打开 Eclipse,按运行,截屏。就是这样。我没有碰我的代码,我的代码只有一个副本,在我在两台计算机之间交换的闪存驱动器上。它们都具有相同版本的 JDK。

现在,两台计算机之间的区别之一是我的工作 PC 运行的是 XP,而我的笔记本电脑运行的是 Windows 7。但这真的会有所不同吗?特别是因为我使用的是 OpenGL 2,我认为两台计算机都会同样支持它。事实上,如果你看看我上面的差异页面,我的个人笔记本电脑支持的扩展比工作笔记本电脑多得多——正如我所预料的那样,因为与英特尔集成相比,它是一个 nvidia 7900gs 卡。所以这似乎倒退了;如果有的话,我希望集成芯片会阻塞纹理组合,而不是我的显卡!

救命!

public void drawWorldQuad(GL2 gl, float x, float z, WorldQuad q, WorldVertex tl, WorldVertex tr, WorldVertex bl, WorldVertex br) 
    WorldVertex[] verts = new WorldVertex[] 
        bl, br, tr, tl
    ;
    final float[][] texCoords = new float[][] 
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f,
            0.0f, 1.0f
    ;
    final float[][] coords = new float[][] 
            x,z,
            x+1,z,
            x+1,z+1,
            x,z+1
    ;

    gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    /* BEGIN TEXTURE BLENDING SECTION: */

    /* TEXTURE0 is the alpha map; a texture of type GL_ALPHA8, no rgb channels */
    gl.glActiveTexture(GL2.GL_TEXTURE0);
    q.alphaMap.getTexture().bind();
    q.alphaMap.getTexture().enable();
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_DECAL);

    /* TEXTURE1 is the 'bottom' texture */
    gl.glActiveTexture(GL2.GL_TEXTURE1);
    q.bottom.getTexture().bind();
    q.bottom.getTexture().enable();
    // use the rgb from the bottom texture
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_COMBINE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_RGB, GL2.GL_DECAL);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_RGB, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_RGB, GL2.GL_SRC_COLOR);
    //------------------------
    // use the alpha value from the alphaMap
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_ALPHA, GL2.GL_DECAL);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_ALPHA, GL2.GL_SRC_ALPHA);

    /* TEXTURE2 is the 'top' texture */
    gl.glActiveTexture(GL2.GL_TEXTURE2);
    q.top.getTexture().bind();
    q.top.getTexture().enable();
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_COMBINE);
    // interpolate between texture1 and texture2's colors, using the alpha values
    // from texture1 (which were taken from the alphamap)
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_RGB, GL2.GL_INTERPOLATE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_RGB, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE1_RGB, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE2_RGB, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_RGB, GL2.GL_SRC_COLOR);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND1_RGB, GL2.GL_SRC_COLOR);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND2_RGB, GL2.GL_SRC_ALPHA);
    //------------------------
    // interpolate the alphas (this doesn't really matter, neither of the textures
    // really have alpha values)
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_COMBINE_ALPHA, GL2.GL_INTERPOLATE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE0_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE1_ALPHA, GL2.GL_TEXTURE);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_SOURCE2_ALPHA, GL2.GL_PREVIOUS);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND0_ALPHA, GL2.GL_SRC_ALPHA);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND1_ALPHA, GL2.GL_SRC_ALPHA);
    gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_OPERAND2_ALPHA, GL2.GL_SRC_ALPHA);

    gl.glBegin(GL2.GL_QUADS);
    
        for(int j=0;j<verts.length;j++) 
            // (this loop and the arrays used here are for convenience, it just draws
            // a quad; verts.length == 4)

            WorldVertex v = verts[j];

            gl.glMultiTexCoord2f(GL2.GL_TEXTURE0, texCoords[j][0], texCoords[j][3]);
            gl.glMultiTexCoord2f(GL2.GL_TEXTURE1, texCoords[j][0], texCoords[j][4]);
            gl.glMultiTexCoord2f(GL2.GL_TEXTURE2, texCoords[j][0], texCoords[j][5]);

            gl.glVertex3f(coords[j][0], (float)v.height * VERTICAL_SCALE, coords[j][6]);
        
    
    gl.glEnd();


【问题讨论】:

【参考方案1】:

它工作!经过几个小时的尝试,我终于搞定了。

设置TEXTURE0后,我改了这一行:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_DECAL);

到这里:

gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE);

我只是一时兴起改了它,因为我仍然不清楚 DECAL 和 REPLACE 之间的区别,它起作用了!

【讨论】:

以上是关于OpenGL纹理组合不(总是)工作的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 混合两个纹理总是拾取第一个纹理

OpenGL生成的纹理总是黑色的?

OpenGL ES 2.0 - 纹理总是黑色

SurfaceTexture(外部图像)和普通纹理的Android OpenGL组合

为啥我的 OpenGL 纹理不起作用?

OpenGL纹理无法正常工作-黑屏[关闭]