Closed brodieG closed 4 years ago
This is due to the way procedural texturing works for checker patterns: rayrender takes the sine of the absolute world coordinate of the intersection point and colors the surface one color or the other, depending on the sign. Planes that exactly match up with the zero nodes are ill-defined.
Float sines = sin(invperiod*p.x()*M_PI) * sin(invperiod*p.y()*M_PI) * sin(invperiod*p.z()*M_PI);
if(sines < 0) {
return(odd->value(u,v,p));
} else {
return(even->value(u,v,p));
}
A potential solution involves checking for these zeros and ignoring them.
Float sinx = sin(invperiod*p.x()*M_PI);
sinx = sinx == 0 ? 1 : sinx;
Float siny = sin(invperiod*p.y()*M_PI);
siny = siny == 0 ? 1 : siny;
Float sinz = sin(invperiod*p.z()*M_PI);
sinz = sinz == 0 ? 1 : sinz;
if(sinx * siny * sinz < 0) {
return(odd->value(u,v,p));
} else {
return(even->value(u,v,p));
}
This solution originally didn't work well due to the non-robust comparison to zero, but I just fixed by re-projecting the hit point to the plane after calculating the intersection.
bool yz_rect::hit(const ray& r, Float t_min, Float t_max, hit_record& rec, random_gen& rng) {
Float t = (k-r.origin().x()) / r.direction().x();
if(t < t_min || t > t_max) {
return(false);
}
Float z = r.origin().z() + t*r.direction().z();
Float y = r.origin().y() + t*r.direction().y();
if(z < z0 || z > z1 || y < y0 || y > y1) {
return(false);
}
rec.u = (y-y0)/(y1-y0);
rec.v = (z-z0)/(z1-z0);
rec.t = t;
rec.mat_ptr = mp;
rec.p = r.point_at_parameter(t);
rec.p.e[0] = k; //This is new
rec.normal = vec3(1,0,0);
return(true);
}
I'm going to test this solution to see how robust it is, but this might be workable..
Fixed in cf78fba108ceb095b71a52ea5f26546faa373fac
Sorry, hopefully I'm not making you regret releasing this package. Here is another one:
Created on 2019-11-16 by the reprex package (v0.3.0)