-
Notifications
You must be signed in to change notification settings - Fork 12
/
webgl_geometry_convex.html
209 lines (186 loc) · 7.85 KB
/
webgl_geometry_convex.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - convex geometry</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
color: #fff;
top: 0px;
width: 100%;
padding: 5px;
text-align:center;
}
a {
color: #fff;
}
</style>
</head>
<body>
<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - ConvexGeometry</div>
<script src="../build/three.js"></script>
<!--
轨道控制,鼠标左键旋转(与鼠标方向相同,用于非触摸屏上),右键平移,中键靠近或远离;也可以使用键盘控制
-->
<script src="js/controls/OrbitControls.js"></script>
<!--
凸几何体
-->
<script src="js/geometries/ConvexGeometry.js"></script>
<!--
检测支持(canvas,webgl,workers,fileApi)
-->
<script src="js/Detector.js"></script>
<!--
统计插件(FPS,渲染时间,chrome内存使用率,而且支持自定义)
-->
<script src="js/libs/stats.min.js"></script>
<script>
//如果不支持webgl,则会在body内添加一个不支持的提示信息DIV
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var group, camera, scene, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
//如果它的值是true,会得到一个绘图缓冲区,执行抗锯齿。默认情况下,它的值是true
renderer = new THREE.WebGLRenderer( { antialias: true } );
//devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例,与Android上的DIP相仿,作用是在所有设备上的显示效果都相近
renderer.setPixelRatio( window.devicePixelRatio );
//更新待渲染场景的大小
renderer.setSize( window.innerWidth, window.innerHeight );
//将渲染器的DOM元素(即Canvas)添加到HTML中
document.body.appendChild( renderer.domElement );
// camera
/*
透视相机
PerspectiveCamera(fov, aspect, near, far)
fov(视场):从相机位置能够看到的部分场景。推荐默认值45
aspect(长宽比):渲染结果输出区域的横向长度和纵向长度的比值。推荐默认值window.innerWidth/window.innerHeight
near(近面):定义从距离相机多近的地方开始渲染场景。推荐默认值0.1
far(远面):定义相机可以从它所处的位置看多远。默认值1000
*/
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
//定义相机的位置,有如下两种方式。如果不设置的话,相机位置为默认的Vector3{x:0,y:0,z:0}
//camera.position.x = 15;
//camera.position.y = 20;
//camera.position.z = 30;
camera.position.set( 15, 20, 30 );
scene.add( camera );
// controls
//轨道控制,鼠标左键旋转(与鼠标方向相同,用于非触摸屏上),右键平移,中键靠近或远离;也可以使用键盘控制
controls = new THREE.OrbitControls( camera, renderer.domElement );
//设置通过鼠标滚轮能移动到的最近和最远距离
controls.minDistance = 20;
controls.maxDistance = 50;
//最大极角默认是Math.PI,最小极角默认是0。它们控制可以上下翻转的角度
controls.maxPolarAngle = Math.PI / 2;
/*
环境光,提供的是在不同位置和方向上强度都相同的光源,它的颜色会添加到整个场景和所有对象的当前颜色上,相当于光照模型中各物体之间的反射光,因此通常用来表现光强中非常弱的那部分光
AmbientLight( color, intensity)
color 光源的颜色
intensity 光照强度,默认为1
*/
scene.add( new THREE.AmbientLight( 0x222222 ) );//0x222222,接近黑色
/*
点光源,空间中的一点,朝所有方向发射光线
PointLight(color, intensity, distance, decay)
color 光源的颜色
intensity 光照强度,默认为1
distance 光照射的距离
decay 衰减系数
*/
var light = new THREE.PointLight( 0xffffff, 1 );
camera.add( light );
//AxisHelper(坐标轴)只能在WebGLRenderer下显示,不能在CanvasRenderer下显示
scene.add( new THREE.AxisHelper( 20 ) );
//纹理加载器
var loader = new THREE.TextureLoader();
var texture = loader.load( 'textures/sprites/disc.png' );//这是一个白色的圆,外部透明
group = new THREE.Group();
scene.add( group );
// points
//Dodecahedron(正12面体,每个面均是正五边形),10为外接球半径
var pointsGeometry = new THREE.DodecahedronGeometry( 10 );
for ( var i = 0; i < pointsGeometry.vertices.length; i ++ ) {
//add是向量相加,multiplyScalar是向量乘以一个标量
//pointsGeometry.vertices[ i ].add( randomPoint().multiplyScalar( 2 ) ); // wiggle(扭动) the points
}
//PointsMaterial是WebGLRenderer下的粒子渲染器
var pointsMaterial = new THREE.PointsMaterial( {
//color和map同时设置的话,color和map的颜色会混合叠加(blender)
color: 0x0080ff,//蓝色
map: texture,
size: 1,
/*
当像素的透明度小于alphaTest阈值的时候,它就会被fragment shader舍弃
这是为了处理前面颜色为透明,但是依然保存在缓冲区,这样就会显示为白色,而不会显示后面物体的颜色
*/
alphaTest: 0.5
} );
//粒子系统
var points = new THREE.Points( pointsGeometry, pointsMaterial );
group.add( points );
// convex hull(凸状外壳)
//这种材质会考虑光照的影响,可以用来创建颜色暗淡的、不光亮的物体
var meshMaterial = new THREE.MeshLambertMaterial( {
color: 0xffffff,
opacity: 0.5,
//只有设置tansparent为true,透明度才会有效
transparent: true
} );
//通过改造后的原始几何体,创建凸几何体
var meshGeometry = new THREE.ConvexGeometry( pointsGeometry.vertices );
/*
为了达到透视效果,必须渲染内部和外部,需要分别添加两个side。
注意:这边不能使用DoubleSide,因为效果差距很大
*/
mesh = new THREE.Mesh( meshGeometry, meshMaterial );
mesh.material.side = THREE.BackSide; // back faces
mesh.renderOrder = 0;
group.add( mesh );
mesh = new THREE.Mesh( meshGeometry, meshMaterial.clone() );
mesh.material.side = THREE.FrontSide; // front faces
mesh.renderOrder = 1;
group.add( mesh );
/*
//双面渲染无法实现透视效果
//mesh = new THREE.Mesh( pointsGeometry, meshMaterial );
mesh = new THREE.Mesh( meshGeometry, meshMaterial );
mesh.material.side = THREE.DoubleSide;
group.add( mesh );
*/
window.addEventListener( 'resize', onWindowResize, false );
}
//随机一个在半径为1的球内的点
function randomPoint() {
return new THREE.Vector3( THREE.Math.randFloat( - 1, 1 ), THREE.Math.randFloat( - 1, 1 ), THREE.Math.randFloat( - 1, 1 ) );
}
function onWindowResize() {
//重新设置相机的宽高比。如果宽高比不对,那么正方形可能就不是正方形了
camera.aspect = window.innerWidth / window.innerHeight;
//更新透视相机的投影矩阵
camera.updateProjectionMatrix();
//更新待渲染场景的大小
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
//按照右手螺旋定则绕Y轴旋转
group.rotation.y += 0.005;
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>