-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebGLExercise7.html
More file actions
299 lines (250 loc) · 13.7 KB
/
webGLExercise7.html
File metadata and controls
299 lines (250 loc) · 13.7 KB
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="Libraries/webgl-debug.js"></script>
<script src="Libraries/gl-matrix-min.js"></script>
<script id="vShader" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uModelTransform;
varying vec4 vColor;
void main() {
gl_Position = uModelTransform * aVertexPosition;
vColor = aVertexColor;
}
</script>
<script id="fShader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
</script>
<script>
var gl;
var canvas;
var shadersProgram;
var vertexPositionAttributePointer;
var vertexColorAttributePointer;
var modelUniformPointer;
var vertexBuffer;
var colorBuffer;
var indexBuffer;
var translationMatrix = new Float32Array(16);
// ΚΛΙΜΑ.0. Πίνακες κλιμάκωσης και συνολικού μετασχηματισμού
var scaleMatrix = new Float32Array(16);
var finalMatrix = new Float32Array(16);
// ΚΛΙΜΑ.1. Παράγοντας μεταβολής κλιμάκωσης (scaleFactor) και τελικός υπολογιζόμενος συντελεστής κλιμάκωσης (scale) - θεωρείται κοινός για x και y
var scaleFactor = 1.01;
var scale = 1.0;
// ΒΗΜΑ.1. Προσθέστε δηλώσεις για τρεις νέους buffers: (α) για τις κορυφές του πατώματος, (β) για τα χρώματα των κορυφών του πατώματος και (γ) για τους δείκτες (indices) των κορυφών του πατώματος
// Προτεινόμενα ονόματα: floorVBuffer, floorCBuffer, floorIBuffer
var floorVertexBuffer;
var floorColorBuffer;
var floorIndexBuffer;
var requestID = 0;
function createGLContext(inCanvas) {
var outContext = null;
outContext = inCanvas.getContext("webgl");
if (!outContext)
outContext = inCanvas.getContext("experimental-webgl");
if (!outContext)
alert("WebGL rendering context creation error.");
return outContext;
}
function createCompileShader(shaderType, shaderSource) {
var outShader = gl.createShader(shaderType);
gl.shaderSource(outShader, shaderSource);
gl.compileShader(outShader);
if (!gl.getShaderParameter(outShader, gl.COMPILE_STATUS)) {
alert( "Shader compilation error. " + gl.getShaderInfoLog(outShader) );
gl.deleteShader(outShader);
outShader = null;
}
return outShader;
}
function initShaders() {
var vertexShaderSource = document.getElementById("vShader").textContent;
var fragmentShaderSource = document.getElementById("fShader").textContent;
var vertexShader = createCompileShader(gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createCompileShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
shadersProgram = gl.createProgram();
gl.attachShader(shadersProgram, vertexShader);
gl.attachShader(shadersProgram, fragmentShader);
gl.linkProgram(shadersProgram);
if (!gl.getProgramParameter(shadersProgram, gl.LINK_STATUS)) {
alert("Shaders linking error.");
}
gl.useProgram(shadersProgram);
vertexPositionAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttributePointer);
vertexColorAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexColorAttributePointer);
modelUniformPointer = gl.getUniformLocation(shadersProgram, "uModelTransform");
}
function initBuffers() {
// ΠΑΚΕΤΟ ΕΝΤΟΛΩΝ 1. Κορυφές σε 3 διαστάσεις για δημιουργία (κεντρικού/βασικού) τετράεδρου
var tetraVertices = new Float32Array([
0.0, 0.0, -0.4, 1.0, // Κορυφή Α
-0.2, -0.2, 0.0, 1.0, // Κορυφή Β
0.2, -0.2, 0.0, 1.0, // Κορυφή Γ
0.0, 0.2, 0.0, 1.0 // Κορυφή Δ
]);
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, tetraVertices, gl.STATIC_DRAW);
vertexBuffer.itemSize = 4;
vertexBuffer.itemCount = 4;
// ΠΑΚΕΤΟ ΕΝΤΟΛΩΝ 2. Χρώματα 4 κορυφών
var tetraColors = new Float32Array([
1.0, 0.0, 0.0, 1.0, // Χρώμα κορυφής Α: κόκκινο
0.0, 1.0, 0.0, 1.0, // Χρώμα κορυφής Β: πράσινο
0.0, 0.0, 1.0, 1.0, // Χρώμα κορυφής Γ: μπλε
1.0, 1.0, 0.0, 1.0 // Χρώμα κορυφής Δ: κίτρινο
]);
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, tetraColors, gl.STATIC_DRAW);
colorBuffer.itemSize = 4;
colorBuffer.itemCount = 4;
// ΠΑΚΕΤΟ ΕΝΤΟΛΩΝ 3. Πίνακας με αναφορές στις παραπάνω κορυφές (indices) και σχετικός buffer
var indexMatrix = new Uint16Array([
0,1,2, // ΑΒΓ
0,2,3, // ΑΓΔ
0,3,1, // ΑΔΒ
1,3,2 // ΒΔΓ
]);
indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexMatrix,gl.STATIC_DRAW);
indexBuffer.itemCount = 12;
// ΒΗΜΑ.2. Χρησιμοποιώντας τα 3 παραπάνω πακέτα εντολών σαν παράδειγμα,
// δημιουργήστε και "ταΐστε" εδώ τους 3 νέους buffers που δηλώσατε για το πάτωμα
// Θεωρήστε και τοποθετήστε το πάτωμα παράλληλο στο επίπεδο xy και στο κέντρο του,
// με διαστάσεις 1,8x1,8 (δηλαδή από -0,9 ως 0,9 σε x και y) και με z=0 για όλες τις κορυφές του
// Χρησιμοποιήστε διαφορετικές αποχρώσεις του γκρι για τις κορυφές του
var floorVertices = new Float32Array([
-0.9, 0.9, 0.0, 1.0, // Κορυφή Α
-0.9, -0.9, 0.0, 1.0, // Κορυφή Β
0.9, -0.9, 0.0, 1.0, // Κορυφή Γ
0.9, 0.9, 0.0, 1.0 // Κορυφή Δ
]);
floorVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, floorVertices, gl.STATIC_DRAW);
floorVertexBuffer.itemSize = 4;
floorVertexBuffer.itemCount = 4;
// ΠΑΚΕΤΟ ΕΝΤΟΛΩΝ 2. Χρώματα 4 κορυφών
var floorColors = new Float32Array([
0.0, 0.0, 0.0, 1.0, // Χρώμα κορυφής Α: κόκκινο
0.3, 0.3, 0.3, 1.0, // Χρώμα κορυφής Β: πράσινο
0.7, 0.7, 0.7, 1.0, // Χρώμα κορυφής Γ: μπλε
1.0, 1.0, 1.0, 1.0 // Χρώμα κορυφής Δ: κίτρινο
]);
floorColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, floorColors, gl.STATIC_DRAW);
floorColorBuffer.itemSize = 4;
floorColorBuffer.itemCount = 4;
// ΠΑΚΕΤΟ ΕΝΤΟΛΩΝ 3. Πίνακας με αναφορές στις παραπάνω κορυφές (indices) και σχετικός buffer
var floorIndexMatrix = new Uint16Array([
0,1,2, // ΑΒΓ
0,2,3, // ΑΓΔ
// ΑΔΒ
// ΒΔΓ
]);
floorIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, floorIndexMatrix,gl.STATIC_DRAW);
floorIndexBuffer.itemCount = 6;
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// ΑΡΧΗ 1ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(vertexPositionAttributePointer, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(vertexColorAttributePointer, colorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// ΤΕΛΟΣ 1ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ
// ΚΛΙΜΑ.2. Κλιμάκωση αντικειμένου μεταξύ 50% και 150% του αρχικού μεγέθους με (πολλαπλασιαστικό) βήμα μεγέθυνσης ή σμίκρυνσης 1%
if (scale > 1.5)
scaleFactor = 0.99; // 99%
if (scale < 0.5)
scaleFactor = 1.01; // 101%
scale = scaleFactor*scale;
// ΚΛΙΜΑ.3. Δημιουργία πίνακα κλιμάκωσης κατά scale μόνο ως προς x και y
glMatrix.mat4.fromScaling(scaleMatrix,[scale,scale,1.0]);
// Μετακίνηση για δημιουργία αντιγράφου/τοποθέτηση του αντικειμένου:
for (var p = -0.5; p<=0.5; p+=0.5)
{
// ΑΡΧΗ 2ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ
glMatrix.mat4.fromTranslation(translationMatrix,[p,p,0]);
// ΚΛΙΜΑ.4. Εφαρμογή πρώτα της κλιμάκωσης και μετά της μετακίνησης για τη δημιουργία του κάθε αντιγράφου (: στόχος τα τετράεδρα να φαίνονται ότι μεγαλώνουν/μικραίνουν στη θέση τους
glMatrix.mat4.multiply(finalMatrix,translationMatrix,scaleMatrix);
gl.uniformMatrix4fv(modelUniformPointer, false, finalMatrix);
gl.drawElements(gl.TRIANGLES,indexBuffer.itemCount,gl.UNSIGNED_SHORT, 0);
// ΤΕΛΟΣ 2ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ
}
// ΒΗΜΑ.3. ΠΡΟΣΘΕΣΤΕ ΕΔΩ ΤΟΝ ΚΩΔΙΚΑ ΓΙΑ ΝΑ ΕΝΕΡΓΟΠΟΙΗΘΟΥΝ ΟΙ BUFFERS ΤΟΥ "ΠΑΤΩΜΑΤΟΣ" ΚΑΙ ΝΑ ΣΧΕΔΙΑΣΤΕΙ ΤΟ ΠΑΤΩΜΑ. ΑΝΑΛΥΤΙΚΑ:
// ΒΗΜΑ 3.1 ΔΕΙΤΕ ΤΟΝ ΚΩΔΙΚΑ "ΑΡΧΗ-ΤΕΛΟΣ 1ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ" ΓΙΑ ΕΝΕΡΓΟΠΟΙΗΣΗ ΚΑΙ ΑΝΤΙΣΤΟΙΧΙΣΗ ΤΩΝ ATTRIBUTES ΤΟΥ VERTEX SHADER ME ΤΟΥΣ ΚΑΤΑΛΛΗΛΟΥΣ BUFFERS ΤΗΣ ΠΥΡΑΜΙΔΑΣ" ΠΑΡΑΠΑΝΩ, ΒΑΛΤΕ ΕΔΩ ΤΙΣ ΑΝΤΙΣΤΟΙΧΕΣ ΕΝΤΟΛΕΣ
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexBuffer);
gl.vertexAttribPointer(vertexPositionAttributePointer, floorVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, floorColorBuffer);
gl.vertexAttribPointer(vertexColorAttributePointer, floorColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorIndexBuffer);
// ΒΗΜΑ 3.2 ...ΚΑΙ ΤΟΝ ΚΩΔΙΚΑ "ΑΡΧΗ-ΤΕΛΟΣ 2ων ΕΡΓΑΣΙΩΝ ΤΕΤΡΑΕΔΡΟΥ" ΓΙΑ ΔΗΜΙΟΥΡΓΙΑ/ΕΝΗΜΕΡΩΣΗ ΠΙΝΑΚΑ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟΥ, ΤΑΪΣΜΑ ΣΤΟ ΑΝΤΙΣΤΟΙΧΟ uniform ΚΑΙ ΣΧΕΔΙΑΣΗ
// ΔΕ ΘΑ ΧΡΕΙΑΣΤΕΙ for ΓΙΑ ΤΟ ΠΑΤΩΜΑ, ΟΥΤΕ ΚΑΠΟΙΑ ΚΛΙΜΑΚΩΣΗ Ή ΜΕΤΑΚΙΝΗΣΗ: Ο ΠΙΝΑΚΑΣ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟΥ ΘΑ ΕΙΝΑΙ ΜΟΝΑΔΙΑΙΟΣ
// ΩΣΤΟΣΟ ΧΡΕΙΑΖΕΤΑΙ ΠΙΝΑΚΑΣ ΜΕΤΑΣΧΗΜΑΤΙΣΜΟΥ, ΠΑΡΟΤΙ ΘΑ ΕΙΝΑΙ ΜΟΝΑΔΙΑΙΟΣ,
// ΓΙΑΤΙ ΤΟΝ ΕΧΟΥΜΕ "ΤΑΞΕΙ" ΣΤΟ VERTEX SHADER ΩΣ UNIFORM (ΤΟ uTransformMatrix) ΠΟΥ ΠΕΡΙΜΕΝΕΙ "ΤΑΪΣΜΑ". ΒΑΛΤΕ ΕΔΩ ΤΙΣ ΑΝΤΙΣΤΟΙΧΕΣ ΕΝΤΟΛΕΣ ΔΗΜΙΟΥΡΓΙΑΣ ΜΟΝΑΔΙΑΙΟΥ ΠΙΝΑΚΑ ΣΤΟΝ finalMatrix, ταΐσματος του uniform και σχεδίασης
glMatrix.mat4.identity(finalMatrix);
gl.uniformMatrix4fv(modelUniformPointer, false, finalMatrix);
gl.drawElements(gl.TRIANGLES,floorIndexBuffer.itemCount, gl.UNSIGNED_SHORT, 0);
}
function main() {
minDimension = Math.min(window.innerHeight, window.innerWidth);
canvas = document.getElementById("sceneCanvas");
canvas.width = 0.9*minDimension;
canvas.height = 0.9*minDimension;
gl = WebGLDebugUtils.makeDebugContext(createGLContext(canvas));
initShaders();
initBuffers();
gl.clearColor(0.5, 0.5, 0.5, 1.0);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.enable(gl.DEPTH_TEST);
drawScene();
}
function startAnimation() {
if (requestID == 0)
requestID = window.requestAnimationFrame(animationStep);
}
function animationStep() {
drawScene();
requestID = window.requestAnimationFrame(animationStep);
}
function stopAnimation() {
window.cancelAnimationFrame(requestID);
requestID = 0;
}
</script>
</head>
<body onload="main()">
<canvas id="sceneCanvas">
</canvas>
<p>
<button id="startButton" onclick="startAnimation()">Ξεκίνα!</button>
<button id="stopButton" onclick="stopAnimation()">Σταμάτα!</button>
</p>
</body>
</html>
<!--
ΚΛΙΜΑΚΩΣΗ ΜΕΤΑΞΥ ΟΡΙΩΝ (Read-only)
Στον κώδικα έχουν προστεθεί τα απαραίτητα (εντολές ΚΛΙΜΑ) για την κλιμάκωση των τετράεδρων μεταξύ 50% και 150% του αρχικού τους μεγέθους.
Η κλιμάκωση εφαρμόζεται μόνο ως προς x και y και θέλουμε να εμφανίζεται σα να συμβαίνει "τοπικά" για κάθε τετράεδρο.
ΧΡΗΣΗ ΠΟΛΛΩΝ BUFFERS ΓΙΑ ΣΧΕΔΙΑΣΗ: ΒΗΜΑ.ΤΑ 1,2,3
Στόχος αυτής της άσκησης είναι η σχεδίαση ενός "πατώματος" κάτω από τα τετράεδρα: το πάτωμα είναι παράλληλο στο επίπεδο xy,
με διαστάσεις 1.8x1.8 και με z=0, δηλαδή εκτείνεται από -0.9 ως 0.9 ως προς x και y...
Σε επόμενο στάδιο θα μετακινηθεί η κάμερα και θα εμφανιστεί η σκηνή από άλλη οπτική γωνία.
ΑΚΟΛΟΥΘΗΣΤΕ ΤΑ ΒΗΜΑ.ΤΑ ΠΟΥ ΕΜΦΑΝΙΖΟΝΤΑΙ ΣΑΝ ΑΡΙΘΜΗΜΕΝΑ ΣΧΟΛΙΑ ΣΤΟΝ ΚΩΔΙΚΑ, ΣΥΜΠΛΗΡΩΝΟΝΤΑΣ ΤΙΣ ΑΝΤΙΣΤΟΙΧΕΣ ΕΝΤΟΛΕΣ ΜΕ ΤΗ ΣΕΙΡΑ ΤΗΣ ΑΡΙΘΜΗΣΗΣ
-->