WebGL中如何在片元着色器获取裁剪空间下的当前输出像素位置?
直接解决方案
片元着色器没有内置变量可以直接读取顶点阶段输出的原始裁剪空间坐标,完全不需要绕路通过gl_FragCoord换算,最简洁高效的方式是通过自定义逐顶点插值变量,把顶点阶段计算好的裁剪空间坐标直接传递到片元阶段。
具体实现
- 顶点着色器中,将原逻辑里计算出的裁剪空间xy值存入顶点输出变量(WebGL1中为
varying,WebGL2中为out)
代码示例:// 顶点着色器开头声明输出变量 varying vec2 v_clipXY; void main() { vec4 clipPos = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1); // 将需要的裁剪空间坐标传入插值通道 v_clipXY = clipPos.xy; gl_Position = clipPos; } - 片元着色器中声明同名的接收变量(WebGL1中为
varying,WebGL2中为in),即可直接获得经光栅化插值后、对应当前片元的裁剪空间坐标:// 片元着色器开头声明接收的插值变量 varying vec2 v_clipXY; void main() { // v_clipXY 就是你需要的裁剪空间坐标,可直接用于纹理采样、像素混合逻辑 vec4 sampleColor = texture2D(u_sampleTex, v_clipXY * 0.5 + 0.5); gl_FragColor = sampleColor; }
方案优势
- 不需要额外传入画布尺寸的uniform变量,后续调整画布大小时不需要同步更新uniform值
- 坐标计算和顶点变换逻辑完全绑定,不会出现视口偏移、坐标系不匹配带来的计算误差
- 结合你当前的顶点逻辑,最终
gl_Position的w分量恒为1,光栅化插值为线性过程,没有透视畸变,得到的坐标值和顶点阶段计算结果完全一致
关于内置gl_FragCoord换算的说明
如果尝试通过gl_FragCoord逆推裁剪空间坐标,本质是套用视口变换的逆公式:
// 依然需要传入视口宽高uniform才能计算 vec2 clipXY = vec2( gl_FragCoord.x / u_viewportWidth * 2.0 - 1.0, gl_FragCoord.y / u_viewportHeight * 2.0 - 1.0 );
这种方式不仅没有省去传uniform的步骤,一旦使用非全画布的视口、存在视口偏移时,计算结果就会出现偏差,可靠性远不如通过插值变量直接传递的方案。
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

