基础环境搭建:
添加圆环网格模型:
Shader材质处理:
- 载入texture
const texture = new THREE.TextureLoader()
const texture1 = texture.load('textures/lava/cloud.png')
const texture2 = texture.load('textures/lava/lavatile.jpg')
texture1.wrapS = texture1.wrapT = THREE.RepeatWrapping
texture2.wrapS = texture2.wrapT = THREE.RepeatWrapping
uniforms = {
"texture1": { value: texture1 },
"texture2": { value: texture2 },
}
- Shader-texture
vertexShader:
varying vec2 vUv;
void main(){
vUv=uv;
gl_Position=vec4(position,1.0)
}
fragmentShader:
varying vec2 vUv;
uniform sampler2D texture2;
void main(){
vec4 color=texture2D(texture2,vUv);
gl_FragColor=color;
}
- Shader-time
fragmentShader:
'time': { value: 1.0 },
...
uniform float time;
void main(){
vec2 T1=vUv+vec2(1.5,-1.5)*time*0.02;
vec2 T2=vUv+vec2(-0.5,2.0)*time*0.01;
vec4 color=texture2D(texture2,T2*2.0);
gl_FragColor=color;
}
...
uniforms['time'].value += 0.1
- Shader-noise
genType clamp (genType x, float minVal, float maxVal)
clamp翻译为夹具,就叫夹具函数吧,这个函数是什么意思呢?看看解释的意思是:获取x和minVal之间较大的那个值,然后再拿较大的那个值和最后那个最大的值进行比较然后获取较小的那个。clamp实际上是获得三个参数中大小处在中间的那个值。函数有个说明:如果minVal > minMax的话,函数返回的结果是未定的。也就是说x的值大小没有限制,但是minval的值必须比maxVal小。
uniform sampler2D texture1;
...
vec2 T1=vUv+vec2(1.5,-1.5)*time*0.02;
vec2 T2=vUv+vec2(-0.5,2.0)*time*0.01;
vec4 noise=texture2D(texture1,vUv);
T1.x+=noise.x*2.0;
T1.y+=noise.y*2.0;
T2.x+=noise.y*0.2;
T2.y+=noise.z*0.2;
vec4 color=texture2D(texture2,T2*2.0);
float p=texture2D(texture1,T1*2.0).a;
vec4 temp=color*(vec4(p,p,p,p)*2.0)+(color*color-0.1);
if(temp.r>1.0){
temp.bg+=clamp(temp.r-2.0,0.0,100.0);
}
if(temp.g>1.0){
temp.rb+=temp.g-1.0;
}
if(temp.b>1.0){
temp.rg+=temp.b-1.0;
}
gl_FragColor=temp;
- Shader-fog
'fogDensity': { value: 0.45 },
'fogColor': { value: new THREE.Vector3(0, 0, 0) }
...
uniform float fogDensity;
uniform vec3 fogColor;
...
float depth=gl_FragCoord.z/gl_FragCoord.w;
const float LOG2=1.442695;
float fogFactor=exp2(-fogDensity*fogDensity*depth*depth*LOG2);
fogFactor=1.0-clamp(fogFactor,0.0,1.0);
gl_FragColor=mix(gl_FragColor,vec4(fogColor,gl_FragColor.w),fogFactor);
- Shader-uvScale
vertexShader:
'uvScale': { value: new THREE.Vector2(3.0, 1.0) },
...
uniform vec2 uvScale;
void main(){
vUv=uv*uvScale;
vec4 mvPosition=modelViewMatrix*vec4(position,1.0);
gl_Position=projectionMatrix*mvPosition;
}
视觉效果变暗且自适应浏览器窗口大小:
后期处理:
效果合成器(EffectComposer)
用于在three.js中实现后期处理效果,该类管理了产生最终视觉效果的后期处理过程链。后期处理过程根据它们添加/插入的顺序来执行,最后一个过程会被自动渲染到屏幕上。
EffectComposer( renderer : WebGLRenderer, renderTarget : WebGLRenderTarget )
- 导入
源码:
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { FilmPass } from 'three/examples/jsm/postprocessing/FilmPass'
import { BloomPass } from 'three/examples/jsm/postprocessing/BloomPass'
- 函数调用
function postProcessing() {
composer = new EffectComposer(renderer)
const renderPass = new RenderPass(scene, camera)
const bloomPass = new BloomPass(1.25)
const filmPass = new FilmPass(0.35, 0.95, 2048, false)
composer.addPass(renderPass)
composer.addPass(bloomPass)
composer.addPass(filmPass)
}
- 渲染器设置
.autoClear : Boolean
定义渲染器是否在渲染每一帧之前自动清除其输出。
renderer.autoClear = false
...
// renderer.render(scene, camera)
renderer.clear()
composer.render(0.01)
效果合成器下的渲染器接手原来的渲染器,修改下bloomPass,可以看到:
- 岩浆圈旋转设置
const delta = 5 * clock.getDelta()
mesh.rotation.x += 0.05 * delta
mesh.rotation.y += 0.0125 * delta
uniforms['time'].value += 0.2 * delta
- 完善判断
if (composer !== undefined) {
composer.setSize(window.innerWidth, window.innerHeight)
}
...
if (composer !== undefined) {
renderer.clear()
composer.render(0.01)
}
else {
renderer.render(scene, camera)
}