首页
/ The Book of Shaders 项目解析:月球纹理与光照效果的实现

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球体表面的法线向量,通过以下步骤实现:

  1. 将UV坐标从[0,1]范围映射到[-1,1]范围
  2. 计算XY平面的法线分量
  3. 根据XY分量计算Z分量,确保向量长度为1
  4. 将法线向量从[-1,1]范围重新映射到[0,1]范围
  5. 使用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;
}

这个函数实现了:

  1. 将平面坐标转换为球面坐标
  2. 使用三角函数计算球面投影
  3. 处理球体边缘的情况

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);
}

关键点包括:

  1. 使用sphereCoords进行坐标转换
  2. 考虑纹理的宽高比(aspect ratio)
  3. 添加随时间变化的动画效果(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);
  1. 太阳位置随时间变化(speedSun控制速度)
  2. 计算表面法线
  3. 使用点积计算光照强度,实现明暗效果

边缘处理技巧

// 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);

这段代码实现了:

  1. 计算像素到球心的距离
  2. 使用smoothstep函数平滑处理球体边缘
  3. 使球体边缘逐渐变暗,形成自然过渡

技术亮点总结

  1. 球体渲染技术:通过数学计算将2D纹理映射到3D球体表面
  2. 动态光照:模拟太阳位置变化产生的光影效果
  3. 边缘处理:使用smoothstep实现平滑的边缘过渡
  4. 性能优化:所有计算都在片段着色器中完成,无需几何体

应用场景

这种技术可以应用于:

  1. 天文模拟程序中的行星渲染
  2. 游戏中的球体对象渲染
  3. 数据可视化中的球形展示
  4. 创意编码艺术项目

扩展思考

读者可以尝试修改以下参数来观察不同效果:

  1. 调整speedMoon和speedSun的值改变动画速度
  2. 修改光照方向的计算方式
  3. 尝试不同的纹理贴图
  4. 添加大气散射效果增强真实感

这个着色器示例展示了如何用相对简单的数学计算实现复杂的3D渲染效果,是学习计算机图形学中光照和纹理映射的优秀教材。