gelatin-shaders (empty) → 0.1.0.0
raw patch · 13 files changed
+1175/−0 lines, 13 filesdep +basedep +bytestringdep +filepathsetup-changed
Dependencies added: base, bytestring, filepath, gelatin
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- gelatin-shaders.cabal +33/−0
- shaders/simple2d.frag +196/−0
- shaders/simple2d.vert +89/−0
- shaders/simple2dwebgl.frag +193/−0
- shaders/simple2dwebgl.vert +83/−0
- shaders/simple3d.frag +196/−0
- shaders/simple3d.vert +89/−0
- src/Gelatin/Shaders.hs +25/−0
- src/Gelatin/Shaders/Common.hs +93/−0
- src/Gelatin/Shaders/Simple2D.hs +74/−0
- src/Gelatin/Shaders/TypeLevel.hs +72/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Schell Scivally (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Schell Scivally nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ gelatin-shaders.cabal view
@@ -0,0 +1,33 @@+name: gelatin-shaders+version: 0.1.0.0+synopsis: Gelatin's OpenGL shaders.+description: Gelatin's OpenGL shaders. Please see README.md+homepage: https://github.com/schell/gelatin-shaders#readme+license: BSD3+license-file: LICENSE+author: Schell Scivally+maintainer: schell@zyghost.com+copyright: Schell Scivally+category: Web+build-type: Simple+cabal-version: >=1.10+data-files: shaders/*.frag,+ shaders/*.vert+stability: experimental++library+ hs-source-dirs: src+ exposed-modules: Gelatin.Shaders.Common+ , Gelatin.Shaders.Simple2D+ , Gelatin.Shaders.TypeLevel+ , Gelatin.Shaders+ other-modules: Paths_gelatin_shaders+ build-depends: base >=4.8 && <4.11+ , gelatin >=0.1 && <0.2+ , bytestring >=0.10 && <0.11+ , filepath >=1.4 && <1.5+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/schell/gelatin-shaders
+ shaders/simple2d.frag view
@@ -0,0 +1,196 @@+#version 330 core++in vec4 fcolor;+in vec2 fuv;+in vec3 fbez;+in vec2 fbezuv;++out vec4 fragColor;++uniform int primitive;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;+uniform float feather;+uniform float sumlength;+uniform vec2 cap;+uniform float alpha;+uniform vec4 mult;++uniform vec4 replaceColor;+uniform bool shouldColorReplace;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Types for rendering line caps+const float CapNone = 0;+const float CapButt = 1;+const float CapSquare = 2;+const float CapRound = 3;+const float CapTriOut = 4;+const float CapTriIn = 5;++// Colors a fragment based solely on either an input color or a texture.+vec4 coord_fragment(bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 uvs) {+ if (isUV) {+ return texture(s, uvs.st);+ } else {+ return clr;+ }+}++// Colors a fragment using Loop-Blinn curve rendering.+vec4 bez_fragment(bool isUV,+ sampler2D s,+ vec3 bz,+ vec4 clr,+ vec2 uvs) {+ vec2 p = bz.xy;+ // when cw is true, winding is clockwise and we're drawing outside the+ // curve.+ bool cw = bool(bz.z);+ // gradients+ vec2 px = dFdx(p);+ vec2 py = dFdy(p);+ // chain rule+ float fx = (2*p.x)*px.x - px.y;+ float fy = (2*p.x)*py.x - py.y;+ // signed distance+ float sd = (p.x*p.x - p.y) / sqrt(fx*fx + fy*fy);+ // linear alpha+ float alpha = 0.5 - sd;+ alpha = cw ? 1 - alpha : alpha;+ // find the resulting fragment color+ float a = 0;++ if (alpha > 1) {+ a = 1;+ } else if (alpha < 0) {+ discard;+ } else {+ // we are right on the boundary, interpolate the color intensity.+ a = alpha;+ }++ vec4 color = vec4(0);+ if (isUV) {+ color = texture(s, uvs.st);+ } else {+ color = clr;+ }+ return vec4(color.rgb, color.a * a);+}++// Renders a polyline cap fragment.+float capd(float type, float u, float v, float t ) {+ // None+ if ( type == CapNone) discard;+ // Round+ else if (type == CapRound) return sqrt(u*u+v*v);+ // Triangle out+ else if (type == CapTriOut) return (u+abs(v));+ // Triangle in+ else if (type == CapTriIn) return max(abs(v),(t+u-abs(v)));+ // Square+ else if (type == CapSquare) return max(u,v);+ // Butt+ else if (type == CapButt) return max(u+t,v);+ discard;+}++vec4 line_fragment(float thick,+ float fthr,+ float slen,+ vec2 cp,+ bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 bzuv,+ vec2 uvs) {+ float u = bzuv.x;+ float v = bzuv.y;+ float l = slen;+ float dx = abs(min(u, u - l));+ float dy = abs(v);+ float d = dy;++ vec4 color = vec4(0);+ if (isUV) {+ color = texture(s, uvs.st);+ } else {+ color = clr;+ }++ float t = thick/2.0 - fthr;++ if (u < 0) {+ // fragment is in the start cap+ d = capd(cp.x, abs(u), dy, t);+ } else if (u > slen) {+ // fragment is in the end cap+ d = capd(cp.y, u - l, dy, t);+ }++ d -= t;+ if (d < 0.0) {+ return color;+ } else {+ d /= fthr;+ return vec4(color.rgb, exp(-d*d)*color.a);+ }+}++// Colors a fragment using two textures, one the input texture and one as the+// alpha masking texture.+vec4 mask_fragment(sampler2D main,+ sampler2D mask,+ vec2 uvs) {+ vec4 color = texture(main, uvs.st);+ vec4 msk = texture(mask, uvs.st);+ return vec4(color.rgb, color.a * msk.a);+}++// Runs a color op on the fragment.+vec4 color_op_fragment(vec4 c, float a, vec4 m) {+ vec4 c1 = vec4(0);+ if (shouldColorReplace) {+ // Use a replacement color multiplied by the current red channel value.+ c1 = vec4(replaceColor.r, replaceColor.g, replaceColor.b, replaceColor.a * c.r) * m;+ } else {+ c1 = c * m;+ }+ return vec4(c1.rgb, c1.a * a);+}++void main() {+ vec4 out_color = vec4(0);+ switch (primitive) {+ case PrimTri:+ out_color = coord_fragment(hasUV, sampler, fcolor, fuv);+ break;+ case PrimBez:+ out_color = bez_fragment(hasUV, sampler, fbez, fcolor, fuv);+ break;+ case PrimLine: {+ out_color = line_fragment(thickness, feather, sumlength, cap, hasUV,+ sampler, fcolor, fbezuv, fuv);+ break;+ }+ case PrimMask:+ out_color = mask_fragment(mainTex, maskTex, fuv);+ break;+ default:+ break;+ }++ fragColor = color_op_fragment(out_color, alpha, mult);+}
+ shaders/simple2d.vert view
@@ -0,0 +1,89 @@+#version 330 core++in vec2 position;+in vec4 color;+in vec2 uv;+in vec3 bez;+in vec2 bezuv;+in vec2 next;+in vec2 previous;++out vec4 fcolor;+out vec2 fuv;+out vec3 fbez;+out vec2 fbezuv;++uniform int primitive;+uniform mat4 projection;+uniform mat4 modelview;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Projects a polyline segment into screen coordinates.+vec4 project_line(mat4 pj,+ mat4 mv,+ float thick,+ vec2 pos,+ vec2 bzuv,+ vec2 nxt,+ vec2 prev) {+ vec2 a = prev;+ vec2 b = pos;+ vec2 c = nxt;+ vec2 ab = normalize(b - a);+ vec2 bc = normalize(c - b);+ vec2 tangent = normalize(ab + bc);+ vec2 extrusion = vec2(-tangent.y, tangent.x);+ float direction = sign(bzuv.y);+ float len = thick;++ // find the length of the miter line+ vec2 perpab = vec2(-ab.y,ab.x);+ len = len / dot(extrusion, perpab);++ vec2 delta = extrusion * len * direction;+ return pj * mv * vec4(pos + delta, 0.0, 1.0);+}++// Projects a plain point into screen coords.+// Used for alpha masking and "regular" uv mapping and coloring.+vec4 project_position(mat4 pj, mat4 mv, vec2 pos) {+ return pj * mv * vec4(pos.xy, 0.0, 1.0);+}++void main () {+ // Figure out what kind of projection to use.+ vec4 out_position = vec4(0);++ switch (primitive) {+ case PrimTri:+ case PrimBez:+ case PrimMask:+ out_position = project_position(projection, modelview, position);+ break;++ case PrimLine: {+ out_position = project_line(projection, modelview, thickness, position,+ bezuv, next, previous);+ break;+ }+ default:+ out_position = project_position(projection, modelview, position);+ }++ fcolor = color;+ fuv = uv;+ fbez = bez;+ fbezuv = bezuv;++ gl_Position = out_position;+}
+ shaders/simple2dwebgl.frag view
@@ -0,0 +1,193 @@+#extension GL_OES_standard_derivatives : enable++precision highp float;+precision highp int;++varying vec4 fcolor;+varying vec2 fuv;+varying vec3 fbez;+varying vec2 fbezuv;++uniform int primitive;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;+uniform float feather;+uniform float sumlength;+uniform vec2 cap;+uniform float alpha;+uniform vec4 mult;++uniform vec4 replaceColor;+uniform bool shouldColorReplace;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Types for rendering line caps+const float CapNone = 0.0;+const float CapButt = 1.0;+const float CapSquare = 2.0;+const float CapRound = 3.0;+const float CapTriOut = 4.0;+const float CapTriIn = 5.0;++// Colors a fragment based solely on either an input color or a texture.+vec4 coord_fragment(bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 uvs) {+ if (isUV) {+ return texture2D(s, uvs.st);+ } else {+ return clr;+ }+}++// Colors a fragment using Loop-Blinn curve rendering.+vec4 bez_fragment(bool isUV,+ sampler2D s,+ vec3 bz,+ vec4 clr,+ vec2 uvs) {+ vec2 p = bz.xy;+ // when cw is true, winding is clockwise and we're drawing outside the+ // curve.+ bool cw = bool(bz.z);+ // gradients+ vec2 px = dFdx(p);+ vec2 py = dFdy(p);+ // chain rule+ float fx = (2.0*p.x)*px.x - px.y;+ float fy = (2.0*p.x)*py.x - py.y;+ // signed distance+ float sd = (p.x*p.x - p.y) / sqrt(fx*fx + fy*fy);+ // linear alpha+ float alpha = 0.5 - sd;+ alpha = cw ? 1.0 - alpha : alpha;+ // find the resulting fragment color+ float a = 0.0;++ if (alpha > 1.0) {+ a = 1.0;+ } else if (alpha < 0.0) {+ discard;+ } else {+ // we are right on the boundary, interpolate the color intensity.+ a = alpha;+ }++ vec4 color = vec4(0);+ if (isUV) {+ color = texture2D(s, uvs.st);+ } else {+ color = clr;+ }+ return vec4(color.rgb, color.a * a);+}++// Renders a polyline cap fragment.+float capd(float type, float u, float v, float t ) {+ // None+ if ( type == CapNone) discard;+ // Round+ else if (type == CapRound) return sqrt(u*u+v*v);+ // Triangle out+ else if (type == CapTriOut) return (u+abs(v));+ // Triangle in+ else if (type == CapTriIn) return max(abs(v),(t+u-abs(v)));+ // Square+ else if (type == CapSquare) return max(u,v);+ // Butt+ else if (type == CapButt) return max(u+t,v);+ discard;+}++vec4 line_fragment(float thick,+ float fthr,+ float slen,+ vec2 cp,+ bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 bzuv,+ vec2 uvs) {+ float u = bzuv.x;+ float v = bzuv.y;+ float l = slen;+ float dx = abs(min(u, u - l));+ float dy = abs(v);+ float d = dy;++ vec4 color = vec4(0);+ if (isUV) {+ color = texture2D(s, uvs.st);+ } else {+ color = clr;+ }++ float t = thick/2.0 - fthr;++ if (u < 0.0) {+ // fragment is in the start cap+ d = capd(cp.x, abs(u), dy, t);+ } else if (u > slen) {+ // fragment is in the end cap+ d = capd(cp.y, u - l, dy, t);+ }++ d -= t;+ if (d < 0.0) {+ return color;+ } else {+ d /= fthr;+ return vec4(color.rgb, exp(-d*d)*color.a);+ }+}++// Colors a fragment using two textures, one the input texture and one as the+// alpha masking texture.+vec4 mask_fragment(sampler2D main,+ sampler2D mask,+ vec2 uvs) {+ vec4 color = texture2D(main, uvs.st);+ vec4 msk = texture2D(mask, uvs.st);+ return vec4(color.rgb, color.a * msk.a);+}++// Runs a color op on the fragment.+vec4 color_op_fragment(vec4 c, float a, vec4 m) {+ vec4 c1 = vec4(0);+ if (shouldColorReplace) {+ // Use a replacement color multiplied by the current red channel value.+ c1 = vec4(replaceColor.r, replaceColor.g, replaceColor.b, replaceColor.a * c.r) * m;+ } else {+ c1 = c * m;+ }+ return vec4(c1.rgb, c1.a * a);+}++void main() {+ vec4 out_color = vec4(0);+ if (primitive == PrimTri) {+ out_color = coord_fragment(hasUV, sampler, fcolor, fuv);+ }+ if (primitive == PrimBez) {+ out_color = bez_fragment(hasUV, sampler, fbez, fcolor, fuv);++ }+ if (primitive == PrimLine) {+ out_color = line_fragment(thickness, feather, sumlength, cap, hasUV,+ sampler, fcolor, fbezuv, fuv);+ }+ if (primitive == PrimMask) {+ out_color = mask_fragment(mainTex, maskTex, fuv);+ }++ gl_FragColor = color_op_fragment(out_color, alpha, mult);+}
+ shaders/simple2dwebgl.vert view
@@ -0,0 +1,83 @@+precision highp float;+precision highp int;++attribute vec2 position;+attribute vec4 color;+attribute vec2 uv;+attribute vec3 bez;+attribute vec2 bezuv;+attribute vec2 next;+attribute vec2 previous;++varying vec4 fcolor;+varying vec2 fuv;+varying vec3 fbez;+varying vec2 fbezuv;++uniform int primitive;+uniform mat4 projection;+uniform mat4 modelview;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Projects a polyline segment into screen coordinates.+vec4 project_line(mat4 pj,+ mat4 mv,+ float thick,+ vec2 pos,+ vec2 bzuv,+ vec2 nxt,+ vec2 prev) {+ vec2 a = prev;+ vec2 b = pos;+ vec2 c = nxt;+ vec2 ab = normalize(b - a);+ vec2 bc = normalize(c - b);+ vec2 tangent = normalize(ab + bc);+ vec2 extrusion = vec2(-tangent.y, tangent.x);+ float direction = sign(bzuv.y);+ float len = thick;++ // find the length of the miter line+ vec2 perpab = vec2(-ab.y,ab.x);+ len = len / dot(extrusion, perpab);++ vec2 delta = extrusion * len * direction;+ return pj * mv * vec4(pos + delta, 0.0, 1.0);+}++// Projects a plain point into screen coords.+// Used for alpha masking and "regular" uv mapping and coloring.+vec4 project_position(mat4 pj, mat4 mv, vec2 pos) {+ return pj * mv * vec4(pos.xy, 0.0, 1.0);+}++void main () {+ // Figure out what kind of projection to use.+ vec4 out_position = vec4(0);++ if (primitive == PrimTri || primitive == PrimBez || primitive == PrimMask) {+ out_position = project_position(projection, modelview, position);+ } else if (primitive == PrimLine) {+ out_position = project_line(projection, modelview, thickness, position,+ bezuv, next, previous);+ } else {+ out_position = project_position(projection, modelview, position);+ }++ fcolor = color;+ fuv = uv;+ fbez = bez;+ fbezuv = bezuv;++ gl_Position = out_position;+}
+ shaders/simple3d.frag view
@@ -0,0 +1,196 @@+#version 300 core++in vec4 fcolor;+in vec2 fuv;+in vec3 fbez;+in vec2 fbezuv;++out vec4 fragColor;++uniform int primitive;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;+uniform float feather;+uniform float sumlength;+uniform vec2 cap;+uniform float alpha;+uniform vec4 mult;++uniform vec4 replaceColor;+uniform bool shouldColorReplace;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Types for rendering line caps+const float CapNone = 0;+const float CapButt = 1;+const float CapSquare = 2;+const float CapRound = 3;+const float CapTriOut = 4;+const float CapTriIn = 5;++// Colors a fragment based solely on either an input color or a texture.+vec4 coord_fragment(bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 uvs) {+ if (isUV) {+ return texture(s, uvs.st);+ } else {+ return clr;+ }+}++// Colors a fragment using Loop-Blinn curve rendering.+vec4 bez_fragment(bool isUV,+ sampler2D s,+ vec3 bz,+ vec4 clr,+ vec2 uvs) {+ vec2 p = bz.xy;+ // when cw is true, winding is clockwise and we're drawing outside the+ // curve.+ bool cw = bool(bz.z);+ // gradients+ vec2 px = dFdx(p);+ vec2 py = dFdy(p);+ // chain rule+ float fx = (2*p.x)*px.x - px.y;+ float fy = (2*p.x)*py.x - py.y;+ // signed distance+ float sd = (p.x*p.x - p.y) / sqrt(fx*fx + fy*fy);+ // linear alpha+ float alpha = 0.5 - sd;+ alpha = cw ? 1 - alpha : alpha;+ // find the resulting fragment color+ float a = 0;++ if (alpha > 1) {+ a = 1;+ } else if (alpha < 0) {+ discard;+ } else {+ // we are right on the boundary, interpolate the color intensity.+ a = alpha;+ }++ vec4 color = vec4(0);+ if (isUV) {+ color = texture(s, uvs.st);+ } else {+ color = clr;+ }+ return vec4(color.rgb, color.a * a);+}++// Renders a polyline cap fragment.+float capd(float type, float u, float v, float t ) {+ // None+ if ( type == CapNone) discard;+ // Round+ else if (type == CapRound) return sqrt(u*u+v*v);+ // Triangle out+ else if (type == CapTriOut) return (u+abs(v));+ // Triangle in+ else if (type == CapTriIn) return max(abs(v),(t+u-abs(v)));+ // Square+ else if (type == CapSquare) return max(u,v);+ // Butt+ else if (type == CapButt) return max(u+t,v);+ discard;+}++vec4 line_fragment(float thick,+ float fthr,+ float slen,+ vec2 cp,+ bool isUV,+ sampler2D s,+ vec4 clr,+ vec2 bzuv,+ vec2 uvs) {+ float u = bzuv.x;+ float v = bzuv.y;+ float l = slen;+ float dx = abs(min(u, u - l));+ float dy = abs(v);+ float d = dy;++ vec4 color = vec4(0);+ if (isUV) {+ color = texture(s, uvs.st);+ } else {+ color = clr;+ }++ float t = thick/2.0 - fthr;++ if (u < 0) {+ // fragment is in the start cap+ d = capd(cp.x, abs(u), dy, t);+ } else if (u > slen) {+ // fragment is in the end cap+ d = capd(cp.y, u - l, dy, t);+ }++ d -= t;+ if (d < 0.0) {+ return color;+ } else {+ d /= fthr;+ return vec4(color.rgb, exp(-d*d)*color.a);+ }+}++// Colors a fragment using two textures, one the input texture and one as the+// alpha masking texture.+vec4 mask_fragment(sampler2D main,+ sampler2D mask,+ vec2 uvs) {+ vec4 color = texture(main, uvs.st);+ vec4 msk = texture(mask, uvs.st);+ return vec4(color.rgb, color.a * msk.a);+}++// Runs a color op on the fragment.+vec4 color_op_fragment(vec4 c, float a, vec4 m) {+ vec4 c1 = vec4(0);+ if (shouldColorReplace) {+ // Use a replacement color multiplied by the current red channel value.+ c1 = vec4(replaceColor.r, replaceColor.g, replaceColor.b, replaceColor.a * c.r) * m;+ } else {+ c1 = c * m;+ }+ return vec4(c1.rgb, c1.a * a);+}++void main() {+ vec4 out_color = vec4(0);+ switch (primitive) {+ case PrimTri:+ out_color = coord_fragment(hasUV, sampler, fcolor, fuv);+ break;+ case PrimBez:+ out_color = bez_fragment(hasUV, sampler, fbez, fcolor, fuv);+ break;+ case PrimLine: {+ out_color = line_fragment(thickness, feather, sumlength, cap, hasUV,+ sampler, fcolor, fbezuv, fuv);+ break;+ }+ case PrimMask:+ out_color = mask_fragment(mainTex, maskTex, fuv);+ break;+ default:+ break;+ }++ fragColor = color_op_fragment(out_color, alpha, mult);+}
+ shaders/simple3d.vert view
@@ -0,0 +1,89 @@+#version 300 core++in vec3 position;+in vec4 color;+in vec2 uv;+in vec3 bez;+in vec2 bezuv;+in vec3 next;+in vec3 previous;++out vec4 fcolor;+out vec2 fuv;+out vec3 fbez;+out vec2 fbezuv;++uniform int primitive;+uniform mat4 projection;+uniform mat4 modelview;+uniform bool hasUV;+uniform sampler2D sampler;+uniform sampler2D mainTex;+uniform sampler2D maskTex;+uniform float thickness;++// Primitive types+const int PrimTri = 0;+const int PrimBez = 1;+const int PrimLine = 2;+const int PrimMask = 4;++// Projects a polyline segment into screen coordinates.+vec4 project_line(mat4 pj,+ mat4 mv,+ float thick,+ vec3 pos,+ vec2 bzuv,+ vec2 nxt,+ vec2 prev) {+ vec3 a = prev;+ vec3 b = pos;+ vec3 c = nxt;+ vec3 ab = normalize(b - a);+ vec3 bc = normalize(c - b);+ vec3 tangent = normalize(ab + bc);+ vec3 extrusion = vec2(-tangent.y, tangent.x);+ float direction = sign(bzuv.y);+ float len = thick;++ // find the length of the miter line+ vec2 perpab = vec2(-ab.y,ab.x);+ len = len / dot(extrusion, perpab);++ vec2 delta = extrusion * len * direction;+ return pj * mv * vec4(pos + delta, 0.0, 1.0);+}++// Projects a plain point into screen coords.+// Used for alpha masking and "regular" uv mapping and coloring.+vec4 project_position(mat4 pj, mat4 mv, vec2 pos) {+ return pj * mv * vec4(pos.xy, 0.0, 1.0);+}++void main () {+ // Figure out what kind of projection to use.+ vec4 out_position = vec4(0);++ switch (primitive) {+ case PrimTri:+ case PrimBez:+ case PrimMask:+ out_position = project_position(projection, modelview, position);+ break;++ case PrimLine: {+ out_position = project_line(projection, modelview, thickness, position,+ bezuv, next, previous);+ break;+ }+ default:+ out_position = project_position(projection, modelview, position);+ }++ fcolor = color;+ fuv = uv;+ fbez = bez;+ fbezuv = bezuv;++ gl_Position = out_position;+}
+ src/Gelatin/Shaders.hs view
@@ -0,0 +1,25 @@+module Gelatin.Shaders+ ( module S+ , simple2dVertFilePath+ , simple2dFragFilePath+ , simple2dVertWebGLFilePath+ , simple2dFragWebGLFilePath+ ) where++import Gelatin.Shaders.Common as S+import Gelatin.Shaders.Simple2D as S+import Gelatin.Shaders.TypeLevel as S+import Paths_gelatin_shaders as S+import System.FilePath++simple2dVertFilePath :: IO FilePath+simple2dVertFilePath = getDataFileName $ "shaders" </> "simple2d.vert"++simple2dFragFilePath :: IO FilePath+simple2dFragFilePath = getDataFileName $ "shaders" </> "simple2d.frag"++simple2dVertWebGLFilePath :: IO FilePath+simple2dVertWebGLFilePath = getDataFileName $ "shaders" </> "simple2dwebgl.vert"++simple2dFragWebGLFilePath :: IO FilePath+simple2dFragWebGLFilePath = getDataFileName $ "shaders" </> "simple2dwebgl.frag"
+ src/Gelatin/Shaders/Common.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-}+module Gelatin.Shaders.Common+ ( VertexShader+ , FragmentShader+ , Uniform+ , Attribute+ , AttributeToggling(..)+ , AttributeBuffering(..)+ , IsShaderType(..)+ , ShaderSteps(..)+ ) where++import Data.Proxy (Proxy (..))+--------------------------------------------------------------------------------+import Gelatin.Shaders.TypeLevel+--------------------------------------------------------------------------------+-- $shader Defining shaders using (mostly) just types+--------------------------------------------------------------------------------+data VertexShader+data FragmentShader++data ShaderType = ShaderTypeVertex | ShaderTypeFragment++class IsShaderType a b where+ getShaderType :: Proxy a -> b++instance IsShaderType VertexShader ShaderType where+ getShaderType _ = ShaderTypeVertex++instance IsShaderType FragmentShader ShaderType where+ getShaderType _ = ShaderTypeFragment++instance (IsShaderType t b, IsShaderType ts [b])+ => IsShaderType (t ': ts) [b] where+ getShaderType _ = getShaderType (Proxy :: Proxy t) : getShaderType (Proxy :: Proxy ts)++instance IsShaderType '[] [x] where+ getShaderType _ = []++-- | A glsl uniform type.+data Uniform name val++instance GetLits name String => GetLits (Uniform name val) String where+ getSymbols _ = getSymbols (Proxy :: Proxy name)++-- | A glsl attribute type.+data Attribute name val loc++instance (GetLits name String, GetLits loc Integer)+ => GetLits (Attribute name val loc) (String, Integer) where+ getSymbols _ =+ let name = getSymbols (Proxy :: Proxy name)+ loc = getSymbols (Proxy :: Proxy loc)+ in (name, loc)++-- | Used to resolve typeclass instances for generating enable/disable attribute+-- functions.+data AttributeToggling a++-- | Used to resolve typeclass instances for generating attribute buffering+-- functions.+data AttributeBuffering a++-- | A shader step is a step in the shader compilation process. This means that+-- `ShaderSteps '[VertexShader, FragmentShader] [ByteString]` is a list of+-- vertex and fragment shader source code that needs to be compiled.+-- `ShaderSteps '[VertexShader, FragmentShader] GLuint` most likely means a list+-- of vertex and fragment shaders that need to be linked.+data ShaderSteps t v = ShaderSteps { unShaderSteps :: [v] }++-- | This is some future work in progress.+class MonadShader a where+ data M a :: * -> *++ data Program a+ readProgram :: (M a) (Program a)++ data Uniforms a+ updateUniforms :: Uniforms a -> (M a) ()++ data Attributes a+ enableAttributes :: Attributes a -> (M a) ()+ disableAttributes :: Attributes a -> (M a) ()+ bufferAttributes :: Attributes a -> (M a) ()
+ src/Gelatin/Shaders/Simple2D.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+module Gelatin.Shaders.Simple2D where++import Gelatin++import Gelatin.Shaders.Common+import Gelatin.Shaders.TypeLevel++-- | TODO: Most of this stuff is shader specific and shoud be moved to a+-- different part of the repo.++--------------------------------------------------------------------------------+-- $layout+-- Attributes layout locations are unique and global.+--------------------------------------------------------------------------------+type APosition = Attribute "position" (V2 Float) 0+type AColor = Attribute "color" (V4 Float) 1+type AUV = Attribute "uv" (V2 Float) 2+type ABez = Attribute "bez" (V3 Float) 3+type ABezUV = Attribute "bezuv" (V2 Float) 4+type APrev = Attribute "prev" (V2 Float) 5+type ANext = Attribute "next" (V2 Float) 6++type Simple2DAttribs = '[APosition, AColor, AUV, ABez, ABezUV, APrev, ANext]+type Simple2DAttribToggles = TypeMap AttributeToggling Simple2DAttribs+type Simple2DAttribBuffers = TypeMap AttributeBuffering Simple2DAttribs++--------------------------------------------------------------------------------+-- $uniforms+-- Uniform Helper Types+--------------------------------------------------------------------------------+data PrimType = PrimTri+ | PrimBez+ | PrimLine+ | PrimMask+ deriving (Show, Eq, Enum, Ord, Bounded)+--------------------------------------------------------------------------------+-- Updating uniforms+--------------------------------------------------------------------------------+type UPrimType = Uniform "primitive" PrimType+type UProjection = Uniform "projection" (M44 Float)+type UModelView = Uniform "modelview" (M44 Float)+type UThickness = Uniform "thickness" Float+type UFeather = Uniform "feather" Float+type USumLength = Uniform "sumlength" Float+type ULineCaps = Uniform "cap" (LineCap,LineCap)+type UHasUV = Uniform "hasUV" Bool+type USampler = Uniform "sampler" Int+type UMainTex = Uniform "mainTex" Int+type UMaskTex = Uniform "maskTex" Int+type UAlpha = Uniform "alpha" Float+type UMult = Uniform "mult" (V4 Float)+type UShouldReplaceColor = Uniform "shouldColorReplace" Bool+type UReplaceColor = Uniform "replaceColor" (V4 Float)++type Simple2DUniforms = '[ UPrimType+ , UProjection+ , UModelView+ , UThickness+ , UFeather+ , USumLength+ , ULineCaps+ , UHasUV+ , USampler+ , UMainTex+ , UMaskTex+ , UAlpha+ , UMult+ , UShouldReplaceColor+ , UReplaceColor+ ]++type Simple2DShaders = '[VertexShader, FragmentShader]
+ src/Gelatin/Shaders/TypeLevel.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++module Gelatin.Shaders.TypeLevel+ ( -- * Type level combinators+ (:&)(..)+ -- * Generating symbol values on type lists+ , GetLits(..)+ -- * Generating function class+ , HasGenFunc(..)+ -- * Mapping types+ , TypeMap+ ) where++import Data.Proxy (Proxy (..))+import GHC.TypeLits (KnownNat, KnownSymbol, natVal, symbolVal)+--------------------------------------------------------------------------------+-- Type level combinators+--------------------------------------------------------------------------------+-- | A heterogenious list.+data a :& b = a :& b+infixr 8 :&++class GetLits a t where+ getSymbols :: Proxy a -> t++instance GetLits '[] [t] where+ getSymbols _ = []++instance (GetLits a t, GetLits as [t]) => GetLits (a ': as) [t] where+ getSymbols _ = getSymbols (Proxy :: Proxy a) : getSymbols (Proxy :: Proxy as)++instance KnownSymbol a => GetLits a String where+ getSymbols = symbolVal++instance KnownNat a => GetLits a Integer where+ getSymbols = natVal+--------------------------------------------------------------------------------+-- Generating a function from a type+--------------------------------------------------------------------------------+class HasGenFunc a where+ type GenFunc a :: *+ genFunction :: Proxy a -> GenFunc a++instance (HasGenFunc a, HasGenFunc b) => HasGenFunc (a :& b) where+ type GenFunc (a :& b) = GenFunc a :& GenFunc b+ genFunction _ =+ let a = (Proxy :: Proxy a)+ b = (Proxy :: Proxy b)+ in genFunction a :& genFunction b++instance HasGenFunc '[] where+ type GenFunc '[] = ()+ genFunction _ = ()++instance (HasGenFunc a, HasGenFunc as) => HasGenFunc (a ': as) where+ type GenFunc (a ': as) = GenFunc a :& GenFunc as+ genFunction _ =+ let a = (Proxy :: Proxy a)+ as = (Proxy :: Proxy as)+ in genFunction a :& genFunction as++type family TypeMap (a :: * -> *) (xs :: [*]) :: [*]+type instance TypeMap t '[] = '[]+type instance TypeMap t (x ': xs) = t x ': TypeMap t xs