GLSL片元着色器实现三角形从左到右透明度递减渐变方法
原有代码错误点
- GLSL 1.20 语法不支持对
uniform变量使用gl_FragCoord这类动态内置值做初始化,uniform的默认值必须是编译期可确定的常量,你写的uniform float startX = gl_FragCoord.x;会直接触发片元着色器编译失败。 - 透明度计算逻辑不符合需求:就算忽略语法错误,
startX / gl_FragCoord.x的计算结果也无法实现「从左到右透明度线性降低」的效果,gl_FragCoord是窗口像素坐标系下的坐标,原点在窗口左下角,直接做除法得到的值没有线性映射到0~1的透明度范围。 - 没有做坐标值的插值传递:要实现平滑渐变,最稳妥的方式是通过顶点着色器把归一化的顶点坐标插值传给片元着色器,不需要依赖窗口像素尺寸,窗口缩放时效果也不会变形。
正确实现方案
你不需要修改C++端的主逻辑,只需要替换两个着色器的源码即可,原有代码里的混合模式开启、顶点数据传递都是正确的。
修改后的顶点着色器
增加varying变量,把顶点坐标插值传递给片元着色器:
#version 120 attribute vec2 coord2d; varying vec2 frag_pos; // 用于跨阶段传递插值后的坐标 void main(void) { frag_pos = coord2d; gl_Position = vec4(coord2d, 0.0, 1.0); }
修改后的片元着色器
移除错误的uniform初始化逻辑,通过插值得到的坐标计算线性渐变的透明度:
#version 120 varying vec2 frag_pos; void main(void) { // 固定蓝色填充 gl_FragColor.r = 0.0; gl_FragColor.g = 0.0; gl_FragColor.b = 1.0; // 三角形X轴范围:最左点x=-0.8,最右点x=0.8,映射alpha从1到0线性变化 float tri_left = -0.8; float tri_right = 0.8; gl_FragColor.a = 1.0 - (frag_pos.x - tri_left) / (tri_right - tri_left); }
代码运行后效果为:三角形最左侧完全不透明,最右侧完全透明,中间区域透明度线性过渡,符合从左到右透明度逐渐降低的需求。
如果你希望基于窗口像素坐标实现渐变,也可以在C++端获取窗口尺寸、三角形在屏幕上的左边界X值,作为
uniform变量传入片元着色器计算,但这种方式需要在窗口resize时重新更新uniform值,实现更繁琐。
内容的提问来源于stack exchange,提问作者Arkadi
相关产品推荐
相关产品推荐

