three ShaderChunk ShaderLib UniformsLib UniformsUtils 渲染器 / 着色器

171 阅读5分钟

在 Three.js 中,ShaderChunk 是一个非常重要的概念,主要用于管理和组织着色器代码的片段。它允许开发者重用着色器的常见部分,以提高代码的可维护性和可读性。
在 Three.js 中,ShaderLib 是一个存储了一些预定义着色器库的对象,它提供了多种常见材质的着色器代码,可以帮助开发者快速创建各种效果。通过使用这些内置的着色器库,开发者可以省去自己编写基础着色器的时间,同时还可以根据自己的需求进行扩展或修改。
在 Three.js 中,UniformsLib 是一个用于管理着色器中 uniforms 的集合,它提供了各种常用的 uniforms,如光照、环境贴图、雾等。UniformsLib 可以帮助开发者快速配置和使用这些 uniforms,而不需要手动定义每一个。
THREE.UniformsUtils 是 Three.js 中用于管理和合并 uniforms 的工具类,特别适用于着色器程序。在自定义着色器时,您可能需要将不同的 uniforms 组合在一起,以便为顶点和片元着色器提供所需的数据。以下是 UniformsUtils 的主要功能和一个使用示例。

ShaderChunk 使用示例

    // 定义自定义 ShaderChunk
    THREE.ShaderChunk['myCustomChunk'] = `
        vec3 myCustomFunction(vec3 color) {
            return color * 0.5; // 简单的颜色减半示例
        }
    `;
    // 自定义材质
    const customMaterial = new THREE.ShaderMaterial({
        vertexShader: `
            varying vec3 vColor;
            void main() {
                vColor = position; // 将立方体的顶点位置作为颜色值
                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            varying vec3 vColor;
            // 引入自定义代码片段
            #include <myCustomChunk>
            void main() {
                vec3 finalColor = myCustomFunction(vColor * 0.5 + 0.5); // 使用自定义函数处理颜色
                gl_FragColor = vec4(finalColor, 1.0);
            }
        `
    });
    // 创建立方体几何体
    const geometry = new THREE.BoxGeometry();
    const cube = new THREE.Mesh(geometry, customMaterial);
    scene.add(cube);

ShaderLib 有以下属性列表

    **`basic`** - 基础材质的着色器。
    **`lambert`** - 使用 Lambertian 反射模型的材质。
    **`phong`** - 使用 Phong 反射模型的材质。
    **`standard`** - 物理基础渲染(PBR)材质,适用于现代光照模型。
    **`physical`** - 基于物理的材质,通常用于需要更复杂的光照和反射效果。
    **`depth`** - 深度测试用的着色器,通常用于后期处理效果。
    **`normal`** - 用于显示法线信息的着色器。
    **`meshbasic`** - 适用于简单的基础材质。
    **`meshlambert`** - 适用于 Lambert 材质。
    **`meshphong`** - 适用于 Phong 材质。
    **`meshstandard`** - 适用于标准 PBR 材质。
    **`meshphysical`** - 适用于物理 PBR 材质。
    **`sprite`** - 精灵的着色器,用于2D效果。
    **`line`** - 线条的着色器,用于渲染线条几何体。
    **`points`** - 点的着色器,用于渲染粒子效果。
    
    
    // 创建几何体
    const geometry = new THREE.BoxGeometry(10, 10, 10);
    // 复制 THREE.ShaderLib.basic
    const basicShader = { ...THREE.ShaderLib.basic };
    // 使用 replace 方法替换片元着色器代码
    basicShader.fragmentShader = `
        varying vec3 vNormal; // 接收法线
        varying vec3 vViewPosition; // 视点位置
        uniform vec3 diffuse; // 用于替换颜色的 Uniform

        void main() {
            // 设置颜色为红色
            gl_FragColor = vec4(1.0,0.0,0.0, 1.0); // RGBA
        }
    `;
    // 创建自定义材质,使用替换后的着色器
    const material = new THREE.ShaderMaterial({
        uniforms: basicShader.uniforms,
        vertexShader: basicShader.vertexShader,
        fragmentShader: basicShader.fragmentShader,
    });
    // 创建网格并添加到场景
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

# UniformsLib 有以下属性

`lights` 用于光照的 uniforms,包含以下属性:
-   `ambient`: 环境光颜色。
-   `directionalLight[0].color`: 第一个方向光的颜色。
-   `directionalLight[0].direction`: 第一个方向光的方向。
-   `directionalLight[0].intensity`: 第一个方向光的强度。
-   `pointLight[0].color`: 第一个点光源的颜色。
-   `pointLight[0].position`: 第一个点光源的位置。
-   `pointLight[0].intensity`: 第一个点光源的强度。
-   `spotLight[0].color`: 第一个聚光灯的颜色。
-   `spotLight[0].position`: 第一个聚光灯的位置。
-   `spotLight[0].direction`: 第一个聚光灯的方向。
-   `spotLight[0].angle`: 第一个聚光灯的角度。
-   `spotLight[0].intensity`: 第一个聚光灯的强度。
`fog` 用于雾效果的 uniforms,包含以下属性:
-   `fog.color`: 雾的颜色。
-   `fog.near`: 雾开始的距离。
-   `fog.far`: 雾结束的距离。
`envMap` 用于环境映射的 uniforms,包含以下属性:
-   `envMap`: 环境贴图纹理。
-   `reflectivity`: 反射率。
`map` 用于纹理映射的 uniforms,包含以下属性:
-   `map`: 基础纹理。
-   `alphaMap`: 透明纹理。
-   `lightMap`: 光照贴图。
-   `aoMap`: 环境光遮蔽贴图。
-   `emissiveMap`: 自发光贴图。
`skin` 用于皮肤渲染的 uniforms,包含以下属性:
-   `boneTexture`: 骨骼纹理。
-   `boneCount`: 骨骼数量。
-   `skinWeight`: 皮肤权重。
`fog` 用于雾效果的 uniforms,包含以下属性:
-   `fog.color`: 雾的颜色。
-   `fog.near`: 雾开始的距离。
-   `fog.far`: 雾结束的距离。


    // 添加光源
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); 
    scene.add(ambientLight);
    const pointLight = new THREE.PointLight(0xffffff, 1); 
    pointLight.position.set(10, 10, 10);
    scene.add(pointLight);
    // 创建几何体
    const geometry = new THREE.BoxGeometry(10, 10, 10);
    // 从 UniformsLib 获取光照和雾相关的 uniforms
    const uniforms = THREE.UniformsUtils.merge([
        THREE.UniformsLib.lights, // 添加光照 uniforms
    ]);
    // 自定义材质
    const material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        lights: true, // 启用光照
        vertexShader: `
            varying vec3 vNormal;
            varying vec3 vPosition;
            void main() {
                vNormal = normalize(normalMatrix * normal);
                vPosition = position;
                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec3 diffuse;
            varying vec3 vNormal;
            void main() {
                vec3 normal = normalize(vNormal);
                vec3 lightDirection = normalize(vec3(1.0, 1.0, 1.0)); // 光源方向
                float brightness = max(dot(normal, lightDirection), 0.0);
                gl_FragColor = vec4(diffuse * brightness, 1.0); // 计算最终颜色
            }
        `,
    });
    // 设置材质的扩散颜色(例如红色)
    material.uniforms.diffuse = { value: new THREE.Color(1.0, 0.0, 0.0) }; // 红色
    // 创建网格并添加到场景
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

UniformsUtils 有两个方法

  • clone ( src : Object ) : Object src -- 表示定义uniforms的对象的路径 通过执行深层复制克隆给定的统一定义。 这意味着如果uniform的[page:Uniform.value 值]引用Vector3或Texture之类的对象,则克隆的uniform将引用新的对象引用。
    // 定义一个包含一些 uniforms 的对象
    const originalUniforms = {
        diffuse: { value: new THREE.Color(0xff0000) },
        opacity: { value: 1.0 },
        lightPosition: { value: new THREE.Vector3(10, 10, 10) }
    };
    // 克隆原始 uniforms 对象
    const clonedUniforms = THREE.UniformsUtils.clone(originalUniforms);
    // 修改克隆对象的某个属性
    clonedUniforms.diffuse.value.set(0x00ff00); // 将颜色改为绿色
    console.log('Original Uniforms:', originalUniforms); // 原始 uniforms 仍然是红色
    console.log('Cloned Uniforms:', clonedUniforms); // 克隆的 uniforms 是绿色
  • merge ( uniforms : Array ) : Object uniforms -- 包含uniforms定义的对象数组 将给定的统一定义合并到一个对象中。由于该方法在内部使用.clone(),因此它在生成合并的统一定义时执行深度复制。