on master help sign in
starting something new here
8bfca73John P Mayer Jr
libraries/Graphics/WebGL.elm+16−20
@@ -1,32 +1,28 @@
1−module Graphics.WebGL (makeGL, linkProgram, linkModel, webgl) where
1+module Graphics.WebGL (encapsulate, webgl) where
2
2
3−{-| WebGL
3+{-| WebGL -}
4
4
5−-}
6−
7−import Basics (Float)
8−import Signal (Signal)
9−import MJS (V3,M4x4)
10−import Color (Color)
11import Graphics.Element (Element)
5import Graphics.Element (Element)
12import Native.Graphics.WebGL
6import Native.Graphics.WebGL
13
7
14−data GLContext = Fake_Context
8+data Shader a u v = Dummy_Shader
9+data Program a u = Dummy_Program
10+type Linker = Shader a u v -> Shader {} {} v -> Program a u
15
11
16−makeGL : Int -> Int -> Signal GLContext
12+-- Binder really should not need a program
17−makeGL = Native.Graphics.WebGL.makeGL
13+-- I need runtime type information from something though...
18
14
19−data GLShader declarations = Fake_GLShader
15+data Buffer a = Dummy_Buffer
20−data GLProgram attributes = Fake_Program
16+type Binder = Program a u -> [a] -> Buffer a
21
17
22−linkProgram : GLShader { attribute : a, uniform : u, varying : v } -> GLShader { attribute : {}, uniform : {}, varying : v } -> GLContext -> GLProgram { attribute : a, uniform : u }
18+-- Now I cheat here because elm lacks existential types or rank-n
23−linkProgram = Native.Graphics.WebGL.linkProgram
19+-- I'm in essense doing the following
20+-- data Model = forall a u. Model (Program a u) (Buffer a) u
24
21
25−data GLModel = Fake_Model
22+data Model = Dummy_Model
26
23
27−linkModel : (GLProgram { attribute : a, uniform : u }) -> u -> [a] -> GLModel
24+encapsulate : Program a u -> Buffer a -> u -> Model
28−linkModel = Native.Graphics.WebGL.linkModel
25+encapsulate = Native.Graphics.WebGL.encapsulate
29
26
30−webgl : GLContext -> [GLModel] -> Element
27+webgl : Int -> Int -> (Linker -> Binder -> [Model]) -> Element
31webgl = Native.Graphics.WebGL.webgl
28webgl = Native.Graphics.WebGL.webgl
32−
libraries/Native/Graphics/WebGL.js+103−132
@@ -15,76 +15,111 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
15 var MJS = Elm.Native.MJS.make(elm);
15 var MJS = Elm.Native.MJS.make(elm);
16 var List = Elm.Native.List.make(elm);
16 var List = Elm.Native.List.make(elm);
17
17
18− function createShader(gl, str, type) {
18+ function encapsulate(program, buffer, uniforms) {
19− var shader = gl.createShader(type);
20− gl.shaderSource(shader, str);
21− gl.compileShader(shader);
22
19
23− if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
20+ var model = {
24− throw gl.getShaderInfoLog(shader);
21+ program: program,
25− }
22+ buffer: buffer,
23+ uniforms: uniforms
24+ };
26
25
27− return shader;
26+ return model;
28− };
29
27
30− function linkProgram(vSrc, fSrc, context) {
31− var gl = context.gl;
32− var vshader = createShader(gl, vSrc, gl.VERTEX_SHADER);
33− var fshader = createShader(gl, fSrc, gl.FRAGMENT_SHADER);
34− var program = gl.createProgram()
35− gl.attachShader(program, vshader);
36− gl.attachShader(program, fshader);
37− gl.linkProgram(program);
38− if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
39− throw gl.getProgramInfoLog(program);
40− }
41− return program;
42 }
28 }
43
29
44− function drawGL(model) {
30+ function webgl(w, h, draw) {
45− var aspect = model.aspect;
46
31
47− var gl = model.gl;
32+ var node = newNode('canvas');
48− gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
33+ var gl = node.getContext('webgl');
49
34
50− var program = model.program;
35+ function link (vSrc, fSrc) {
51
36
52− function drawMesh(mesh, sceneMatrix) {
37+ function createShader(str, type) {
53− gl.useProgram(program.programPtr);
54−
55− gl.enableVertexAttribArray(program.vertexPositionAttribute);
56− gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indexBuffer);
57− gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vertexPosBuffer);
58− gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
59
38
60− gl.enableVertexAttribArray(program.vertexColorAttribute);
39+ var shader = gl.createShader(type);
61− gl.bindBuffer(gl.ARRAY_BUFFER, mesh.vertexColorBuffer);
40+
62− gl.vertexAttribPointer(program.vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
41+ gl.shaderSource(shader, str);
42+ gl.compileShader(shader);
43+ var compile = gl.COMPILE_STATUS;
44+ if (!gl.getShaderParameter(shader,compile)) {
45+ throw gl.getShaderInfoLog(shader);
46+ }
47+
48+ return shader;
49+
50+ };
51+
52+ var vshader = createShader(vSrc, gl.VERTEX_SHADER);
53+ var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
54+ var program = gl.createProgram();
55+
56+ gl.attachShader(program, vshader);
57+ gl.attachShader(program, fshader);
58+ gl.linkProgram(program);
59+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
60+ throw gl.getProgramInfoLog(program);
61+ }
62+
63+ return program;
63
64
64− gl.uniformMatrix4fv(program.sceneMatrixUniform, false, sceneMatrix);
65−
66− gl.drawElements(gl.TRIANGLES, mesh.numIndices, gl.UNSIGNED_SHORT, 0);
67 }
65 }
68
66
69− var sceneMatrixStack = [MJS.M4x4.identity];
67+ function bind (program, bufferElems) {
70−
68+
71− function drawScene(scene,n) {
69+ var bufferObject = {};
72− switch(scene.ctor) {
70+
73− case 'SceneLeaf':
71+ var attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
74− drawMesh(scene._0, sceneMatrixStack[n]);
72+ for (var i = 0; i < attributes; i += 1) {
75− break;
73+ var attribute = gl.getActiveAttrib(program, i);
76− default:
74+ switch (attribute.type) {
77− var m = scene._0;
75+ case gl.FLOAT_VEC3:
78− sceneMatrixStack[n+1] = MJS.M4x4.mul(sceneMatrixStack[n],m)
76+
79− function drawChild(c) {
77+ // Might want to invert the loop
80− drawScene(c,n+1);
78+ // to build the array buffer first
81− }
79+ // and then bind each one-at-a-time
82− var children = scene._1;
80+ var data = [];
83− List.each(drawChild, children);
81+ List.each(function(elem){
82+ data.push(elem[attribute.name][0]);
83+ data.push(elem[attribute.name][1]);
84+ data.push(elem[attribute.name][2]);
85+ }, bufferElems);
86+ var array = new Float32Array(data);
87+
88+ var buffer = gl.createBuffer();
89+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
90+ gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
91+
92+ bufferObject[attribute.name] = buffer;
93+
94+ break;
95+
96+ default:
97+ console.log("Bad buffer type");
84− break;
98+ break;
99+ }
100+
85 }
101 }
102+
103+ return bufferObject;
104+
105+ }
106+
107+ function render(model) {
108+ drawGL(model);
109+ return model.node;
86 }
110 }
87−
111+
112+ function update(canvasNode, oldModel, newModel) {
113+ drawGL(newModel)
114+ }
115+
116+ }
117+
118+ function drawGL(model) {
119+
120+ var gl = model.gl;
121+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
122+
88 function drawModel(glModel) {
123 function drawModel(glModel) {
89 var program = glModel.program;
124 var program = glModel.program;
90 gl.useProgram(program);
125 gl.useProgram(program);
@@ -156,90 +191,26 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
156 drawGL(newModel)
191 drawGL(newModel)
157 }
192 }
158
193
159− function makeGL(w,h) {
160− var node = newNode('canvas');
161− var gl = node.getContext('webgl');
162− return Signal.constant({w:w,h:h,gl:gl,node:node});
163− }
164−
165− function bufferMesh(triangles, context) {
166− var indices = [];
167− var positions = [];
168− var colors = [];
169−
170− function pushTriangle(n, node) {
171− if (node.ctor === "[]") return;
172− var tri = node._0;
173− for (var i = 0; i < 3; i+= 1) {
174− indices.push(3 * n + i);
175− var vertex = tri['_' + i];
176− for (var j = 0; j < 3; j += 1) {
177− positions.push(vertex.pos[j]);
178− }
179− colors.push(vertex.color._0 / 256);
180− colors.push(vertex.color._1 / 256);
181− colors.push(vertex.color._2 / 256);
182− colors.push(vertex.color._3);
183− }
184− pushTriangle(n+1,node._1);
185− }
186−
187− pushTriangle(0,triangles);
188−
189− var gl = context.gl;
190−
191− var indexBuffer = gl.createBuffer();
192− gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
193− gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
194−
195− var vertexPosBuffer = gl.createBuffer();
196− gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
197− gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
198−
199− var vertexColorBuffer = gl.createBuffer();
200− gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
201− gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
202−
203− return {
204− indexBuffer: indexBuffer,
205− vertexPosBuffer: vertexPosBuffer,
206− vertexColorBuffer: vertexColorBuffer,
207− numIndices: indices.length,
208− };
209−
210− }
211−
212 function webgl(context, glModels) {
194 function webgl(context, glModels) {
213−
195+
214 return A3(newElement, context.w, context.h, {
196 return A3(newElement, context.w, context.h, {
215 ctor: 'Custom',
197 ctor: 'Custom',
216− type: 'WebGL',
198+ type: 'WebGL',
217− render: render,
199+ render: render,
218− update: update,
200+ update: update,
219− model: {
201+ model: {
220− aspect: context.w/context.h,
202+ aspect: context.w/context.h,
221− node: context.node,
203+ node: context.node,
222− gl: context.gl,
204+ gl: context.gl,
223− glModels: glModels,
205+ glModels: glModels,
224− },
206+ },
225 });
207 });
226
208
227 }
209 }
228
210
229− function linkModel(program, uniforms, attributes) {
230− return {
231− program: program,
232− uniforms: uniforms,
233− attributes: attributes,
234− };
235− }
236−
237 return elm.Native.Graphics.WebGL.values = {
211 return elm.Native.Graphics.WebGL.values = {
238− makeGL:F2(makeGL),
212+ encapsulate:F3(linkModel),
239− bufferMesh:F2(bufferMesh),
213+ webgl:F3(webgl),
240− webgl:F2(webgl),
241− linkProgram:F3(linkProgram),
242− linkModel:F3(linkModel),
243 };
214 };
244
215
245};
216};