Skip to content

Instantly share code, notes, and snippets.

@roovo
Created April 11, 2017 16:07
Show Gist options
  • Save roovo/04881726413fcd78b0e91ade50c92bab to your computer and use it in GitHub Desktop.
Save roovo/04881726413fcd78b0e91ade50c92bab to your computer and use it in GitHub Desktop.
elm: stuff wot I did to get text from canvas into webGL
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
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
}
}();
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;
}
}
|]
@kfish
Copy link

kfish commented Jul 17, 2017

Hi, this looks super-useful. Do you have any plans to put it together into a library?

@roovo
Copy link
Author

roovo commented Jul 26, 2017

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