当前位置: 首页 > news >正文

基于Babylon.js的Shader入门二(让Shader使用一个纹理)

一、顶点着色器

文件名为"BaseTexture.vertex.fx"的内容:

// 顶点着色器
attribute vec3 position;
attribute vec2 uv; // 添加纹理坐标属性

uniform mat4 worldViewProjection;

varying vec2 vUV; // 用于将纹理坐标传递给片段着色器

void main() {
    gl_Position = worldViewProjection * vec4(position, 1.0);
    vUV = uv; // 传递纹理坐标
}

        若要让shader使用一个纹理,那么需要在顶点着色器阶段获取模型的uv,并且将该uv传递给片元着色器,顶点着色器通过attribute类型的vec2变量uv来分别获取每个顶底的uv,同时将这个uv传递给varying类型的的vec2变量vUV,下面我们再啰嗦一下attribute变量、uniform变量和varying变量之间的区别。

attribute变量、uniform变量和varying变量之间的区别

1. attribute 变量

attribute 变量是顶点着色器的输入变量,用于从应用程序(如 JavaScript 或 Babylon.js)向顶点着色器传递数据。每个顶点可以有不同的 attribute 值。

特点:
  • 作用域:只能在顶点着色器中使用。

  • 数据来源:由应用程序通过缓冲区(如顶点缓冲区)提供。

  • 典型用途:传递顶点的位置(position)、法线(normal)、纹理坐标(uv)等逐顶点数据。

示例:
attribute vec3 position; // 顶点位置
attribute vec2 uv;       // 纹理坐标

         在 Babylon.js 中,attribute 变量通常通过 Mesh 的几何数据(如顶点位置、纹理坐标)自动传递。


2. varying 变量

varying 变量用于在顶点着色器片段着色器之间传递数据。顶点着色器计算每个顶点的值,然后这些值会在图元(如三角形)的片段之间进行插值,最终传递给片段着色器。

特点:
  • 作用域:可以在顶点着色器和片段着色器中使用。

  • 数据来源:由顶点着色器赋值,经过插值后传递给片段着色器。

  • 典型用途:传递纹理坐标(uv)、颜色、法线等需要在片段之间插值的数据。

示例:
// 顶点着色器
varying vec2 vUV; // 声明 varying 变量
void main() {
    vUV = uv; // 从 attribute 变量赋值
}

// 片段着色器
varying vec2 vUV; // 声明相同的 varying 变量
void main() {
    gl_FragColor = texture2D(textureSampler, vUV); // 使用插值后的纹理坐标
}

插值过程

  • 顶点着色器为每个顶点计算 vUV

  • 在光栅化阶段,vUV 会在图元的片段之间进行插值。

  • 片段着色器接收插值后的 vUV 值。


3. uniform 变量

uniform 变量是全局变量,用于从应用程序向 Shader 传递常量数据。这些数据在绘制调用中不会改变(即对于所有顶点和片段都是相同的)。

特点:
  • 作用域:可以在顶点着色器和片段着色器中使用。

  • 数据来源:由应用程序通过 Shader 的 uniform 接口设置。

  • 典型用途:传递变换矩阵(如 worldViewProjection)、颜色(如 diffuseColor)、纹理采样器等。

示例:
uniform mat4 worldViewProjection; // 变换矩阵
uniform vec3 diffuseColor;        // 颜色
uniform sampler2D textureSampler; // 纹理采样器

在 Babylon.js 中,uniform 变量可以通过 ShaderMaterial 的 setXXX 方法设置,例如:

shaderMaterial.setMatrix("worldViewProjection", matrix);
shaderMaterial.setColor3("diffuseColor", color);
shaderMaterial.setTexture("textureSampler", texture);

4. 三者的区别总结

特性attributevaryinguniform
作用域顶点着色器顶点着色器和片段着色器顶点着色器和片段着色器
数据来源应用程序(顶点缓冲区)顶点着色器赋值并插值应用程序(ShaderMaterial)
是否可变每个顶点不同在图元中插值绘制调用中不变
典型用途顶点位置、法线、纹理坐标插值后的纹理坐标、颜色变换矩阵、颜色、纹理采样器

二、片元着色器

文件名为"BaseTexture.fragment.fx"

// 片段着色器
precision highp float;

uniform vec3 diffuseColor;
uniform sampler2D textureSampler; // 添加纹理采样器

varying vec2 vUV; // 接收从顶点着色器传递过来的纹理坐标

void main() {
    vec4 textureColor = texture2D(textureSampler, vUV); // 采样贴图颜色
    gl_FragColor = textureColor * vec4(diffuseColor, 1.0); // 将贴图颜色与原来的颜色相乘
}

再说varying变量

         这里又出现了一个varying vec2 vUV变量,实际上,顶点着色器中的 vUV 和片元着色器中的 vUV 是同一个变量在不同着色器阶段的引用。它们通过 varying 关键字连接起来,用于在顶点着色器和片元着色器之间传递数据。

流程说明:

  1. 顶点着色器

    • 每个顶点的 uv 属性被赋值给 vUV

    • 例如,一个三角形的三个顶点的 vUV 值分别为 (0, 0)(1, 0) 和 (0.5, 1)

  2. 光栅化阶段

    • 在光栅化过程中,vUV 的值会在三角形的每个片段之间进行插值。

    • 例如,三角形内部的某个片段的 vUV 可能是 (0.3, 0.4)

  3. 片元着色器

    • 每个片段的 vUV 值是通过插值计算得到的。

    • 使用 texture2D 函数根据 vUV 采样纹理颜色。


varying 变量的特点

  • 同名匹配:顶点着色器和片元着色器中的 varying 变量必须同名(如 vUV),否则无法正确传递数据。

  • 插值行为varying 变量的值会在图元的顶点之间进行插值。例如,颜色、纹理坐标等需要插值的属性通常使用 varying 传递。

  • 只读性:在片元着色器中,varying 变量是只读的,不能修改它的值。

关于sampler2D纹理采样器

        在 Babylon.js 中,sampler2D 类型的变量用于表示纹理采样器。Babylon.js 通过 ShaderMaterial 或 Effect 将纹理传递给 Shader,并在 Shader 中使用 texture2D 函数对纹理进行采样。以下是 Babylon.js 向 Shader 传送纹理的原理和具体使用方法。


1. Shader 中的 sampler2D 变量

在 GLSL(WebGL Shader 语言)中,sampler2D 是一种特殊的变量类型,用于表示 2D 纹理。通常,sampler2D 变量会与 texture2D 函数一起使用,以从纹理中采样颜色。

2. Babylon.js 向 Shader 传递纹理的原理

Babylon.js 通过以下步骤将纹理传递给 Shader:

  1. 声明 sampler2D 变量
    在 Shader 中声明一个 uniform sampler2D 变量,例如 textureSampler

  2. 绑定纹理到纹理单元
    Babylon.js 会将纹理绑定到一个纹理单元(Texture Unit),例如 GL_TEXTURE0GL_TEXTURE1 等。

  3. 设置 sampler2D 的纹理单元索引
    Babylon.js 会将纹理单元的索引(如 01 等)传递给 Shader 中的 sampler2D 变量。

  4. 在 Shader 中使用纹理
    在 Shader 中,使用 texture2D 函数对纹理进行采样。


3. Babylon.js 传递纹理的内部原理

(1) 纹理单元(Texture Unit)

WebGL 支持多个纹理单元(通常至少 8 个),每个纹理单元可以绑定一个纹理。Babylon.js 会自动管理纹理单元的分配。

(2) 绑定纹理

当调用 setTexture 时,Babylon.js 会执行以下操作:

  1. 将纹理绑定到一个可用的纹理单元(如 GL_TEXTURE0)。

  2. 将纹理单元的索引传递给 Shader 中的 sampler2D 变量。

(3) Shader 中的纹理采样

在 Shader 中,texture2D 函数会根据 sampler2D 变量绑定的纹理单元索引,从对应的纹理中采样颜色。

三、Babylon.js使用示例

// 创建 ShaderMaterial
const shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, 
    "./src/Shader/BaseTexture",
     {
        attributes: ["position", "uv"], // 确保包含 uv 属性
        uniforms: ["worldViewProjection", "diffuseColor", "textureSampler"], // 确保包含纹理采样器
    });

// 设置颜色
shaderMaterial.setColor3("diffuseColor", new BABYLON.Color3(1, 0, 0)); // 例如红色

// 加载纹理
const texture = new BABYLON.Texture("path/to/texture.png", scene);
shaderMaterial.setTexture("textureSampler", texture); // 设置纹理

// 应用材质到网格
const mesh = BABYLON.MeshBuilder.CreateBox("box", {}, scene);
mesh.material = shaderMaterial;

相关文章:

  • Mybatis批量操作
  • 前端知识点---原型-原型链(javascript)
  • 【鸿蒙开发】Hi3861学习笔记-Visual Studio Code安装(New)
  • matlab 模糊pid实现温度控制
  • Java 常用工具类大全:高频工具类及代码示例(后续继续补充)
  • 大模型最新面试题系列:微调篇之微调基础知识
  • 使用 Elasticsearch 构建多模式 RAG 系统:哥谭市的故事
  • 【SpringMVC】常用注解:@MatrixVariable
  • C 语言实战:打造字符串加密器及实验要点解析
  • leetcode 3305. 元音辅音字符串计数 I 中等
  • Ubuntu从源代码编译安装QT
  • Git 的基本概念和使用方式
  • 网络安全就业形势
  • AGI大模型(6):提示词模型进阶
  • 【软考-架构】11.3、设计模式-新
  • C#中SerialPort 的使用
  • LabVIEW VI Scripting随机数波形图自动生成
  • MySQL的一些八股文
  • 上位机数据可视化:Qt表格美化
  • VSTO(C#)Excel开发10:启动和卸载顺序 事件处理 监视变化
  • 昆明警方重拳打击经济领域违法犯罪:去年抓获905名嫌犯
  • 香港根据《维护国家安全条例》订立附属法例
  • 有关部门负责人就《新时代的中国国家安全》白皮书答记者问
  • 媒体和打拐志愿者暗访长沙一地下代孕实验室,警方已控制涉案人员
  • 中国目的地·入境游简报006|外国网红游中国启示录
  • 《瞭望》周刊社原总编辑、党委书记姬斌逝世,享年67岁