Created
December 27, 2019 14:59
-
-
Save eitoball/475811ae303d670cacf22c62eb04f8f1 to your computer and use it in GitHub Desktop.
マンデルブロ集合
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 Main exposing (main) | |
import Browser | |
import Browser.Dom exposing ( Viewport, getViewport ) | |
import Browser.Events exposing ( onMouseMove, onResize ) | |
import Html exposing ( Html ) | |
import Html.Attributes exposing ( height, style, width ) | |
import Json.Decode as Decode exposing ( Decoder ) | |
import Math.Vector2 exposing ( Vec2, vec2 ) | |
import Math.Vector3 exposing ( Vec3, vec3 ) | |
import Task | |
import Time | |
import WebGL exposing ( Mesh, Shader ) | |
type alias Model = | |
{ size : | |
{ width : Float | |
, height : Float | |
} | |
, location : | |
{ x : Float | |
, y : Float | |
} | |
, load_time : Float | |
} | |
main : Program () Model Msg | |
main = | |
Browser.element | |
{ init = init | |
, view = view | |
, update = update | |
, subscriptions = subscriptions | |
} | |
init : () -> ( Model, Cmd Msg ) | |
init _ = | |
( | |
{ load_time = 0.0 | |
, size = { width = 0.0, height = 0.0 } | |
, location = { x = 0.0, y = 0.0 } | |
} | |
, Cmd.batch | |
[ Task.perform GetViewport getViewport | |
] | |
) | |
view : Model -> Html Msg | |
view model = | |
let | |
location = model.location | |
size = model.size | |
_ = Debug.log "location" location | |
in | |
WebGL.toHtml | |
[ width (size.width |> round) | |
, height (size.height |> round) | |
] | |
[ WebGL.entity | |
vertexShader | |
fragmentShader | |
mesh | |
{ mouse = vec2 location.x location.y | |
, resolution = vec2 size.width size.height | |
, time = model.load_time | |
} | |
] | |
type Msg | |
= GetViewport Viewport | |
| MouseMove Float Float | |
| Resize Int Int | |
| Tick Time.Posix | |
mouseMoveDecoder : Decode.Decoder Msg | |
mouseMoveDecoder = | |
Decode.map2 MouseMove | |
(Decode.field "pageX" Decode.float) | |
(Decode.field "pageY" Decode.float) | |
update : Msg -> Model -> ( Model, Cmd Msg ) | |
update msg model = | |
case msg of | |
GetViewport { viewport } -> | |
( { model | |
| size = | |
{ width = viewport.width | |
, height = viewport.height | |
} | |
} | |
, Cmd.none | |
) | |
MouseMove left top -> | |
let | |
location = { x = left / 1000.0, y = top / 1000.0 } | |
in | |
( { model | location = location }, Cmd.none ) | |
Resize width height -> | |
( { model | |
| size = | |
{ width = width |> toFloat | |
, height = height |> toFloat | |
} | |
} | |
, Cmd.none | |
) | |
Tick time -> | |
( { model | load_time = model.load_time + 1.0 }, Cmd.none ) | |
subscriptions : Model -> Sub Msg | |
subscriptions _ = | |
Sub.batch | |
[ onMouseMove mouseMoveDecoder | |
, onResize Resize | |
, Time.every 1000 Tick | |
] | |
mesh : Mesh { position : Vec3 } | |
mesh = | |
WebGL.triangles | |
[ | |
( { position = vec3 -1.0 1.0 0.0 } | |
, { position = vec3 1.0 1.0 0.0 } | |
, { position = vec3 1.0 -1.0 0.0 } | |
) | |
, ( { position = vec3 1.0 -1.0 0.0 } | |
, { position = vec3 -1.0 -1.0 0.0 } | |
, { position = vec3 -1.0 1.0 0.0 } | |
) | |
] | |
type alias Uniforms = | |
{ mouse : Vec2 | |
, resolution : Vec2 | |
, time : Float | |
} | |
vertexShader : Shader { position : Vec3 } Uniforms {} | |
vertexShader = | |
[glsl| | |
attribute vec3 position; | |
void main() { | |
gl_Position = vec4(position, 1.0); | |
} | |
|] | |
fragmentShader : Shader {} Uniforms {} | |
fragmentShader = | |
[glsl| | |
precision mediump float; | |
uniform vec2 mouse; | |
uniform vec2 resolution; | |
uniform float time; | |
vec3 hsv(float h, float s, float v) { | |
vec4 t = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); | |
vec3 p = abs(fract(vec3(h) + t.xyz) * 6.0 - vec3(t.w)); | |
return v * mix(vec3(t.x), clamp(p - vec3(t.x), 0.0, 1.0), s); | |
} | |
void main() { | |
vec2 m = vec2(mouse.x * 2.0 - 1.0, -mouse.y * 2.0 + 1.0); | |
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y); | |
int j = 0; | |
vec2 x = p + vec2(-0.5, 0.0); | |
float y = 1.5 - m.x * 0.5; | |
vec2 z = vec2(0.0, 0.0); | |
for (int i = 0; i < 360; ++i) { | |
j++; | |
if (length(z) > 2.0) { | |
break; | |
} | |
z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + x * y; | |
} | |
float h = mod(time * 20.0, 360.0) / 360.0; | |
vec3 rgb = hsv(h, 1.0, 1.0); | |
float t = float(j) / 360.0; | |
gl_FragColor = vec4(rgb * t, 1.0); | |
} | |
|] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment