-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebGLExercise4.html
More file actions
245 lines (207 loc) · 11 KB
/
webGLExercise4.html
File metadata and controls
245 lines (207 loc) · 11 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
<!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 uVerticesTransform;
varying vec4 vColor;
void main() {
gl_Position = uVerticesTransform * 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 verticesTransformUniformPointer;
var vertexBuffer;
var colorBuffer;
var totalAngle = 0.0;
var rotationXMatrix = new Float32Array(16);
var totalX = 0.0, totalY = 0.0;
var translationMatrix = new Float32Array(16);
var requestID = 0; // ΝΕΟΤΕΡΟ.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);
verticesTransformUniformPointer = gl.getUniformLocation(shadersProgram, "uVerticesTransform");
}
function initBuffers() {
var triangleVertices = new Float32Array([
0.5, 0.5, 0.0, 1.0, // v0
-0.5, 0.5, 0.0, 1.0, // v1
0.5, -0.5, 0.0, 1.0, // v2
-0.5, -0.5, 0.0, 1.0,
0.9, 0.9, 0.0, 1.0,
-0.9, 0.9, 0.0, 1.0,
0.9, 0.5, 0.0, 1.0,
-0.9, 0.5, 0.0, 1.0
]);
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, triangleVertices, gl.STATIC_DRAW);
vertexBuffer.itemSize = 4;
vertexBuffer.itemCount = 8;
var triangleColors = new Float32Array([
1.0, 0.0, 0.0, 1.0, // χρώμα v0
0.0, 1.0, 0.0, 1.0, // χρώμα v1
0.0, 0.0, 1.0, 1.0, // χρώμα v2
1.0, 0.0, 1.0, 1.0,
0.0, 1.0, 1.0, 1.0,
1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 1.0,
0.0, 0.0, 0.0, 1.0
]);
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, triangleColors, gl.STATIC_DRAW);
colorBuffer.itemSize = 4;
colorBuffer.itemCount = 8;
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT);
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);
// Ομάδα εντολών για υπολογισμό συνολικής γωνίας περιστροφής
var txtStepAngle;
txtStepAngle = document.getElementById("stepAngleTxt").value;
var numStepAngle = parseFloat(txtStepAngle);
numStepAngle = numStepAngle*Math.PI/180.0;
totalAngle += numStepAngle;
glMatrix.mat4.fromXRotation(rotationXMatrix, totalAngle ); // ΒΗΜΑ.-1 Δημιουργία πίνακα μετασχηματισμού περιστροφής
// Ομάδα εντολών για συνολική μετακίνηση κατά x
var txtX;
txtX = document.getElementById("xTxt").value;
var numX = parseFloat(txtX);
totalX += numX;
// Ομάδα εντολών για συνολική μετακίνηση κατά y
var txtY;
txtY = document.getElementById("yTxt").value;
var numY = parseFloat(txtY);
totalY += numY;
glMatrix.mat4.fromTranslation(translationMatrix,[totalX,totalY,0]); // Δημιουργία πίνακα μετασχηματισμού μετακίνησης
var finalM = new Float32Array(16);
glMatrix.mat4.multiply(finalM, translationMatrix, rotationXMatrix); // Δημιουργία πίνακα συνολικού μετασχηματισμού
gl.uniformMatrix4fv(verticesTransformUniformPointer, false, finalM);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexBuffer.itemCount);
}
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.frontFace(gl.CCW); // ΝΕΟΤΕΡΟ.4 "Εμπρός" όψη να θεωρείται η αριστερόστροφη (counter-clockwise CCW)
gl.enable(gl.CULL_FACE); // ΝΕΟΤΕΡΟ.5 Ενεργοποίησε την απόκρυψη της "κρυφής όψης" (CULL FACE)
gl.cullFace(gl.BACK); // ΝΕΟΤΕΡΟ.6 Κάνε "κρυφή" την "πίσω" όψη
drawScene();
}
// ΝΕΟΤΕΡΟ.1
function startAnimation() {
if (requestID == 0)
requestID = window.requestAnimationFrame(animationStep);
}
// ΝΕΟΤΕΡΟ.2
function animationStep() {
drawScene();
requestID = window.requestAnimationFrame(animationStep);
}
// ΝΕΟΤΕΡΟ.3
function stopAnimation() {
window.cancelAnimationFrame(requestID);
requestID = 0;
}
</script>
</head>
<body onload="main()">
<canvas id="sceneCanvas">
</canvas>
<p>
Βήμα γωνίας περιστροφής:<input type="text" id="stepAngleTxt" value="2" autocomplete="off">
Βήμα x μετακίνησης:<input type="text" id="xTxt" value="0.002" autocomplete="off">
Βήμα y μετακίνησης:<input type="text" id="yTxt" value="0" autocomplete="off">
<button id="startButton" onclick="startAnimation()">Ξεκίνα!</button>
<button id="stopButton" onclick="stopAnimation()">Σταμάτα!</button>
</p>
</body>
</html>
<!--
Βήμα.-1. (read-only) Παρατηρήστε ότι (για λόγους που θα φανούν στη συνέχεια) η περιστροφή αυτή τη φορά είναι γύρω από τον άξονα x.
Δημιουργήθηκε στην εντολή ΒΗΜΑ.-1 πίνακας περιστροφής γύρω από τον άξονα x'x.
ANIMATION
Βήμα.0. (read-only) Παρατηρήστε το μηχανισμό του animation. Το κουμπί start καλεί τη startAnimation (ΝΕΟΤΕΡΟ.1).
Αυτή, αν το requestId είναι null (το requestId είναι global μεταβλητή - ΝΕΟΤΕΡΟ.0), καλεί την animationStep() (ΝΕΟΤΕΡΟ.2).
Αν το requestId έχει τιμή διαφορετική από 0 δεν καλείται η animationStep() - αυτό γίνεται για να υπάρχει μόνο μία μοναδική ακολουθία requests).
Η animationStep αρχικά καλεί τη drawScene που σχεδιάζει μια νέα εκδοχή της σκηνής. Στη συνέχεια, υποβάλλει αίτημα για animation frame,
λαμβάνει requestId και εντάσσεται σε ουρά (callback list) μία επόμενη κλήση της. Όταν έρχεται η ώρα εκτέλεσης της κλήσης
που είναι στην ουρά, εκτελείται η drawScene και μία νέα κλήση μπαίνει στην ουρά κ.ο.κ.
Το animation σταματά μέσω της stopAnimation (ΝΕΟΤΕΡΟ.3) με αίτημα ακύρωσης της επανεκτέλεσης της animationStep,
μέσω του (τελευταίου) requestId που είχε λάβει, και το requestId τίθεται 0 ώστε να μπορεί να ξαναρχίσει.
ΔΙΑΛΟΓΗ ΟΨΕΩΝ
Βήμα.1. Εκτελέστε τον κώδικα ως έχει και μετά αφαιρέστε τα σχόλια στις ΝΕΟΤΕΡΟ.4, ΝΕΟΤΕΡΟ.5, ΝΕΟΤΕΡΟ.6 ώστε να ενεργοποιηθούν οι
εντολές στο τέλος της main.
Τι παρατηρείτε;
Συμβουλευτείτε τις σχετικές διαφάνειες του εργαστηρίου και διορθώστε τις συντεταγμένες του τριγώνου ώστε ΑΡΧΙΚΑ αυτό να είναι ορατό.
TRIANGLE STRIP & ΔΙΑΛΟΓΗ ΟΨΕΩΝ
Bήμα.2. (read-only) Η πρώτη παράμετρος της gl.drawArrays είναι gl.TRIANGLE_STRIP.
Δείτε στις σχετικές διαφάνειες του εργαστηρίου με ποιο τρόπο λαμβάνεται υπόψη η σειρά των κορυφών,
των οποίων τις συντεταγμένες έχουμε δώσει μέσα στον πίνακα στην initBuffers, όταν αυτές είναι περισσότερες από 3.
Βήμα.3. Λαμβάνοντας υπόψη και το Βήμα.2. μετατρέψτε το τρίγωνο σε τετράγωνο που οι 4 κορυφές του βρίσκονται στα x=+/- 0.5, y=+/- 0.5, z=0.
Φροντίστε να είναι ΑΡΧΙΚΑ να είναι ορατό (δηλαδή να μην το απορρίπτει η ΔΙΑΛΟΓΗ ΟΨΕΩΝ), παρόμοια με το Βήμα.1. Οι αλλαγές που χρειάζονται να γίνουν είναι όλες στην initBuffers.
Βήμα.4. Προσπαθήστε να επεκτείνετε το τετράγωνο του προηγούμενου βήματος στο TAY του σχήματος στην τελευταία σχετική διαφάνεια του εργαστηρίου,
χρησιμοποιώντας TRIANGLE_STRIP και διαλογή όψεων - θα χρειαστεί να εισάγετε και εκφυλισμένα τρίγωνα, δηλαδή να επαναλάβετε κάποιες κορυφές.
-->