The Book of Shaders 项目解析:月球纹理与光照效果的实现
2025-07-07 06:19:05作者:卓艾滢Kingsley
概述
本文将深入分析一个来自The Book of Shaders项目的片段着色器代码,该着色器实现了月球表面纹理的渲染以及动态光照效果。这个示例展示了如何使用GLSL创建逼真的球体渲染效果,包括纹理映射、法线计算和光照模拟。
核心功能解析
1. 球体法线计算
sphereNormals
函数负责计算球体表面各点的法线向量:
vec3 sphereNormals(in vec2 uv) {
uv = fract(uv)*2.0-1.0;
vec3 ret;
ret.xy = sqrt(uv * uv) * sign(uv);
ret.z = sqrt(abs(1.0 - dot(ret.xy,ret.xy)));
ret = ret * 0.5 + 0.5;
return mix(vec3(0.0), ret, smoothstep(1.0,0.98,dot(uv,uv)) );
}
这个函数将2D坐标转换为3D球体表面的法线向量,通过以下步骤实现:
- 将UV坐标从[0,1]范围映射到[-1,1]范围
- 计算XY平面的法线分量
- 根据XY分量计算Z分量,确保向量长度为1
- 将法线向量从[-1,1]范围重新映射到[0,1]范围
- 使用smoothstep函数平滑处理球体边缘
2. 球面坐标转换
sphereCoords
函数实现了从平面坐标到球面坐标的转换:
vec2 sphereCoords(vec2 _st, float _scale){
float maxFactor = sin(1.570796327);
vec2 uv = vec2(0.0);
vec2 xy = 2.0 * _st.xy - 1.0;
float d = length(xy);
if (d < (2.0-maxFactor)){
d = length(xy * maxFactor);
float z = sqrt(1.0 - d * d);
float r = atan(d, z) / 3.1415926535 * _scale;
float phi = atan(xy.y, xy.x);
uv.x = r * cos(phi) + 0.5;
uv.y = r * sin(phi) + 0.5;
} else {
uv = _st.xy;
}
return uv;
}
这个函数实现了:
- 将平面坐标转换为球面坐标
- 使用三角函数计算球面投影
- 处理球体边缘的情况
3. 纹理映射
sphereTexture
函数将纹理映射到球体表面:
vec4 sphereTexture(in sampler2D _tex, in vec2 _uv) {
vec2 st = sphereCoords(_uv, 1.0);
float aspect = u_tex0Resolution.y/u_tex0Resolution.x;
st.x = fract(st.x*aspect + u_time*speedMoon);
return texture2D(_tex, st);
}
关键点包括:
- 使用
sphereCoords
进行坐标转换 - 考虑纹理的宽高比(aspect ratio)
- 添加随时间变化的动画效果(speedMoon控制速度)
光照效果实现
主函数中实现了动态光照效果:
// Calculate sun direction
vec3 sunPos = normalize(vec3(cos(u_time*speedSun-HALF_PI),0.0,sin(speedSun*u_time-HALF_PI)));
vec3 surface = normalize(sphereNormals(st)*2.0-1.0);
// Add lighting effects
color *= dot(sunPos,surface);
- 太阳位置随时间变化(speedSun控制速度)
- 计算表面法线
- 使用点积计算光照强度,实现明暗效果
边缘处理技巧
// Blend black the edge of the sphere
float radius = 1.0-length( vec2(0.5)-st )*2.0;
color *= smoothstep(0.001,0.05,radius);
这段代码实现了:
- 计算像素到球心的距离
- 使用smoothstep函数平滑处理球体边缘
- 使球体边缘逐渐变暗,形成自然过渡
技术亮点总结
- 球体渲染技术:通过数学计算将2D纹理映射到3D球体表面
- 动态光照:模拟太阳位置变化产生的光影效果
- 边缘处理:使用smoothstep实现平滑的边缘过渡
- 性能优化:所有计算都在片段着色器中完成,无需几何体
应用场景
这种技术可以应用于:
- 天文模拟程序中的行星渲染
- 游戏中的球体对象渲染
- 数据可视化中的球形展示
- 创意编码艺术项目
扩展思考
读者可以尝试修改以下参数来观察不同效果:
- 调整speedMoon和speedSun的值改变动画速度
- 修改光照方向的计算方式
- 尝试不同的纹理贴图
- 添加大气散射效果增强真实感
这个着色器示例展示了如何用相对简单的数学计算实现复杂的3D渲染效果,是学习计算机图形学中光照和纹理映射的优秀教材。