1. ๊ธฐ๋ณธ ์ปจ์ ¶
OpenGL์์ ์ ๋ง ์ค๋ฌด์์ ์ฐ๋ ๋ถ๋ถ๋ง ๋ฐ๋ก ๋ผ์ด๋ธ OpenGL ES(Embeded System)์ Javascript ๊ตฌํ์ฒด์ด๋ฉฐ HTML5 Canvas๋ฅผ ํตํด ๋ํ๋๋ค. ๋ฐ๋ผ์ ์ด๋ณด์๊ฐ ์ฝ๊ฒ ๋ฐฐ์ฐ๋๋ฐ์ ์ด์ ์ด ๋ง์ถ์ด์ ธ ์์ง ์๊ณ ์ค์ง ์ ๋ฌธ๊ฐ๊ฐ ๊ตฌํ์ ํ๋๋ฐ์ ์ด์ ์ด ๋ง์ถ์ด์ ธ ์๋ค.
2. ํน์ง ¶
Javascript์์๋ ๋ถ๊ตฌํ๊ณ ๋ง์น Cํ๋ก๊ทธ๋๋ฐ ์คํ์ผ์ ํจ์๋ค์ด ์กด์ฌํ๋ค. WinAPI๊ฐ C์คํ์ผ์ OOP์ด๋ฏ WebGL ๋ํ C์คํ์ผ์ OOP์ด๋ค. ๋ชจ๋ ํจ์๋ WebGLcontext๋ผ๋ ๊ฐ์ฒด์ ์๋๋ฐ ๋ณด๋ฉด ๊ทธ๋ฅ ์ ๋์ด๋ฅผ ๋ถ์ด๋ ๋๋์ด๋ค.
var gl = canvas.getContext("experimental-webgl"); gl.attachShader(shaderProgram, fragmentShader); gl.attachShader(shaderProgram, vertexShader);์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์์ด๋ ํ๋ก๊ทธ๋จ์ fragmentShader์ vertexShader๋ฅผ Link ์ํค๋ ๊ตฌ๋ฌธ์ธ๋ฐ ์ฃผ์ฒด์ธ shaderProgram์ ์ฒซ๋ฒ์จฐ ์ธ์์ด๊ณ gl์ ๊ทธ๋ฅ ์ ๋์ด ์ฒ๋ผ ๋ณด์ธ๋ค. ์ ๊ตฌ๋ฌธ๋ง ๊ทธ๋ฐ๊ฒ์ด ์๋๋ผ ๋ค๋ฅธ ๋ชจ๋ ํจ์๋ค์ด ์ gl ๊ฐ์ฒด์ ๋ถ์ด์๋ค. ํ์ง๋ง ์ ์ gl์ด ์ฃผ์ฒด๊ฐ ์๋ ๊ฒ๋ค์ด ๋ง๋ค. ๋ฐ๋ผ์ ๋ํํ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ์ฐ๋ ๊ฒ์ด ์ํธํ๋ฐ ์ด์คํ๊ฒ ํ๋ค๊ฐ๋ ๋ฌด์ฒ ๊ผฌ์ด๊ฒ ๋๋ค.
์ด ๊ด์ต์ OpenGL์ด ๊ธฐ๋ณธ์ ์ผ๋ก C๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ผ ๊ทธ๋ฐ๋ฏ ํ๋ค. ์ค์ ๋ํ์ ์งํํด๋ณธ๊ฒฐ๊ณผ ๋ง์น MFC๋ฅผ ๋ณด๋๋ฏํ ๋๋์ ๊ฐํ๊ฒ ๋ฐ๊ณ ์๋ค.
2.1. OpenGL๊ณผ ์ฐจ์ด์ ¶
- WebGL์ ๊ธฐ์กด OpenGL๊ณผ ๋ค๋ฅด๊ฒ ์ง์ ๊ทธ๋ฆฌ๊ธฐ๊ฐ ์ง์๋์ง ์๋๋ค. ๊ธฐ์กด์ glBegin()์ glEnd()์ฌ์ด์์ ๊ฐ์ ๊ณ์์ ์ผ๋ก ์ ๋ฌํ์ ์๊ณ ์ค์ง glDrawElement()๋ฅผ ํตํ ๋ฐฐ์ด์ ํ๊บผ๋ฒ์ ์ ๋ฌํ๋ ๊ฒ'๋ง' ์ง์ํ๋ค. ์ด๋ณด์๋ค์ ์ฒซ๋๊ด์ด๋ค.
- ์ฌ๊ฐํ๊ทธ๋ฆฌ๊ธฐ ๋ฐ ๋ค๊ฐํ ๊ทธ๋ฆฌ๊ธฐ๊ฐ ์ง์๋์ง ์๋๋ค. ์ค์ ๋ก ๋ค๊ฐํ ๊ทธ๋ฆฌ๊ธฐ๋ ์ฐ์ต์์๋ง ์์ฃผ ์ฐ๊ณ ์ค์ ์ฝ๋์์๋ ์ผ๊ฐํ์ผ๋ก ์ด๋ฃจ์ด์ง ๋ชจ๋ธ์ ๊ฐ์ ธ๋ค ์ฐ๊ธฐ ๋๋ฌธ์ธ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค๊ฐํ์ ์ผ๊ฐํ์ ์งํฉ์ผ๋ก ํํํ ์ ์๋ค.
- ์ ํธ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ ๊ณต๋๋ ํ๋ธ, ๊ตฌ, ์ค๋ฆฐ๋, ํฐํฌํธ๊ฐ ๋ชจ๋ ์ง์๋์ง ์๋๋ค. ์ญ์ ์์ ์๋ง ์ฐ์ด๊ณ ์ฐ์ง ์๊ธฐ ๋๋ฌธ์ ๊ณผ๊ฐํ ์ ๊ฑฐํ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
- ๊ด์, ์นด๋ฉ๋ผ ์กฐ์, ํ์ ๋ฑ์ด ์ ๊ณต๋์ง ์๋๋ค. ๋ชจ๋ ์์ ์ด ์ง์ ์ฐ์ฐ์ ํตํด ํ๋ ฌ์ ๊ตฌํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ณด์๋ค์ ๋์จฐ ๋๊ด์ด๋ค.
- ํ
์ค์ณ ๋ชจ๋์ ์กฐ๋ช
๋ชจ๋๊ฐ ๋งค์ฐ ์ ํ๋์ด ์๋ค.
- ์์ด๋๋ฅผ ์ง์ง์์ผ๋ฉด ์ธ์๊ฐ ์๋ค. ์ฌ์ง์ด ํ
์ค์ณ๋ฅผ ์
ํ๋ ๊ฒ๋ ์์ด๋์์ ์ฒ๋ฆฌํ๋ค. ๊ทธ๋ฅ ๋จ์์ผ๋ก ์ฒ๋ฆฌํ๋ ์ฝ๋๋ ์์ด๋ ์ฝ๋๋ฅผ ์ง์ง ์์ผ๋ฉด ๊ทธ๋ฅ ํ์ ๊ฒ๋ง ๋ณด๊ฒ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ ํ์ ์ํฌ์๋ ์๋ค.
3.1. ํ์ดํ ๋ผ์ธ ¶
WebGL์ ์ผ์ ํ ํ๋ฆ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ๋๊ณ ๊ทธ ๊ฐ๋ถ๋ถ์ ๋ง๋ค์ ์๋๋ก ํด ๋์๋ค. ์๋ง ์ต์ ํ๊ฐ ์ฌ์ด ํ์ ๊ทธ๋ฌํ์ผ๋ฆฌ๊ณ ์๊ฐ๋๋ค.

Attribute๋ ๊ฐ ํฌ์ธํธ ๋ณ๋ก ์ ๋ฌ๋๋ ์ ๋ณด์ด๊ณ uniform ์ ์ ์ฒด์์ ๊ณตํต์ ์ธ ์ ๋ณด์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก Attribute๋ ๊ฐ ์ ์ ์ ์์น ์ ๋ณด์ ๊ฐ ์ง์ ์ ๋ฒ์ ๋ฒกํฐ ์ ๋ณด๋ฅผ์ ์ ๋ฌํ๋ค. uniform์ ์ผ๋ฐ์ ์ผ๋ก ์นด๋ฉ๋ผ์ ์์น๋ ํ๊ฒฝ๊ด์ ์์น์ฒ๋ผ ์ ์ฒด์ ์ธ ๊ฒ์ ์ ๋ฌํ๋ค. Attribute๋ uniform์ ์ผ์ข ์ ๋ณ์์ธ๋ฐ ํธ๋ค์ ์ป์ด์์ ๊ทธ๊ฒ์ ํตํด ๊ฐ์ ์ ๋ฌํ ์ ์๋ค. ์ฆ Atrribute๋ Uniform์ Javascript์ธก์์ ์์ด๋๋ก ์ ๋ณด๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด๋ค. varying์ ์์ด๋ ๊ฐ์ ์ ๋ณด ์ ๋ฌ์ ์ฌ์ฉ๋๋ค. vertex shader์์ fragment shader๋ก ๊ฐ์ด ์ ๋ฌ๋๋ฉฐ ๋ฐ๋๋ ๋ถ๊ฐ๋ฅํ๋ค(ํ์ดํ๋ผ์ธ ๊ตฌ์กฐ์ ๋น์ฐํ ๊ฒ์ด๋ค). ์ด๋ vertex shader๋ ๊ฐ ์ ์ (๊ผญ์ง์ ) fragment shader๋ ๊ฐ ํฝ์ ์ ํ๋ฒ ํธ์ถ๋๊ฒ ๋๋๋ฐ ๊ฐ ์ ์ ์ฌ์ด์ ๊ฐ๋ค์ ๋ณด๊ฐ๋ฒ์ ๊ฑฐ์ณ ์ ๋ฌ๋๊ฒ ๋๋ค(๊ทธ๋ผ๋์ธํธ ๊ฐ์ ๋๋์ด๋ค ์ค๊ฐ๊ฐ์ ์์์ ๋ง๋ค์ด ์ค๋ค).

[PNG image (52.47 KB)]
Attribute๋ ๊ฐ ํฌ์ธํธ ๋ณ๋ก ์ ๋ฌ๋๋ ์ ๋ณด์ด๊ณ uniform ์ ์ ์ฒด์์ ๊ณตํต์ ์ธ ์ ๋ณด์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก Attribute๋ ๊ฐ ์ ์ ์ ์์น ์ ๋ณด์ ๊ฐ ์ง์ ์ ๋ฒ์ ๋ฒกํฐ ์ ๋ณด๋ฅผ์ ์ ๋ฌํ๋ค. uniform์ ์ผ๋ฐ์ ์ผ๋ก ์นด๋ฉ๋ผ์ ์์น๋ ํ๊ฒฝ๊ด์ ์์น์ฒ๋ผ ์ ์ฒด์ ์ธ ๊ฒ์ ์ ๋ฌํ๋ค. Attribute๋ uniform์ ์ผ์ข ์ ๋ณ์์ธ๋ฐ ํธ๋ค์ ์ป์ด์์ ๊ทธ๊ฒ์ ํตํด ๊ฐ์ ์ ๋ฌํ ์ ์๋ค. ์ฆ Atrribute๋ Uniform์ Javascript์ธก์์ ์์ด๋๋ก ์ ๋ณด๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด๋ค. varying์ ์์ด๋ ๊ฐ์ ์ ๋ณด ์ ๋ฌ์ ์ฌ์ฉ๋๋ค. vertex shader์์ fragment shader๋ก ๊ฐ์ด ์ ๋ฌ๋๋ฉฐ ๋ฐ๋๋ ๋ถ๊ฐ๋ฅํ๋ค(ํ์ดํ๋ผ์ธ ๊ตฌ์กฐ์ ๋น์ฐํ ๊ฒ์ด๋ค). ์ด๋ vertex shader๋ ๊ฐ ์ ์ (๊ผญ์ง์ ) fragment shader๋ ๊ฐ ํฝ์ ์ ํ๋ฒ ํธ์ถ๋๊ฒ ๋๋๋ฐ ๊ฐ ์ ์ ์ฌ์ด์ ๊ฐ๋ค์ ๋ณด๊ฐ๋ฒ์ ๊ฑฐ์ณ ์ ๋ฌ๋๊ฒ ๋๋ค(๊ทธ๋ผ๋์ธํธ ๊ฐ์ ๋๋์ด๋ค ์ค๊ฐ๊ฐ์ ์์์ ๋ง๋ค์ด ์ค๋ค).
๊ฐ ์์ด๋๋ ๋์์ ๋์ํ ์ ์๋๋ฐ ๋น์ฐํ ์ด๋ค์ ์๋ก๊ฐ์ ๋
๋ฆฝ์ ์ด์ด์ผ ํ๋ค.
3.2. ์์ด๋ ¶
์์ด๋๋ ์์ด๋ ์ธ์ด๋ก ๋ฐ๋ก ์ง์ฃผ๊ณ ์ปดํ์ผ ํด์ผํ๋ฉฐ ์ฌ์ง์ด ๋งํฌ๊น์ง ์์ผ์ฃผ์ด์ผ ํ๋ค. GPU์ ๊ฐ๋ ฅํ ํ๋ ฌ์ฐ์ฐ ๋ฅ๋ ฅ์ ๊ฐ์ ธ๋ค ์ฐ๊ธฐ ์ํด์์ธ๊ฒ์ผ๋ก ๋ณด์ด๋๋ฐ ์ด๊ฒ์ ์ฌ์ฉํ์ง ์๊ณ ์๋ ์์ ํ์ผ๋ ๋๋ ค๋ณผ์๊ฐ ์๋ค. ๋คํ์ด ์ธ์ด๋ C์ธ์ด์ ๋งค์ฐ ์ ์ฌํ๊ณ ํ๋ ฌ์ฐ์ฐ์ด ๋ชจ๋ ์๊ธฐ ๋๋ฌธ์ ๋ฑํ ์ด๋ ต๊ฑฐ๋ ํ์ง ์๋ค. ๋ค๋ง ์ด๋๋ถ๋ถ์์ ์ด๋์ ์ฐ๊ฒฐ๋๋์ง ์ดํดํ๋๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค.
3.2.1. vertex shader ¶
๊ฐ ์ ์ (vertex, ๊ผญ์ง์ )๋ง๋ค ํธ์ถ๋๋ฉฐ ์ฃผ๋ก ๊ผญ์ง์ ์ ์์น๋ฅผ ์ฐ์ฐํ๊ณ ์ค์ View์ ํฌ์ํ๋ ์ฐ์ฐ์ ์ฃผ๋ก ํ๊ฒ ๋๋ค. ํ๋ง๋๋ก ๋ชจ๋ธ์ ์์น ๋ณํ๊ณผ ์นด๋ฉ๋ผ ์์ ์ ๋ฐ๋ฅธ ๋ณํ ์๊ทผ๋ฒ์ ์ ์ฉํ๋ ๋ณํ๋ฑ์ ์ํํ๋ค.
3.2.2. fragment shader ¶
๊ฐ ์ ์ ์ฌ์ด์ ์๋ ํฝ์
๋ง๋ค ํธ์ถ๋๋ค. ์ฃผ๋ก ๊ด์ํจ๊ณผ๋ฅผ ์ ์ฉํ ํฝ์
์ ์ต์ข
์ ์ธ ์๊น์ด๋ ํ
์ค์ณ ์ฐ์ฐ์ ์ฌ์ฉ๋๋ค. varying๋ณ์๋ฅผ vertex shader์์ fragment shader๋ก ๋๊ฒจ์ฃผ๋ฉด ๊ฐ ์ ์ ์ฌ์ด์๋ ๋ณด๊ฐ๋ฒ์ผ๋ก ๋ณํ๋ ๊ฐ์ด ๋์ด ์จ๋ค.
4. ์์ ์ฝ๋ ¶
์๋ ์ฝ๋๋ ์ ํํ์ง ์์ผ๋ฉฐ ์ฐ์ต ๋์ค์ ์ฝ๋์
๋๋ค. ๋ํ WebGL์ ํน์ฑ์ ์ฝ๋๊ฐ ๋ถ์ฐ๋์ด ์์ต๋๋ค. ํ์ฌ ๊ฐ์ฒด ๋ํ์ ์งํ์ค์
๋๋ค.
ํ์ฌ ๊ฐ์ฒด ๋ํ์ค ์ค๋ํ ๋ฌธ์ ์ ๋ด์ฐฉ. ๋๋ถ๋ถ์ ๋ชจ๋๊ณผ ์ธ์ด๋ ์ฝ๋๋ ์ฝ๋ฐฑ์ผ๋ก ํธ์ถ๋๋๋ฐ ์ด๊ฒ์ ์ ์ ํ ๋ํํ ๋ฐฉ๋ฒ์ด ์๋ค. webGL๊ณผ๋ ํ๋ฑ ์ฐ๊ด์ด ์๋ ๋ถ๋ถ์ด๋ผ์ ๊ฐ์ ์์์ ๊ตฌํํ๋๋ก ํด๋ ๋์ง๋ง ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๊ฐ์ ์ฝ๋๋ฅผ ๋ค์ค ์ง๊ณ ์๋ ๋๋ฅผ ๋ณด๊ฒ ๋๋ค. ์ด๊ฒ์ ์ด๋ป๊ฒ ํด์ผ ์ํ ๋ํ์ด๋ผ ํ ์ ์์๊น?
4.1. vertexShader ¶
attribute vec3 aVertexPosition; attribute vec3 aVertexNormal; uniform mat4 matCamara; uniform mat4 matProject; uniform vec3 lightPos; uniform vec3 lightDirection; uniform vec4 materialDiffuse; uniform vec4 lightDiffuse; varying vec4 vFinalColor; varying vec3 vNormal; void main(void){ vec3 N = normalize((vec4(aVertexNormal, 1.0) * matCamara).xyz);//nomal compute vec3 L = normalize(lightDirection); //lightDrection float lambertTerm = max(dot(N, -L), 0.0); vec4 Id = lightDiffuse * materialDiffuse * lambertTerm; vNormal = normalize((vec4(aVertexNormal, 1.0) * matCamara).xyz); vFinalColor = Id; vFinalColor.a = 1.0; gl_Position = matProject * matCamara * vec4((aVertexPosition), 1.0); gl_Position.w = 1.0; }
4.2. fragmentShader ¶
#ifdef GL_ES precision highp float; #endif uniform vec3 lightPos; uniform vec3 lightDirection; uniform vec4 materialDiffuse; uniform vec4 lightDiffuse; varying vec4 vFinalColor; varying vec3 vNormal; void main(void) { vec3 L = normalize(lightDirection); gl_FragColor = vFinalColor + vec4(0.01,0.01,0.01, 1.0); }
4.3. javascript ¶
var cube = { "vertices": [ 0.2, 0.2, 0.2, //0 0.2, 0.2,-0.2, //1 0.2,-0.2, 0.2, //2 0.2,-0.2,-0.2, //3 -0.2, 0.2,-0.2, //4 -0.2, 0.2, 0.2, //2 -0.2,-0.2,-0.2, //6 -0.2,-0.2, 0.2 //7 ], "normals": [ 1, 1, 1, //0 1, 1,-1, //1 1,-1, 1, //2 1,-1,-1, //3 -1, 1,-1, //4 -1, 1, 1, //5 -1,-1,-1, //6 -1,-1, 1 //7 ], "indices" : [ 0,2,3, 0,3,1, 4,6,7, 4,7,5, 4,5,0, 4,0,1, 7,6,3, 7,3,2, 5,7,2, 5,2,0, 1,3,6, 1,6,4 ] } var init = function(){ var gl = getGLContext(); var cubeBuffer = new GLBuffer(gl, cube); var shader; async.parallel([ function(callback){ var url = document.getElementById("vertexShader").getAttribute("src"); ajax(url, callback); }, function(callback){ var url = document.getElementById("fragmentShader").getAttribute("src"); ajax(url, callback); }, ], function (err, data){ shader = new GLShader(gl, data[0], data[1]); gl.useProgram(shader.program); shader.aVertexPosition = gl.getAttribLocation(shader.program, "aVertexPosition"); shader.aVertexNormal = gl.getAttribLocation(shader.program, "aVertexNormal"); var cam = gl.getUniformLocation(shader.program, "matCamara"); var camMat = mat4.identity(mat4.create()); mat4.translate(camMat, camMat, [0, 0, 0.1]); mat4.rotate(camMat, camMat, Math.PI/4, [1,0.5,0.5]); gl.uniformMatrix4fv(cam, false, camMat); var lightPos = shader.getUniformLocation("lightPos"); gl.uniform3fv(lightPos, [0.1,0.1,0.1]); var lightDirection = shader.getUniformLocation("lightDirection"); gl.uniform3fv(lightDirection, [-1, -1, -1]); var materialDiffuse = shader.getUniformLocation("materialDiffuse"); gl.uniform4fv(materialDiffuse, [0.8, 0.2, 0.2, 1.0]); var lightDiffuse = shader.getUniformLocation("lightDiffuse"); gl.uniform4fv(lightDiffuse, [1,1,1,1]); var matProject = mat4.identity(mat4.create());//2PI = 360d -> 1d = PI/180 mat4.perspective(matProject, Math.PI/180 * 80, 1, 0, 1); gl.uniformMatrix4fv( shader.getUniformLocation("matProject"), false, matProject ); onReady(gl, cubeBuffer, shader); }); } setTimeout(init, 0); function onReady(gl, buffer, shader){ onDraw(); function onDraw(){ gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.enable(gl.DEPTH_TEST); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.viewport(0,0,300,300); gl.enableVertexAttribArray(shader.aVertexPosition); gl.enableVertexAttribArray(shader.aVertexNormal); gl.bindBuffer(gl.ARRAY_BUFFER, buffer.vertex); gl.vertexAttribPointer(shader.aVertexPosition, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, buffer.normal); gl.vertexAttribPointer(shader.aVertexNormal, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.index); gl.drawElements(gl.TRIANGLES, buffer.index.length, gl.UNSIGNED_SHORT, 0); } } function ajax(url, callback){ var ajax = new XMLHttpRequest(); ajax.onreadystatechange = function(){ if(ajax.readyState === 4){ //complete requset if(ajax.status === 200){ //not error callback(null, ajax.responseText); } } } ajax.open("GET", url, true);//if need Sync method set false; ajax.send(null); } //Lib function function getGLContext(){ var canvas = document.getElementsByTagName("canvas"); canvas = [].filter.call(canvas, function(element){ if(element.getAttribute("WebGL") != null) return true; else return false; }); canvas = canvas[0]; return canvas.getContext("experimental-webgl"); } //Lib Class function GLBuffer(gl, model){ this.model = model; try { //only binded buffer can send data //vertex is coord of points var vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER, null); //index is triangle point index of suface var indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); //normals Buffer var normalBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(model.normals), gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER, null); this.vertex = vertexBuffer; this.index = indexBuffer; this.index.length = model.indices.length; this.normal = normalBuffer; } catch(e){ throw Error("Can not create Buffer"); } } function GLShader(gl, vertexSource, fragmentSource){ var shaderProgram = gl.createProgram(); //compile Source var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexSource); gl.compileShader(vertexShader); checkCompile(vertexShader); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentSource); gl.compileShader(fragmentShader); checkCompile(fragmentShader); //attach shader gl.attachShader(shaderProgram, fragmentShader); gl.attachShader(shaderProgram, vertexShader); //link gl.linkProgram(shaderProgram); this.program = shaderProgram; this._private = { gl : gl } function checkCompile(shader){ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { throw Error(gl.getShaderInfoLog(shader)); } } } GLShader.prototype.getUniformLocation = function(name){ return this._private.gl.getUniformLocation(this.program, name); } GLShader.prototype.uniform4fv = function(name, arr){ this._private.gl.uniform4fv(this.getUniformLocation(name), arr); } GLShader.prototype.uniform3fv = function(name, arr){ this._private.gl.uniform3fv(this.getUniformLocation(name), arr); } GLShader.prototype.uniformMatrix4fv = function(name, arr){ this._private.gl.uniformMatrix4fv(this.getUniformLocation(name), false, arr); }