on master help sign in
partial staging with stuff
fec4a41John P Mayer Jr
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
2
2
3{-| WebGL -}
3{-| WebGL -}
4
4
@@ -6,20 +6,29 @@ import Graphics.Element (Element)
6import Native.Graphics.WebGL
6import Native.Graphics.WebGL
7import Signal (Signal)
7import Signal (Signal)
8
8
9−data GL = Dummy_GL
10−
11−data Shader auv = Dummy_Shader
9+data Shader a u v = Dummy_Shader
12data Program a u = Dummy_Program
10data Program a u = Dummy_Program
13
11
14−link : GL -> Shader a u v -> Shader {} {} v -> Program a u
12+link : Shader a u v -> Shader {} {} v -> Program a u
15link = Native.Graphics.WebGL.link
13link = Native.Graphics.WebGL.link
16
14
17-- Binder really should not need a program
15-- Binder really should not need a program
18-- I need runtime type information from something though...
16-- I need runtime type information from something though...
19
17
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+
20data Buffer a = Dummy_Buffer
29data Buffer a = Dummy_Buffer
21
30
22−bind : GL -> Program a u -> [a] -> Buffer a
31+bind : [Triangle a] -> Buffer a
23bind = Native.Graphics.WebGL.bind
32bind = Native.Graphics.WebGL.bind
24
33
25-- Now I cheat here because elm lacks existential types or rank-n
34-- Now I cheat here because elm lacks existential types or rank-n
@@ -31,5 +40,5 @@ data Model = Dummy_Model
31encapsulate : Program a u -> Buffer a -> u -> Model
40encapsulate : Program a u -> Buffer a -> u -> Model
32encapsulate = Native.Graphics.WebGL.encapsulate
41encapsulate = Native.Graphics.WebGL.encapsulate
33
42
34−webgl : Signal (Int,Int) -> (Signal GL -> Signal [Model]) -> Signal Element
43+webgl : (Int,Int) -> [Model] -> Element
35webgl = Native.Graphics.WebGL.webgl
44webgl = Native.Graphics.WebGL.webgl
libraries/Native/Graphics/WebGL.js+94−45
@@ -1,6 +1,8 @@
1Elm.Native.Graphics.WebGL = {};
1Elm.Native.Graphics.WebGL = {};
2Elm.Native.Graphics.WebGL.make = function(elm) {
2Elm.Native.Graphics.WebGL.make = function(elm) {
3
3
4+ // LOG LEVEL
5+
4 elm.Native = elm.Native || {};
6 elm.Native = elm.Native || {};
5 elm.Native.Graphics = elm.Native.Graphics || {};
7 elm.Native.Graphics = elm.Native.Graphics || {};
6 elm.Native.Graphics.WebGL = elm.Native.Graphics.WebGL || {};
8 elm.Native.Graphics.WebGL = elm.Native.Graphics.WebGL || {};
@@ -17,17 +19,29 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
17
19
18 function encapsulate(program, buffer, uniforms) {
20 function encapsulate(program, buffer, uniforms) {
19
21
20− var model = {
22+ return model = {
21 program: program,
23 program: program,
22 buffer: buffer,
24 buffer: buffer,
23 uniforms: uniforms
25 uniforms: uniforms
24 };
26 };
25
27
28+ }
29+
30+ function link (vSrc, fSrc) {
31+
32+ var guid = Utils.guid();
33+
34+ console.log("Wrapped program #" + guid);
35+
26− return model;
36+ return program = {
37+ guid: guid,
38+ vSrc: vSrc,
39+ fSrc: fSrc
40+ };
27
41
28 }
42 }
29
43
30− function link (gl, vSrc, fSrc) {
44+ function do_link (gl, vSrc, fSrc) {
31
45
32 function createShader(str, type) {
46 function createShader(str, type) {
33
47
@@ -47,6 +61,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
47 var vshader = createShader(vSrc, gl.VERTEX_SHADER);
61 var vshader = createShader(vSrc, gl.VERTEX_SHADER);
48 var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
62 var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
49 var program = gl.createProgram();
63 var program = gl.createProgram();
64+ console.log("Created shaders and program");
50
65
51 gl.attachShader(program, vshader);
66 gl.attachShader(program, vshader);
52 gl.attachShader(program, fshader);
67 gl.attachShader(program, fshader);
@@ -59,7 +74,20 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
59
74
60 }
75 }
61
76
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+
62− function bind (gl, program, bufferElems) {
90+ function do_bind (gl, program, bufferElems) {
63
91
64 var buffers = {};
92 var buffers = {};
65
93
@@ -74,9 +102,15 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
74 // and then bind each one-at-a-time
102 // and then bind each one-at-a-time
75 var data = [];
103 var data = [];
76 List.each(function(elem){
104 List.each(function(elem){
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]);
77− data.push(elem[attribute.name][0]);
111+ data.push(elem._2[attribute.name][0]);
78− data.push(elem[attribute.name][1]);
112+ data.push(elem._2[attribute.name][1]);
79− data.push(elem[attribute.name][2]);
113+ data.push(elem._2[attribute.name][2]);
80 }, bufferElems);
114 }, bufferElems);
81 var array = new Float32Array(data);
115 var array = new Float32Array(data);
82
116
@@ -96,8 +130,8 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
96
130
97 }
131 }
98
132
99− var numIndices = List.length(bufferElems);
133+ var numIndices = 3 * List.length(bufferElems);
100− var indices = List.toArray(List.range(0,numIndices));
134+ var indices = List.toArray(List.range(0, numIndices - 1));
101 console.log("Created index buffer");
135 console.log("Created index buffer");
102 var indexBuffer = gl.createBuffer();
136 var indexBuffer = gl.createBuffer();
103 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
137 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
@@ -113,13 +147,21 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
113
147
114 }
148 }
115
149
116− function drawGL(gl,state) {
150+ function drawGL(model) {
151+
152+ var gl = model.cache.gl;
117
153
118 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
154 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
155+ console.log("Drawing");
156+
157+ function drawModel(m) {
119
158
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+ }
121
164
122− var program = model.program;
123 gl.useProgram(program);
165 gl.useProgram(program);
124
166
125 var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
167 var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
@@ -128,7 +170,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
128 var uniformLocation = gl.getUniformLocation(program, uniform.name);
170 var uniformLocation = gl.getUniformLocation(program, uniform.name);
129 switch (uniform.type) {
171 switch (uniform.type) {
130 case gl.FLOAT_MAT4:
172 case gl.FLOAT_MAT4:
131− gl.uniformMatrix4fv(uniformLocation, false, model.uniforms[uniform.name]);
173+ gl.uniformMatrix4fv(uniformLocation, false, m.uniforms[uniform.name]);
132 break;
174 break;
133 default:
175 default:
134 console.log("Unsupported uniform type: " + uniform.type);
176 console.log("Unsupported uniform type: " + uniform.type);
@@ -136,8 +178,14 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
136 }
178 }
137 }
179 }
138
180
139− var numIndices = model.buffer.numIndices;
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;
140− var indexBuffer = model.buffer.indexBuffer;
188+ var indexBuffer = buffer.indexBuffer;
141 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
189 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
142
190
143 var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
191 var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
@@ -145,7 +193,7 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
145 var attribute = gl.getActiveAttrib(program, i);
193 var attribute = gl.getActiveAttrib(program, i);
146 var attribLocation = gl.getAttribLocation(program, attribute.name);
194 var attribLocation = gl.getAttribLocation(program, attribute.name);
147 gl.enableVertexAttribArray(attribLocation);
195 gl.enableVertexAttribArray(attribLocation);
148− attributeBuffer = model.buffer.buffers[attribute.name];
196+ attributeBuffer = buffer.buffers[attribute.name];
149
197
150 switch (attribute.type) {
198 switch (attribute.type) {
151 case gl.FLOAT_VEC3:
199 case gl.FLOAT_VEC3:
@@ -162,58 +210,59 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
162
210
163 }
211 }
164
212
165− List.each(drawModel, state.models);
213+ List.each(drawModel, model.models);
166
214
167 }
215 }
168
216
169− function webgl(sDimensions, sfDraw) {
217+ function webgl(dimensions, models) {
170
218
171 if (!window.WebGLRenderingContext) {
219 if (!window.WebGLRenderingContext) {
172 throw new Error("It appears your browser does not support WebGL! http://get.webgl.org/troubleshooting");
220 throw new Error("It appears your browser does not support WebGL! http://get.webgl.org/troubleshooting");
173 return;
221 return;
174 }
222 }
175
223
176− var node = newNode('canvas');
224+ var w = dimensions._0;
177− var gl = node.getContext('webgl');
225+ var h = dimensions._1;
178− var sGL = Signal.constant(gl);
179
226
180− var sModels = sfDraw(sGL);
227+ function render(model) {
181
228
182− function makeGLelement(dimensions, models, gl) {
229+ var node = newNode('canvas');
230+ var gl = node.getContext('webgl');
183
231
184− var w = dimensions._0;
232+ model.cache.gl = gl;
185− var h = dimensions._1;
233+ model.cache.programs = [];
234+ model.cache.buffers = [];
186
235
187− function render(state) {
188− drawGL(gl,state);
236+ drawGL(model);
189− return node;
237+ return node;
190− }
191
238
192− function update(_node, oldState, newState) {
193− drawGL(gl,newState)
194− }
239+ }
195
240
196− var elem = {
241+ function update(_node, oldModel, newModel) {
197− ctor: 'Custom',
198− type: 'WebGL',
199− render: render,
200− update: update,
201− model: {
202− models: models,
203− }
204− };
205
242
206− return A3(newElement, w, h, elem);
243+ newModel.cache = oldModel.cache;
244+ drawGL(newModel);
207
245
208 }
246 }
209
247
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);
211
260
212 }
261 }
213
262
214 return elm.Native.Graphics.WebGL.values = {
263 return elm.Native.Graphics.WebGL.values = {
215− link:F3(link),
264+ link:F2(link),
216− bind:F3(bind),
265+ bind:bind,
217 encapsulate:F3(encapsulate),
266 encapsulate:F3(encapsulate),
218 webgl:F2(webgl)
267 webgl:F2(webgl)
219 };
268 };
tests/good/Box.elm+33−15
@@ -1,38 +1,56 @@
1
1
2−import MJS (V3,v3,m4x4makeRotate)
2+import MJS (V3,v3,M4x4,m4x4makeRotate)
3−import Graphics.WebGL (GL, Model, link, bind, encapsulate, webgl)
3+import Graphics.WebGL (Program, link, Triangle, zipTriangle, Buffer, bind, Model, encapsulate, webgl)
4
4
5-- Define what our geometry looks like
5-- Define what our geometry looks like
6
6
7−top = v3 0 1 0
7+topleft = v3 -1 1 0
8+topright = v3 1 1 0
8−left = v3 -1 -1 0
9+botleft = v3 -1 -1 0
9−right = v3 1 -1 0
10+botright = v3 1 -1 0
10
11
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+
11−mesh : [{ pos : V3 }]
18+mesh : [Triangle {pos : V3, color : V3}]
12−mesh = map (\vec -> { pos = vec }) [top, left, right]
19+mesh = zipWith (zipTriangle (\pos color -> { pos = pos, color = color })) [(topleft, topright, botleft), (topright, botleft, botright)] colors
13
20
14vert = [glShader|
21vert = [glShader|
15attribute vec3 pos;
22attribute vec3 pos;
23+attribute vec3 color;
16uniform mat4 rot;
24uniform mat4 rot;
25+varying vec3 vcolor;
17void main () {
26void main () {
18 gl_Position = rot * vec4(pos, 1.0);
27 gl_Position = rot * vec4(pos, 1.0);
28+ vcolor = color;
19}
29}
20|]
30|]
21
31
22frag = [glShader|
32frag = [glShader|
33+precision mediump float;
34+varying vec3 vcolor;
23void main () {
35void main () {
24− gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
36+ gl_FragColor = vec4(vcolor, 1.0);
25}
37}
26|]
38|]
27
39
28−draw : Signal Float -> Signal GL -> Signal [Model]
40+prog : Program {pos : V3, color : V3} { rot : M4x4 }
29−draw theta gl =
30− let prog = link <~ gl ~ constant vert ~ constant frag
41+prog = link vert frag
42+
43+buf : Buffer {pos : V3, color : V3}
31− buf = bind <~ gl ~ prog ~ constant mesh
44+buf = bind mesh
32− rot = (\t vec -> { rot = m4x4makeRotate t vec }) <~ theta ~ constant (v3 0 1 0)
33− in combine [ encapsulate <~ prog ~ buf ~ rot ]
34
45
46+angle : Signal Float
35angle = foldp (\_ n -> n + 0.1) 0 (fps 25)
47angle = foldp (\_ n -> n + 0.1) 0 (fps 25)
36
48
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+
37−main = webgl (constant (400,400)) (draw angle)
55+main = webgl (400,400) <~ draw
38
56