Created
April 11, 2017 16:07
-
-
Save roovo/04881726413fcd78b0e91ade50c92bab to your computer and use it in GitHub Desktop.
elm: stuff wot I did to get text from canvas into webGL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module CanvasTexture exposing (canvasTexture) | |
-- imports are weird for Native modules | |
-- You import them as you would normal modules | |
-- but you can't alias them nor expose stuff from them | |
import Task exposing (Task) | |
import WebGL exposing (Error, Texture) | |
import Native.CanvasTexture | |
-- this will be our function which returns a number plus one | |
canvasTexture : String -> Texture | |
canvasTexture text = Native.CanvasTexture.canvasTexture text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _roovonotreally$replaceme$Native_CanvasTexture = function() { | |
function nearestPow2(aSize){ | |
return Math.pow(2, Math.round(Math.log(aSize) / Math.log(2))); | |
} | |
function higherPow2(aSize){ | |
return Math.pow(2, Math.ceil(Math.log(aSize) / Math.log(2))); | |
} | |
function makeTextCanvas(context, text, fontSize, width, height) { | |
context.canvas.width = width; | |
context.canvas.height = height; | |
context.clearRect(0, 0, context.canvas.width, context.canvas.height); | |
context.fillRect(0, 0, context.canvas.width, context.canvas.height); | |
context.fillStyle = "rgba(0, 0, 0, 0.0)"; | |
context.fill(); | |
context.font = fontSize + "px monospace"; | |
context.textAlign = "center"; | |
context.textBaseline = "middle"; | |
context.fillStyle = "white"; | |
context.fillText(text, width / 2, height / 2); | |
return context.canvas; | |
} | |
function loadCanvasTexture(text) { | |
var fontSize = 22; | |
var context = document.createElement("canvas").getContext("2d"); | |
context.font = fontSize + "px monospace"; | |
var width = context.measureText(text).width + 16; | |
var height = fontSize + 10; | |
var canvas = makeTextCanvas(context, text, fontSize, higherPow2(width), higherPow2(height)); | |
return { ctor: 'Texture', img: canvas }; | |
} | |
return { | |
canvasTexture: loadCanvasTexture | |
} | |
}(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type alias LabelVertex = | |
{ position : Vec2 | |
, textureCoord : Vec3 | |
} | |
type alias LabelUniform = | |
{ model : Mat4 | |
, view : Mat4 | |
, projection : Mat4 | |
, texture : Texture | |
} | |
nodeLabel : PositionedNode -> Renderable | |
nodeLabel node = | |
let | |
nodewodey = | |
node.node | |
nodeAttributes = | |
nodewodey.label | |
texture = | |
CanvasTexture.canvasTexture nodeAttributes.name | |
xPostion = | |
(plotWidth * (getX node.position)) - (plotWidth / 2) + 125 | |
yPosition = | |
(plotHeight * (getY node.position)) - (plotHeight / 2) | |
in | |
render | |
labelVertexShader | |
labelFragmentShader | |
(textMesh (textureSize texture)) | |
{ labelUniform | |
| model = makeTranslate3 xPostion yPosition 1.0 | |
, texture = texture | |
} | |
textMesh : ( Int, Int ) -> Drawable LabelVertex | |
textMesh ( width, height ) = | |
Triangle (textShape (toFloat width) (toFloat height)) | |
textShape : Float -> Float -> List ( LabelVertex, LabelVertex, LabelVertex ) | |
textShape width height = | |
let | |
topLeft = | |
{ position = vec2 (width / -2) (height / 2), textureCoord = vec3 0 1 0 } | |
topRight = | |
{ position = vec2 (width / 2) (height / 2), textureCoord = vec3 1 1 0 } | |
bottomLeft = | |
{ position = vec2 (width / -2) (height / -2), textureCoord = vec3 0 0 0 } | |
bottomRight = | |
{ position = vec2 (width / 2) (height / -2), textureCoord = vec3 1 0 0 } | |
in | |
[ ( topLeft, topRight, bottomLeft ) | |
, ( bottomLeft, topRight, bottomRight ) | |
] | |
labelVertexShader : Shader LabelVertex LabelUniform { texCoord : Vec2 } | |
labelVertexShader = | |
[glsl| | |
attribute vec2 position; | |
attribute vec3 textureCoord; | |
uniform mat4 model; | |
uniform mat4 view; | |
uniform mat4 projection; | |
varying vec2 texCoord; | |
void main () { | |
gl_Position = projection * view * model * vec4(position, 1.0, 1.0); | |
texCoord = textureCoord.xy; | |
} | |
|] | |
labelFragmentShader : Shader {} LabelUniform { texCoord : Vec2 } | |
labelFragmentShader = | |
[glsl| | |
precision mediump float; | |
uniform sampler2D texture; | |
varying vec2 texCoord; | |
void main () { | |
gl_FragColor = texture2D(texture, texCoord); | |
if (gl_FragColor.rgb == vec3(0.0, 0.0, 0.0)) { | |
discard; | |
} | |
} | |
|] |
Hey - and thanks - but I don't really have any plans for this as its not compatible with the latest version of the elm webgl package. If I re-pick up the side project where I was messing with this I'd see if I could get it working with the latest version and get some discussion going as an issue on elm-community/webgl to see if there was any appetite for inclusion - as it did work well and seemed to be the best way to get text working how I wanted it to. No immediate plans to do this atm tho as other things are taking priority...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, this looks super-useful. Do you have any plans to put it together into a library?