Daily Creative Coding

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

【GLSL】色付きのオブジェクト

See the Pen objects with color by aadebdeb (@aadebdeb) on CodePen.

#define PI 3.14159265359
#define TWO_PI PI * 2.0
#define HALF_PI PI / 2.0


precision mediump float;

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

struct Camera {
    vec3 position;
    vec3 ray;
};

float random(float v) {
    return fract(sin(v) * 43758.5453123);
}

float smoothmin(float d1, float d2, float k) {
    return -log(exp(-k * d1) + exp(-k * d2)) / k;
}

vec3 repeat(vec3 p, vec3 interval) {
    return mod(p, interval) - interval / 2.0;
}

vec3 repeatX(vec3 p, float interval) {
    return vec3(mod(p.x, interval) - interval / 2.0, p.y, p.z);
}

vec3 repeatY(vec3 p, float interval) {
    return vec3(p.x, mod(p.y, interval) - interval / 2.0, p.z);
}

vec3 repeatZ(vec3 p, float interval) {
    return vec3(p.x, p.y, mod(p.z, interval) - interval / 2.0);
}

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 calcRoundBoxDistance(vec3 p, vec3 size, float r) {
    return calcBoxDistance(p, size) - r;
}

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

float calcPlainDistance(vec3 p, vec3 n) {
    return dot(p, n);
}

float calcTorusDistance(vec3 p, vec2 size) {
    vec2 q = vec2(length(p.xz) - size.x, p.y);
    return length(q) - size.y;
}

float calcCylinderDistance(vec3 p, vec3 size) {
    return length(p.xz - size.xy) - size.z;
}

float calcDistance(vec3 p) {
    float d = 10000000.0;
    d = min(d, calcSphereDistance(translate(p, vec3(-1.0, 0.0, 0.0)), 0.4));
    d = min(d, calcSphereDistance(translate(p, vec3(0.0, 0.0, 0.0)), 0.4));
    d = min(d, calcSphereDistance(translate(p, vec3(1.0, 0.0, 0.0)), 0.4));
    return d;
}

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))
    ));
}

vec3 calcColor(vec3 p) {
    vec4 cd = vec4(vec3(1.0), 1000000.0);
    float d;
    d = calcSphereDistance(translate(p, vec3(-1.0, 0.0, 0.0)), 0.4);
    cd = d < cd.w  ? vec4(1.0, 0.0, 0.0, d) : cd;
    d = calcSphereDistance(translate(p, vec3(0.0, 0.0, 0.0)), 0.4);
    cd = d < cd.w  ? vec4(0.0, 1.0, 0.0, d) : cd;
    d = calcSphereDistance(translate(p, vec3(1.0, 0.0, 0.0)), 0.4);
    cd = d < cd.w ? vec4(0.0, 0.0, 1.0, d) : cd;

    return vec3(cd.x, cd.y, cd.z);
}

Camera getPerspectiveCamera(vec2 pos, vec3 eye, vec3 center, vec3 top, float fov) {
    float camRadian = fov / 2.0 * PI / 180.0;
    vec3 viewDir = normalize(center - eye);
    vec3 camSide = cross(viewDir, top);
    vec3 camTop = cross(camSide, viewDir);

    Camera camera;
    camera.position = eye;
    camera.ray = normalize(camTop * sin(camRadian * pos.y) + camSide * sin(camRadian * pos.x) + viewDir * cos(camRadian * pos.x));
    return camera;
}

Camera getOrthographicCamera(vec2 pos, vec3 eye, vec3 center, vec3 top, float width, float height) {
    vec3 viewDir = normalize(center - eye);
    vec3 camSide = cross(viewDir, top);
    vec3 camTop = cross(camSide, viewDir);

    Camera camera;
    camera.position = eye + vec3(camTop * pos.y * height / 2.0 + camSide * pos.x * width / 2.0);
    camera.ray = viewDir;
    return camera;
}

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

    vec3 cameraPosition = vec3(mouse.x * 3.0, mouse.y * 3.0, 3.0);
    vec3 viewCenter = vec3(0.0);
    vec3 cameraTop = vec3(0.0, 1.0, 0.0);
    Camera camera = getPerspectiveCamera(st, cameraPosition, viewCenter, vec3(0.0, 1.0, 0.0), 60.0);
    // Camera camera = getOrthographicCamera(st, cameraPosition, viewCenter, vec3(0.0, 1.0, 0.0), 50.0, 50.0);
    vec3 rayPosition = camera.position;
    vec3 rayDirection = camera.ray;

    float radian = u_time * 0.0003;
    vec3 lightPosition = vec3(20.0, 20.0, 20.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);
        vec3 vecToLight = normalize(lightPosition - rayPosition);

        float diffuseWeight = max(dot(normal, vecToLight), 0.0);

        vec3 reflectVec = normalize(reflect(-vecToLight, normal));
        float specularWeight = pow(max(dot(reflectVec, -rayDirection), 0.0), 16.0);

        vec3 c = calcColor(rayPosition);
        color = c * (vec3(0.2, 0.2, 0.2) + vec3(0.7, 0.7, 0.7) * diffuseWeight) + vec3(1.0, 1.0, 1.0) * specularWeight;
    }

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