使用 GLSL 在纹理上覆盖透明颜色

Overlaying a transparent color over a Texture with GLSL

我正在使用 Slick 库加载一张图像,并且在我的着色器未激活的情况下图像渲染良好。当我使用我的着色器在图像上覆盖透明颜色时,整个图像被透明颜色替换。

没有着色器

使用着色器

顶点着色器

varying vec4 vertColor;

void main(){
    vec4 posMat = gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * posMat;
    vertColor = vec4(0.5, 1.0, 1.0, 0.2);
}

片段着色器

varying vec4 vertColor;

void main(){
    gl_FragColor = vertColor;
}

精灵渲染代码

Color.white.bind();
GL11.glBindTexture(GL11.GL_TEXTURE, image.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(this.x, this.y);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(x + w, y);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(x + w, y + h);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(x, y + h);
GL11.glEnd();
GL11.glBindTexture(GL11.GL_TEXTURE, 0);

}

OpenGL 初始化

GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, Screen.getW(), Screen.getH(), 0, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

a) vertColor = vec4(0.5, 1.0, 1.0, 0.2); b) gl_FragColor = vertColor;

着色器完全按照您的要求进行 - 它将所有片段的颜色设置为该颜色。如果你想混合颜色,你应该以某种方式在着色器中 add/multiply 它们(例如,有一个颜色属性 and/or 纹理采样器,然后,在将属性从顶点着色器导出到片段着色器之后,使用gl_FragColor = vertexColor * textureColor * blendColor; 等)。

另请注意:您将固定功能管线与即时模式 (glBegin/glEnd) 与着色器混合使用……这不是一个好主意。另外,我没看到你的制服放在哪里;使用没有制服的着色器 == 自找麻烦。

IMO 最好的解决方案是使用常规 OpenGL >= 3.1 和适当的、兼容的着色器等,或者只使用固定功能管道而不使用遗留 OpenGL 的着色器。


至于如何使用 GLSL 加载纹理:(如果需要,请参阅 https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php 了解更多信息)

a) 通过创建纹理并将其绑定到 GPU 纹理单元通过调用

将数据提供给 GPU
int id = glGenTexture();
glBindTexture( GL_TEXTURE_2D, id );
glTexImage2D( ... );
// see https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml for details

(我想你已经完成了,因为你已经在使用 glBindTexture 和图像参数)

b) 为几何体提供 UV 纹理坐标;您已经通过提供 glTexCoord2f 来做到这一点,这可能允许您像 https://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/attributes.php 那样使用遗留属性名称,但正确的方法是将其作为打包属性结构的一部分传递,

c) 通过在着色器中采样纹理来使用绑定纹理,例如(紧随其后的是旧版 GLSL)

// vertex shader
varying vec2 vTexCoord;

void main() {
   vTexCoord = gl_MultiTexCoord0;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

// fragment shader
uniform sampler2D texture;
varying vec2 vTexCoord;

void main() {
   vec4 colorMultiplier = vec4(0.5, 1.0, 1.0, 0.2);
   gl_FragColor = texture2D(texture, vTexCoord) * colorMultiplier;
}

不过,如果您打算在运行时更改它,最好将 colorMultiplier 作为统一传递。