当前位置: 首页 > 知识库问答 >
问题:

每次写入后,OpenGL Frag着色器纹理都会褪色

谭向晨
2023-03-14

我有一个采用以下纹理的程序:

这是通过FreeType2生成的。基本上,它是为我要求绘制的每个角色创建一个纹理图谱。正如你所看到的,这些字符明亮而清晰。事实上,当我在RenderDoc中检查纹理时,可以看到小写字母“i”最左上角的像素值为71(共255)或0.7098

接下来,引擎将字母闪烁到帧缓冲对象上。这是通过纹理四边形完成的。顶点着色器:

#version 330

layout(location=0) in vec2 inVertexPosition;
layout(location=1) in vec2 inTexelCoords;
layout(location=2) in float inDepth;

out vec2 texelCoords;
out float depth;

void main()
{
    gl_Position = vec4(inVertexPosition.x,-inVertexPosition.y, 0.0, 1.0);
    texelCoords = vec2(inTexelCoords.x,1-inTexelCoords.y);
    depth = inDepth;
}

还有frag着色器:

#version 330

layout(location=0) out vec4 frag_colour;

in vec2 texelCoords;
in float depth;

uniform sampler2D uTexture;
uniform vec4 uTextColor;

void main()
{
    vec4 c = texture(uTexture,texelCoords);
    frag_colour = uTextColor * c.r;
    gl_FragDepth = depth;
}

如您所见,它将像素颜色设置为红色通道的一个因素。

但是,当我通过RenderDoc查看FBO的内容并保存到此处的文件时,您会看到:

如果你在没有透明度的情况下看这个(只是在Gimp下面添加了第二层,以便更好地说明):

你可以看到文本与之前相比有点褪色。如果查看小写字母“i”最左上方的像素,它现在的值为50.2,或者在0-1范围内,它的值为0.50196(通过RenderDoc)。

接下来,当FBO最终通过另一个带纹理的四边形放在屏幕上时,它会更加褪色。首先是顶点着色器:

#version 330

layout(location=0) in vec2 inVertexPosition;
layout(location=1) in vec2 inTexelCoords;

varying vec2 texelCoords;

void main()
{
    gl_Position = vec4(inVertexPosition.x,-inVertexPosition.y, 0.0, 1.0);
    texelCoords = vec2(inTexelCoords.x,1-inTexelCoords.y);
}

和片段着色器:

#version 330

precision highp float;

layout(location=0) out vec4 frag_colour;

varying vec2 texelCoords;

uniform sampler2D uTexture;

void main()
{
    vec4 c = texture(uTexture,texelCoords);
    frag_colour = c;
}

正如我所说,结果比以前更加暗淡:

为了清晰起见,gimp背景:

现在,该像素的值为25.10.05139

每次渲染后,是什么导致这种褪色?

我认为重要的是要注意更亮的区域不会褪色。

我的帧缓冲区创建代码

glGenFramebuffers(1, &m_framebuffer);
glGenTextures(1, &m_fboColorAttachment);
glGenTextures(1, &m_fboAdditionalInfo);
glGenTextures(1, &m_fboDepthStencil);

glCall(glBindFramebuffer,GL_FRAMEBUFFER, m_framebuffer);

    /* setup color output 0 */
    glBindTexture(GL_TEXTURE_2D, m_fboColorAttachment);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGBA8, screenDimensionsX, screenDimensionsY, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fboColorAttachment, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

    /* setup color output 1 */
    glBindTexture(GL_TEXTURE_2D, m_fboAdditionalInfo);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_R32UI, screenDimensionsX, screenDimensionsY, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_fboAdditionalInfo, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

    /* setup depth and stencil */
    glBindTexture(GL_TEXTURE_2D, m_fboDepthStencil);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
        glCall(glTexImage2D, GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, screenDimensionsX, screenDimensionsY, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_fboDepthStencil, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

初始(红色)纹理创建:

glActiveTexture(GL_TEXTURE0);
glGenTextures(1,&textureData.texture);
glBindTexture(GL_TEXTURE_2D,textureData.texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 500, 500, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

我的混合完成为

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

共有1个答案

越望
2023-03-14

值为71(来自255)或0.7098

不知道你这是什么意思<代码>71/255将为0.278<代码>0.7098标准化为181255。看起来你的“255分”只是百分数,百分数是100%。

glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去_SRC_ALPHA);

您将红色通道中的颜色值也用作alpha,因此,当您启用混合时,最终会得到0.7098*0.7098=.5038。由于结果将四舍五入到最接近的可报告值,因此我们以181/255*181/255=.50382四舍五入到128/255

它现在是50.2的值,或者对于0-1的范围,它是0.50196

128/255is0.50196078

所以解决方案是:当您不需要时禁用所有步骤的混合。或者如果您需要它,请设置有用的alpha值。

附带说明:

现在,该像素的值为25.10.05139

不知道这意味着什么,25.10.05139之间没有任何明显的关联,您最终再次切换了这些值的含义。

 类似资料:
  • 标准着色器 Unity 标准着色器是一个内置着色器,具有非常全面的功能。它可以用于渲染『真实世界』的对象,例如,石头、木材、玻璃、塑料和金属,并支持各种各样的着色器类型和组合。通过使用或不使用材质编辑器中的各种纹理插槽和参数,可以很容易地启动或禁用其功能。 标准着色器还包括一个称为 物理着色器(Physically Based Shading,PBS) 的高级光照模型。物理着色器以模拟真实世界的方

  • 我正在努力发送多个纹理到一个单一的着色器,并有一个奇怪的问题,在着色器中的两个采样器似乎得到相同的纹理数据。我知道还有很多其他的多纹理问题和答案(这里有一些我已经读过很多次了1,2,3),但一些bug正在逃避我,我开始失去我的弹珠。我很有信心我已经把一切都安排好了,但显然还是有一些问题。 所以,目前我有形状,材料,纹理,和着色器类。我的shape类是执行实际绘制的父类。它有一个具有着色器和纹理数组

  • 我是OpenGL的新手,在整理如何将纹理和着色器绑定到VBOs时遇到了困难。 我正在使用Cinder的纹理和着色器类。以下是我绘制方法的一部分: 在上面的代码中,如果我注释掉对mShader的调用。bind(),我的球体VBO将显示纹理(myImage)。我的着色器适用于普通(无纹理)形状,但当我在绘制任何带有包裹纹理的形状之前绑定着色器时,它会阻止纹理显示。 这是我使用的着色器的问题,还是我不理

  • 如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?

  • 在一个教程之后,我将尝试使用FreeType在OpenGL中渲染文本。因此,灰度8位图像用作每个字符的纹理,使图像的每个字节对应于纹理的红色分量。 为了以其他颜色呈现文本,建议您使用着色器。但是,当使用提供的着色器时,我看到的不是彩色字母,而是彩色框,好像根本没有纹理。 以下是没有着色器时的效果: 这是它在着色器中的外观: (盒子的位置也会发生变化) 以下是顶点着色器代码: 这是片段着色器代码:

  • 材质、着色器、纹理 在 Unity 中,渲染通过 材质、着色器 和 纹理 完成。 在 Unity 中,材质、着色器和纹理之间的关系非常紧密。 材质 定义了应该如何渲染表面,包含了对贴图的引用、拼接信息、颜色等等。材质的有效选项取决于所使用的的着色器。 着色器 是一些小脚本,包含了计算每个像素渲染颜色的数学计算和算法,基于光照输入和材质配置。 纹理 是一些位图图像。一个材质可以包含对多个纹理的引用,