-- elm install elm-explorations/linear-algebra -- elm install elm-explorations/webgl import Browser import Browser.Events as E import Html exposing (Html) import Html.Attributes exposing (width, height, style) import Math.Matrix4 as Mat4 exposing (Mat4) import Math.Vector3 as Vec3 exposing (Vec3, vec3) import WebGL -- MAIN main = Browser.element { init = init , view = view , update = update , subscriptions = subscriptions } -- MODEL type alias Model = Float init : () -> (Model, Cmd Msg) init () = ( 0, Cmd.none ) -- UPDATE type Msg = TimeDelta Float update : Msg -> Model -> (Model, Cmd Msg) update msg currentTime = case msg of TimeDelta delta -> ( delta + currentTime, Cmd.none ) -- SUBSCRIPTIONS subscriptions : Model -> Sub Msg subscriptions _ = E.onAnimationFrameDelta TimeDelta -- VIEW view : Model -> Html msg view t = WebGL.toHtml [ width 400, height 400, style "display" "block" ] [ WebGL.entity vertexShader fragmentShader mesh { perspective = perspective (t / 1000) } ] perspective : Float -> Mat4 perspective t = Mat4.mul (Mat4.makePerspective 45 1 0.01 100) (Mat4.makeLookAt (vec3 (4 * cos t) 0 (4 * sin t)) (vec3 0 0 0) (vec3 0 1 0)) -- MESH type alias Vertex = { position : Vec3 , color : Vec3 } mesh : WebGL.Mesh Vertex mesh = WebGL.triangles [ ( Vertex (vec3 0 0 0) (vec3 1 0 0) , Vertex (vec3 1 1 0) (vec3 0 1 0) , Vertex (vec3 1 -1 0) (vec3 0 0 1) ) ] -- SHADERS type alias Uniforms = { perspective : Mat4 } vertexShader : WebGL.Shader Vertex Uniforms { vcolor : Vec3 } vertexShader = [glsl| attribute vec3 position; attribute vec3 color; uniform mat4 perspective; varying vec3 vcolor; void main () { gl_Position = perspective * vec4(position, 1.0); vcolor = color; } |] fragmentShader : WebGL.Shader {} Uniforms { vcolor : Vec3 } fragmentShader = [glsl| precision mediump float; varying vec3 vcolor; void main () { gl_FragColor = vec4(vcolor, 1.0); } |]