引入threejs库
<!--引入three.js三维引擎-->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
<!-- 引入threejs扩展控件OrbitControls.js -->
<script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
顶点着色器
<!-- 顶点着色器 -->
<script id="vertexShader" type="x-shader/x-vertex">
// varying关键字声明一个变量表示顶点纹理坐标插值后的结果
varying vec2 vUv;
void main(){
// 顶点纹理坐标uv数据进行插值计算
vUv = uv;
// 投影矩阵projectionMatrix、视图矩阵viewMatrix、模型矩阵modelMatrix
gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4( position, 1.0 );
}
</script>
片元着色器
<!-- 片元着色器 -->
<script id="fragmentShader" type="x-shader/x-fragment">
// 声明一个时间变量用来控制UV动画
uniform float time;
// 声明一个纹理对象变量
uniform sampler2D texture;
// 顶点片元化后有多少个片元就有多少个纹理坐标数据vUv
varying vec2 vUv;
void main() {
vec2 newT= vUv + vec2( -0.02, 0.02 ) * time;
//通过偏移后的纹理坐标newT采样像素
gl_FragColor = texture2D( texture, newT );
// 大气层整体透明度增加
gl_FragColor.a *=0.6;
}
</script>
scene代码
/**
* 创建场景对象Scene
*/
var scene = new THREE.Scene();
// 创建一个纹理贴图加载器
var textureLoader = new THREE.TextureLoader()
// 创建一个组对象,用来插入地球、大气层网格模型
var group = new THREE.Group()
/**
* 地球网格模型
*/
var earthGeometry = new THREE.SphereBufferGeometry(100, 30, 30);
var earthMaterial = new THREE.MeshPhongMaterial({
map: textureLoader.load('Earth.png'),
normalMap: textureLoader.load('EarthNormal.png'),
normalScale: new THREE.Vector2(2.9, 2.9),
specularMap: textureLoader.load('EarthSpec.png'),
transparent: true,
opacity: 0.7,
});
var earthMesh = new THREE.Mesh(earthGeometry, earthMaterial);
// 地球网格模型插入组对象中
group.add(earthMesh);
// 创建一个大气层几何体,注意比地球几何体的半径略大一些
var geometry = new THREE.SphereBufferGeometry(100.1, 30, 30); //球体
var texture = textureLoader.load('./大气.png');
// 设置重复的作用是:能够让一个效果循环
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
// 自定义顶点着色器对象
var material = new THREE.ShaderMaterial({
uniforms: {
// texture对应顶点着色器中uniform声明的texture变量
texture: {
value: texture,
},
time: {
value: 0.0
},
},
// 顶点着色器
vertexShader: document.getElementById('vertexShader').textContent,
// 片元着色器
fragmentShader: document.getElementById('fragmentShader').textContent,
// 开启透明度
transparent: true,
});
// 创建大气层网格模型
var mesh = new THREE.Mesh(geometry, material);
group.add(mesh); //大气层网格模型对象插入组对象中
scene.add(group);
/**
* 光源设置
*/
// 方向光1
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight.position.set(400, 200, 300);
scene.add(directionalLight);
// 方向光2
var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.9);
directionalLight2.position.set(-400, -200, -300);
scene.add(directionalLight2);
//环境光
var ambient = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambient);
/**
* 相机设置
*/
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
var k = width / height; //窗口宽高比
var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
//创建相机对象
var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(0, 100, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
/**
* 创建渲染器对象
*/
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(width, height); //设置渲染区域尺寸
document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
// 创建一个时钟对象Clock
var clock = new THREE.Clock();
// 渲染函数
function render() {
// 获得两次渲染的时间间隔deltaTime
var deltaTime = clock.getDelta();
// 更新uniforms中时间,这样就可以更新着色器中time变量的值
material.uniforms.time.value += deltaTime;
group.rotateY(-0.005)
renderer.render(scene, camera); //执行渲染操作
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
render();
//创建控件对象 相机对象camera作为参数 控件可以监听鼠标的变化,改变相机对象的属性
var controls = new THREE.OrbitControls(camera,renderer.domElement);