使用 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 作为统一传递。
我正在使用 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 纹理单元通过调用
将数据提供给 GPUint 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 作为统一传递。