LoginSignup
3
1

More than 5 years have passed since last update.

GLSLレイマーチング研究_距離関数について勉強してみた04(signed(符号あり)のBoxの関数をいじる)

Last updated at Posted at 2017-02-15

GLSLレイマーチング研究_距離関数について勉強してみた02(unsigned(符号なし)のBoxの関数をいじる)からあまり進歩はないと思いますが…

書こうと思います.

cube01.PNG

signed(符号あり)のBoxの関数は,

vec3 d = abs(p) - vec3(0.5, 0.5, 0.5);
return min(max(d.x, max(d.y, d.z)), 0.0) + sqrt(max(d.x, 0.0) * max(d.x, 0.0) + max(d.y, 0.0) * max(d.y, 0.0) + max(d.z, 0.0) * max(d.z, 0.0))

省略して書くと,

vec3 d = abs(p) - vec3(0.5, 0.5, 0.5);
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));

値を変化させるところを書くと

vec3 d = abs(p) - vec3(x軸方向の長さ】, y軸方向の長さ】, z軸方向の長さ】);
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));

ちなみに、unsigned(符号なし)のBoxの関数は,

vec3 d = abs(p) - vec3(x軸方向の長さ】, y軸方向の長さ】, z軸方向の長さ】);
return length(max(d, 0.0));

ということは!

unsigned(符号なし)のBoxの関数に, min(max(d.x, max(d.y, d.z)), 0.0) を加えただけなのです!

min(max(d.x, max(d.y, d.z)), 0.0) って何よ?

って話ですが…

とりあえず、x,y,zの一番大きな負の値を取る関数ですね.

イメージが出来ないないので、あれですが…

とりあえず、

clmap関数で、書き換えてみる.

vec3 d = abs(p) - vec3(0.5, 0.5, 0.5);
return clamp(d.x, max(d.y, d.z), 0.0) + length(max(d, 0.0));

少しすっきりしたかな?

わかったら記事を更新します。

少しかっこいいやつできたので貼っとく

harituku.gif

vec3 d = abs(p) - vec3(1.0, 1.0, 1.0);
return min(max(d.x, max(d.y, d.z)) * -(0.8+0.02*sin(time)), 0.0) + length(max(d, 0.0));

今回のコード

// ============================================================================
// Box-signed distance function
// ============================================================================

precision mediump float;
uniform vec2  resolution;    // resolution (512.0, 512.0)
uniform vec2  mouse;         // mouse      (-1.0 ~ 1.0)
uniform float time;          // time       (1second == 1.0)
uniform sampler2D prevScene; // previous scene texture

// Boxの距離関数
float dCube(vec3 p){
    vec3 d = abs(p) - vec3(0.5, 0.5, 0.5);
    // Box-unsignedの描画
    // return length(max(d, 0.0));

    // Box-signedの描画
    return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));

    // clamp関数で書き換えてみる
    // return clamp(d.x, max(d.y, d.z), 0.0) + length(max(d, 0.0));

    // Box-signedのlength使用しない方法
    // return min(max(d.x, max(d.y, d.z)), 0.0) + sqrt(max(d.x, 0.0) * max(d.x, 0.0) + max(d.y, 0.0) * max(d.y, 0.0) + max(d.z, 0.0) * max(d.z, 0.0));

    // Round Box-signed
    // return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0)) - 1.0;

    // animetion
    // return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0)) + abs(sin(time));
    // return min(max(d.x, max(d.y, d.z)) * -(0.81+0.01*sin(time)), 0.0) + length(max(d, 0.0));
    // vec3 d = abs(p) - vec3(1.0, 1.0, 1.0);
    // return min(max(d.x, max(d.y, d.z)) * -(0.8+0.02*sin(time)), 0.0) + length(max(d, 0.0));

    /* min(max(d.x, max(d.y, d.z)), 0.0)研究 */
    // x成分のみ変位させる
    // return min(max(-abs(sin(time)), max(d.y, d.z)), 0.0) + length(max(d, 0.0));
    // y成分のみ変位させる
    // return min(max(d.x, max(-abs(sin(time)), d.z)), 0.0) + length(max(d, 0.0));
    // z成分のみ変位させる
    // return min(max(d.x, max(d.y, -abs(sin(time)))), 0.0) + length(max(d, 0.0));
    // y,z成分のみ変位させる
    // return min(max(d.x, max(-abs(sin(time)), -abs(sin(time)))), 0.0) + length(max(d, 0.0));
    // x,z成分のみ変位させる
    // return min(max(-abs(sin(time)), max(d.y, -abs(sin(time)))), 0.0) + length(max(d, 0.0));
    // x,y成分のみ変位させる
    // return min(max(-abs(sin(time)), max(-abs(sin(time)), d.z)), 0.0) + length(max(d, 0.0));
    // 全成分変位
    // return min(max(-abs(sin(time)), max(-abs(sin(time)), -abs(sin(time)))), 0.0) + length(max(d, 0.0));

    // return min(max(abs(sin(time)), max(abs(sin(time+time)), abs(sin(time*time*time)))), 0.0);

    // modを入れてみる
    // return min(max(-abs(mod(time, 3.0)), max(-abs(mod(time, 3.0)), -abs(sin(time)))), 0.0) + length(max(d, 0.0));

}

// 距離関数を呼び出すハブ関数
float distanceHub(vec3 p){
    return dCube(p);
    // return max(dCube(p), length(p)-1.0*abs(sin(time)));
}

// 法線を生成する
vec3 genNormal(vec3 p){
    float d = 0.001;
    return normalize(vec3(
        distanceHub(p + vec3(  d, 0.0, 0.0)) - distanceHub(p + vec3( -d, 0.0, 0.0)),
        distanceHub(p + vec3(0.0,   d, 0.0)) - distanceHub(p + vec3(0.0,  -d, 0.0)),
        distanceHub(p + vec3(0.0, 0.0,   d)) - distanceHub(p + vec3(0.0, 0.0,  -d))
    ));
}

void main(){
    // スクリーンスペースを考慮して座標を正規化する
    vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);

    // カメラを定義する
    vec3 cPos = vec3(0.0,  0.0,  3.0); // カメラの位置
    vec3 cDir = vec3(0.0,  0.0, -1.0); // カメラの向き(視線)
    vec3 cUp  = vec3(0.0,  1.0,  0.0); // カメラの上方向
    vec3 cSide = cross(cDir, cUp);     // 外積を使って横方向を算出
    float targetDepth = 1.0;           // フォーカスする深度

    // カメラの情報からレイを定義する
    vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);

    // マーチングループを組む
    float dist = 0.0;  // レイとオブジェクト間の最短距離
    float rLen = 0.0;  // レイに継ぎ足す長さ
    vec3  rPos = cPos; // レイの先端位置(初期位置)
    for(int i = 0; i < 32; ++i){
        dist = distanceHub(rPos);
        rLen += dist;
        rPos = cPos + ray * rLen;
    }

    // レイとオブジェクトの距離を確認
    if(abs(dist) < 0.001){
        // 法線を算出
        vec3 normal = genNormal(rPos);

        // ライトベクトルの定義(マウスの影響を受けるように)
        vec3 light = normalize(vec3(mouse + 1.0, 1.0));

        // ライトベクトルとの内積を取る
        float diff = max(dot(normal, light), 0.1);

        // diffuse を出力する
        gl_FragColor = vec4(vec3(diff), 1.0);
    }else{
        // 衝突しなかった場合はそのまま黒
        gl_FragColor = vec4(vec3(0.0), 1.0);
    }
}
3
1
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
3
1