on master help sign in
much cleaned API in my opinion, plus a much simpler example
commit68e8bca2c47933bf84314b3c9d4d793197914510 authorJohn P Mayer Jr <john.p.mayer.jr@gmail.com> dateSun 8 Dec 2013, 23:05 (13 years ago) parent8bfca73
6 files changed+163−197
.gitignore+2 compiler/Type/Constrain/Expression.hs+1−1 libraries/Graphics/WebGL.elm+11−5 libraries/Native/Graphics/WebGL.js+126−143 tests/good/.gitignore−2 tests/good/Box.elm+23−46
.gitignore+2
@@ -10,3 +10,5 @@ cabal-dev
1010data
1111*/ElmFiles/*
1212.DS_Store
13+build
14+cache
compiler/Type/Constrain/Expression.hs+1−1
@@ -42,7 +42,7 @@ constrain env (L span expr) tipe =
4242 Nothing -> throwError [PP.text "Some sort of GLSL parse error"]
4343 Just sourceTipe -> return . L span $ CEqual tipe (shaderTipe sourceTipe)
4444 where
45− shaderTipe t = Env.get env Env.types "Graphics.WebGL.GLShader" <| t
45+ shaderTipe t = Env.get env Env.types "Graphics.WebGL.Shader" <| t
4646 glTipe = Env.get env Env.types . PH.glTipeName
4747 declsRecord :: PH.GLShaderDecls -> TermN Variable
4848 declsRecord extractedTipes = record (fields' extractedTipes) (TermN EmptyRecord1)
libraries/Graphics/WebGL.elm+11−5
@@ -1,19 +1,25 @@
1−module Graphics.WebGL (encapsulate, webgl) where
1+module Graphics.WebGL (link, bind, encapsulate, webgl) where
22
33{-| WebGL -}
44
55import Graphics.Element (Element)
66import Native.Graphics.WebGL
77
8−data Shader a u v = Dummy_Shader
8+data GL = Dummy_GL
9+
10+data Shader auv = Dummy_Shader
911data Program a u = Dummy_Program
10−type Linker = Shader a u v -> Shader {} {} v -> Program a u
12+
13+link : GL -> Shader { attribute : a, uniform : u, varying : v } -> Shader { attribute : {}, uniform : {}, varying : v } -> Program a u
14+link = Native.Graphics.WebGL.link
1115
1216-- Binder really should not need a program
1317-- I need runtime type information from something though...
1418
1519data Buffer a = Dummy_Buffer
16−type Binder = Program a u -> [a] -> Buffer a
20+
21+bind : GL -> Program a u -> [a] -> Buffer a
22+bind = Native.Graphics.WebGL.bind
1723
1824-- Now I cheat here because elm lacks existential types or rank-n
1925-- I'm in essense doing the following
@@ -24,5 +30,5 @@ data Model = Dummy_Model
2430encapsulate : Program a u -> Buffer a -> u -> Model
2531encapsulate = Native.Graphics.WebGL.encapsulate
2632
27−webgl : Int -> Int -> (Linker -> Binder -> [Model]) -> Element
33+webgl : Int -> Int -> (GL -> [Model]) -> Element
2834webgl = Native.Graphics.WebGL.webgl
libraries/Native/Graphics/WebGL.js+126−143
@@ -27,190 +27,173 @@ Elm.Native.Graphics.WebGL.make = function(elm) {
2727
2828 }
2929
30− function webgl(w, h, draw) {
31−
32− var node = newNode('canvas');
33− var gl = node.getContext('webgl');
34−
35− function link (vSrc, fSrc) {
30+ function link (gl, vSrc, fSrc) {
3631
37− function createShader(str, type) {
32+ function createShader(str, type) {
3833
39− var shader = gl.createShader(type);
34+ var shader = gl.createShader(type);
4035
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− };
36+ gl.shaderSource(shader, str);
37+ gl.compileShader(shader);
38+ var compile = gl.COMPILE_STATUS;
39+ if (!gl.getShaderParameter(shader,compile)) {
40+ throw gl.getShaderInfoLog(shader);
41+ }
5142
52− var vshader = createShader(vSrc, gl.VERTEX_SHADER);
53− var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
54− var program = gl.createProgram();
43+ return shader;
5544
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− }
45+ };
6246
63− return program;
47+ var vshader = createShader(vSrc, gl.VERTEX_SHADER);
48+ var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
49+ var program = gl.createProgram();
6450
51+ gl.attachShader(program, vshader);
52+ gl.attachShader(program, fshader);
53+ gl.linkProgram(program);
54+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
55+ throw gl.getProgramInfoLog(program);
6556 }
6657
67− function bind (program, bufferElems) {
58+ return program;
6859
69− var bufferObject = {};
60+ }
7061
71− var attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
72− for (var i = 0; i < attributes; i += 1) {
73− var attribute = gl.getActiveAttrib(program, i);
74− switch (attribute.type) {
75− case gl.FLOAT_VEC3:
62+ function bind (gl, program, bufferElems) {
7663
77− // Might want to invert the loop
78− // to build the array buffer first
79− // and then bind each one-at-a-time
80− var data = [];
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);
64+ var buffers = {};
8765
88− var buffer = gl.createBuffer();
89− gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
90− gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
66+ var attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
67+ for (var i = 0; i < attributes; i += 1) {
68+ var attribute = gl.getActiveAttrib(program, i);
69+ switch (attribute.type) {
70+ case gl.FLOAT_VEC3:
9171
92− bufferObject[attribute.name] = buffer;
72+ // Might want to invert the loop
73+ // to build the array buffer first
74+ // and then bind each one-at-a-time
75+ var data = [];
76+ 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]);
80+ }, bufferElems);
81+ var array = new Float32Array(data);
9382
94− break;
83+ var buffer = gl.createBuffer();
84+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
85+ gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
9586
96− default:
97− console.log("Bad buffer type");
98− break;
99− }
87+ buffers[attribute.name] = buffer;
10088
101− }
89+ break;
10290
103− return bufferObject;
91+ default:
92+ console.log("Bad buffer type");
93+ break;
94+ }
10495
10596 }
10697
107− function render(model) {
108− drawGL(model);
109− return model.node;
110− }
98+ var bufferObject = {
99+ numIndices: List.length(bufferElems),
100+ buffers: buffers
101+ };
111102
112− function update(canvasNode, oldModel, newModel) {
113− drawGL(newModel)
114− }
103+ return bufferObject;
115104
116105 }
117106
118− function drawGL(model) {
119−
120− var gl = model.gl;
121− gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
122−
123− function drawModel(glModel) {
124− var program = glModel.program;
125− gl.useProgram(program);
126−
127− var activeUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
128− for (var i = 0; i < activeUniforms; i += 1) {
129− var uniform = gl.getActiveUniform(program, i);
130− var uniformLocation = gl.getUniformLocation(program, uniform.name);
131− switch (uniform.type) {
132− case gl.FLOAT_MAT4:
133− gl.uniformMatrix4fv(uniformLocation, false, glModel.uniforms[uniform.name]);
134− break;
135− default:
136− console.log("Unsupported uniform type: " + uniform.type);
137− break;
107+ function webgl(w, h, draw) {
108+
109+ var node = newNode('canvas');
110+ var gl = node.getContext('webgl');
111+
112+ function drawGL(state) {
113+
114+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
115+
116+ function drawModel(model) {
117+
118+ var program = model.program;
119+ gl.useProgram(program);
120+
121+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
122+ for (var i = 0; i < numUniforms; i += 1) {
123+ var uniform = gl.getActiveUniform(program, i);
124+ var uniformLocation = gl.getUniformLocation(program, uniform.name);
125+ switch (uniform.type) {
126+ case gl.FLOAT_MAT4:
127+ gl.uniformMatrix4fv(uniformLocation, false, model.uniforms[uniform.name]);
128+ break;
129+ default:
130+ console.log("Unsupported uniform type: " + uniform.type);
131+ break;
132+ }
138133 }
139− }
140134
141− var numIndices = List.length(glModel.attributes);
142− var indices = List.toArray(List.range(0,numIndices));
143− var indexBuffer = gl.createBuffer();
144− gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
145− gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
146−
147− var activeAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
148− for (var i = 0; i < activeAttributes; i += 1) {
149− var attribute = gl.getActiveAttrib(program, i);
150− var attribLocation = gl.getAttribLocation(program, attribute.name);
151− gl.enableVertexAttribArray(attribLocation);
152− switch (attribute.type) {
153− case gl.FLOAT_VEC3:
154− var data = [];
155− List.each(function(elem){
156− data.push(elem[attribute.name][0]);
157− data.push(elem[attribute.name][1]);
158− data.push(elem[attribute.name][2]);
159− }, glModel.attributes);
160− var attributeBuffer = gl.createBuffer();
161− gl.bindBuffer(gl.ARRAY_BUFFER, attributeBuffer);
162− gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
163− gl.vertexAttribPointer(attribLocation, 3, gl.FLOAT, false, 0, 0);
164− break;
165− default:
166− console.log("Unsupported attribute type: " + attribute.type);
167− break;
135+ var numIndices = model.buffer.numIndices;
136+ var indices = List.toArray(List.range(0,numIndices));
137+
138+ var indexBuffer = gl.createBuffer();
139+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
140+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
141+
142+ var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
143+ for (var i = 0; i < numAttributes; i += 1) {
144+ var attribute = gl.getActiveAttrib(program, i);
145+ var attribLocation = gl.getAttribLocation(program, attribute.name);
146+ gl.enableVertexAttribArray(attribLocation);
147+ attributeBuffer = model.buffer.buffers[attribute.name];
148+
149+ switch (attribute.type) {
150+ case gl.FLOAT_VEC3:
151+ gl.bindBuffer(gl.ARRAY_BUFFER, attributeBuffer);
152+ gl.vertexAttribPointer(attribLocation, 3, gl.FLOAT, false, 0, 0);
153+ break;
154+ default:
155+ console.log("Unsupported attribute type: " + attribute.type);
156+ break;
157+ }
168158 }
169− }
170159
171− gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0);
160+ gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0);
172161
173− }
162+ }
174163
175− List.each(drawModel, model.glModels);
164+ List.each(drawModel, state.models);
176165
177− }
166+ }
178167
179− /*
180− * Called for new node, caches lots of stuff
181− */
182− function render(model) {
183− drawGL(model);
184− return model.node;
185− }
168+ function render(state) {
169+ drawGL(state);
170+ return node;
171+ }
186172
187− /*
188− * Called at existing node
189− */
190− function update(canvasNode, oldModel, newModel) {
191− drawGL(newModel)
192− }
173+ function update(_node, oldState, newState) {
174+ drawGL(newState)
175+ }
193176
194− function webgl(context, glModels) {
177+ var models = draw(gl);
195178
196− return A3(newElement, context.w, context.h, {
179+ var elem = {
197180 ctor: 'Custom',
198− type: 'WebGL',
199− render: render,
200− update: update,
201− model: {
202− aspect: context.w/context.h,
203− node: context.node,
204− gl: context.gl,
205− glModels: glModels,
206− },
207− });
181+ type: 'WebGL',
182+ render: render,
183+ update: update,
184+ model: {
185+ models: models,
186+ }
187+ };
208188
189+ return A3(newElement, w, h, elem);
209190 }
210191
211192 return elm.Native.Graphics.WebGL.values = {
212− encapsulate:F3(linkModel),
213− webgl:F3(webgl),
193+ link:F3(link),
194+ bind:F3(bind),
195+ encapsulate:F3(encapsulate),
196+ webgl:F3(webgl)
214197 };
215198
216199};
tests/good/.gitignoredeleted−2
@@ -1,2 +0,0 @@
1−build
2−cache
tests/good/Box.elm+23−46
@@ -1,59 +1,36 @@
11
2−import open Color
3−import open MJS
4−
5−import Graphics.WebGL (GLContext, Vertex, Triangle, Mesh, Scene, makeGL, bufferMesh, transform, mesh, webgl)
6−
7−-- Setup the GLContext
8−
9−gl : Signal GLContext
10−gl = makeGL 400 400
2+import MJS (V3,v3)
3+import Graphics.WebGL (link, bind, encapsulate, webgl)
114
125-- Define what our geometry looks like
136
7+top : V3
148top = v3 0 1 0
9+left : V3
1510left = v3 -1 -1 0
11+right : V3
1612right = v3 1 -1 0
1713
18−geometry : Triangle
19−geometry = (Vertex top red, Vertex left blue, Vertex right green)
20−
21−-- Bind our geometry to a mesh in our GL gl
22−
23−geoMesh : Signal Mesh
24−geoMesh = lift (bufferMesh [geometry]) gl
25−
26−-- Build two helper transforms
27−
28−perspective : M4x4
29−perspective = m4x4makePerspective 45 1 0.01 100
30−
31−camera : Float -> M4x4
32−camera r =
33− let eye = v3 0 0 r
34− center = v3 0 0 0
35− up = v3 0 1 0
36− in m4x4makeLookAt eye center up
37−
38−-- Build the scene with extra model rotate transforms
14+mesh : [{ pos : V3 }]
15+mesh = map (\vec -> { pos = vec }) [top, left, right]
3916
40−scene : Float -> Mesh -> Scene
41−scene angle m =
42− let xAxis = v3 1 0 0
43− yAxis = v3 0 1 0
44− rotationX = m4x4makeRotate (angle / 2) xAxis
45− rotationY = m4x4makeRotate (angle / 3) yAxis
46− in transform perspective [
47− transform (camera <| 5 + 3 * sin angle) [
48− transform rotationX [
49− transform rotationY [
50− mesh m ]]]]
17+vert = [glShader|
18+attribute vec3 pos;
19+void main () {
20+ gl_Position = vec4(pos, 1.0);
21+}
22+|]
5123
52−-- Standard accumulator and wiring it up with main
24+frag = [glShader|
25+void main () {
26+ gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
27+}
28+|]
5329
54−angle : Signal Float
55−angle = foldp (\_ a -> a + 0.1) 0 (fps 25)
30+draw gl =
31+ let prog = link gl vert frag
32+ buf = bind gl prog mesh
33+ in [ encapsulate prog buf {} ]
5634
57−main : Signal Element
58−main = lift2 webgl gl (lift2 scene angle geoMesh)
35+main = webgl 400 400 draw
5936