175 lines
4.7 KiB
GLSL
175 lines
4.7 KiB
GLSL
#version 330 core
|
|
#include hg_sdf.glsl
|
|
layout (location = 0) out vec4 fragColor;
|
|
|
|
uniform vec2 u_resolution;
|
|
uniform vec2 u_mouse;
|
|
uniform float u_time;
|
|
uniform vec3 ro;
|
|
uniform mat3 cam;
|
|
|
|
const float FOV = 2;
|
|
const int MAX_STEPS = 256;
|
|
const float MAX_DIST = 500;
|
|
const float EPSILON = 0.0005;
|
|
const float DIST_CAM = 2;
|
|
|
|
float packColor(vec3 color) {
|
|
return color.r + color.g * 256.0 + color.b * 256.0 * 256.0;
|
|
}
|
|
|
|
vec3 unpackColor(float f) {
|
|
vec3 color;
|
|
color.b = floor(f / 256.0 / 256.0);
|
|
color.g = floor((f - color.b * 256.0 * 256.0) / 256.0);
|
|
color.r = floor(f - color.b * 256.0 * 256.0 - color.g * 256.0);
|
|
// now we have a vec3 with the 3 components in range [0..255]. Let's normalize it!
|
|
return color / 255.0;
|
|
}
|
|
|
|
vec3 fOpUnionChamferId(vec3 res1, vec3 res2, float r) {
|
|
float a = res1.x;
|
|
float b = res2.x;
|
|
|
|
return vec3(min(min(a, b), (a - r + b)*sqrt(0.5)), res1.yz);
|
|
}
|
|
|
|
vec3 fOpDifferenceId(vec3 res1, vec3 res2) {
|
|
return (res1.x > -res2.x) ? res1 : vec3(-res2.x, res2.yz);
|
|
}
|
|
|
|
vec3 fOpUnionId(in vec3 res1, in vec3 res2){
|
|
return (res1.x < res2.x) ? res1 : res2;
|
|
}
|
|
|
|
|
|
vec3 map(in vec3 p){
|
|
//pMod3(p, vec3(10.0));
|
|
|
|
float planeId = 1;
|
|
float planeColor = packColor(vec3(50, 50, 50));
|
|
float planeDist = fPlane(p, vec3(0, 1, 0), 1.0);
|
|
vec3 plane = vec3(planeDist, planeColor, planeId);
|
|
|
|
float sphereId = 2;
|
|
float sphereColor = packColor(vec3(200, 0, 0));
|
|
vec3 spherePos = vec3(2.0, 0.0, 0.0);
|
|
float sphereDist = fSphere(p-spherePos, 1);
|
|
vec3 sphere = vec3(sphereDist, sphereColor, sphereId);
|
|
|
|
float playerId = 3;
|
|
float playerColor = packColor(vec3(0, 200, 0));;
|
|
vec3 playerPos = ro+vec3(0, -1, DIST_CAM);
|
|
float playerDist = fCapsule(p-playerPos, 0.2, 0.2);
|
|
vec3 player = vec3(playerDist, playerColor, playerId);
|
|
|
|
float mandelBulbId = 3;
|
|
float mandelBulbColor = packColor(vec3(50, 50, 50));;
|
|
float mandelBulbDist = fmandelBulbe(p);;
|
|
vec3 mandelBulb = vec3(mandelBulbDist, mandelBulbColor, mandelBulbId);;
|
|
|
|
//vec3 res = fOpUnionId(plane, sphere);
|
|
vec3 res = mandelBulb;
|
|
//res = fOpUnionId(res, mandelBulb);
|
|
|
|
|
|
return res;
|
|
}
|
|
|
|
vec4 rayMarch(vec3 ro, vec3 rd) {
|
|
vec3 hit = vec3(0.0);
|
|
vec3 object = vec3(0.0);
|
|
vec3 p = vec3(0.0);
|
|
float compt = 0;
|
|
for (float i = 0; i < MAX_STEPS; i++) {
|
|
p = ro + object.x * rd;
|
|
hit = map(p);
|
|
object.x += hit.x;
|
|
object.yz = hit.yz;
|
|
if (hit.z == 2 || hit.z == 3) compt += 1;
|
|
|
|
if (abs(hit.x) < EPSILON || object.x > MAX_DIST){
|
|
if (hit.z != 2) return vec4(object, compt);
|
|
return vec4(object, 0);
|
|
}
|
|
}
|
|
return vec4(object, compt);
|
|
}
|
|
|
|
vec3 getNormal(vec3 p) {
|
|
vec2 e = vec2(EPSILON, 0.0);
|
|
vec3 n = vec3(map(p).x) - vec3(map(p - e.xyy).x, map(p - e.yxy).x, map(p - e.yyx).x);
|
|
return normalize(n);
|
|
}
|
|
|
|
vec3 getLight(vec3 p, vec3 rd, vec3 color) {
|
|
vec3 lightPos = vec3(10.0, 55.0, -20.0);
|
|
vec3 L = normalize(lightPos - p);
|
|
vec3 N = getNormal(p);
|
|
vec3 V = -rd;
|
|
vec3 R = reflect(-L, N);
|
|
|
|
vec3 specColor = vec3(0.5);
|
|
vec3 specular = specColor * pow(clamp(dot(R, V), 0.0, 1.0), 10.0);
|
|
vec3 diffuse = color * clamp(dot(L, N), 0.0, 1.0);
|
|
vec3 ambient = color * 0.05;
|
|
vec3 fresnel = 0.25 * color * pow(1.0 + dot(rd, N), 3.0);
|
|
|
|
// shadows
|
|
float d = rayMarch(p + N * 0.02, normalize(lightPos)).x;
|
|
if (d < length(lightPos - p)) return ambient + fresnel;
|
|
|
|
return diffuse + ambient + specular + fresnel;
|
|
}
|
|
|
|
vec3 getMaterial(vec3 p, float color_pack, float id) {
|
|
vec3 m = vec3(0.0);
|
|
vec3 color = unpackColor(color_pack);
|
|
switch (int(id)) {
|
|
case 1:
|
|
m = vec3(0.2 + 0.4 * mod(floor(p.x) + floor(p.z), 2.0)); break;
|
|
}
|
|
return color+m;
|
|
return color;
|
|
}
|
|
|
|
|
|
|
|
|
|
void render(inout vec3 col, in vec3 ro, in mat3 cam, in vec2 uv) {
|
|
vec3 r1 = vec3(0, 0, 1);
|
|
vec3 lookAt = ro + r1;
|
|
vec3 rd = cam*normalize(vec3(uv, FOV));
|
|
vec4 result = rayMarch(ro, rd);
|
|
vec3 object = result.xyz;
|
|
vec3 glowing_color = vec3(0.5, 0, 0);
|
|
float nb_itter = result.w;
|
|
|
|
|
|
|
|
vec3 background = vec3(0, 0, 0);
|
|
if (object.x < MAX_DIST) {
|
|
vec3 p = ro + object.x * rd;
|
|
vec3 material = getMaterial(p, object.y, object.z);
|
|
col += getLight(p, rd, material);
|
|
// fog
|
|
col = mix(col, background, 1.0 - exp(-0.00002 * object.x * object.x));
|
|
|
|
} else {
|
|
// col += background - max(0.9 * rd.y, 0.0);
|
|
col = col;
|
|
}
|
|
float glow_fact = smoothstep(0, MAX_STEPS, nb_itter);
|
|
col += glowing_color*glow_fact;
|
|
}
|
|
|
|
void main() {
|
|
vec2 uv = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y;
|
|
|
|
vec3 col;
|
|
render(col, ro, cam, uv);
|
|
|
|
// gamma correction
|
|
col = pow(col, vec3(0.4545));
|
|
fragColor = vec4(col, 1.0);
|
|
}
|