Skip to content

Commit

Permalink
much cleaned API in my opinion, plus a much simpler example
Browse files Browse the repository at this point in the history
  • Loading branch information
johnpmayer committed Dec 9, 2013
1 parent 8bfca73 commit 68e8bca
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 197 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ cabal-dev
data
*/ElmFiles/*
.DS_Store
build
cache
2 changes: 1 addition & 1 deletion compiler/Type/Constrain/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ constrain env (L span expr) tipe =
Nothing -> throwError [PP.text "Some sort of GLSL parse error"]
Just sourceTipe -> return . L span $ CEqual tipe (shaderTipe sourceTipe)
where
shaderTipe t = Env.get env Env.types "Graphics.WebGL.GLShader" <| t
shaderTipe t = Env.get env Env.types "Graphics.WebGL.Shader" <| t
glTipe = Env.get env Env.types . PH.glTipeName
declsRecord :: PH.GLShaderDecls -> TermN Variable
declsRecord extractedTipes = record (fields' extractedTipes) (TermN EmptyRecord1)
Expand Down
16 changes: 11 additions & 5 deletions libraries/Graphics/WebGL.elm
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
module Graphics.WebGL (encapsulate, webgl) where
module Graphics.WebGL (link, bind, encapsulate, webgl) where

{-| WebGL -}

import Graphics.Element (Element)
import Native.Graphics.WebGL

data Shader a u v = Dummy_Shader
data GL = Dummy_GL

data Shader auv = Dummy_Shader
data Program a u = Dummy_Program
type Linker = Shader a u v -> Shader {} {} v -> Program a u

link : GL -> Shader { attribute : a, uniform : u, varying : v } -> Shader { attribute : {}, uniform : {}, varying : v } -> Program a u
link = Native.Graphics.WebGL.link

-- Binder really should not need a program
-- I need runtime type information from something though...

data Buffer a = Dummy_Buffer
type Binder = Program a u -> [a] -> Buffer a

bind : GL -> Program a u -> [a] -> Buffer a
bind = Native.Graphics.WebGL.bind

-- Now I cheat here because elm lacks existential types or rank-n
-- I'm in essense doing the following
Expand All @@ -24,5 +30,5 @@ data Model = Dummy_Model
encapsulate : Program a u -> Buffer a -> u -> Model
encapsulate = Native.Graphics.WebGL.encapsulate

webgl : Int -> Int -> (Linker -> Binder -> [Model]) -> Element
webgl : Int -> Int -> (GL -> [Model]) -> Element
webgl = Native.Graphics.WebGL.webgl
269 changes: 126 additions & 143 deletions libraries/Native/Graphics/WebGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,190 +27,173 @@ Elm.Native.Graphics.WebGL.make = function(elm) {

}

function webgl(w, h, draw) {

var node = newNode('canvas');
var gl = node.getContext('webgl');

function link (vSrc, fSrc) {
function link (gl, vSrc, fSrc) {

function createShader(str, type) {
function createShader(str, type) {

var shader = gl.createShader(type);
var shader = gl.createShader(type);

gl.shaderSource(shader, str);
gl.compileShader(shader);
var compile = gl.COMPILE_STATUS;
if (!gl.getShaderParameter(shader,compile)) {
throw gl.getShaderInfoLog(shader);
}

return shader;

};
gl.shaderSource(shader, str);
gl.compileShader(shader);
var compile = gl.COMPILE_STATUS;
if (!gl.getShaderParameter(shader,compile)) {
throw gl.getShaderInfoLog(shader);
}

var vshader = createShader(vSrc, gl.VERTEX_SHADER);
var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
var program = gl.createProgram();
return shader;

gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw gl.getProgramInfoLog(program);
}
};

return program;
var vshader = createShader(vSrc, gl.VERTEX_SHADER);
var fshader = createShader(fSrc, gl.FRAGMENT_SHADER);
var program = gl.createProgram();

gl.attachShader(program, vshader);
gl.attachShader(program, fshader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw gl.getProgramInfoLog(program);
}

function bind (program, bufferElems) {
return program;

var bufferObject = {};
}

var attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < attributes; i += 1) {
var attribute = gl.getActiveAttrib(program, i);
switch (attribute.type) {
case gl.FLOAT_VEC3:
function bind (gl, program, bufferElems) {

// Might want to invert the loop
// to build the array buffer first
// and then bind each one-at-a-time
var data = [];
List.each(function(elem){
data.push(elem[attribute.name][0]);
data.push(elem[attribute.name][1]);
data.push(elem[attribute.name][2]);
}, bufferElems);
var array = new Float32Array(data);
var buffers = {};

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
var attributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < attributes; i += 1) {
var attribute = gl.getActiveAttrib(program, i);
switch (attribute.type) {
case gl.FLOAT_VEC3:

bufferObject[attribute.name] = buffer;
// Might want to invert the loop
// to build the array buffer first
// and then bind each one-at-a-time
var data = [];
List.each(function(elem){
data.push(elem[attribute.name][0]);
data.push(elem[attribute.name][1]);
data.push(elem[attribute.name][2]);
}, bufferElems);
var array = new Float32Array(data);

break;
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);

default:
console.log("Bad buffer type");
break;
}
buffers[attribute.name] = buffer;

}
break;

return bufferObject;
default:
console.log("Bad buffer type");
break;
}

}

function render(model) {
drawGL(model);
return model.node;
}
var bufferObject = {
numIndices: List.length(bufferElems),
buffers: buffers
};

function update(canvasNode, oldModel, newModel) {
drawGL(newModel)
}
return bufferObject;

}

function drawGL(model) {

var gl = model.gl;
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

function drawModel(glModel) {
var program = glModel.program;
gl.useProgram(program);

var activeUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i = 0; i < activeUniforms; i += 1) {
var uniform = gl.getActiveUniform(program, i);
var uniformLocation = gl.getUniformLocation(program, uniform.name);
switch (uniform.type) {
case gl.FLOAT_MAT4:
gl.uniformMatrix4fv(uniformLocation, false, glModel.uniforms[uniform.name]);
break;
default:
console.log("Unsupported uniform type: " + uniform.type);
break;
function webgl(w, h, draw) {

var node = newNode('canvas');
var gl = node.getContext('webgl');

function drawGL(state) {

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

function drawModel(model) {

var program = model.program;
gl.useProgram(program);

var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i = 0; i < numUniforms; i += 1) {
var uniform = gl.getActiveUniform(program, i);
var uniformLocation = gl.getUniformLocation(program, uniform.name);
switch (uniform.type) {
case gl.FLOAT_MAT4:
gl.uniformMatrix4fv(uniformLocation, false, model.uniforms[uniform.name]);
break;
default:
console.log("Unsupported uniform type: " + uniform.type);
break;
}
}
}

var numIndices = List.length(glModel.attributes);
var indices = List.toArray(List.range(0,numIndices));
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

var activeAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < activeAttributes; i += 1) {
var attribute = gl.getActiveAttrib(program, i);
var attribLocation = gl.getAttribLocation(program, attribute.name);
gl.enableVertexAttribArray(attribLocation);
switch (attribute.type) {
case gl.FLOAT_VEC3:
var data = [];
List.each(function(elem){
data.push(elem[attribute.name][0]);
data.push(elem[attribute.name][1]);
data.push(elem[attribute.name][2]);
}, glModel.attributes);
var attributeBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, attributeBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
gl.vertexAttribPointer(attribLocation, 3, gl.FLOAT, false, 0, 0);
break;
default:
console.log("Unsupported attribute type: " + attribute.type);
break;
var numIndices = model.buffer.numIndices;
var indices = List.toArray(List.range(0,numIndices));

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < numAttributes; i += 1) {
var attribute = gl.getActiveAttrib(program, i);
var attribLocation = gl.getAttribLocation(program, attribute.name);
gl.enableVertexAttribArray(attribLocation);
attributeBuffer = model.buffer.buffers[attribute.name];

switch (attribute.type) {
case gl.FLOAT_VEC3:
gl.bindBuffer(gl.ARRAY_BUFFER, attributeBuffer);
gl.vertexAttribPointer(attribLocation, 3, gl.FLOAT, false, 0, 0);
break;
default:
console.log("Unsupported attribute type: " + attribute.type);
break;
}
}
}

gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, numIndices, gl.UNSIGNED_SHORT, 0);

}
}

List.each(drawModel, model.glModels);
List.each(drawModel, state.models);

}
}

/*
* Called for new node, caches lots of stuff
*/
function render(model) {
drawGL(model);
return model.node;
}
function render(state) {
drawGL(state);
return node;
}

/*
* Called at existing node
*/
function update(canvasNode, oldModel, newModel) {
drawGL(newModel)
}
function update(_node, oldState, newState) {
drawGL(newState)
}

function webgl(context, glModels) {
var models = draw(gl);

return A3(newElement, context.w, context.h, {
var elem = {
ctor: 'Custom',
type: 'WebGL',
render: render,
update: update,
model: {
aspect: context.w/context.h,
node: context.node,
gl: context.gl,
glModels: glModels,
},
});
type: 'WebGL',
render: render,
update: update,
model: {
models: models,
}
};

return A3(newElement, w, h, elem);
}

return elm.Native.Graphics.WebGL.values = {
encapsulate:F3(linkModel),
webgl:F3(webgl),
link:F3(link),
bind:F3(bind),
encapsulate:F3(encapsulate),
webgl:F3(webgl)
};

};
2 changes: 0 additions & 2 deletions tests/good/.gitignore

This file was deleted.

Loading

0 comments on commit 68e8bca

Please sign in to comment.