返回

WebGL 高手之路:多贴图绘制的神奇世界

前端

简介

欢迎来到 WebGL 系列教程的第 28 课,这次我们将踏入多贴图绘制的奇妙领域。多贴图是一种强大的技术,可以极大增强场景的真实感和细节。准备好展开一场视觉盛宴,让你的 WebGL 技能再攀高峰!

什么是多贴图?

多贴图允许我们在 3D 模型表面使用多张纹理,从而创建更复杂、更逼真的效果。例如,我们可以使用一张漫反射纹理来控制物体的颜色,一张法线纹理来模拟表面凹凸,一张高光纹理来赋予光泽,依此类推。

多种纹理类型

在多贴图中,我们可以使用以下几种类型的纹理:

  • 漫反射纹理: 控制物体的颜色和图案。
  • 法线纹理: 提供表面凹凸的错觉,增强深度和细节。
  • 高光纹理: 控制物体的反射特性,模拟高光和阴影。
  • 光照贴图: 一种烘焙纹理,包含特定光照条件下物体的照明信息。
  • 环境光遮挡纹理: 模拟物体周围环境对光照的影响,产生更加逼真的阴影。

设置多贴图

在 WebGL 中设置多贴图包括以下步骤:

  1. 创建纹理对象: 使用 WebGL 的 createTexture() 函数为每种纹理类型创建一个纹理对象。
  2. 配置纹理参数: 使用 texParameteri() 函数配置纹理参数,例如过滤模式和封装模式。
  3. 上传纹理数据: 使用 texImage2D() 函数上传纹理数据到 GPU。
  4. 在着色器中采样纹理: 在片段着色器中使用 texture2D() 函数从纹理采样值,并将它们应用到表面。

多贴图示例

为了演示多贴图的强大功能,让我们构建一个简单的 WebGL 场景。我们将创建一个带有多张纹理的 3D 球体:

  • 漫反射纹理:地球表面的颜色和图案
  • 法线纹理:球体的表面细节和地形
  • 高光纹理:球体的高光和反射
  • 环境光遮挡纹理:球体的环境阴影

代码示例

以下是一段 WebGL 代码示例,展示了如何设置和使用多贴图:

// ... 省略其他代码 ...

// 创建纹理对象
const diffuseTexture = gl.createTexture();
const normalTexture = gl.createTexture();
const specularTexture = gl.createTexture();
const aoTexture = gl.createTexture();

// 配置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

// 上传纹理数据
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, diffuseData);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, normalData);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, specularData);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, aoData);

// 在着色器中采样纹理
const fragmentShaderCode = `
    #version 300 es
    precision mediump float;

    in vec3 v_normal;
    in vec2 v_texcoord;

    uniform sampler2D diffuseTexture;
    uniform sampler2D normalTexture;
    uniform sampler2D specularTexture;
    uniform sampler2D aoTexture;

    out vec4 fragColor;

    void main() {
        // 获取纹理坐标
        vec2 texcoord = v_texcoord;

        // 采样漫反射纹理
        vec4 diffuseColor = texture2D(diffuseTexture, texcoord);

        // 采样法线纹理
        vec3 normal = normalize(texture2D(normalTexture, texcoord).rgb * 2.0 - 1.0);

        // 采样高光纹理
        vec4 specularColor = texture2D(specularTexture, texcoord);

        // 采样环境光遮挡纹理
        float ao = texture2D(aoTexture, texcoord).r;

        // 计算光照
        vec3 lightDirection = normalize(vec3(0.5, 0.5, 1));
        float diffuse = max(dot(normal, lightDirection), 0.0);
        float specular = pow(max(dot(reflect(-lightDirection, normal), vec3(0, 0, 1)), 0.0), 32.0);

        // 组合所有纹理和光照计算
        fragColor = vec4(diffuseColor.rgb * diffuse + specularColor.rgb * specular * ao, diffuseColor.a);
    }
`;

**体验多贴图的魅力** 

WebGL 中的多贴图技术为创建令人惊叹的 3D 场景打开了大门。通过利用多张纹理,我们可以赋予物体前所未有的真实感和细节。从逼真的自然环境到复杂的角色模型,多贴图都是 WebGL 开发者不可或缺的工具。

**结论** 

感谢收看本期教程,我们探讨了 WebGL 中多贴图的强大功能。在接下来的课程中,我们将深入研究更高级的多贴图技术,如纹理映射和法线贴图。做好准备,因为 WebGL 之旅才刚刚开始!