webgl阴影需用阴影贴图实现:先以光源视角渲染深度图,再在主渲染中比对深度判断遮挡;关键含depth/lighting双着色器、深度纹理fbo及light space矩阵;需偏移修正、pcf等优化抗锯齿与阴影瑕疵。

WebGL 本身不提供内置阴影功能,必须通过编程方式模拟,最常用且实用的方法是 阴影贴图(Shadow Mapping)。它原理清晰、兼容性好,适用于大多数实时渲染场景。
阴影贴图核心思路
阴影贴图本质是“从光源视角看世界”,提前渲染一张深度图(shadow map),再在主摄像机渲染时比对每个像素的深度是否被遮挡:
- 第一步:用光源(通常是平行光或聚光灯)的视图-投影矩阵(light space matrix)渲染场景,只记录片元深度值到纹理中
- 第二步:主渲染阶段,把每个顶点变换到光源空间,用该坐标采样 shadow map,比较当前片元深度与贴图中存储的深度
- 若当前深度更大 → 该点在阴影中;否则处于光照下
关键实现步骤
需两个着色器程序(光源渲染用的 depth shader + 主场景用的 lighting shader)和一张深度纹理:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 创建 1024×1024 或 2048×2048 的
TEXTURE_2D,格式设为DEPTH_COMPONENT,并绑定为帧缓冲对象(FBO)的深度附件 - 构建光源视角矩阵:平行光用
ortho投影,聚光灯用perspective;位置/方向决定 view 矩阵 - depth shader 中只需输出 gl_Position,fragment shader 可为空(因写入的是深度缓冲)
- lighting shader 中,用 light space 坐标做透视除法后归一化(
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;),再映射到 [0,1] 范围用于采样
常见问题与优化技巧
原始阴影贴图易出现锯齿、彼得潘效应(shadow acne)、漏光等问题,可通过以下方式缓解:
-
偏移修正(Depth Bias):在生成 shadow map 时给深度加微小偏移(如
glPolygonOffset(2.0, 2.0)),避免自阴影错误 -
PCF(Percentage-Closer Filtering):采样时对周围 4 或 9 个纹素取平均,实现软阴影边缘,例如用
textureProj配合vec2偏移循环 - 正交投影裁剪优化:对平行光,让 ortho 范围紧贴场景包围盒(而非固定值),提升深度精度
- 双深度范围处理:注意 WebGL 深度范围是 [0,1],而 OpenGL 是 [-1,1],确保 light space 矩阵正确适配
简单代码结构示意
主流程大致如下(省略具体矩阵计算):
- 绑定 shadow FBO → 渲染深度 → 解绑
- 绑定默认 FBO → 设置 light space matrix、shadow map 纹理单元 → 正常渲染带光照模型的物体
- lighting shader 中判断:
float visibility = (currentDepth - bias) > texture(shadowMap, projCoords.xy).r ? 0.0 : 1.0;
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










