on master help sign in
partial staging with stuff
commitfec4a41521eb0d15b2c09d63459f17c04629a35b authorJohn P Mayer Jr <john.p.mayer.jr@gmail.com> dateTue 10 Dec 2013, 20:11 (13 years ago) parent3c338bd
3 files changed+143−67
libraries/Graphics/WebGL.elm+16−7 libraries/Native/Graphics/WebGL.js+94−45 tests/good/Box.elm+33−15
libraries/Graphics/WebGL.elm+16−7
@@ -1,4 +1,4 @@
1−module Graphics.WebGL (link, bind, encapsulate, webgl) where
1+module Graphics.WebGL (link, mapTriangle, zipTriangle, bind, encapsulate, webgl) where
22
33{-| WebGL -}
44
@@ -6,20 +6,29 @@ import Graphics.Element (Element)
66import Native.Graphics.WebGL
77import Signal (Signal)
88
9−data GL = Dummy_GL
10−
11−data Shader auv = Dummy_Shader
9+data Shader a u v = Dummy_Shader
1210data Program a u = Dummy_Program
1311
14−link : GL -> Shader a u v -> Shader {} {} v -> Program a u
12+link : Shader a u v -> Shader {} {} v -> Program a u
1513link = Native.Graphics.WebGL.link
1614
1715-- Binder really should not need a program
1816-- I need runtime type information from something though...
1917
18+type Triangle a = (a,a,a)
19+
20+triangle : a -> a -> a -> Triangle a
21+triangle = (,,)
22+
23+mapTriangle : (a -> b) -> Triangle a -> Triangle b
24+mapTriangle f (x,y,z) = (f x, f y, f z)
25+
26+zipTriangle : (a -> b -> c) -> Triangle a -> Triangle b -> Triangle c
27+zipTriangle f (x,y,z) (x',y',z') = (f x x', f y y', f z z')
28+
2029data Buffer a = Dummy_Buffer
2130
22−bind : GL -> Program a u -> [a] -> Buffer a
31+bind : [Triangle a] -> Buffer a
2332bind = Native.Graphics.WebGL.bind
2433
2534-- Now I cheat here because elm lacks existential types or rank-n
@@ -31,5 +40,5 @@ data Model = Dummy_Model
3140encapsulate : Program a u -> Buffer a -> u -> Model
3241encapsulate = Native.Graphics.WebGL.encapsulate
3342
34−webgl : Signal (Int,Int) -> (Signal GL -> Signal [Model]) -> Signal Element
43+webgl : (Int,Int) -> [Model] -> Element
3544webgl = Native.Graphics.WebGL.webgl
libraries/Native/Graphics/WebGL.js+94−45
@@ -1,6 +1,8 @@
11Elm.Native.Graphics.WebGL = {};
22Elm.Native.Graphics.WebGL.make = function(elm) {
33
4+ // LOG LEVEL
5+
46 elm.Native = elm.Native || {};
57 elm.Native.Graphics = elm.Native.Graphics || {};
68 elm.Native.Graphics.WebGL = elm.Native.Graphics.WebGL || {};
@@ -17,17 +19,29 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
1719
1820 function encapsulate(program, buffer, uniforms) {
1921
20− var model = {
22+ return model = {
2123 program: program,
2224 buffer: buffer,
2325 uniforms: uniforms
2426 };
2527
26− return model;
28+ }
29+
30+ function link (vSrc, fSrc) {
31+
32+ var guid = Utils.guid();
33+
34+ console.log("Wrapped program #" + guid);
35+
36+ return program = {
37+ guid: guid,
38+ vSrc: vSrc,
39+ fSrc: fSrc
40+ };
2741
2842 }
2943
30− function link (gl, vSrc, fSrc) {
44+ function do_link (gl, vSrc, fSrc) {
3145
3246 function createShader(str, type) {
3347
@@ -47,6 +61,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
4761 var vshader = createShader(vSrc, gl.VERTEX_SHADER);
4862 var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
4963 var program = gl.createProgram();
64+ console.log("Created shaders and program");
5065
5166 gl.attachShader(program, vshader);
5267 gl.attachShader(program, fshader);
@@ -59,7 +74,20 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
5974
6075 }
6176
62− function bind (gl, program, bufferElems) {
77+ function bind (bufferElems) {
78+
79+ var guid = Utils.guid();
80+
81+ console.log("Wrapped buffer #" + guid);
82+
83+ return buffer = {
84+ guid: guid,
85+ bufferElems: bufferElems
86+ };
87+
88+ }
89+
90+ function do_bind (gl, program, bufferElems) {
6391
6492 var buffers = {};
6593
@@ -74,9 +102,15 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
74102 // and then bind each one-at-a-time
75103 var data = [];
76104 List.each(function(elem){
77− data.push(elem[attribute.name][0]);
78− data.push(elem[attribute.name][1]);
79− data.push(elem[attribute.name][2]);
105+ data.push(elem._0[attribute.name][0]);
106+ data.push(elem._0[attribute.name][1]);
107+ data.push(elem._0[attribute.name][2]);
108+ data.push(elem._1[attribute.name][0]);
109+ data.push(elem._1[attribute.name][1]);
110+ data.push(elem._1[attribute.name][2]);
111+ data.push(elem._2[attribute.name][0]);
112+ data.push(elem._2[attribute.name][1]);
113+ data.push(elem._2[attribute.name][2]);
80114 }, bufferElems);
81115 var array = new Float32Array(data);
82116
@@ -96,8 +130,8 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
96130
97131 }
98132
99− var numIndices = List.length(bufferElems);
100− var indices = List.toArray(List.range(0,numIndices));
133+ var numIndices = 3 * List.length(bufferElems);
134+ var indices = List.toArray(List.range(0, numIndices - 1));
101135 console.log("Created index buffer");
102136 var indexBuffer = gl.createBuffer();
103137 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
@@ -113,13 +147,21 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
113147
114148 }
115149
116− function drawGL(gl,state) {
150+ function drawGL(model) {
151+
152+ var gl = model.cache.gl;
117153
118154 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
155+ console.log("Drawing");
156+
157+ function drawModel(m) {
119158
120− function drawModel(model) {
159+ var program = model.cache.programs[m.program.guid];
160+ if (!program) {
161+ program = do_link(gl, m.program.vSrc, m.program.fSrc);
162+ model.cache.programs[m.program.guid] = program;
163+ }
121164
122− var program = model.program;
123165 gl.useProgram(program);
124166
125167 var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
@@ -128,7 +170,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
128170 var uniformLocation = gl.getUniformLocation(program, uniform.name);
129171 switch (uniform.type) {
130172 case gl.FLOAT_MAT4:
131− gl.uniformMatrix4fv(uniformLocation, false, model.uniforms[uniform.name]);
173+ gl.uniformMatrix4fv(uniformLocation, false, m.uniforms[uniform.name]);
132174 break;
133175 default:
134176 console.log("Unsupported uniform type: " + uniform.type);
@@ -136,8 +178,14 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
136178 }
137179 }
138180
139− var numIndices = model.buffer.numIndices;
140− var indexBuffer = model.buffer.indexBuffer;
181+ var buffer = model.cache.buffers[m.buffer.guid];
182+ if (!buffer) {
183+ buffer = do_bind(gl, program, m.buffer.bufferElems);
184+ model.cache.buffers[m.buffer.guid] = buffer;
185+ }
186+
187+ var numIndices = buffer.numIndices;
188+ var indexBuffer = buffer.indexBuffer;
141189 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
142190
143191 var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
@@ -145,7 +193,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
145193 var attribute = gl.getActiveAttrib(program, i);
146194 var attribLocation = gl.getAttribLocation(program, attribute.name);
147195 gl.enableVertexAttribArray(attribLocation);
148− attributeBuffer = model.buffer.buffers[attribute.name];
196+ attributeBuffer = buffer.buffers[attribute.name];
149197
150198 switch (attribute.type) {
151199 case gl.FLOAT_VEC3:
@@ -162,58 +210,59 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
162210
163211 }
164212
165− List.each(drawModel, state.models);
213+ List.each(drawModel, model.models);
166214
167215 }
168216
169− function webgl(sDimensions, sfDraw) {
217+ function webgl(dimensions, models) {
170218
171219 if (!window.WebGLRenderingContext) {
172220 throw new Error("It appears your browser does not support WebGL! http://get.webgl.org/troubleshooting");
173221 return;
174222 }
175223
176− var node = newNode('canvas');
177− var gl = node.getContext('webgl');
178− var sGL = Signal.constant(gl);
224+ var w = dimensions._0;
225+ var h = dimensions._1;
179226
180− var sModels = sfDraw(sGL);
227+ function render(model) {
181228
182− function makeGLelement(dimensions, models, gl) {
229+ var node = newNode('canvas');
230+ var gl = node.getContext('webgl');
183231
184− var w = dimensions._0;
185− var h = dimensions._1;
232+ model.cache.gl = gl;
233+ model.cache.programs = [];
234+ model.cache.buffers = [];
186235
187− function render(state) {
188− drawGL(gl,state);
189− return node;
190− }
236+ drawGL(model);
237+ return node;
191238
192− function update(_node, oldState, newState) {
193− drawGL(gl,newState)
194− }
239+ }
195240
196− var elem = {
197− ctor: 'Custom',
198− type: 'WebGL',
199− render: render,
200− update: update,
201− model: {
202− models: models,
203− }
204− };
241+ function update(_node, oldModel, newModel) {
205242
206− return A3(newElement, w, h, elem);
243+ newModel.cache = oldModel.cache;
244+ drawGL(newModel);
207245
208246 }
209247
210− return A4(Signal.lift3,F3(makeGLelement),sDimensions,sModels,sGL);
248+ var elem = {
249+ ctor: 'Custom',
250+ type: 'WebGL',
251+ render: render,
252+ update: update,
253+ model: {
254+ models: models,
255+ cache: {},
256+ }
257+ };
258+
259+ return A3(newElement, w, h, elem);
211260
212261 }
213262
214263 return elm.Native.Graphics.WebGL.values = {
215− link:F3(link),
216− bind:F3(bind),
264+ link:F2(link),
265+ bind:bind,
217266 encapsulate:F3(encapsulate),
218267 webgl:F2(webgl)
219268 };
tests/good/Box.elm+33−15
@@ -1,38 +1,56 @@
11
2−import MJS (V3,v3,m4x4makeRotate)
3−import Graphics.WebGL (GL, Model, link, bind, encapsulate, webgl)
2+import MJS (V3,v3,M4x4,m4x4makeRotate)
3+import Graphics.WebGL (Program, link, Triangle, zipTriangle, Buffer, bind, Model, encapsulate, webgl)
44
55-- Define what our geometry looks like
66
7−top = v3 0 1 0
8−left = v3 -1 -1 0
9−right = v3 1 -1 0
7+topleft = v3 -1 1 0
8+topright = v3 1 1 0
9+botleft = v3 -1 -1 0
10+botright = v3 1 -1 0
1011
11−mesh : [{ pos : V3 }]
12−mesh = map (\vec -> { pos = vec }) [top, left, right]
12+red = v3 1 0 0
13+green = v3 0 1 0
14+blue = v3 0 0 1
15+
16+colors = [(red,green,blue),(red,green,blue)]
17+
18+mesh : [Triangle {pos : V3, color : V3}]
19+mesh = zipWith (zipTriangle (\pos color -> { pos = pos, color = color })) [(topleft, topright, botleft), (topright, botleft, botright)] colors
1320
1421vert = [glShader|
1522attribute vec3 pos;
23+attribute vec3 color;
1624uniform mat4 rot;
25+varying vec3 vcolor;
1726void main () {
1827 gl_Position = rot * vec4(pos, 1.0);
28+ vcolor = color;
1929}
2030|]
2131
2232frag = [glShader|
33+precision mediump float;
34+varying vec3 vcolor;
2335void main () {
24− gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
36+ gl_FragColor = vec4(vcolor, 1.0);
2537}
2638|]
2739
28−draw : Signal Float -> Signal GL -> Signal [Model]
29−draw theta gl =
30− let prog = link <~ gl ~ constant vert ~ constant frag
31− buf = bind <~ gl ~ prog ~ constant mesh
32− rot = (\t vec -> { rot = m4x4makeRotate t vec }) <~ theta ~ constant (v3 0 1 0)
33− in combine [ encapsulate <~ prog ~ buf ~ rot ]
40+prog : Program {pos : V3, color : V3} { rot : M4x4 }
41+prog = link vert frag
42+
43+buf : Buffer {pos : V3, color : V3}
44+buf = bind mesh
3445
46+angle : Signal Float
3547angle = foldp (\_ n -> n + 0.1) 0 (fps 25)
3648
37−main = webgl (constant (400,400)) (draw angle)
49+rot : Signal { rot : M4x4 }
50+rot = (\t -> { rot = m4x4makeRotate t (v3 0 1 0) }) <~ angle
51+
52+draw : Signal [Model]
53+draw = combine [ (encapsulate prog buf) <~ rot ]
54+
55+main = webgl (400,400) <~ draw
3856