three.js案例解析之天空

编程入门 行业动态 更新时间:2024-10-15 12:33:57

three.js<a href=https://www.elefans.com/category/jswz/34/1770649.html style=案例解析之天空"/>

three.js案例解析之天空

场景初始化

 camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 100, 2000000 );camera.position.set( 0, 100, 2000 );scene = new THREE.Scene();renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.toneMappingExposure = 0.5; 

上述代码已经是老生常谈了。

这里再谈一次。

一般,我们有正交相机和透视相机,正交相机可以说是透视相机的一种特殊情况。

其视锥体为一个长方体或者正方体。其效果是无论远近,物体大小是一样的。

我们看一看透视矩阵:

makePerspective( left, right, top, bottom, near, far ) {const te = this.elements;const x = 2 * near / ( right - left );const y = 2 * near / ( top - bottom );const a = ( right + left ) / ( right - left );const b = ( top + bottom ) / ( top - bottom );const c = - ( far + near ) / ( far - near );const d = - 2 * far * near / ( far - near );te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;return this;} 

首先,拿到矩阵元素,用程序的话说,就是一个二维数组。

用拿到的这个矩阵和三维向量坐标点相乘得到其在裁剪坐标系中的坐标点,这个坐标点绘制在裁剪空间中的效果就是近大远小。

下面是一个标准矩阵。

var identityMatrix = [1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1
]; 

一般第四行代表平移:

var translationMatrix = [1,    0,    0,   0,0,    1,    0,   0,0,    0,    1,   0,x,    y,    z,   1
]; 

那么,我们知道,矩阵上不同的元素代表不同的点的状态。我们只需要改变对应元素的值,就能改变点在三维空间中的一个状态。

具体是怎样一个算法,那就是一个复杂的问题,笔者一直觉得是一个复杂的问题,需要学习整本3d数学。

不过,不会3d数学并不会影响你做出一个好游戏。这些3d数学已经被现有的库实现了。

天空

 sky = new Sky();sky.scale.setScalar( 450000 );scene.add( sky );sun = new THREE.Vector3();const effectController = {turbidity: 10,rayleigh: 3,mieCoefficient: 0.005,mieDirectionalG: 0.7,elevation: 2,azimuth: 180,exposure: renderer.toneMappingExposure}; 

核心来了,这个案例将天空抽象为一个对象。

其属性如下:

  • turbidity,浑浊度,代表云层等对光纤的影响。
  • rayleigh,瑞利散射,由于大气密度随高度急剧降低,大气分子的散射效应相应减弱,天空的颜色也随高度由蔚蓝色变为青色

还有许多其他属性,本文只打算剖析上述两个光学现象。

ShaderMaterial

class Sky extends Mesh {constructor() {const shader = Sky.SkyShader;const material = new ShaderMaterial( {name: 'SkyShader',fragmentShader: shader.fragmentShader,vertexShader: shader.vertexShader,uniforms: UniformsUtils.clone( shader.uniforms ),side: BackSide,depthWrite: false} );super( new BoxGeometry( 1, 1, 1 ), material );}} 

天空也是三维场景的一个Object3D的概念。只不过其材质属于天空的效果。

天空和大海一样,都使用了ShaderMaterial。

自定义着色器材质。

 uniforms: {'turbidity': { value: 2 },'rayleigh': { value: 1 },}, 

天空的特性在一个时间段来说,通常都是稳定的,因此使用了uniforms这个修饰符。

uniform的英文意思为一致的; 统一的; 一律的。

着色器代码

 uniform vec3 sunPosition; // 一个向量uniform float rayleigh; // 瑞利散射 值为1uniform float turbidity; // 浑浊度,值为2 
vBetaM = totalMie( turbidity ) * mieCoefficient; 

所谓散射效果,其实影响的是像素颜色,也就是对片元着色器的影响。

 float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );vBetaR = totalRayleigh * rayleighCoefficient; 

这是一个复杂的光学算法。

更多推荐

three.js案例解析之天空

本文发布于:2024-02-19 13:13:38,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1764259.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:案例   天空   js

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!