1. 程式人生 > >使用threejs實現地球輝光和大氣層效果

使用threejs實現地球輝光和大氣層效果

使用threejs實現地球輝光和大氣層效果

實現原理就是使用three.js的ShaderMaterial材質。
我們把輝光分為幾個步驟來實現:

  1. 建立兩個球體,一個作為原始物體,一個略大一些作為它的輝光
  2. 作為輝光的球體從內到外片元透明度逐漸減小(線性減小或是指數減小都可以)
  3. 將覆蓋原始物體的部分丟棄掉

主要程式碼如下:

var vertexShader = [
    'varying vec3	vVertexWorldPosition;',
    'varying vec3	vVertexNormal;',
    'varying vec4	vFragColor;'
, 'void main(){', ' vVertexNormal = normalize(normalMatrix * normal);',//將法線轉換到檢視座標系中 ' vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;',//將頂點轉換到世界座標系中 ' // set gl_Position', ' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);', '}' ].join('\n')
; //大氣層效果 THREE.AeroSphere = { uniforms: { coeficient: { type: "f", value: 1.0 }, power: { type: "f", value: 2 }, glowColor: { type: "c", value: new THREE.Color(0xffff00) } }, vertexShader:
vertexShader, fragmentShader: [ 'uniform vec3 glowColor;', 'uniform float coeficient;', 'uniform float power;', 'varying vec3 vVertexNormal;', 'varying vec3 vVertexWorldPosition;', 'varying vec4 vFragColor;', 'void main(){', ' vec3 worldCameraToVertex= vVertexWorldPosition - cameraPosition;', //世界座標系中從相機位置到頂點位置的距離 ' vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;',//檢視座標系中從相機位置到頂點位置的距離 ' viewCameraToVertex = normalize(viewCameraToVertex);',//規一化 ' float intensity = pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);', ' gl_FragColor = vec4(glowColor, intensity);', '}'//vVertexNormal檢視座標系中點的法向量 //viewCameraToVertex檢視座標系中點到攝像機的距離向量 //dot點乘得到它們的夾角的cos值 //從中心向外面角度越來越小(從鈍角到銳角)從cos函式也可以知道這個值由負變正,不透明度最終從低到高 ].join('\n') //輝光效果Grow THREE.GlowSphere = { uniforms: { coeficient: { type: "f", value: 0.0 }, power: { type: "f", value: 2 }, glowColor: { type: "c", value: new THREE.Color(0xff22ff) } }, vertexShader: vertexShader, fragmentShader: [ 'uniform vec3 glowColor;', 'uniform float coeficient;', 'uniform float power;', 'varying vec3 vVertexNormal;', 'varying vec3 vVertexWorldPosition;', 'varying vec4 vFragColor;', 'void main(){', ' vec3 worldVertexToCamera= cameraPosition - vVertexWorldPosition;', //世界座標系中頂點位置到相機位置到的距離 ' vec3 viewCameraToVertex = (viewMatrix * vec4(worldVertexToCamera, 0.0)).xyz;',//檢視座標系中從相機位置到頂點位置的距離 ' viewCameraToVertex = normalize(viewCameraToVertex);',//規一化 ' float intensity = coeficient + dot(vVertexNormal, viewCameraToVertex);', ' if(intensity > 0.65){ intensity = 0.0;}', ' gl_FragColor = vec4(glowColor, intensity);', '}'//vVertexNormal檢視座標系中點的法向量 //viewCameraToVertex檢視座標系中點到攝像機的距離向量 //dot點乘得到它們的夾角的cos值 //從中心向外面角度越來越大(從銳角到鈍角)從cos函式也可以知道這個值由負變正,不透明度最終從高到低 ].join('\n') } //球體 輝光 大氣層 function shad() { var material1 = new THREE.ShaderMaterial({ uniforms: THREE.AeroSphere.uniforms, vertexShader: THREE.AeroSphere.vertexShader, fragmentShader: THREE.AeroSphere.fragmentShader, blending: THREE.NormalBlending, transparent: true, depthWrite:false }); var material2 = new THREE.ShaderMaterial({ uniforms: THREE.GlowSphere.uniforms, vertexShader: THREE.GlowSphere.vertexShader, fragmentShader: THREE.GlowSphere.fragmentShader, blending: THREE.NormalBlending, transparent: true }); var sphere = new THREE.SphereBufferGeometry(16, 32, 32); var mesh = new THREE.Mesh(sphere, material1); scene.add(mesh); var sphere2 = new THREE.SphereBufferGeometry(10, 32, 32); var mesh2 = new THREE.Mesh(sphere2, material2); //mesh2.position.x = 15; scene.add(mesh2); }

效果如下圖所示:
輝光和大氣層

輝光和大氣層

程式碼參考:https://blog.csdn.net/srk19960903/article/details/78734238