使用three.js著色器創(chuàng)建地球首先要知道一下幾個點
1.著色器的介紹
Webgl繪制圖形是基于著色器(shader)的繪圖機制赏廓,著色器提供了靈活且強大的繪制二維或三維圖形的方法彰触,所有Webgl程序必須使用它娇澎。
著色器語言類似于c語言铛纬,當我們寫webgl程序時跳昼,著色器語言以字符串的形式嵌入在javascript語言中碌廓。
2.ShaderMaterial介紹
three.js中的ShaderMaterial可以讓我們自己定制著色器机蔗,直接操作像素闰非。我們只需要理解著色器的基本原理膘格。
使用自定義著色器渲染的材質(zhì)。著色器是用GLSL編寫的在GPU 上運行的小程序 财松。如果需要瘪贱,您可能需要使用自定義著色器:實現(xiàn)不包含在任何內(nèi)置材質(zhì)中的效果將許多對象組合成一個BufferGeometry以提高性能
3.Vertex Shader介紹
作用于每個頂點,通常是處理從世界空間到裁剪空間(屏幕坐標)的坐標轉(zhuǎn)換辆毡,后面緊接的是光柵化菜秦。
4.Fragment Shader介紹
作用于每個屏幕上的片元(這里可近似理解為像素),通常是計算顏色舶掖。
下面是代碼
<!DOCTYPE html>
<html>
<head>
? <meta charset="utf-8">
? <title>My first three.js app</title>
? <style>
? ? body {
? ? ? margin: 0;
? ? }
? </style>
</head>
<body>
? <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.js"></script>
? <script src="d:/3D/node_modules/@three-ts/orbit-controls/dist/index"></script>
? <script type="module">
? ? const clock = new THREE.Clock();
? ? const scene = new THREE.Scene();
? ? const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
? ? const renderer = new THREE.WebGLRenderer({
? ? ? antialias: true
? ? });
? ? renderer.setPixelRatio(window.devicePixelRatio);
? ? renderer.setSize(window.innerWidth, window.innerHeight);
? ? document.body.appendChild(renderer.domElement);
? ? let AeroSphere = {
? ? ? uniforms: {
? ? ? ? globeTexture: {
? ? ? ? ? value: new THREE.TextureLoader().load('./global.jpg'),
? ? ? ? },
? ? ? ? time: {
? ? ? ? ? value: 0,
? ? ? ? },
? ? ? },
? ? ? vertexShader: [
? ? ? ? 'varying vec2 vUv;',
? ? ? ? 'varying vec3 vertexNormal;',
? ? ? ? 'void main(){',
? ? ? ? 'vUv = uv;',
? ? ? ? 'vertexNormal = normalize(normalMatrix * normal);', //將法線轉(zhuǎn)換到視圖坐標系中
? ? ? ? 'gl_Position ?= projectionMatrix * modelViewMatrix * vec4(position, 1);',// 計算頂點著色器中頂點的位置
? ? ? ? '}',
? ? ? ].join('\n'),
? ? ? fragmentShader: [
? ? ? ? 'uniform sampler2D globeTexture;',
? ? ? ? 'varying vec2 vUv;',
? ? ? ? 'varying vec3 vertexNormal;',
? ? ? ? 'void main(){',
? ? ? ? 'float intensity = 1.05 -dot(vertexNormal,vec3(0.0,0.0,1.0));',
? ? ? ? 'vec3 atmosphere = vec3(0.3 , 0.6 , 1.0) * pow(intensity,1.5);',
? ? ? ? ' gl_FragColor = vec4(atmosphere + texture2D(globeTexture,vUv).xyz,1.0);',
? ? ? ? '}',
? ? ? ].join('\n'),
? ? };
? ? let Atmosphere = {
? ? ? uniforms: {
? ? ? ? time: {
? ? ? ? ? value: 0,
? ? ? ? },
? ? ? },
? ? ? vertexShader: [
? ? ? ? 'varying vec3 vertexNormal;',
? ? ? ? 'varying vec2 depthUv;',
? ? ? ? 'void main(){',
? ? ? ? 'vertexNormal = normalize(normalMatrix * normal);', //將法線轉(zhuǎn)換到視圖坐標系中
? ? ? ? 'gl_Position ?= projectionMatrix * modelViewMatrix * vec4(position, 1.0);',// 計算頂點著色器中頂點的位置
? ? ? ? 'depthUv = gl_Position.xy/1.0 + 0.5;',
? ? ? ? '}',
? ? ? ].join('\n'),
? ? ? fragmentShader: [
? ? ? ? 'varying vec3 vertexNormal;',
? ? ? ? 'varying vec2 depthUv;',
? ? ? ? 'uniform float time;',
? ? ? ? 'void main(){',
? ? ? ? 'float step = abs(time - depthUv.x);',
? ? ? ? 'if(step < 0.02){',
? ? ? ? 'float d = ?(1.0 - step * 50.0);',
? ? ? ? '}',
? ? ? ? 'float intensity = pow(0.5 - dot(vertexNormal, vec3(0.3 ,1 , 1)) ,0.5);',
? ? ? ? ' gl_FragColor = vec4(0.3, 0.6 , 1.0 ?, 1.0) * intensity;',
? ? ? ? '}',
? ? ? ].join('\n'),
? ? };
? ? const sphere = new THREE.Mesh(new THREE.SphereGeometry(5, 50, 50), new THREE.ShaderMaterial({
? ? ? vertexShader: AeroSphere.vertexShader,
? ? ? fragmentShader: AeroSphere.fragmentShader,
? ? ? uniforms: AeroSphere.uniforms,
? ? }))
? ? const atmosphere = new THREE.Mesh(new THREE.SphereGeometry(5, 50, 50), new THREE.ShaderMaterial({
? ? ? vertexShader: Atmosphere.vertexShader,
? ? ? fragmentShader: Atmosphere.fragmentShader,
? ? ? uniforms: Atmosphere.uniforms,
? ? ? blending: THREE.AdditiveBlending,
? ? ? side: THREE.BackSide
? ? }))
? ? atmosphere.scale.set(1.05, 1.05, 1.05)
? ? scene.add(sphere)
? ? scene.add(atmosphere)
? ? camera.position.z = 12
? ? const animate = function () {
? ? ? requestAnimationFrame(animate);
? ? ? renderer.render(scene, camera);
? ? ? sphere.rotation.y += 0.005
? ? ? const delta = clock.getDelta();
? ? ? const time = (clock.getElapsedTime() / 5) % 1;
? ? ? if (AeroSphere.uniforms) {
? ? ? ? Atmosphere.uniforms.time.value = time;
? ? ? }
? ? };
? ? animate();
? </script>
</body>
</html>
以上為個人拙見不喜勿噴,謝謝觀看