2013-02-22 09:07:31 +04:00
|
|
|
$input v_color0, v_texcoord0
|
|
|
|
|
|
|
|
/*
|
2014-02-11 10:07:04 +04:00
|
|
|
* Copyright 2011-2014 Branimir Karadzic. All rights reserved.
|
2013-02-22 09:07:31 +04:00
|
|
|
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
// References:
|
|
|
|
// Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces - John C. Hart
|
|
|
|
// http://web.archive.org/web/20110331200546/http://graphics.cs.uiuc.edu/~jch/papers/zeno.pdf
|
|
|
|
//
|
|
|
|
// Modeling with distance functions
|
|
|
|
// http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
|
|
|
|
|
|
|
|
#include "../common/common.sh"
|
|
|
|
#include "iq_sdf.sh"
|
|
|
|
|
|
|
|
uniform float u_time;
|
|
|
|
uniform mat4 u_mtx;
|
|
|
|
uniform vec3 u_lightDir;
|
|
|
|
|
|
|
|
float sceneDist(vec3 _pos)
|
|
|
|
{
|
|
|
|
float d1 = udRoundBox(_pos, vec3(2.5, 2.5, 2.5), 0.5);
|
|
|
|
float d2 = sdSphere(_pos + vec3( 4.0, 0.0, 0.0), 1.0);
|
|
|
|
float d3 = sdSphere(_pos + vec3(-4.0, 0.0, 0.0), 1.0);
|
|
|
|
float d4 = sdSphere(_pos + vec3( 0.0, 4.0, 0.0), 1.0);
|
|
|
|
float d5 = sdSphere(_pos + vec3( 0.0,-4.0, 0.0), 1.0);
|
|
|
|
float d6 = sdSphere(_pos + vec3( 0.0, 0.0, 4.0), 1.0);
|
|
|
|
float d7 = sdSphere(_pos + vec3( 0.0, 0.0,-4.0), 1.0);
|
|
|
|
float dist = min(min(min(min(min(min(d1, d2), d3), d4), d5), d6), d7);
|
|
|
|
return dist;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec3 calcNormal(vec3 _pos)
|
|
|
|
{
|
|
|
|
const vec2 delta = vec2(0.002, 0.0);
|
|
|
|
float nx = sceneDist(_pos + delta.xyy) - sceneDist(_pos - delta.xyy);
|
|
|
|
float ny = sceneDist(_pos + delta.yxy) - sceneDist(_pos - delta.yxy);
|
|
|
|
float nz = sceneDist(_pos + delta.yyx) - sceneDist(_pos - delta.yyx);
|
|
|
|
return normalize(vec3(nx, ny, nz) );
|
|
|
|
}
|
|
|
|
|
|
|
|
float calcAmbOcc(vec3 _pos, vec3 _normal)
|
|
|
|
{
|
|
|
|
float occ = 0.0;
|
|
|
|
float aostep = 0.2;
|
|
|
|
for (int ii = 1; ii < 4; ii++)
|
|
|
|
{
|
|
|
|
float fi = float(ii);
|
|
|
|
float dist = sceneDist(_pos + _normal * fi * aostep);
|
|
|
|
occ += (fi * aostep - dist) / pow(2.0, fi);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1.0 - occ;
|
|
|
|
}
|
|
|
|
|
|
|
|
float trace(vec3 _ray, vec3 _dir, float _maxd)
|
|
|
|
{
|
|
|
|
float tt = 0.0;
|
|
|
|
float epsilon = 0.001;
|
|
|
|
|
|
|
|
for (int ii = 0; ii < 64; ii++)
|
|
|
|
{
|
|
|
|
float dist = sceneDist(_ray + _dir*tt);
|
|
|
|
if (dist > epsilon)
|
|
|
|
{
|
|
|
|
tt += dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tt < _maxd ? tt : 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2 blinn(vec3 _lightDir, vec3 _normal, vec3 _viewDir)
|
|
|
|
{
|
|
|
|
float ndotl = dot(_normal, _lightDir);
|
|
|
|
vec3 reflected = _lightDir - 2.0*ndotl*_normal; // reflect(_lightDir, _normal);
|
|
|
|
float rdotv = dot(reflected, _viewDir);
|
|
|
|
return vec2(ndotl, rdotv);
|
|
|
|
}
|
|
|
|
|
|
|
|
float fresnel(float _ndotl, float _bias, float _pow)
|
|
|
|
{
|
|
|
|
float facing = (1.0 - _ndotl);
|
|
|
|
return max(_bias + (1.0 - _bias) * pow(facing, _pow), 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
vec4 lit(float _ndotl, float _rdotv, float _m)
|
|
|
|
{
|
|
|
|
float diff = max(0.0, _ndotl);
|
|
|
|
float spec = step(0.0, _ndotl) * max(0.0, _rdotv * _m);
|
|
|
|
return vec4(1.0, diff, spec, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
vec4 tmp;
|
2014-05-11 07:51:44 +04:00
|
|
|
tmp = mul(u_mtx, vec4(v_texcoord0.xy, 0.0, 1.0) );
|
2013-02-22 09:07:31 +04:00
|
|
|
vec3 eye = tmp.xyz/tmp.w;
|
|
|
|
|
2014-05-11 07:51:44 +04:00
|
|
|
tmp = mul(u_mtx, vec4(v_texcoord0.xy, 1.0, 1.0) );
|
2013-02-22 09:07:31 +04:00
|
|
|
vec3 at = tmp.xyz/tmp.w;
|
|
|
|
|
|
|
|
float maxd = length(at - eye);
|
|
|
|
vec3 dir = normalize(at - eye);
|
|
|
|
|
|
|
|
float dist = trace(eye, dir, maxd);
|
|
|
|
|
|
|
|
if (dist > 0.5)
|
|
|
|
{
|
|
|
|
vec3 pos = eye + dir*dist;
|
|
|
|
vec3 normal = calcNormal(pos);
|
|
|
|
|
|
|
|
vec2 bln = blinn(u_lightDir, normal, dir);
|
|
|
|
vec4 lc = lit(bln.x, bln.y, 1.0);
|
|
|
|
float fres = fresnel(bln.x, 0.2, 5.0);
|
|
|
|
|
|
|
|
float val = 0.9*lc.y + pow(lc.z, 128.0)*fres;
|
|
|
|
val *= calcAmbOcc(pos, normal);
|
|
|
|
val = pow(val, 1.0/2.2);
|
|
|
|
|
|
|
|
gl_FragColor = vec4(val, val, val, 1.0);
|
|
|
|
gl_FragDepth = dist/maxd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl_FragColor = v_color0;
|
|
|
|
gl_FragDepth = 1.0;
|
|
|
|
}
|
|
|
|
}
|