원하는 결과는 다음과 같습니다.
장면에 추가된 모델은 3개입니다. 지구 본체, 지구 주변의 푸른 빛(Blooming Light), 지구 주위의 하얀 작은 무수한 별들.
먼저 지구 본체에 대한 코드입니다.
const sphere = new THREE.Mesh( new THREE.SphereGeometry(5, 50, 50), new THREE.ShaderMaterial({ uniforms: { globeTexture: { value: new THREE.TextureLoader().load("data/earth.jpg") } }, vertexShader: ` varying vec2 vertexUV; varying vec3 vertexNormal; void main() { vertexUV = uv; vertexNormal = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` uniform sampler2D globeTexture; varying vec2 vertexUV; void main() { vec4 color = texture2D(globeTexture, vertexUV); gl_FragColor = vec4(color.xyz, 1.); } ` }) );
결과는 다음과 같습니다.
지구 가장자리가 어두워서 가장자리를 밝게 만들기 위해 위의 코드에서 fragmentShader 코드를 다음처럼 변경합니다.
fragmentShader: ` uniform sampler2D globeTexture; varying vec2 vertexUV; varying vec3 vertexNormal; void main() { float intensity = 1.05 - dot(vertexNormal, vec3(0.,0.,1.)); vec3 atmosphere = vec3(0.3, 0.6, 1.0) * pow(intensity, 1.5); vec4 color = texture2D(globeTexture, vertexUV); gl_FragColor = vec4(atmosphere + color.xyz, 1.); } `,
결과는 다음과 같습니다.
지구 주변의 푸른 빛(Blooming Light)에 대한 코드입니다.
const atmosphere = new THREE.Mesh( new THREE.SphereGeometry(5, 50, 50), new THREE.ShaderMaterial({ vertexShader: ` varying vec3 vertexNormal; void main() { vertexNormal = normalize(normalMatrix * normal); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` varying vec3 vertexNormal; void main() { float intensity = pow(0.76 - dot(vertexNormal, vec3(0,0,1.)), 2.0); gl_FragColor = vec4(0.3, 0.6, 1.0, 1) * intensity; } `, transparent: true, blending: THREE.AdditiveBlending, side: THREE.BackSide }) ); atmosphere.scale.set(1.2, 1.2, 1.2);
결과는 다음과 같습니다.
이제 지구 주위의 하얀 작은 무수한 별들에 대한 코드입니다.
const starGeometry = new THREE.BufferGeometry(); const starVertices = []; for(let i=0; i<10000; i++) { const x = (Math.random() - 0.5) * 1000; const y = (Math.random() - 0.5) * 1000; const z = (Math.random() - 0.5) * 1000; starVertices.push(x, y, z); } starGeometry.setAttribute("position", new THREE.Float32BufferAttribute(starVertices, 3)); const starMaterial = new THREE.PointsMaterial({color: 0xffffff}); const stars = new THREE.Points(starGeometry, starMaterial); this._scene.add(stars);
결과는 이 글의 가장 첫번째 이미지와 같습니다.