CesiumJS源码杂谈之从光到 Uniform

yizhihongxing

下面是关于“CesiumJS源码杂谈之从光到Uniform”的完整攻略的详细讲解。

前置知识

在讲解这个话题之前,需要对一些基本的知识有一定的了解。包括:WebGL的基础知识、Shader的基础知识、CesiumJS的基础知识等。

从光开始

在WebGL的渲染过程中,光是非常重要的一个环节。CesiumJS中的光源主要有以下几种:

  • sun:太阳光。
  • moon:月球光。
  • pointLight:点光源光。
  • spotLight:聚光灯光。

在CesiumJS中,光源的渲染是通过Shader来实现的。常见的光照Shader有PBRBlinnPhong两种。

其中,BlinnPhong是比较常用的光照模型。它可以通过Shader中的Uniform等变量来获取光源信息,并进行计算,最终得出物体在光照下的表现。

Uniform

在Shader中,Uniform是一类可以被纹理以外的外部数据修改的变量。

在CesiumJS源码中,Uniform主要是通过ShaderProgram来实现的。其中,ShaderProgram是一个Shader程序的封装,用于管理Shader中的变量。

ShaderProgram中,Uniform主要包括两种类型的变量:

  • 向量类型:包括vec2、vec3、vec4等等。
  • 矩阵类型:包括mat2、mat3、mat4等等。

在使用Uniform之前,首先需要在Shader中使用uniform关键字来声明和定义这些变量。然后,在JavaScript代码中获取这些Uniform变量的位置,并通过gl.uniformXXX系列函数来设置Uniform变量的值。

下面是一个使用Uniform的示例:

uniform mat4 u_ModelViewProjectionMatrix;

void main()
{
    gl_Position = u_ModelViewProjectionMatrix * vec4(a_Position, 1.0);
}

在JavaScript代码中,获取Uniform变量的位置,并设置其值:

var modelViewProjectionMatrixLoc = gl.getUniformLocation(shaderProgram, "u_ModelViewProjectionMatrix");
gl.uniformMatrix4fv(modelViewProjectionMatrixLoc, false, modelViewProjectionMatrix);

示例说明

下面,通过两条示例来具体说明“从光到Uniform”的攻略。

示例1:添加太阳光源

在CesiumJS中,要添加太阳光源,需要在对应的UIView中创建Sun对象,并设置其属性。

在Shader中,需要通过Uniform来获取太阳光源的信息。

具体步骤如下:

  1. 在UIView中创建Sun对象,并设置其颜色、方向等属性。
var sun = new Cesium.Sun();
sun.color = new Cesium.Color(1.0, 1.0, 1.0);
sun.direction = Cesium.Cartesian3.normalize(new Cesium.Cartesian3(1.0, 1.0, 1.0));
  1. 在Shader中声明和定义uniform变量,用于接收太阳光的方向和颜色信息。
uniform vec3 u_SunDirection;
uniform vec3 u_SunColor;
  1. 在Shader中计算太阳光的光照强度,并将其作为输出。
vec3 sunLightColor = u_SunColor * max(dot(-v_Normal, u_SunDirection), 0.0);
  1. 在JavaScript代码中获取uniform变量的位置,并设置其值。
var sunDirectionLoc = gl.getUniformLocation(shaderProgram, "u_SunDirection");
var sunColorLoc = gl.getUniformLocation(shaderProgram, "u_SunColor");

gl.uniform3fv(sunDirectionLoc, sun.direction);
gl.uniform3fv(sunColorLoc, sun.color.toRgb());

示例2:实现法线贴图

在3D场景中,法线贴图(Normal Map)可以用来增强物体表面的细节感。

在CesiumJS中,要实现法线贴图,需要在ShaderProgram中添加Texture类型的Uniform,并且在Shader中计算出法向量和切向量,最终计算出使用法线贴图之后的颜色信息。

具体步骤如下:

  1. 在ShaderProgram中添加Texture类型的Uniform。
var program = new Cesium.ShaderProgram({
    vertexShaderSource : vertexShaderSource,
    fragmentShaderSource : fragmentShaderSource,
    uniformMap : {
        u_ColorMap: colorMap,
        u_NormalMap: normalMap,
        u_WorldMatrix: function() {
            return Cesium.Matrix4.IDENTITY;
        }
    }
});
  1. 在Shader中声明和定义uniform变量,用于接收ColorMap和NormalMap的信息。
uniform sampler2D u_ColorMap;
uniform sampler2D u_NormalMap;
  1. 在Shader中计算出使用法线贴图之后的法向量和切向量,并计算出最终的颜色信息。
// 计算使用法线贴图之后的法向量和切向量
vec3 normal = texture2D(u_NormalMap, v_TexCoord).rgb * 2.0 - 1.0;
mat3 TBN = mat3(v_Tangent, v_Bitangent, v_Normal);
vec3 normalTangent = normalize(TBN * normal);

// 计算光源对物体的影响
vec3 ambient = u_AmbientColor.rgb * u_AmbientIntensity;
vec3 diffuse = texture2D(u_ColorMap, v_TexCoord).rgb * max(dot(normalTangent, u_LightDirection), 0.0);

// 计算最终的颜色信息
gl_FragColor = vec4(ambient + diffuse, 1.0);
  1. 在JavaScript代码中加载ColorMap和NormalMap,并设置其值。
var colorMap = new Cesium.Texture({
    context: gl,
    source: "/textures/colorMap.png",
    flipY: false
});

var normalMap = new Cesium.Texture({
    context: gl,
    source: "/textures/normalMap.png",
    flipY: false
});

program.uniforms.u_ColorMap = colorMap;
program.uniforms.u_NormalMap = normalMap;

以上就是从光到Uniform的攻略及两个示例的具体实现。希望可以帮助你更好地了解CesiumJS中的Shader和Uniform的使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:CesiumJS源码杂谈之从光到 Uniform - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript中三个等号和两个等号你了解多少

    JavaScript中的等于操作符有两种,分别是双等于”==”和三等于”===”。这两个操作符的区别在于判断相等性时类型的转换策略不同。下面进一步说明两种操作符的区别和应用场景。 双等于”==” 当使用双等于”==”进行相等比较时,如果两边的值类型不同,JavaScript会自动将值进行类型转换再进行比较判断。转换规则如下: 如果其中一边是布尔值,则将其转换…

    JavaScript 2023年5月28日
    00
  • 微信小程序tabBar模板用法实例分析【附demo源码下载】

    微信小程序tabBar模板用法实例分析 简介 本文将介绍微信小程序的tabBar模板用法,并提供一个demo供下载。 tabBar模板 tabBar模板可以让开发者更方便地实现小程序的底部导航栏功能。tabBar可以包含2-5个按钮,每个按钮对应一个不同的页面。当用户点击按钮时,小程序会自动跳转到相应的页面。 tabBar模板的常用属性有以下几个: back…

    JavaScript 2023年6月11日
    00
  • 探究JavaScript中的五种事件处理程序方式

    让我们来探究JavaScript中的五种事件处理程序方式: 事件处理程序方式 在JavaScript中,有五种主要的事件处理程序方式: HTML事件处理程序 DOM0级事件处理程序 DOM2级事件处理程序 DOM3级事件处理程序 EventUtil事件处理程序 下面我们将会详细讲解这五种事件处理程序方式的用法和区别。 1. HTML事件处理程序 HTML事件…

    JavaScript 2023年5月18日
    00
  • javaScript 页面自动加载事件详解

    JavaScript 页面自动加载事件详解 JavaScript 以其强大的交互性和动态性而成为 Web 前端开发中必不可少的一部分。在 Web 页面加载时,若有需要在页面中自动加载或动态生成内容的需求,可通过使用 JavaScript 页面自动加载事件来实现。 常用的 JavaScript 页面自动加载事件有两种:DOMContentLoaded 和 wi…

    JavaScript 2023年5月27日
    00
  • 解决javascript 全局变量失效的问题

    解决 JavaScript 全局变量失效的问题,一般是指变量定义了,但是在某个函数或代码块中却无法访问到该变量。这个问题的根本原因是 JavaScript 的作用域机制,可以通过以下两种方法解决: 方法一:使用全局对象Window 在 JavaScript 中,全局变量是绑定在全局对象 window 上的,所以在定义变量时,可以通过 window 对象来定义…

    JavaScript 2023年6月10日
    00
  • JavaScript实现页面跳转的八种方式

    下面是关于“JavaScript实现页面跳转的八种方式”的详细讲解: 1. 使用Location对象 使用Location对象的assign方法、replace方法或href属性来实现页面的跳转。其中,assign方法会在浏览器的历史记录中留下当前页面记录,而replace方法则不会。href属性用于读取或设置文档的地址。 // 使用assign方法来实现页…

    JavaScript 2023年6月11日
    00
  • 将HTML格式的String转化为HTMLElement的实现方法

    将HTML格式的String转化为HTMLElement的实现方法,主要是通过DOM操作来实现的。下面是具体的步骤: 创建一个元素 我们可以使用 createElement 方法创建任何类型的元素。下面是一个示例,我们将使用 createElement 方法创建一个 div 元素: const div = document.createElement(‘di…

    JavaScript 2023年6月10日
    00
  • 如何在TypeScript中正确的遍历一个对象

    要在 TypeScript 中正确地遍历一个对象,需要使用 for…in 循环。for…in 循环允许我们遍历对象的所有属性,而不需要手动指定每个属性的名称。 下面是遍历对象的完整步骤: 1. 创建一个对象 首先,我们需要创建一个对象。例如,我们创建以下对象: const myObject = { name: "John", ag…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部