Last active
August 24, 2020 09:45
-
-
Save dptole/251a1fa4706442a2ca170f1772a1260c to your computer and use it in GitHub Desktop.
WebGL standalone example: Traceable cartesian plane (elm) https://ellie-app.com/7CqCLBYQCYHa1
This file contains hidden or 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
-- https://ellie-app.com/7CqCLBYQCYHa1 | |
-- https://webglfundamentals.org/ | |
-- elm install elm-explorations/linear-algebra | |
-- elm install elm-explorations/webgl | |
-- elm install elm/json | |
module Main exposing (..) | |
import Browser | |
import Json.Decode | |
import Html | |
import Html.Attributes | |
import Html.Events | |
import Math.Vector3 | |
import WebGL | |
-- MAIN | |
main = | |
Browser.element | |
{ init = init | |
, view = view | |
, update = update | |
, subscriptions = subscriptions | |
} | |
-- MODEL | |
type alias Coords = | |
{ x : Int | |
, y : Int | |
} | |
type alias Model = | |
{ x : Int | |
, y : Int | |
, v : List Vertex | |
, canvas_width : Int | |
, canvas_height : Int | |
} | |
init : () -> ( Model, Cmd Msg ) | |
init () = | |
( Model 0 0 [] 300 300, Cmd.none ) | |
-- UPDATE | |
type Msg | |
= CartesianPlaneCoords Coords | |
| RemoveLastVertex | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
RemoveLastVertex -> | |
( { model | |
| v = List.take ( List.length model.v - 1 ) model.v | |
} | |
, Cmd.none | |
) | |
CartesianPlaneCoords {x, y} -> | |
let | |
vertex_x = | |
toFloat x / toFloat model.canvas_width | |
|> (*) 2 | |
|> firstMinusSecond 1.0 | |
|> (*) 10 | |
|> round | |
|> toFloat | |
|> firstDivideSecond 10.0 | |
vertex_y = | |
toFloat y / toFloat model.canvas_height | |
|> (*) 2 | |
|> (-) 1 | |
|> (*) 10 | |
|> round | |
|> toFloat | |
|> firstDivideSecond 10.0 | |
v = | |
List.append | |
model.v | |
[ Vertex ( Math.Vector3.vec3 vertex_x vertex_y 0 ) ( Math.Vector3.vec3 1 0 0 ) ] | |
in | |
( { model | |
| x = x | |
, y = y | |
, v = v | |
} | |
, Cmd.none | |
) | |
-- SUBSCRIPTIONS | |
subscriptions : Model -> Sub Msg | |
subscriptions model = | |
Sub.none | |
-- VIEW | |
view : Model -> Html.Html Msg | |
view model = | |
Html.div | |
[] | |
[ WebGL.toHtml | |
[ Html.Attributes.width model.canvas_width | |
, Html.Attributes.height model.canvas_height | |
, Html.Attributes.style "display" "block" | |
, Html.Events.on "click" | |
(Json.Decode.map2 Coords | |
(Json.Decode.field "offsetX" Json.Decode.int) | |
(Json.Decode.field "offsetY" Json.Decode.int) | |
|> Json.Decode.map CartesianPlaneCoords | |
) | |
] | |
[ WebGL.entity vertexShader fragmentShader ( mesh model.v ) Uniforms ] | |
, Html.div | |
[] | |
[ Html.input | |
[ Html.Attributes.type_ "button" | |
, Html.Attributes.value "Remove last vertex" | |
, Html.Events.onClick RemoveLastVertex | |
] | |
[] | |
] | |
, Html.pre | |
[ Html.Attributes.style "white-space" "pre-wrap" ] | |
[ Html.text <| Debug.toString model ] | |
] | |
-- MISC | |
firstMinusSecond : number -> number -> number | |
firstMinusSecond a b = | |
b - a | |
firstDivideSecond : Float -> Float -> Float | |
firstDivideSecond a b = | |
b / a | |
-- MESH | |
type alias Vertex = | |
{ position : Math.Vector3.Vec3 | |
, color : Math.Vector3.Vec3 | |
} | |
mesh : List Vertex -> WebGL.Mesh Vertex | |
mesh vertexes = | |
let | |
pairedVertexes : List a -> List (a, a) | |
pairedVertexes p = | |
case p of | |
p1 :: p2 :: rest -> | |
( p1, p2 ) :: pairedVertexes ( p2 :: rest ) | |
_ -> | |
[] | |
vertex_points = | |
pairedVertexes vertexes | |
in | |
-- In WebGL clipspace goes from -1 to 1 | |
-- https://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html | |
List.range -10 10 | |
|> List.map (\i -> ( toFloat i ) / 10.0) | |
|> List.concatMap | |
(\i -> | |
let | |
position_horizontal_line_coord_1 = | |
Math.Vector3.vec3 -1 i 0 | |
position_horizontal_line_coord_2 = | |
Math.Vector3.vec3 1 i 0 | |
position_vertical_line_coord_1 = | |
Math.Vector3.vec3 i 1 0 | |
position_vertical_line_coord_2 = | |
Math.Vector3.vec3 i -1 0 | |
vcolor = | |
if i == 0 then -- Axis | |
Math.Vector3.vec3 0.3 0.3 0.3 | |
else | |
Math.Vector3.vec3 0.6 0.6 0.6 | |
in | |
[ ( Vertex position_horizontal_line_coord_1 vcolor | |
, Vertex position_horizontal_line_coord_2 vcolor | |
) | |
, ( Vertex position_vertical_line_coord_1 vcolor | |
, Vertex position_vertical_line_coord_2 vcolor | |
) | |
] | |
) | |
|> List.append vertex_points | |
|> WebGL.lines | |
-- SHADERS | |
type alias Uniforms = | |
{} | |
vertexShader : WebGL.Shader Vertex Uniforms { vcolor : Math.Vector3.Vec3 } | |
vertexShader = | |
[glsl| | |
attribute vec3 position; | |
attribute vec3 color; | |
varying vec3 vcolor; | |
void main () { | |
gl_Position = vec4(position, 1.0); | |
vcolor = color; | |
} | |
|] | |
fragmentShader : WebGL.Shader {} Uniforms { vcolor : Math.Vector3.Vec3 } | |
fragmentShader = | |
[glsl| | |
precision mediump float; | |
varying vec3 vcolor; | |
void main () { | |
gl_FragColor = vec4(vcolor, 1.0); | |
} | |
|] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment