forked from sketchpunk/FunWithWebGL2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgl.js
212 lines (173 loc) · 9.17 KB
/
gl.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
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
//--------------------------------------------------
// Global Constants
//--------------------------------------------------
const ATTR_POSITION_NAME = "a_position";
const ATTR_POSITION_LOC = 0;
const ATTR_NORMAL_NAME = "a_norm";
const ATTR_NORMAL_LOC = 1;
const ATTR_UV_NAME = "a_uv";
const ATTR_UV_LOC = 2;
//--------------------------------------------------
// Util Class
//--------------------------------------------------
class GlUtil{
//Convert Hex colors to float arrays, can batch process a list into one big array.
//example : GlUtil.rgbArray("#FF0000","00FF00","#0000FF");
static rgbArray(){
if(arguments.length == 0) return null;
var rtn = [];
for(var i=0,c,p; i < arguments.length; i++){
if(arguments[i].length < 6) continue;
c = arguments[i]; //Just an alias(copy really) of the color text, make code smaller.
p = (c[0] == "#")?1:0; //Determine starting position in char array to start pulling from
rtn.push(
parseInt(c[p] +c[p+1],16) / 255.0,
parseInt(c[p+2] +c[p+3],16) / 255.0,
parseInt(c[p+4] +c[p+5],16) / 255.0
);
}
return rtn;
}
}
//--------------------------------------------------
// Custom GL Context Object
//--------------------------------------------------
function GLInstance(canvasID){
var canvas = document.getElementById(canvasID),
gl = canvas.getContext("webgl2");
if(!gl){ console.error("WebGL context is not available."); return null; }
//...................................................
//Setup custom properties
gl.mMeshCache = []; //Cache all the mesh structs, easy to unload buffers if they all exist in one place.
gl.mTextureCache = [];
//...................................................
//Setup GL, Set all the default configurations we need.
gl.cullFace(gl.BACK); //Back is also default
gl.frontFace(gl.CCW); //Dont really need to set it, its ccw by default.
gl.enable(gl.DEPTH_TEST); //Shouldn't use this, use something else to add depth detection
gl.enable(gl.CULL_FACE); //Cull back face, so only show triangles that are created clockwise
gl.depthFunc(gl.LEQUAL); //Near things obscure far things
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); //Setup default alpha blending
gl.clearColor(1.0,1.0,1.0,1.0); //Set clear color
//...................................................
//Methods
//Reset the canvas with our set background color.
gl.fClear = function(){ this.clear(this.COLOR_BUFFER_BIT | this.DEPTH_BUFFER_BIT); return this; }
//Create and fill our Array buffer.
gl.fCreateArrayBuffer = function(floatAry,isStatic){
if(isStatic === undefined) isStatic = true; //So we can call this function without setting isStatic
var buf = this.createBuffer();
this.bindBuffer(this.ARRAY_BUFFER,buf);
this.bufferData(this.ARRAY_BUFFER, floatAry, (isStatic)? this.STATIC_DRAW : this.DYNAMIC_DRAW );
this.bindBuffer(this.ARRAY_BUFFER,null);
return buf;
}
//Turns arrays into GL buffers, then setup a VAO that will predefine the buffers to standard shader attributes.
gl.fCreateMeshVAO = function(name,aryInd,aryVert,aryNorm,aryUV,vertLen){ //TODO : ADDED VERT LEN
var rtn = { drawMode:this.TRIANGLES };
//Create and bind vao
rtn.vao = this.createVertexArray();
this.bindVertexArray(rtn.vao); //Bind it so all the calls to vertexAttribPointer/enableVertexAttribArray is saved to the vao.
//.......................................................
//Set up vertices
if(aryVert !== undefined && aryVert != null){
rtn.bufVertices = this.createBuffer(); //Create buffer...
rtn.vertexComponentLen = vertLen || 3; //How many floats make up a vertex
rtn.vertexCount = aryVert.length / rtn.vertexComponentLen; //How many vertices in the array
this.bindBuffer(this.ARRAY_BUFFER, rtn.bufVertices);
this.bufferData(this.ARRAY_BUFFER, new Float32Array(aryVert), this.STATIC_DRAW); //then push array into it.
this.enableVertexAttribArray(ATTR_POSITION_LOC); //Enable Attribute location
//this.vertexAttribPointer(ATTR_POSITION_LOC,3,this.FLOAT,false,0,0); //Put buffer at location of the vao\
this.vertexAttribPointer(ATTR_POSITION_LOC,rtn.vertexComponentLen,this.FLOAT,false,0,0); //Put buffer at location of the vao
}
//.......................................................
//Setup normals
if(aryNorm !== undefined && aryNorm != null){
rtn.bufNormals = this.createBuffer();
this.bindBuffer(this.ARRAY_BUFFER, rtn.bufNormals);
this.bufferData(this.ARRAY_BUFFER, new Float32Array(aryNorm), this.STATIC_DRAW);
this.enableVertexAttribArray(ATTR_NORMAL_LOC);
this.vertexAttribPointer(ATTR_NORMAL_LOC,3,this.FLOAT,false, 0,0);
}
//.......................................................
//Setup UV
if(aryUV !== undefined && aryUV != null){
rtn.bufUV = this.createBuffer();
this.bindBuffer(this.ARRAY_BUFFER, rtn.bufUV);
this.bufferData(this.ARRAY_BUFFER, new Float32Array(aryUV), this.STATIC_DRAW);
this.enableVertexAttribArray(ATTR_UV_LOC);
this.vertexAttribPointer(ATTR_UV_LOC,2,this.FLOAT,false,0,0); //UV only has two floats per component
}
//.......................................................
//Setup Index.
if(aryInd !== undefined && aryInd != null){
rtn.bufIndex = this.createBuffer();
rtn.indexCount = aryInd.length;
this.bindBuffer(this.ELEMENT_ARRAY_BUFFER, rtn.bufIndex);
this.bufferData(this.ELEMENT_ARRAY_BUFFER, new Uint16Array(aryInd), this.STATIC_DRAW);
//this.bindBuffer(this.ELEMENT_ARRAY_BUFFER,null); //TODO REMOVE THIS AND ADD TO CLEANUP
}
//Clean up
this.bindVertexArray(null); //Unbind the VAO, very Important. always unbind when your done using one.
this.bindBuffer(this.ARRAY_BUFFER,null); //Unbind any buffers that might be set
if(aryInd != null && aryInd !== undefined) this.bindBuffer(this.ELEMENT_ARRAY_BUFFER,null);
this.mMeshCache[name] = rtn;
return rtn;
}
gl.fLoadTexture = function(name,img,doYFlip){
var tex = this.createTexture();
if(doYFlip == true) this.pixelStorei(this.UNPACK_FLIP_Y_WEBGL, true); //Flip the texture by the Y Position, So 0,0 is bottom left corner.
this.bindTexture(this.TEXTURE_2D, tex); //Set text buffer for work
this.texImage2D(this.TEXTURE_2D, 0, this.RGBA, this.RGBA, this.UNSIGNED_BYTE, img); //Push image to GPU.
this.texParameteri(this.TEXTURE_2D, this.TEXTURE_MAG_FILTER, this.LINEAR); //Setup up scaling
this.texParameteri(this.TEXTURE_2D, this.TEXTURE_MIN_FILTER, this.LINEAR_MIPMAP_NEAREST); //Setup down scaling
this.generateMipmap(this.TEXTURE_2D); //Precalc different sizes of texture for better quality rendering.
this.bindTexture(this.TEXTURE_2D,null); //Unbind
this.mTextureCache[name] = tex; //Save ID for later unloading
if(doYFlip == true) this.pixelStorei(this.UNPACK_FLIP_Y_WEBGL, false); //Stop flipping textures
return tex;
};
//imgAry must be 6 elements long and images placed in the right order
//RIGHT,LEFT,TOP,BOTTOM,BACK,FRONT
gl.fLoadCubeMap = function(name,imgAry){
if(imgAry.length != 6) return null;
//Cube Constants values increment, so easy to start with right and just add 1 in a loop
//To make the code easier costs by making the imgAry coming into the function to have
//the images sorted in the same way the constants are set.
// TEXTURE_CUBE_MAP_POSITIVE_X - Right :: TEXTURE_CUBE_MAP_NEGATIVE_X - Left
// TEXTURE_CUBE_MAP_POSITIVE_Y - Top :: TEXTURE_CUBE_MAP_NEGATIVE_Y - Bottom
// TEXTURE_CUBE_MAP_POSITIVE_Z - Back :: TEXTURE_CUBE_MAP_NEGATIVE_Z - Front
var tex = this.createTexture();
this.bindTexture(this.TEXTURE_CUBE_MAP,tex);
//push image to specific spot in the cube map.
for(var i=0; i < 6; i++){
this.texImage2D(this.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, this.RGBA, this.RGBA, this.UNSIGNED_BYTE, imgAry[i]);
}
this.texParameteri(this.TEXTURE_CUBE_MAP, this.TEXTURE_MAG_FILTER, this.LINEAR); //Setup up scaling
this.texParameteri(this.TEXTURE_CUBE_MAP, this.TEXTURE_MIN_FILTER, this.LINEAR); //Setup down scaling
this.texParameteri(this.TEXTURE_CUBE_MAP, this.TEXTURE_WRAP_S, this.CLAMP_TO_EDGE); //Stretch image to X position
this.texParameteri(this.TEXTURE_CUBE_MAP, this.TEXTURE_WRAP_T, this.CLAMP_TO_EDGE); //Stretch image to Y position
this.texParameteri(this.TEXTURE_CUBE_MAP, this.TEXTURE_WRAP_R, this.CLAMP_TO_EDGE); //Stretch image to Z position
//this.generateMipmap(this.TEXTURE_CUBE_MAP);
this.bindTexture(this.TEXTURE_CUBE_MAP,null);
this.mTextureCache[name] = tex;
return tex;
};
//...................................................
//Setters - Getters
//Set the size of the canvas html element and the rendering view port
gl.fSetSize = function(w,h){
//set the size of the canvas, on chrome we need to set it 3 ways to make it work perfectly.
this.canvas.style.width = w + "px";
this.canvas.style.height = h + "px";
this.canvas.width = w;
this.canvas.height = h;
//when updating the canvas size, must reset the viewport of the canvas
//else the resolution webgl renders at will not change
this.viewport(0,0,w,h);
return this;
}
//Set the size of the canvas to fill a % of the total screen.
gl.fFitScreen = function(wp,hp){ return this.fSetSize(window.innerWidth * (wp || 1),window.innerHeight * (hp || 1)); }
return gl;
}