LoginSignup
25

More than 5 years have passed since last update.

無限に数式を自動生成するシェーダーガチャつくってみた

Last updated at Posted at 2019-01-03

はじめに

あけましておめでとうございます。
お正月といえば初詣のおみくじですが、
実行する度に違う映像が出てくるシェーダー(数式)ガチャをつくってみました。

シェーダープログラムを実行できるProcessing上で、
プログラムが実行される度にシェーダーの数式を生成します。

shader.gif

簡単に試せます

目次

  • まずは数式生成だけを試してみる
  • Processingで実行
    • 環境構築
    • ソースコードの設置
    • 実装&実行
    • どのように数式を生成しているのか

まずは数式生成だけを試してみる

数式の生成コードをこちらでweb上で実行可能なようにまとめてみました。
python2 https://paiza.io/projects/dKRwcY0D_wWGkMMa1rNIAw
まずはこちらのサイトを開き、実行ボタンを押してみましょう。
しばらくすると、出力のところに以下のようにシェーダーの数式が吐き出されます。

============================
        #ifdef GL_ES
        precision mediump float;
        #endif
        uniform vec2 resolution;
        uniform float time;
        void main() {
            vec2 uv = -1. + 2. * gl_FragCoord.xy / resolution.xy;
            gl_FragColor = clamp( abs( vec4(
               cos( time * 5.) ,
               uv.y * sin( sin( log( sin( fract( uv.x * sign( sqrt( floor( exp( abs( sin( uv.y * floor( log2(  uv.x * uv.y + time  ) ) - floor(uv.y * floor( log2(  uv.x * uv.y + time  ) )) * time) ) ) ) ) ) - floor(uv.x * sign( sqrt( floor( exp( abs( sin( uv.y * floor( log2(  uv.x * uv.y + time  ) ) - floor(uv.y * floor( log2(  uv.x * uv.y + time  ) )) * time) ) ) ) ) )) ) * time) ) ) * time) - floor(uv.y * sin( sin( log( sin( fract( uv.x * sign( sqrt( floor( exp( abs( sin( uv.y * floor( log2(  uv.x * uv.y + time  ) ) - floor(uv.y * floor( log2(  uv.x * uv.y + time  ) )) * time) ) ) ) ) ) - floor(uv.x * sign( sqrt( floor( exp( abs( sin( uv.y * floor( log2(  uv.x * uv.y + time  ) ) - floor(uv.y * floor( log2(  uv.x * uv.y + time  ) )) * time) ) ) ) ) )) ) * time) ) ) * time)) ,
               uv.x + time ,
               1. ) ),0.,1.);
        }
============================
(878, 'characters code')

生成された数式の文字数も同時に表示されます。

シェーダーにはいくつか種類がありますが、
フラグメントシェーダーは基本的に gl_FragColor = vec4(R,G,B,A);のように
RGBAのそれぞれの色を計算する数式でできています。

このままだと意味が分かりませんが、出力されたコード(=====で囲まれた部分)をGLSL sandboxなどのwebサービスに貼り付けると、映像を確認することができます。

sandbox.jpg
正しく実行できるシェーダープログラムだということが分かります。

Processingで数式ガチャをつくる

コードを生成できることが確認できたので、次はProcessing上でこれを実行したいと思います。

環境構築

windowsでもmacでも大丈夫です。
Processingをインストールします。

Processingのダウンロードはこちらから
https://processing.org/download/

続いてPythonモードのインストール(こちらのリンクが画像付きで分かりやすいです)
https://pycarnival.com/processingpy1/

ソースコードの設置

Processingのプロジェクト(pydeファイル)が保存されるディレクトリと同じ場所に、
https://github.com/mizumasa/pyShaderGenerator
こちらからダウンロードしたソースコードを丸ごと置きます。

dataフォルダ、shader_lib.py、などのファイルがプロジェクトファイル(.pyde)と同じ階層になるようにしてください。

実装&実行

実行するpydeファイルには、以下のように実装します。

import shader_lib

def setup():
    global sd
    size(600, 600, P2D)
    global code
    code = shader_lib.makeNewShader()
    print(code)
    shader_lib.saveShader("data/sample.glsl",code)
    sd = loadShader("sample.glsl")

def keyPressed():
    if key == "s":
        global code
        timeStamp = shader_lib.getTimeStamp()
        shader_lib.saveShader("data/"+timeStamp+".glsl",code)
        save("data/"+timeStamp+".png")

def draw():
    global sd
    sd.set("time", millis() / 1000.0)
    sd.set("resolution", float(width), float(height))  
    shader(sd)
    rect(0, 0, width, height)

そのまま実行ボタンを押せば自動でシェーダーが生成されます!
windowsだと以下のような感じのフォルダ構成、実装、実行結果になります。

thumb_windows.png

どのように数式を生成しているのか

詳しいことはここでは書きませんが、数式を生成するために、枝分かれする木のように数式を繋げる処理を行なっています。そのため、基本的に同じ数式はほぼ二度と出てこないような仕組みになっています。

code2.png

何回かやってみて、気に入ったものはsキーを押すとdataフォルダの中に
キャプチャ画像がシェーダーコードと一緒に保存されます。

thumb_mac.gif

おまけ

これを発展させていくと、さらに長く、複雑なコードを生成することも可能です。
charactor7.jpg

強化学習を組み合わせてさらに生成を賢くすることも実験中です。


まとめ

Processing上で実行可能な数式(シェーダープログラム)のガチャをつくりました。
最初にPythonモードを入れる以外は依存ライブラリもないので是非お試しくださいー。

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
25