You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么该OpenGL着色器渲染的立方体未呈现纯水平渐变效果

现象成因

你观察到的竖线差异核心是片元着色器中没有做透视除法,直接使用了裁剪空间的齐次坐标x分量作为颜色输出,具体逻辑如下:

  1. 首先纠正你顶点着色器的一处笔误:你代码中gl_Position = u_ProjectionMatrix * u_ViewMatrix * worldPos;里的worldPos未定义,实际应为你之前赋值的fs.pos,这个笔误不影响当前现象的分析,因为你在片元着色器中重新对世界空间坐标做了VP矩阵变换。
  2. 你对MVP变换的流程认知少了关键一步:经过投影矩阵变换后得到的是裁剪空间齐次坐标,格式为vec4(clip_x, clip_y, clip_z, clip_w),此时的x/y/z分量还不是和屏幕坐标对应的NDC坐标,必须经过透视除法ndc = clip.xyz / clip.w之后,得到的ndc.x才和屏幕x坐标一一对应,同一竖线的像素ndc.x完全相同。
  3. 透视投影的规则下,clip_w等于相机空间中顶点z坐标的相反数,也就是片元离相机越远,clip_w的值越大。你在片元着色器中直接将裁剪坐标转为vec3(相当于直接丢弃了w分量),取x分量作为颜色值,此时的颜色值不仅和屏幕x有关,还和片元的深度直接相关:就算两个片元在同一竖线(屏幕x相同),只要深度不同,对应的clip_x就会不同,输出的灰度自然有差异,就形成了你看到的竖线分界。

验证方案

你可以修改片元着色器代码,加上透视除法步骤,就能得到你预期的纯水平渐变效果:

uniform mat4 u_ModelMatrix;
uniform mat4 u_ViewMatrix;
uniform mat4 u_ProjectionMatrix;

in FS {
    vec4 pos;
} fs;

out vec4 out_Color;

void main()
{
    vec4 clip_pos = u_ProjectionMatrix * u_ViewMatrix * fs.pos;
    vec3 ndc = clip_pos.xyz / clip_pos.w;
    out_Color.rgb = ndc.xxx;
}

内容的提问来源于stack exchange,提问作者rafoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:24:04