読者です 読者をやめる 読者になる 読者になる

Daily Creative Coding

元「30 min. Processing」。毎日、Creative Codingします。

大域的・局所的に回転するボックス

See the Pen globally and locally rotating boxes by aadebdeb (@aadebdeb) on CodePen.

#define PI 3.14159265359
#define TWO_PI PI * 2.0


precision mediump float;

uniform float u_time;
uniform vec2 u_mouse;
uniform vec2 u_resolution;

vec3 rotateX(vec3 p, float theta) {
    float c = cos(-theta);
    float s = sin(-theta);

    mat3 m = mat3(vec3(1, 0.0, 0.0),
                  vec3(0.0, c, -s),
                  vec3(0.0, s, c));
    return m * p;
}


vec3 rotateY(vec3 p, float theta) {
    float c = cos(-theta);
    float s = sin(-theta);

    mat3 m = mat3(vec3(c, 0.0, s),
                  vec3(0.0, 1.0, 0.0),
                  vec3(-s, 0.0, c));
    return m * p;
}

vec3 rotateZ(vec3 p, float theta) {
    float c = cos(-theta);
    float s = sin(-theta);

    mat3 m = mat3(vec3(c, -s, 0.0),
                  vec3(s, c, 0.0),
                  vec3(0.0, 0.0, 1.0));
    return m * p;
}

vec3 translate(vec3 p, vec3 t) {
    mat4 m = mat4(vec4(1.0, 0.0, 0.0, 0.0),
                  vec4(0.0, 1.0, 0.0, 0.0),
                  vec4(0.0, 0.0, 1.0, 0.0),
                  vec4(-t.x, -t.y, -t.z, 1.0));

    return (m * vec4(p, 1.0)).xyz;
}

float calcBoxDistance(vec3 p, vec3 size) {
    return length(max(abs(p) - size, 0.0));
}

float calcSphereDistance(vec3 p, float size) {
    return length(p) - size;
}

float calcDistance(vec3 p) {
    float t = u_time * 0.001;
    vec2 mouse = (u_mouse * 2.0 - u_resolution) / min(u_resolution.x, u_resolution.y);

    vec3 q = p;
    q = rotateX(q, mouse.x * PI);
    q = rotateY(q, mouse.x * PI);
    q = rotateZ(q, mouse.x * PI);

    vec3 p1 = translate(q, vec3(-0.5, 0.0, 0.0));
    float d1 = calcBoxDistance(p1, vec3(0.2));

    vec3 p2 = translate(q, vec3(0.5, 0.0, 0.0));
    p2 = rotateX(p2, mouse.y * PI);
    p2 = rotateY(p2, mouse.y * PI);
    p2 = rotateZ(p2, mouse.y * PI);
    float d2 = calcBoxDistance(p2, vec3(0.2));
    return min(d1, d2);
}

vec3 calcNormal(vec3 p) {
    float delta = 0.00001;
    return normalize(vec3(
        calcDistance(p + vec3(delta, 0.0, 0.0)) - calcDistance(p - vec3(delta, 0.0, 0.0)),
        calcDistance(p + vec3(0.0, delta, 0.0)) - calcDistance(p - vec3(0.0, delta, 0.0)),
        calcDistance(p + vec3(0.0, 0.0, delta)) - calcDistance(p - vec3(0.0, 0.0, delta))
    ));
}

void main(void) {
    vec2 st = (gl_FragCoord.xy * 2.0 - u_resolution) / min(u_resolution.x, u_resolution.y);

    vec3 cameraPosition = vec3(0.0, 0.0, 5.0);
    vec3 rayDirection = normalize(vec3(st, 0.0) - cameraPosition);
    vec3 rayPosition = cameraPosition;
    float radian = u_time * 0.0003;
    vec3 lightPosition = vec3(5.0, 5.0, 5.0);
    vec3 color = vec3(0.0);
    float d;
    for (int i = 0; i < 64; i++) {
        d = calcDistance(rayPosition);
        rayPosition += rayDirection * d;
    }

    if (d < 0.0001) {
        vec3 normal = calcNormal(rayPosition);
        float weight = dot(normal, normalize(lightPosition));
        color = vec3(1.0) * max(weight, 0.0) + vec3(0.1);
    }

    gl_FragColor = vec4(color, 1.0);
}
f:id:aa_debdeb:20170427225932p:plain