on 68e8bca help sign in
199 lines 6.3 kB history raw
1Elm.Native.Graphics.WebGL = {};
2Elm.Native.Graphics.WebGL.make = function(elm) {
4 elm.Native = elm.Native || {};
5 elm.Native.Graphics = elm.Native.Graphics || {};
6 elm.Native.Graphics.WebGL = elm.Native.Graphics.WebGL || {};
7 if (elm.Native.Graphics.WebGL.values) return elm.Native.Graphics.WebGL.values;
9 var newNode = ElmRuntime.use(ElmRuntime.Render.Utils).newElement;
11 var Signal = Elm.Signal.make(elm);
12 var newElement = Elm.Graphics.Element.make(elm).newElement;
13 var Utils = Elm.Native.Utils.make(elm);
14 var Tuple2 = Utils.Tuple2;
15 var MJS = Elm.Native.MJS.make(elm);
16 var List = Elm.Native.List.make(elm);
18 function encapsulate(program, buffer, uniforms) {
20 var model = {
21 program: program,
22 buffer: buffer,
23 uniforms: uniforms
24 };
26 return model;
28 }
30 function link (gl, vSrc, fSrc) {
32 function createShader(str, type) {
34 var shader = gl.createShader(type);
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 }
43 return shader;
45 };
47 var vshader = createShader(vSrc, gl.VERTEX_SHADER);
48 var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
49 var program = gl.createProgram();
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);
56 }
58 return program;
60 }
62 function bind (gl, program, bufferElems) {
64 var buffers = {};
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:
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);
83 var buffer = gl.createBuffer();
84 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
85 gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
87 buffers[attribute.name] = buffer;
89 break;
91 default:
92 console.log("Bad buffer type");
93 break;
94 }
96 }
98 var bufferObject = {
99 numIndices: List.length(bufferElems),
100 buffers: buffers
101 };
103 return bufferObject;
105 }
107 function webgl(w, h, draw) {
109 var node = newNode('canvas');
110 var gl = node.getContext('webgl');
112 function drawGL(state) {
114 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
116 function drawModel(model) {
118 var program = model.program;
119 gl.useProgram(program);
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 }
133 }
135 var numIndices = model.buffer.numIndices;
136 var indices = List.toArray(List.range(0,numIndices));
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);
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];
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 }
158 }
160 gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0);
162 }
164 List.each(drawModel, state.models);
166 }
168 function render(state) {
169 drawGL(state);
170 return node;
171 }
173 function update(_node, oldState, newState) {
174 drawGL(newState)
175 }
177 var models = draw(gl);
179 var elem = {
180 ctor: 'Custom',
181 type: 'WebGL',
182 render: render,
183 update: update,
184 model: {
185 models: models,
186 }
187 };
189 return A3(newElement, w, h, elem);
190 }
192 return elm.Native.Graphics.WebGL.values = {
193 link:F3(link),
194 bind:F3(bind),
195 encapsulate:F3(encapsulate),
196 webgl:F3(webgl)
197 };
199};