//The main rendering code
int aspectRatio = 16/9;
int w = 640; //render width
int h = (int)(w/aspectRatio); //render height
int sample = 8; //samples
int depth = 50; //depth
Camera cam = new Camera();
Material test = new Lambertian(new Vec3(0.8,0.8,0));
HitableList world = new HitableList();
world.add(new Sphere(new Vec3(0,0,-1), 0.5, test));
world.add(new Sphere(new Vec3(0,-100.5,-1), 100, test));
for(int j=h-1;j>0;--j)
{
System.out.println("scanlines remaining: "+j);
for(int i=0;i<w;++i)
{
Vec3 col = new Vec3(0,0,0);
for(int s=0;s<sample;++s) {
double u = (double)(i+random_double(0, 1))/(display.getWidth()-1);
double v = (double)(j+random_double(0, 1))/(display.getHeight()-1);
Ray r = cam.getRay(u, v);
col = col.add(hit(r,world,depth));
}
double r = col.r(),
g = col.g(),
b = col.b();
double scale = 1.0/sample;
r = Math.sqrt(scale*r);
g = Math.sqrt(scale*g);
b = Math.sqrt(scale*b);
int ir = (int)(256*clamp(r, 0, 0.999)); // R component
int ig = (int)(256*clamp(g, 0, 0.999)); // G component
int ib = (int)(256*clamp(b, 0, 0.999)); // B component
display.setRGB(i, h-j-1, (ir<<16)+(ig<<8)+ib); // plot pixel to the screen.
}
}
static Vec3 random_in_unit_sphere() {
while(true) {
Vec3 p = random_Vec3(-1,1);
if(p.lengthSquared() >= 1.0) {
continue;
}
return p;
}
}
static Vec3 randomVec3(double min, double max)
{
double scale = max-min;
return new Vec3((Math.random()*scale)+min, (Math.random()*scale)+min, (Math.random()*scale)+min);
}
static double clamp(double x, double min, double max) {
if(x < min) return min;
if(x > max) return max;
return x;
}
static Vec3 hit(Ray r, Hitable world, int depth) {
hit_record rec = new hit_record();
if(depth <= 0)
return new Vec3(0,0,0);
if(world.hit(r, 0.001, Double.POSITIVE_INFINITY, rec)) {
Vec3 target = rec.p.add(rec.normal).add(random_unit_vector());
return hit(new Ray(rec.p, target.sub(rec.p)), world, depth-1).mul(0.5);
}
Vec3 unit_direction = r.getDirection().unitVector();
double t = 0.5*(unit_direction.y()+1.0);
return new Vec3(1,1,1).mul(1-t).add(new Vec3(0.5,0.7,1).mul(t));
}
//Sphere intersection code
@Override
boolean hit(Ray r, double t_min, double t_max, hit_record rec) {
Vec3 oc = r.getOrigin().sub(this.center);
double a = r.getDirection().lengthSquared();
double half_b = oc.dot(r.getDirection());
double c = oc.lengthSquared()-this.radius*this.radius;
double discriminant = half_b*half_b-a*c;
if(discriminant<0) return false;
double sqrtd = Math.sqrt(discriminant);
double root = (-half_b - sqrtd)/a;
if(root < t_min || t_max < root) {
root = (-half_b + sqrtd)/a;
if(root < t_min || t_max < root)
return false;
}
rec.t = root;
rec.p = r.at(rec.t);
Vec3 outward_normal = (rec.p.sub(this.center)).div(this.radius);
rec.set_face_normal(r, outward_normal);
rec.mat = this.m;
return true;
}
}
//From the hit_record class
void set_face_normal(Ray r, Vec3 outward_normal) {
front_face = r.getDirection().dot(outward_normal)<0;
normal = front_face ? outward_normal : outward_normal.negative();
}
The shading is invisible. I've tried gamma correction, etc, still doesn't work. It seems to be a problem with the normals. I'm following the tutorial at https://raytracing.github.io/books/RayTracingInOneWeekend.html#diffusematerials/limitingthenumberofchildrays
`
Result:


Intended Result: