Skip to content

Commit

Permalink
Shaders: Add generation of uniforms & varying (#8)
Browse files Browse the repository at this point in the history
* Start support for setting shader values

* Add ability to set uniforms on a compiled shader

* Clean up shaders namespace a bit

* Add gl-matrix-min dependency to get working on web
  • Loading branch information
bryphe authored Oct 17, 2018
1 parent 9072ce4 commit c06dd32
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 100 deletions.
2 changes: 1 addition & 1 deletion esy.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"ocaml": "~4.6.0"
},
"resolutions": {
"reason-glfw": "github:bryphe/reason-glfw#d84cdb9",
"reason-glfw": "github:bryphe/reason-glfw#883e1b6",
"reason-gl-matrix": "github:bryphe/reason-gl-matrix#0ae52c1",
"reason-reactify": "github:bryphe/reason-reactify#a62c8e4",
"esy-cmake": "github:bryphe/esy-cmake#5a40a8e",
Expand Down
135 changes: 71 additions & 64 deletions esy.lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions examples/Bin.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Reglm;
open Reglfw.Glfw;
open Revery;
open Revery.Shaders;
open Revery.Shaders.Shader;

let init = app => {
let w = app#createWindow("test");
Expand All @@ -10,13 +10,13 @@ let init = app => {

let quad = Geometry.Cube.create();


w#setRenderCallback(() => {
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);

CompiledShader.use(basicShader);
CompiledShader.setUniform3fv(basicShader, "uColor", Vec3.create(1.0, 0.0, 1.0));

Geometry.draw(quad, basicShader);
});
Expand Down
2 changes: 1 addition & 1 deletion examples/dune
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
(install
(section bin)
(package Revery)
(files binary.dat index.html Bin.bc.js))
(files binary.dat index.html Bin.bc.js gl-matrix-min.js))
28 changes: 28 additions & 0 deletions examples/gl-matrix-min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
</head>
<body>
<p>This is an example paragraph. Anything in the <strong>body</strong> tag will appear on the page, just like this <strong>p</strong> tag and its contents.</p>
<script src="gl-matrix-min.js"></script>
<script src="Bin.bc.js"></script>
</body>
</html>
27 changes: 19 additions & 8 deletions src/Shaders/BasicShader.re
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/**
* Basic Shader
*
* This is the simplest possible shader you can have in Revery -
* simply takes the vertex position as is, and renders it as a
* solid color!
* Simple shader demonstrating usage of attributes, uniforms, and varying parameters.
*/

open Shader;
Expand All @@ -13,27 +11,40 @@ let attribute: list(ShaderAttribute.t) = [
dataType: ShaderDataType.Vector3,
name: "aVertexPosition",
channel: Position,
},
];
}];

let uniform: list(ShaderUniform.t) = [{
dataType: ShaderDataType.Vector3,
name: "uColor",
usage: VertexShader,
}];

let varying: list(ShaderVarying.t) = [{
dataType: ShaderDataType.Vector3,
name: "vColor",
precision: ShaderPrecision.Low,
}];


let vsShader = {|
void main() {
gl_Position = vec4(aVertexPosition, 1.0);
vColor = uColor;
}
|};

let fsShader = {|
void main() {
gl_FragColor = vec4(1.0);
gl_FragColor = vec4(vColor, 1.0);
}
|};

let create = () => {
let shader =
Shader.create(
~attributes=attribute,
~uniforms=[],
~varying=[],
~uniforms=uniform,
~varying=varying,
~vertexShader=vsShader,
~fragmentShader=fsShader,
);
Expand Down
4 changes: 4 additions & 0 deletions src/Shaders/Revery_Shaders.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Shader = Shader;
module CompiledShader = Shader.CompiledShader;

module BasicShader = BasicShader;
123 changes: 99 additions & 24 deletions src/Shaders/Shader.re
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
open Reglfw;
open Reglfw.Glfw;
open Reglm;

type vertexShaderSource = string;
type fragmentShaderSource = string;
Expand Down Expand Up @@ -55,11 +56,6 @@ module ShaderDataType {
};
}

type shaderUniformUsage =
| VertexShader
| FragmentShader
| VertexAndFragmentShader


module ShaderAttribute {
type t = {
Expand All @@ -73,50 +69,120 @@ module ShaderAttribute {
};
}

type shaderUniform = {
dataType: ShaderDataType.t,
usage: shaderUniformUsage,
name: string
module ShaderUniform {
type shaderUniformUsage =
| VertexShader
| FragmentShader
| VertexAndFragmentShader

type t = {
dataType: ShaderDataType.t,
usage: shaderUniformUsage,
name: string
};

let toString = (u) => {
"uniform " ++ ShaderDataType.toString(u.dataType) ++ " " ++ u.name ++ ";"
};
}


module ShaderVarying {
type t = {
dataType: ShaderDataType.t,
precision: ShaderPrecision.t,
name: string
};

let toString = (v) => {
"varying " ++ ShaderPrecision.toString(v.precision) ++ " " ++ ShaderDataType.toString(v.dataType) ++ " " ++ v.name ++ ";"
};
}

type uncompiledShader = (list(ShaderUniform.t), list(ShaderAttribute.t), list(ShaderVarying.t), vertexShaderSource, fragmentShaderSource);

type blockGenerator('a) = 'a => string
let generateBlock = (f:blockGenerator('a), l: list('a)) => {
let strs: list(string) = List.map(f, l);
List.fold_left((prev, cur) => prev ++ "\n" ++ cur, "", strs);
};

type shaderVarying = {
dataType: ShaderDataType.t,
precision: ShaderPrecision.t,
name: string
let generateAttributeVertexShaderBlock = (attributes: list(ShaderAttribute.t)) => {
generateBlock(ShaderAttribute.toString, attributes);
};

type uncompiledShader = (list(shaderUniform), list(ShaderAttribute.t), list(shaderVarying), vertexShaderSource, fragmentShaderSource);
let generateUniformVertexShaderBlock = (uniforms: list(ShaderUniform.t)) => {
let vertexUniforms = List.filter((u: ShaderUniform.t) => u.usage != FragmentShader, uniforms);
generateBlock(ShaderUniform.toString, vertexUniforms);
};

let generateAttributeVertexShaderBlock = (attributes: list(ShaderAttribute.t)) => {
let strs: list(string) = List.map((s) => ShaderAttribute.toString(s), attributes);
List.fold_left((prev, cur) => prev ++ "\n" ++ cur, "", strs);
let generateUniformPixelShaderBlock = (uniforms: list(ShaderUniform.t)) => {
let pixelUniforms = List.filter((u: ShaderUniform.t) => u.usage != VertexShader, uniforms);
generateBlock(ShaderUniform.toString, pixelUniforms);
};

let generateVaryingBlock = (varying: list(ShaderVarying.t)) => {
generateBlock(ShaderVarying.toString, varying);
};

let create = (~uniforms: list(shaderUniform), ~attributes: list(ShaderAttribute.t), ~varying: list(shaderVarying), ~vertexShader: vertexShaderSource, ~fragmentShader: fragmentShaderSource) => {
let create = (~uniforms: list(ShaderUniform.t), ~attributes: list(ShaderAttribute.t), ~varying: list(ShaderVarying.t), ~vertexShader: vertexShaderSource, ~fragmentShader: fragmentShaderSource) => {

let vertexShader = generateAttributeVertexShaderBlock(attributes) ++ vertexShader;
let vertexShader = generateAttributeVertexShaderBlock(attributes)
++ generateUniformVertexShaderBlock(uniforms)
++ generateVaryingBlock(varying)
++ vertexShader;

let fragmentShader = generateUniformPixelShaderBlock(uniforms)
++ generateVaryingBlock(varying)
++ fragmentShader;

(uniforms, attributes, varying, vertexShader, fragmentShader);
};

module CompiledShader {
type attributeNameToLocation = Hashtbl.t(string, attribLocation);
type attributeChannelToLocation = Hashtbl.t(VertexChannel.t, attribLocation);
type uniformNameToLocation = Hashtbl.t(string, uniformLocation);

type t = (list(shaderUniform), list(ShaderAttribute.t), list(shaderVarying), Glfw.program, attributeNameToLocation, attributeChannelToLocation);
type t = (list(ShaderUniform.t), list(ShaderAttribute.t), list(ShaderVarying.t), Glfw.program, attributeNameToLocation, attributeChannelToLocation, uniformNameToLocation);

let attributeNameToLocation = (s: t, a: string) => {
let (_, _, _, _, dict, _) = s;
let (_, _, _, _, dict, _, _) = s;
Hashtbl.find_opt(dict, a)
};

let attributeChannelToLocation = (s: t, a: VertexChannel.t) => {
let (_, _, _, _, _, dict) = s;
let (_, _, _, _, _, dict, _) = s;
Hashtbl.find_opt(dict, a);
};

let uniformNameToLocation = (s: t, name: string) => {
let (_, _, _, _, _, _, u) = s;
Hashtbl.find_opt(u, name);
};

let _setUniformIfAvailable = (s, name, f) => {
let uLoc = uniformNameToLocation(s, name);
switch (uLoc) {
| Some(u) => f(u)
| None => ()
};
};

let setUniform3fv = (s: t, name: string, v: Vec3.t) => {
_setUniformIfAvailable(s, name, (u) => glUniform3fv(u, v));
};

let setUniform4f = (s: t, name: string, x: float, y: float, z: float, w: float) => {
_setUniformIfAvailable(s, name, (u) => glUniform4f(u, x, y, z, w));
};

let setUniformMatrix4fv = (s: t, name: string, m: Mat4.t) => {
_setUniformIfAvailable(s, name, (u) => glUniformMatrix4fv(u, m));
};

let use = (s: t) => {
let (_, _, _, p, _, _) = s;
let (_, _, _, p, _, _, _) = s;
glUseProgram(p);
};
}
Expand Down Expand Up @@ -147,16 +213,25 @@ let compile = (shader: uncompiledShader) => {
let attributeNameToLocation: CompiledShader.attributeNameToLocation = Hashtbl.create(List.length(attributes));
let attributeChannelToLocation: CompiledShader.attributeChannelToLocation = Hashtbl.create(List.length(attributes));

let uniformNameToLocation: CompiledShader.uniformNameToLocation = Hashtbl.create(List.length(uniforms));

let addAttributeToHash = (attr: ShaderAttribute.t) => {
let loc = glGetAttribLocation(program, attr.name);
print_endline ("adding: " ++ attr.name);
Hashtbl.add(attributeNameToLocation, attr.name, loc)
Hashtbl.add(attributeChannelToLocation, attr.channel, loc);
};

let addUniformToHash = (uniform: ShaderUniform.t) => {
let uloc = glGetUniformLocation(program, uniform.name);
print_endline("adding uniform: " ++ uniform.name);
Hashtbl.add(uniformNameToLocation, uniform.name, uloc);
};

List.iter(addAttributeToHash, attributes);
List.iter(addUniformToHash, uniforms);

(uniforms, attributes, varying, program, attributeNameToLocation, attributeChannelToLocation);
(uniforms, attributes, varying, program, attributeNameToLocation, attributeChannelToLocation, uniformNameToLocation);
}
| LinkFailure(v) => raise(ShaderCompilationException(v))
}
Expand Down

0 comments on commit c06dd32

Please sign in to comment.