Files
bluflame/hgplus/ShaderMinifier/tests/real/gfx monitor/raytrace.fs
2026-04-18 22:31:51 +02:00

191 lines
3.7 KiB
GLSL

// FragmentProgram
const int raytraceDepth = 8;
varying vec3 org,dir;
struct Ray
{
vec3 org;
vec3 dir;
};
struct Sphere
{
vec3 c;
float r;
vec3 col;
};
struct Plane
{
vec3 p;
vec3 n;
vec3 col;
};
struct Intersection
{
float t;
vec3 p; // hit point
vec3 n; // normal
int hit;
vec3 col;
};
void shpere_intersect(Sphere s, Ray ray, inout Intersection isect)
{
// rs = ray.org - sphere.c
vec3 rs = ray.org - s.c;
float B = dot(rs, ray.dir);
float C = dot(rs, rs) - (s.r * s.r);
float D = B * B - C;
if (D > 0.0)
{
float t = -B - sqrt(D);
if ( (t > 0.0) && (t < isect.t) )
{
isect.t = t;
isect.hit = 1;
// calculate normal.
vec3 p = vec3(ray.org.x + ray.dir.x * t,
ray.org.y + ray.dir.y * t,
ray.org.z + ray.dir.z * t);
vec3 n = p - s.c;
n = normalize(n);
isect.n = n;
isect.p = p;
isect.col = s.col;
}
}
}
void plane_intersect(Plane pl, Ray ray, inout Intersection isect)
{
// d = -(p . n)
// t = -(ray.org . n + d) / (ray.dir . n)
float d = -dot(pl.p, pl.n);
float v = dot(ray.dir, pl.n);
if (abs(v) < 1.0e-6)
return; // the plane is parallel to the ray.
float t = -(dot(ray.org, pl.n) + d) / v;
if ( (t > 0.0) && (t < isect.t) )
{
isect.hit = 1;
isect.t = t;
isect.n = pl.n;
vec3 p = vec3(ray.org.x + t * ray.dir.x,
ray.org.y + t * ray.dir.y,
ray.org.z + t * ray.dir.z);
isect.p = p;
float offset = 0.2;
vec3 dp = p + offset;
if ((mod(dp.x, 1.0) > 0.5 && mod(dp.z, 1.0) > 0.5)
|| (mod(dp.x, 1.0) < 0.5 && mod(dp.z, 1.0) < 0.5))
isect.col = pl.col;
else
isect.col = pl.col * 0.5;
}
}
Sphere sphere[3];
Plane plane;
void Intersect(Ray r, inout Intersection i)
{
for (int c = 0; c < 3; c++)
{
shpere_intersect(sphere[c], r, i);
}
plane_intersect(plane, r, i);
}
int seed = 0;
float random()
{
seed = int(mod(float(seed)*1364.0+626.0, 509.0));
return float(seed)/509.0;
}
vec3 computeLightShadow(in Intersection isect)
{
int i, j;
int ntheta = 16;
int nphi = 16;
float eps = 0.0001;
// Slightly move ray org towards ray dir to avoid numerical probrem.
vec3 p = vec3(isect.p.x + eps * isect.n.x,
isect.p.y + eps * isect.n.y,
isect.p.z + eps * isect.n.z);
vec3 lightPoint = vec3(5,5,5);
Ray ray;
ray.org = p;
ray.dir = normalize(lightPoint - p);
Intersection lisect;
lisect.hit = 0;
lisect.t = 1.0e+30;
lisect.n = lisect.p = lisect.col = vec3(0, 0, 0);
Intersect(ray, lisect);
if (lisect.hit != 0)
return vec3(0.0,0.0,0.0);
else
{
float shade = max(0.0, dot(isect.n, ray.dir));
shade = pow(shade,3.0) + shade * 0.5;
return vec3(shade,shade,shade);
}
}
void main()
{
sphere[0].c = vec3(-2.0, 0.0, -3.5);
sphere[0].r = 0.5;
sphere[0].col = vec3(1,0.3,0.3);
sphere[1].c = vec3(-0.5, 0.0, -3.0);
sphere[1].r = 0.5;
sphere[1].col = vec3(0.3,1,0.3);
sphere[2].c = vec3(1.0, 0.0, -2.2);
sphere[2].r = 0.5;
sphere[2].col = vec3(0.3,0.3,1);
plane.p = vec3(0,-0.5, 0);
plane.n = vec3(0, 1.0, 0);
plane.col = vec3(1,1, 1);
seed = int(mod(dir.x * dir.y * 4525434.0, 65536.0));
Ray r;
r.org = org;
r.dir = normalize(dir);
vec4 col = vec4(0,0,0,1);
float eps = 0.0001;
vec3 bcol = vec3(1,1,1);
for (int j = 0; j < raytraceDepth; j++)
{
Intersection i;
i.hit = 0;
i.t = 1.0e+30;
i.n = i.p = i.col = vec3(0, 0, 0);
Intersect(r, i);
if (i.hit != 0)
{
col.rgb += bcol * i.col * computeLightShadow(i);
bcol *= i.col;
}
else
{
break;
}
r.org = vec3(i.p.x + eps * i.n.x,
i.p.y + eps * i.n.y,
i.p.z + eps * i.n.z);
r.dir = reflect(r.dir, vec3(i.n.x, i.n.y, i.n.z));
}
gl_FragColor = col;
}