OpenGL:禁用纹理颜色?

Posted

技术标签:

【中文标题】OpenGL:禁用纹理颜色?【英文标题】:OpenGL: Disable texture colors? 【发布时间】:2010-03-22 14:29:52 【问题描述】:

是否可以禁用纹理颜色,只使用白色作为颜色?它仍然会读取纹理,所以我不能使用 glDisable(GL_TEXTURE_2D) 因为我也想渲染 alpha 通道。

我现在能想到的就是制作所有颜色数据都是白色的新纹理,保持原样。

我需要不使用着色器,所以这可能吗?

编辑:澄清:我想同时使用两种纹理:白色和普通颜色。

编辑:显然这是不可能的

【问题讨论】:

你想达到什么目的?为什么按照您的建议制作新纹理不是一个好的解决方案? 因为它的加载速度会变慢并且占用两倍的内存,我正在寻求更好的方法,因为我不知道有没有更好的方法。 只是为了进一步澄清,您想要完成的是(部分时间,并非总是)忽略颜色并仅使用纹理的 Alpha 通道,对吗?跨度> 是的,除了我必须看到它是白色的(或任何带有 glColor4f() 函数的颜色 我刚刚测试了这里发布的解决方案:***.com/questions/2485370/… 它有效! 【参考方案1】:

我仍然不完全确定我正确理解你想要什么,但我会试一试。我想到的是,当你调用glTexImage2D 时,你指定了你正在加载的纹素的格式并且你指定你从这些纹素创建的纹理的“内部格式” .在典型情况下,您为两者指定(大致)相同的格式 - 例如您通常会同时使用GL_RGBA

同时指定两者是有原因的:format(接近列表末尾的参数)指定您正在加载的纹素的格式,但@987654325 @(靠近参数列表开头的那个)指定您从这些纹素创建的实际纹理的格式。

如果你想加载一些纹素,但实际上使用它们的 alpha 通道,你可以为internal format 指定GL_ALPHA,这就是你所得到的——当您将该纹理映射到表面,它只会影响 alpha,而不影响颜色。这不仅避免了制作额外的纹素副本,而且(至少通常)还减少了纹理本身消耗的内存,因为它只包含一个 Alpha 通道,而不是三个颜色通道。

编辑:好的,再想一想,有一种方法可以做(我认为)你想要的,只使用一个纹理。首先,您将混合功能设置为只使用 alpha 通道,然后当您要复制纹理的颜色时,您调用 glTextureEnvfGL_REPLACE,但是当您只想使用 alpha 通道时,您调用它与GL_BLEND。例如,让我们创建一个绿色纹理,并在蓝色四边形上绘制(两次),一次使用 GL_REPLACE,一次使用 GL_BLEND。为简单起见,我们将使用纯绿色纹理,alpha 从顶部 (0) 到底部 (1) 线性增加:

static GLubyte Image[128][128][4];

for (int i=0; i<128; i++)
    for (int j=0; j<128; j++) 
        Image[i][j][0] = 0;
        Image[i][j][1] = 255;
        Image[i][j][2] = 0;
        Image[i][j][3] = i;
    

我将跳过创建和绑定纹理、设置参数等的大部分内容,直接使用纹理绘制几个四边形:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glBegin(GL_QUADS);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 0.0); glVertex3f(-1.0f, 1.0f, 0.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0); glVertex3f(0.0f, 1.0f, 0.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0); glVertex3f(0.0f, -1.0f, 0.0f);
    glColor4f(0.0, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 1.0); glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd();

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);

glBegin(GL_QUADS);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 0.0); glVertex3f(0.0f, 1.0f, 0.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 0.0); glVertex3f(1.0f, 1.0f, 0.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(1.0, 1.0); glVertex3f(1.0f, -1.0f, 0.0f);
    glColor4f(0.0, 0.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0, 1.0); glVertex3f(0.0f, -1.0f, 0.0f);
glEnd();

这会产生:

所以,在使用 GL_REPLACE 绘制的左侧,我们得到了纹理的绿色,但在使用 GL_BLEND 绘制的右侧(并且 glBlendFunc 设置为仅使用 alpha 通道),我们得到蓝色四边形,但它的 Alpha 取自纹理——但我们对两者使用完全相同的纹理。

编辑 2:如果您确定确实需要全白纹理,我只需创建一个 1 像素纹理,并将 GL_TEXTURE_WRAP_S 和 GL_TEXTURE_WRAP_T 设置为 GL_REPEAT。尽管这仍然使用额外的纹理,但额外的纹理将真的很小,因为它只有一个像素。加载它的时间和消耗的内存都非常小——像素的数据基本上是“噪音”。我没有尝试测试,但你可能会更好地使用 8x8 或 16x16 像素块。这仍然很小,几乎无关紧要,但它们分别是 JPEG 和 MPEG 中使用的尺寸,我可以看到卡和(特别是)驱动程序可能针对它们进行优化的地方。它可能会有所帮助,并且不会受到伤害(无论如何都足够关心)。

【讨论】:

我不明白我应该如何在运行时只读取 alpha 通道,请代码。我使用代码 glBindTexture(GL_TEXTURE_2D, tex);要绑定纹理,我还需要读取什么Alpha?我正在使用 glTexImage2D(目标,0,格式,宽度,高度,0,格式,GL_UNSIGNED_BYTE,像素);将纹理保存在我的 GPU 上。这不能在运行时使用,我不能使这个函数加倍,否则它会创建另一个纹理。 我如何将 GL_TEXTURE_ENV_MODE 恢复到更改前的状态?还有一个问题,我必须在使用和不使用 GL_BLEND 的情况下进行这项工作,在那里我可以看到没有 alpha 和 alpha 的白色。 要返回 GL_REPLACE,您需要再次调用 glTexEnvfGL_REPLACE。我认为我不了解您想要的其余部分,因此我无法真正回答。如果您只想要一个白色块,而不使用纹理中的颜色或 alpha,那么为什么要使用纹理呢?这只是一个颜色设置为白色的 GL_QUAD... 啊,你是对的,我会为那些禁用 GL_TEXTURE_2D。生病看看我是否可以让这个其他代码工作。通过将 GL_TEXTURE_ENV_MODE 恢复回来,我的意思是我如何将其设置回我编辑之前的状态,因此我的场景的其余部分将正常渲染。 您的“edit2”没有意义,我使用 Alpha 通道创建形状,如果我删除 Alpha 通道,我的精灵会丢失所有形状。【参考方案2】:

在加载之后和在 OpenGL 中使用它们之前将所有纹理颜色(除了 alpha )更改为白色怎么样?如果您在某个时候将它们作为位图保存在内存中,那应该很容易,并且您不需要单独的纹理文件。

【讨论】:

但我也需要使用纹理。我想要一个将其显示为白色的选项。 @Newbie,复制纹理。这将需要两倍的内存,我知道您正在尝试避免这种情况,但至少您只需要从磁盘加载一个副本,并且它是 DRY。

以上是关于OpenGL:禁用纹理颜色?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL,禁用纹理单元、glActiveTexture 和 glBindTexture

如何在OpenGL中反转纹理颜色

OpenGL纹理颜色分离

OpenGL-载入纹理

OpenGL纹理覆盖材质颜色

受彩色矩形影响的所有纹理颜色 - OpenGL