0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

wslでelixir その185

0
Posted at

概要

wsl(wsl2じゃない)で、elixirやってみた。
Livebookで、kinoshadertoy書いてみた。

写真

image.png

setup

Mix.install([
  {:kino, "~> 0.19"}
])

サンプルコード

defmodule KinoShadertoy do
  use Kino.JS
  use Kino.JS.Live
  def new(shader_code) do
    Kino.JS.Live.new(__MODULE__, shader_code)
  end
  @impl true
  def init(shader_code, ctx) do
    {:ok, assign(ctx, shader_code: shader_code)}
  end
  @impl true
  def handle_connect(ctx) do
    {:ok, ctx.assigns.shader_code, ctx}
  end
  asset "main.js" do
    ~S"""
    export function init(ctx, shaderCode) {
      function showError(title, details) {
        ctx.root.innerHTML = `
          <div style="background: #fee2e2; color: #991b1b; padding: 1rem; border-radius: 0.5rem; font-family: monospace; font-size: 14px; white-space: pre-wrap; border: 1px solid #fca5a5;">
            <strong style="font-size: 16px;">${title}</strong><br/><br/>${details}
          </div>
        `;
      }
      const canvas = document.createElement("canvas");
      canvas.width = 600;
      canvas.height = 400;
      const gl = canvas.getContext("webgl2");
      if (!gl) 
      {
        showError("WebGL 2 Not Supported", "Your browser or system does not support WebGL2.");
        return;
      }
      const vsSource = `#version 300 es
        in vec2 position;
        void main() {
          gl_Position = vec4(position, 0.0, 1.0);
        }
      `;
      const cleanShaderCode = shaderCode.replace(/\r\n/g, "\n");
      const fsSource = `#version 300 es
        precision highp float;
        out vec4 fragColor;
        uniform vec3 iResolution;
        uniform float iTime;
        ${cleanShaderCode}
        void main() {
          mainImage(fragColor, gl_FragCoord.xy);
        }
      `;
      function createShader(gl, type, source, shaderTypeName) {
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) 
        {
          const log = gl.getShaderInfoLog(shader);
          showError(`GLSL Compilation Error (${shaderTypeName})`, log);
          gl.deleteShader(shader);
          return null;
        }
        return shader;
      }
      const vs = createShader(gl, gl.VERTEX_SHADER, vsSource, "Vertex Shader");
      if (!vs) 
        return;
      const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource, "Fragment Shader");
      if (!fs) 
        return;
      const program = gl.createProgram();
      gl.attachShader(program, vs);
      gl.attachShader(program, fs);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) 
      {
        showError("Shader Program Link Error", gl.getProgramInfoLog(program));
        return;
      }
      ctx.root.appendChild(canvas);
      const positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        -1, -1,  1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
      ]), gl.STATIC_DRAW);
      const positionLocation = gl.getAttribLocation(program, "position");
      const iResolutionLocation = gl.getUniformLocation(program, "iResolution");
      const iTimeLocation = gl.getUniformLocation(program, "iTime");
      let startTime = performance.now();
      function render() {
        const time = (performance.now() - startTime) * 0.001;
        gl.viewport(0, 0, canvas.width, canvas.height);
        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.useProgram(program);
        gl.uniform3f(iResolutionLocation, canvas.width, canvas.height, 1.0);
        gl.uniform1f(iTimeLocation, time);
        gl.enableVertexAttribArray(positionLocation);
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
        gl.drawArrays(gl.TRIANGLES, 0, 6);
        requestAnimationFrame(render);
      }
      render();
    }
    """
  end
end





shader_code = """
precision mediump float;
//uniform vec3 iResolution;
//uniform float iTime;
uniform int iFrame;
#define SHAPE length(z.yz)
#define HIGH_QUAL
#ifdef HIGH_QUAL
#define MARCH_STEPS 199
#else
#define MARCH_STEPS 99
#endif
float k;// = 7.0 + 3.0 * sin(iTime * 0.15);
vec3 mcol = vec3(0.0);
void AbsBox(inout vec4 z) {
	z.xyz = abs(z.xyz + 1.0) - 1.0;
	z *= 1.5 / clamp(dot(z.xyz, z.xyz), 0.25, 1.0);
}
void Bulb(inout vec4 z, in vec4 c) {
	k = 7.0 + 3.0 * sin(iTime * 0.15);
	float r = length(z.xyz);
	float zo = asin(z.z / r) * k + iTime * 0.15;
	float zi = atan(z.y, z.x) * 7.0;
	z = pow(r, k - 1.0) * vec4(r * vec3(cos(zo) * vec2(cos(zi), sin(zi)), sin(zo)), z.w * k) + c;
}
float DE(vec3 p) {
	vec4 c = vec4(p, 1.0),
		z = c;
	Bulb(z, c);
	float r0 = (length(z.xyz) - 1.15) / z.w;
	z.xyz -= 1.0;
	for (int i = 0; i < 7; i++) AbsBox(z);
	float r = SHAPE;
	mcol.rgb = vec3(1.0, 0.5, 0.2) + abs(sin(0.2 * r + 100.0 * z.yxz / z.w));
	return 0.5 * max((r - 1.0) / z.w, -r0);
}
vec3 sky(vec3 rd, vec3 L) {
	float d = 0.4 * dot(rd, L) + 0.6;
	rd.y += sin(sqrt(clamp(-rd.y, 0.0, 0.9)) * 90.0) * 0.45 * max(-0.1, rd.y);
	rd = abs(rd);
	float y = max(0., L.y),
		sun = max(1. - (1. + 10. * y + rd.y) * length(rd - L), 0.) + .3 * pow(1. - rd.y, 12.) * (1.6 - y);
	return d * mix(vec3(0.3984, 0.5117, 0.7305), vec3(0.7031, 0.4687, 0.1055), sun) *((.5 + pow(y, .4)) * (1.5 - abs(L.y)) + pow(sun, 5.2) * y * (5. + 15.0 * y));
}
float rnd;
void randomize(in vec2 p) {
	rnd = fract(float(iFrame) + sin(dot(p, vec2(13.3145, 117.7391))) * 42317.7654321);
}
vec3 scene(vec3 ro, vec3 rd) {
	vec3 L = normalize(vec3(0.4, 0.025, 0.5));
	vec3 bcol = sky(rd, L);
	vec4 col = vec4(0.0);
	float t = DE(ro) * rnd,
		d,
		od = 1.0,
		px = 1.0 / iResolution.x;
	ro += rd * t;
	for (int i = 0; i < MARCH_STEPS; i++)
	{
		d = DE(ro);
		if (d < px * t)
		{
			float dif = clamp(1.0 - d / od, 0.2, 1.0);
			vec3 scol = mcol * dif * (1.3 - 0.3 * t);
#ifdef HIGH_QUAL
	  		vec2 s = vec2(DE(ro + d * 4.0 * L), DE(ro + d * 16.0 * L));
			scol *= clamp(0.5 * s.x / d + (s.y / d) / 8.0, 0.0, 1.0);
#endif
			float alpha = (1.0 - col.w) * clamp(1.0 - d / (px * t), 0.0, 1.0);
			col += vec4(clamp(scol, 0.0, 1.0), 1.0) * alpha;
			if (col.w > 0.9) break;
		}
		t += d;
		ro += rd * d;
		od = d;
		if (t > 6.0) break;
	}
	col.rgb += bcol * (1.0 - clamp(col.w, 0.0, 1.0));
	return col.rgb;
}
mat3 lookat(vec3 fw) {
	fw = normalize(fw);
	vec3 rt = normalize(cross(fw, vec3(0.0, 1.0, 0.0)));
	return mat3(rt, cross(rt, fw), fw);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
   randomize(fragCoord);
   float tim = iTime * 0.3,
		r = 2.0 + cos(tim * 0.7);
   vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.x;
   vec3 ro = vec3(sin(tim) * r, sin(tim * 0.4), cos(tim) * r);
   vec3 rd = lookat(-ro) * normalize(vec3(uv, 1.0));
   fragColor = vec4(scene(ro, rd) * 2.0, 1.0);
}
"""

KinoShadertoy.new(shader_code)


以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?