forked from monkin/TallinnJS-WebGL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpoly-sphere1.js
119 lines (99 loc) · 3.82 KB
/
poly-sphere1.js
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
// Normal per face
const vertexSource1 = `
attribute vec3 a_point;
attribute vec3 a_normal;
varying vec3 v_point;
varying vec3 v_normal;
uniform float u_ratio;
void main() {
v_point = a_point;
v_normal = a_normal;
gl_Position = u_ratio > 1.0
? vec4(a_point.x / u_ratio * 0.8, a_point.y * 0.8, 0, 1)
: vec4(a_point.x * 0.8, a_point.y * u_ratio * 0.8, 0, 1);
}`;
const fragmentSource1 = `
precision highp float;
varying vec3 v_point;
varying vec3 v_normal;
uniform vec3 u_light;
void main() {
vec3 light = normalize(v_point - u_light);
vec3 n = normalize(v_normal);
float ambient = 0.05;
float diffuse = max(0.0, dot(n, light));
float specular = 0.8 * pow(max(0.0, dot(normalize(reflect(light, n)), vec3(0, 0, -1))), 15.0);
vec3 color = vec3(0.1 + 0.4 * (ambient + diffuse) + specular);
vec3 sRGBColor = pow(color, vec3(1.0 / 2.2));
gl_FragColor = vec4(sRGBColor, 1);
}`;
function initPolySphere1(gl) {
// Setup WebGL context parameters
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.clearColor(0, 0, 0, 1);
// Generating sphere geometry
const vertexes = [];
for (let i = 0; i < SEGMENTS_COUNT; i++) {
const a = i / (SEGMENTS_COUNT - 1) * Math.PI,
sinA = Math.sin(a),
cosA = Math.cos(a);
for (let j = 0; j < SEGMENTS_COUNT; j++) {
const b = j / SEGMENTS_COUNT * Math.PI * 2,
sinB = Math.sin(b),
cosB = Math.cos(b);
vertexes.push([
cosB * sinA, // x
cosA, // y
- sinB * sinA // z
]);
}
}
const triangles = [];
for (let i = 0; i < SEGMENTS_COUNT; i++) {
for (let j = 0; j <= SEGMENTS_COUNT; j++) {
const cI = i % SEGMENTS_COUNT,
cJ = j % SEGMENTS_COUNT,
nI = (i + 1) % SEGMENTS_COUNT,
nJ = (j + 1) % SEGMENTS_COUNT,
p1 = vertexes[cJ * SEGMENTS_COUNT + cI],
p2 = vertexes[nJ * SEGMENTS_COUNT + cI],
p3 = vertexes[cJ * SEGMENTS_COUNT + nI],
p4 = vertexes[nJ * SEGMENTS_COUNT + nI],
normal = p1.map((v, i) => (v + p2[i] + p3[i] + p4[i]) / 4);
triangles.push(
// first triangle
...p1, ...normal,
...p2, ...normal,
...p3, ...normal,
// second triangle
...p2, ...normal,
...p4, ...normal,
...p3, ...normal
);
}
}
// Buffer with vertexes and normales
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// Write data to buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangles), gl.STATIC_DRAW);
// Prepare program and parameters
const program = buildShaderProgram(gl, vertexSource1, fragmentSource1),
ratioLocation = gl.getUniformLocation(program, "u_ratio"),
lightLocation = gl.getUniformLocation(program, "u_light"),
pointLocation = gl.getAttribLocation(program, "a_point"),
normalLocation = gl.getAttribLocation(program, "a_normal");
gl.useProgram(program);
gl.uniform3f(lightLocation, ...LIGHT_SOURCE);
gl.enableVertexAttribArray(pointLocation);
gl.vertexAttribPointer(pointLocation, 3, gl.FLOAT, false, 6 * 4, 0);
gl.enableVertexAttribArray(normalLocation);
gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 6 * 4, 3 * 4);
// Draw loop
return function drawFrame(ratio) {
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform1f(ratioLocation, ratio);
gl.drawArrays(gl.TRIANGLES, 0, triangles.length / 6);
}
}