Angenommen wird ein Liste von Cellen (das Grid) und in ein Koordinatensystem übersetzt.
module CellsToWebGL exposing (main)
{-
Add Cells with position vec 3 (XYZ) and color vec 3 (RGB)
see -> testCells
-}
import Browser
import Browser.Events exposing (onAnimationFrameDelta)
import Html exposing (Html)
import Html.Attributes exposing (height, style, width)
import Json.Decode exposing (Value)
import List exposing (concat)
import Math.Matrix4 as Mat4 exposing (Mat4)
import Math.Vector3 as Vec3 exposing (Vec3, toRecord, vec3)
import WebGL exposing (Mesh, Shader)
main : Program Value Float Float
main =
Browser.element
{ init = \_ -> ( 0, Cmd.none )
, view = view
, subscriptions = \_ -> onAnimationFrameDelta Basics.identity
, update = \dt theta -> ( theta + dt / 5000, Cmd.none )
}
view : Float -> Html Float
view theta =
WebGL.toHtml
[ width 1000
, height 1000
, style "display" "block"
, style "margin" "auto"
]
(cellsToWebGLEnteties testCells)
--Enteties
testCells =
[ Cell (vec3 0 13 0) (vec3 50 50 250)
, Cell (vec3 1 13 0) (vec3 250 50 50)
, Cell (vec3 2 13 0) (vec3 50 250 50)
, Cell (vec3 0 12 0) (vec3 250 50 250)
, Cell (vec3 1 13 5) (vec3 250 250 50)
, Cell (vec3 2 13 1) (vec3 50 150 50)
, Cell (vec3 2 13 2) (vec3 50 150 150)
]
type alias Cell =
{ position : Vec3
, color : Vec3
}
type alias Uniforms =
{ rotation : Mat4
, perspective : Mat4
, camera : Mat4
, shade : Float
}
uniforms : Uniforms
uniforms =
{ rotation = Mat4.identity
, perspective = Mat4.makePerspective 60 1 0.001 1000
, camera = Mat4.makeLookAt (vec3 6 6 -25) (vec3 6 6 6) (vec3 0 -1 0) -- inverted Camera
, shade = 0.8
}
--COORDINATE HELPER
-- (0,0,6) (0,6,6)
-- ___________________
-- / | / |
-- (0,0,0) /__|_______________/__| (6,0,0)
-- | | | |
-- | | | |
-- | | (0,13,6) | | (6,13,6)
-- | | _____________|___|
-- | / | /
-- (0,13,0) |/_________________|/ (0,13,0)
--
cellsToWebGLEnteties : List Cell -> List WebGL.Entity
cellsToWebGLEnteties cells =
case cells of
[] ->
[]
[ x ] ->
[ WebGL.entity
vertexShader
fragmentShader
(cellToMesh x)
uniforms
]
x :: xs ->
concat
[ [ WebGL.entity
vertexShader
fragmentShader
(cellToMesh x)
uniforms
]
, cellsToWebGLEnteties xs
]
-- Mesh
type alias Vertex =
{ color : Vec3
, position : Vec3
}
cellToMesh : Cell -> Mesh Vertex
cellToMesh cell =
let
--create record to access x y z
posRecord =
toRecord cell.position
--right front top
rft =
vec3 (posRecord.x + 1) (posRecord.y + 1) posRecord.z
-- left front top
lft =
vec3 posRecord.x (posRecord.y + 1) posRecord.z
--left back top
lbt =
vec3 posRecord.x (posRecord.y + 1) (posRecord.z + 1)
--right back top
rbt =
vec3 (posRecord.x + 1) (posRecord.y + 1) (posRecord.z + 1)
--right back bot
rbb =
vec3 (posRecord.x + 1) posRecord.y (posRecord.z + 1)
--right front bot
rfb =
vec3 (posRecord.x + 1) posRecord.y posRecord.z
--left front bot
lfb =
vec3 posRecord.x posRecord.y posRecord.z
-- left back bot
lbb =
vec3 posRecord.x posRecord.y (posRecord.z + 1)
-- Create record to manipulate colors
-- x = r | y = g | z = b
colRecord =
toRecord cell.color
shade1 =
vec3 (colRecord.x - 30) (colRecord.y - 30) (colRecord.z - 30)
shade2 =
vec3 (colRecord.x - 50) (colRecord.y - 50) (colRecord.z - 50)
in
[ face shade2 rft rfb rbb rbt -- right
, face shade1 rft rfb lfb lft -- front
, face cell.color rft lft lbt rbt -- top
, face shade1 rfb lfb lbb rbb -- back
, face cell.color lft lfb lbb lbt --left
, face shade2 rbt rbb lbb lbt -- bot
]
|> List.concat
|> WebGL.triangles
face : Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> List ( Vertex, Vertex, Vertex )
face color a b c d =
let
vertex position =
Vertex (Vec3.scale (1 / 255) color) position
in
[ ( vertex a, vertex b, vertex c )
, ( vertex c, vertex d, vertex a )
]
-- Shaders
vertexShader : Shader Vertex Uniforms { vcolor : Vec3 }
vertexShader =
[glsl|
attribute vec3 position;
attribute vec3 color;
uniform mat4 perspective;
uniform mat4 camera;
uniform mat4 rotation;
varying vec3 vcolor;
void main () {
gl_Position = perspective * camera * rotation * vec4(position, 1.0);
vcolor = color;
}
|]
fragmentShader : Shader {} Uniforms { vcolor : Vec3 }
fragmentShader =
[glsl|
precision mediump float;
uniform float shade;
varying vec3 vcolor;
void main () {
gl_FragColor = shade * vec4(vcolor, 1.0);
}
|]