-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebGLExample2.html
More file actions
181 lines (156 loc) · 15.3 KB
/
webGLExample2.html
File metadata and controls
181 lines (156 loc) · 15.3 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
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="Libraries/webgl-debug.js"></script> <!-- ΝΕΟ 0.1. Κλήση βιβλιοθήκης debugging --->
<script id="vShader" type="x-shader/x-vertex">
// Ο παρακάτω κώδικας δεν είναι Javascript αλλά GLSL-ES
attribute vec4 aVertexPosition; // attribute: παράμετρος εισόδου του shader
attribute vec4 aVertexColor; // ΝΕΟ 1. Προσθέστε ένα νέο attribute (πάλι τύπου vec4) για το χρώμα των κορυφών: aVertexColor
varying vec4 vColor; // varying: μεταβλητή εξόδου προς το fragment shader (μέσω rasterization)
void main() {
gl_Position = aVertexPosition; // Θέση κάθε κορυφής (vertex) σε ομογενείς συντεταγμένες
vColor = aVertexColor; //vColor = vec4(0.0,0.0,1.0,1.0); // Χρώμα κάθε κορυφής (vertex) (r,g,b,a)
// ΝΕΟ 2. Αντικαταστήστε την προηγούμενη εντολή με μία που θα εκχωρεί το νέο attribute στο vColor
// (αντί να δίνουμε "καρφωτά" το χρώμα, εκμεταλλευόμαστε το νέο attribute)
}
</script>
<script id="fShader" type="x-shader/x-fragment">
// Ο παρακάτω κώδικας δεν είναι Javascript αλλά GLSL-ES
precision mediump float; // Ορίζεται η ακρίβεια των πραγματικών που θα χρησιμοποιηθούν
varying vec4 vColor; // varying: Παράμετρος εισόδου από το vertex shader (μέσω rasterization)
void main() {
gl_FragColor = vColor;
}
</script>
<script>
var gl; // Το rendering context που ***ΜΑΣ ΔΙΝΕΙ ΠΡΟΣΒΑΣΗ ΣΤΟ WebGL API*** μέσω των μεθόδων του και των ιδιοτήτων του
var canvas; // Το DOM αντικείμενο που θα φιλοξενήσει το context
var shadersProgram; // O κώδικας των vertex και fragment shaders
var vertexPositionAttributePointer; // Η διεύθυνση του attribute aVertexPosition
// ΝΕΟ 3. Δηλώστε μια νέα μεταβλητή (δείκτης) για τη διεύθυνση του attribute του χρώματος: vertexColorAttributePointer
var vertexColorAttributePointer;
var vertexBuffer; // Η μεταβλητή στην οποία θα αποθηκευτούν προσωρινά τα δεδομένα των vertices
// ΝΕΟ 4. Δηλώστε μια νέα μεταβλητή για τον buffer των χρωμάτων: colorBuffer
var colorBuffer;
function createGLContext(inCanvas) {
var outContext = null;
outContext = inCanvas.getContext("webgl"); // 4.1 Δημιούργησε ένα WebGL context
if (!outContext)
outContext = inCanvas.getContext("experimental-webgl"); // 4.2 Αν δεν πέτυχε προσπάθησε ξανά με το παλαιότερο όνομα
if (!outContext) // 4.3 Αν δεν πέτυχε εμφάνισε μήνυμα λάθους
alert("WebGL rendering context creation error.");
return outContext;
}
function createCompileShader(shaderType, shaderSource) {
var outShader = gl.createShader(shaderType); // 5.3.1 και 5.4.1 Δημιούργησε έναν κενό shader του τύπου που δόθηκε σαν παράμετρος
gl.shaderSource(outShader, shaderSource); // 5.3.2 και 5.4.2 Ενημέρωσε το shader με τον κώδικά του (σε μορφή string)
gl.compileShader(outShader); // 5.3.3 και 5.4.3 Κάνε compile τον κώδικα του shader
if (!gl.getShaderParameter(outShader, gl.COMPILE_STATUS)) { // Αν δεν γίνει compile με επιτυχία
alert( "Shader compilation error. " + gl.getShaderInfoLog(outShader) ); // Δώσε μήνυμα με πληροφορίες για το shader
gl.deleteShader(outShader); // και κατάστρεψέ τον
outShader = null;
}
return outShader; // 5.3.4 και 5.3.5 επίστρεψε τον compiled shader ή null
}
function initShaders() {
var vertexShaderSource = document.getElementById("vShader").textContent;
// 5.1 Δημιούργησε string με τον κώδικα του vertex shader από το κείμενο του αντίστοιχου script
var fragmentShaderSource = document.getElementById("fShader").textContent;
// 5.2 Δημιούργησε string με τον κώδικα του fragment shader από το κείμενο του αντίστοιχου script
var vertexShader = createCompileShader(gl.VERTEX_SHADER, vertexShaderSource); // CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ:
// 5.3 Δημιούργησε και ενημέρωσε το αντικείμενο vertex shader
var fragmentShader = createCompileShader(gl.FRAGMENT_SHADER, fragmentShaderSource); // CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ:
// 5.4 ομοίως το fragment shader
shadersProgram = gl.createProgram();
// 5.5 Δημιούργησε ένα (κενό) πρόγραμμα(=αντικείμενο) (που πρόκειται να περιέχει τους shaders)
gl.attachShader(shadersProgram, vertexShader); // 5.6 Επισύναψε το vertex shader στο συγκεκριμένο πρόγραμμα
gl.attachShader(shadersProgram, fragmentShader); // 5.7 Επισύναψε το fragment shader στο συγκεκριμένο πρόγραμμα
gl.linkProgram(shadersProgram); // 5.8 δημιούργησε το αντίστοιχο εκτελέσιμο (και των δύο shaders)
if (!gl.getProgramParameter(shadersProgram, gl.LINK_STATUS)) {// 5.9 Αν υπήρξε λάθος στη δημιουργία του εκτελέσιμο πες το
alert("Shaders linking error.");
}
gl.useProgram(shadersProgram); // 5.10 Προσάρτησε το εκτελέσιμο στο context
vertexPositionAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexPosition"); // 5.11 Βρες και αποθήκευσε στην αντίστοιχη μεταβλητή, τον αύξοντα αριθμό της διεύθυνσης του attribute του shader program, το οποίο έχει όνομα το string που δόθηκε σα δεύτερη παράμετρος
// ΝΕΟ 5. Κάντε ό,τι και το βήμα 5.11 για το νέο attribute aVertexColor, δηλαδή αποθηκεύστε τον αύξοντα αριθμό της διεύθυνσής του στο δείκτη που δηλώσατε στο ΝΕΟ 3
vertexColorAttributePointer = gl.getAttribLocation(shadersProgram, "aVertexColor");
gl.enableVertexAttribArray(vertexPositionAttributePointer); // 5.12 Προετοίμασε το attribute (μέσω του παραπάνω pointer που δείχνει σε αυτό) να δεχθεί δεδομένα
// ΝΕΟ 6. Κάντε ό,τι και το βήμα 5.12, για τη global μεταβλητή δείκτη του NEO 5, δηλαδή προετοιμάστε το νέο attribute του χρώματος να δεχθεί δεδομένα
gl.enableVertexAttribArray(vertexColorAttributePointer);
}
function initBuffers() {
var triangleVertices = new Float32Array([
0.0, -0.5, 0.0, 1.0,
-0.5, 0.5, 0.0, 1.0,
0.5, 0.5, 0.0, 1.0]);
// 6.1 Δημιούργησε έναν πίνακα (ArrayBuffer) στη μνήμη με τις συντεταγμένες (x,y,z,w) κάθε κορυφής. Ο πίνακας είναι μονοδιάστατος
vertexBuffer = gl.createBuffer(); // 6.2 Δημιούργησε (δέσμευσε) έναν buffer για τις κορυφές
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 6.3 Ενεργοποίησέ τον, δηλ. φέρε τον στο προσκήνιο: ό,τι δουλειά γίνεται με buffer θα αφορά αυτόν
gl.bufferData(gl.ARRAY_BUFFER, triangleVertices, gl.STATIC_DRAW); // 6.4 "Τάισε" τα δεδομένα του πίνακα στον (ενεργοποιημένο) buffer (επίσης μονοδιάστατος)
vertexBuffer.itemSize = 4; // 6.5 Δώσε τιμή στην (custom) ιδιότητα του buffer που καθορίζει ανά πόσες τιμές αφορούν την ίδια κορυφή
vertexBuffer.itemCount = 3; // 6.6 Δώσε τιμή στην (custom) ιδιότητα του buffer που καθορίζει πόσες κορυφές αφορά ο buffer συνολικά
// ΝΕΟ 7. Κάνετε ό,τι και στα 6.1-6.6 χρησιμοποιώντας τον colorBuffer όπου χρειάζεται buffer κι έναν
// νέο πίνακα triangleColors όπου μέσα του θα αποθηκεύσετε τα χρώματα που θέλετε για κάθε κορυφή ως
// αριθμούς r,g,b,a με τρόπο όμοιο με τα x,y,z,w των συντεταγμένων των κορυφών (πραγματικές τιμές
// απο 0 ως 1).
var triangleVerticesColors = 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]);
colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, triangleVerticesColors, gl.STATIC_DRAW);
colorBuffer.itemSize = 4;
colorBuffer.itemCount = 3;
}
function drawScene() {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); // 8.1 Ενεργοποίησε το viewport με τις διαστάσεις που δίνονται σαν παράμετροι
gl.clear(gl.COLOR_BUFFER_BIT); // 8.2 "Καθάρισε" το viewport χρωματίζοντάς το με το χρώμα που έχει οριστεί στο βήμα 7.
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 8.3 Κάνε ενεργό το vertex buffer
gl.vertexAttribPointer(vertexPositionAttributePointer, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
// 8.4 Παίρνε στοιχεία από τον ενεργό buffer και "τάιζέ" τα στη διεύθυνση του attribute μέσω του pointer(1η παράμετρος),
// με μέγεθος στοιχείου σε πλήθος αριθμών (2η παρ.),
// τύπο δεδομένων (3η), κανονικοποιώντας (4η παρ.) με βήμα (παράλειψης) τόσα bytes (5η παρ.) και ξεκινώντας από αυτό το byte (6η παράμετρος..)
// ΝΕΟ 8. (τελευταίο) Κάντε ό,τι στα βήματα 8.3-8.4 για τον buffer των χρωμάτων και τον αντίστοιχο δείκτη
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(vertexColorAttributePointer, colorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.LINE_LOOP, 0, vertexBuffer.itemCount); // 8.5 Σχεδίασε τρίγωνα (1η παρ.) ξεκινώντας από την
// κορυφή με σειρά όση η 2η παρ., και χρησιμοποίησε τόσες κορυφές όσες η 3η παρ.
}
function main() {
minDimension = Math.min(window.innerHeight, window.innerWidth); // 0. Καταχώρησε την ελάχιστη διάσταση του παραθύρου
canvas = document.getElementById("sceneCanvas"); // 1. Απομόνωσε ("ψάρεψε") τον καμβά (έχει δημιουργηθεί ως HTML αντικείμενο)
canvas.width = 0.95*minDimension; // 2. Όρισε τις διαστάσεις του
canvas.height = 0.95*minDimension; // 3. Όρισε τις διαστάσεις του
gl = WebGLDebugUtils.makeDebugContext(createGLContext(canvas)); // 4. ΝΕΟ 0.2 (ΑΛΛΑΓΗ)
// Για τη χρήση της βιβλιοθήκης debugging το (νεό) αντικείμενο context προκύπτει ως έξοδος μεθόδου της βιβλιοθήκης με παράμετρο το αυθεντικό αντικείμενο context
// CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ: Δημιούργησε μέσα στον καμβά ένα WebGL rendering context
initShaders(); // 5. CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ: Προετοίμασε τους shaders
initBuffers(); // 6. CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ: Προετοίμασε τους buffers
gl.clearColor(0.5, 0.5, 0.5, 1.0); // 7. Όρισε το χρώμα του background στο WebGL context (R,G,B,A) με τιμές από 0 ως 1
drawScene(); // 8. CUSTOM ΣΥΝΑΡΤΗΣΗ - ΔΕΣ ΠΑΡΑΠΑΝΩ: Σχεδίασε τη σκηνή
}
</script>
</head>
<body onload="main()">
<canvas id="sceneCanvas">
</canvas>
</body>
</html>
<!--
Πρόλογος: Στην αρχή του κώδικα (γραμμή 5 - ΝΕΟ 0.1) έχει προστεθεί η κλήση μιας βιβλιοθήκης αναφοράς λαθών WebGL
που αξιοποιείται στη δημιουργία του αντικειμένου context (γραμμή 124 - ΝΕΟ 0.2).
Κατεβάστε το σχετικό αρχείο Javascript από το eclass και τοποθετήστε το στον ίδιο κατάλογο με τον κώδικά σας
(ή δώστε το full path μέχρι την τοποθεσία του στη σχετική εντολή της γραμμής 5).
Ο ΚΩΔΙΚΑΣ ΠΕΡΙΕΧΕΙ ΕΝΑ ΜΙΚΡΟ ΛΑΘΟΣ: ΕΛΕΓΞΤΕ ΜΕΣΩ Inspect Element (Επιθεώρηση Στοιχείου) ΚΑΙ Console (Κονσόλα) ΤΟ ΣΧΕΤΙΚΟ ΜΗΝΥΜΑ ΚΑΙ ΔΙΟΡΘΩΣΤΕ ΤΟ
=== Το λάθος είναι στην γραμμή 133 και στην συνάρτηση gl.drawarrays(...) -> gl.drawArrays(...). ===
Μέρος Α': Ακολουθήστε τις οδηγίες στα βήματα ΝΕΟ 1., ΝΕΟ 2.,... για να δώσετε διαφορετικά χρώματα στις κορυφές του τριγώνου και δείτε το τελικό αποτέλεσμα.
Μέρος Β': Πειραματιστείτε με τα χρώματα και τις θέσεις των κορυφών (π.χ. εμφανίστε το τρίγωνο ανάποδα).
=== Στην γραμμή 91 άλλαξα τα πρόσημα στις συντεταγμένες των x, y, z συντεταγμένων για να εμφανιστεί ανάποδα το τρίγωνο ===
Μέρος Γ': Πειραματιστείτε με τις σταθερές gl.LINES, gl.LINE_STRIP, gl.LINE_LOOP αντί της gl.TRIANGLES στην εντολή σχεδίασης gl.drawArrays.
Παρατηρήστε τις διαφορές στο οπτικό αποτέλεσμα. Χρησιμοποιήστε και την gl.POINTS
(για να λειτουργήσει προσθέστε την εντολή gl_PointSize = 2.0; στη main του vertex shader).
=== Η gl.LINES εμφανίζει μία προσκείμενη πλευρά του ισοσκελούς τριγώνου (χωρίς χρωματισμό στο εσωτερικό του τριγώνου) ===
=== Η gl.LINE_STRIP εμφανίζει μία προσκείμενη και την υποτείνουσα πλευρά του ισοσκελούς τριγώνου (χωρίς χρωματισμό στο εσωτερικό του τριγώνου) ===
=== Η gl.LINE_LOOP εμφανίζει όλες τις πλευρές του ισοσκελούς τριγώνου (χωρίς χρωματισμό στο εσωτερικό του τριγώνου) ===
-->