Reputation: 101
I am trying to calculate shadows in a CPU based Raytracing, But i am not getting the shadows in the exact position, I am trying to design famous Cornell Box,
Also the Spheres in the figure are being shaded improperly,
I have pasted the whole code. I have used 2 spheres and 10 triangles in scene, I guess there is problem with my shadow tracing algorithm or normal calculation
class Figure{
public:
Vec3 position;
Vec3 cl;
Vec3 normal;
Figure(void);
Figure(Vec3 pos,Vec3 col,Vec3 Normal);
virtual bool intersection(float* t,Vec3 origin,Vec3 direction);
virtual Vec3 calculateNormal(Vec3 p0,float *intensity,Vec3* Diffusecolor,Vec3* Specular);
virtual bool intersectionShadow(float* t,Vec3 origin,Vec3 direction);
};
Figure::Figure(){
position = Vec3(0,0,0);
cl = Vec3(0,0,0);
normal = Vec3(0,0,0);
}
Figure::Figure(Vec3 post, Vec3 coli,Vec3 Normal){
position = post;
cl = coli;
normal = Normal;
}
bool Figure::intersection(float *t, Vec3 origin,Vec3 direction){
return false;
}
Vec3 Figure::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
return normal;
}
bool Figure::intersectionShadow(float *t, Vec3 origin, Vec3 direction){
return false;
}
class Plane:public Figure{
public:
Vec3 planeNormal;
Plane(void);
Plane(Vec3 pos,Vec3 norm,Vec3 c);
bool intersection(float *t, Vec3 origin, Vec3 direction);
Vec3 Plane::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);
};
Plane::Plane(void){
planeNormal=Vec3(0,0,0);
}
Plane::Plane(Vec3 pos,Vec3 norm,Vec3 c){
position = pos;
planeNormal = norm;
cl = c;
}
bool Plane::intersection(float *t, Vec3 origin, Vec3 direction){
float denom = planeNormal.dot(direction);
if(abs(denom)<0.0001f){
return false;
}
else{
Vec3 p_or = position-origin;
float res = p_or.dot(planeNormal)/denom;
*t = res;
}
}
Vec3 Plane::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
*intensity = 0;
*Diffusecolor = Vec3(0.7, 0.7, 0.7);
*Specular = cl;
return planeNormal;
}
class Sphere:public Figure{
public:
float radius;
Sphere(void);
Sphere(Vec3 pos,float rad,Vec3 col);
bool intersection(float* t,Vec3 origin,Vec3 direction);
Vec3 calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);
};
Sphere::Sphere(){
position = Vec3(0,0,-2);
radius = 0.3f;
cl = Vec3(1.0,0,0);
}
Sphere::Sphere(Vec3 pos, float rad, Vec3 col){
position = pos;
radius = rad;
cl = col;
}
bool Sphere::intersection(float *t, Vec3 origin,Vec3 direction){
Vec3 oc = origin - position;
float a = direction.dot(direction);
float b = 2.0f * oc.dot(direction);
float c = oc.dot(oc) - radius*radius;
float discriminant = b*b - 4*a*c;
if (discriminant < 0) {
return false;
}
else {
float t0;
t0 = std::max((-b + sqrt(discriminant) ) / (2.0f*a),(-b - sqrt(discriminant) ) / (2.0f*a));
*t = t0;
return true;
}
}
Vec3 Sphere::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
*intensity = 50.0f;
*Diffusecolor = cl;
*Specular = Vec3(0.7f, 0.7f, 0.7);
return (p0-position);
}
class Triangle:public Figure{
public:
Vec3 v0;
Vec3 v1;
Vec3 v2;
Vec3 norm;
Vec3 ed0,ed1;
float u,v,w;
Triangle(void);
Triangle(Vec3 a,Vec3 b,Vec3 c,Vec3 col);
bool intersection(float* t,Vec3 origin,Vec3 direction);
bool intersectionShadow(float* t,Vec3 origin,Vec3 direction);
Vec3 calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular);
};
Triangle::Triangle(){
v0 = Vec3(0,0,0);
v1 = Vec3(0,0,0);
v2 = Vec3(0,0,0);
}
Triangle::Triangle(Vec3 a, Vec3 b, Vec3 c, Vec3 col){
v0 = a;
v1 = b;
v2 = c;
cl = col;
}
bool Triangle::intersection(float *t, Vec3 origin,Vec3 direction){
ed0 = v1-v0;
ed1 = v2-v0;
Vec3 r_o = origin-v0;
Vec3 r_ed = direction.cross(ed1);
u = r_o.dot(r_ed)/ed0.dot(r_ed);
Vec3 r0_ed0 = r_o.cross(ed0);
float rd_r0_ed0 = direction.dot(r0_ed0);
v = rd_r0_ed0/ed0.dot(r_ed);
float ed_r0_ed0 = ed1.dot(r0_ed0);
float t0 = ed_r0_ed0/ed0.dot(r_ed);
w = 1-u-v;
if((u<0) || (u>1)){
return false;
}
else if((v<0) || (u+v>1)){
return false;
}
else {
*t = t0;
return true;
}
}
Vec3 Triangle::calculateNormal(Vec3 p0, float *intensity, Vec3 *Diffusecolor, Vec3 *Specular){
*intensity = 0;
*Diffusecolor = Vec3(0.7, 0.7, 0.7);
*Specular = cl;
//https://www.tjhsst.edu/~dhyatt/supercomp/n310.html
Vec3 d1 = Vec3(v1.x()-v0.x(),v1.y()-v0.y(),v1.z()-v0.z());
Vec3 d2 = Vec3(v2.x()-v1.x(),v2.y()-v1.y(),v2.z()-v1.z());
Vec3 n = (d1.cross(d2));
return n ;
}
bool Triangle::intersectionShadow(float* t,Vec3 origin,Vec3 direction){
return false;
}
using Colour = Vec3; // RGB Value
Colour red() { return Colour(1.0f, 0.0f, 0.0f); }
Colour white() { return Colour(1.0f, 1.0f, 1.0f); }
Colour black() { return Colour(0.0f, 0.0f, 0.0f); }
uchar BoundPixelValue(int shading)
{
if (shading < 0) return 0;
if (shading >= 255) return 255;
return shading;
}
Vec3 scalar_multiply(Vec3 b,float v){
return Vec3(b.x()*v,b.y()*v,b.z()*v);
}
int main(int, char**){
Vec3 v0 = Vec3(-1.0f,-1.0f,-1.0f);
Vec3 v1 = Vec3(-1.0f,-1.0f,-2.0f);
Vec3 v2 = Vec3(-1.0f,1.0f,-1.0f);
Vec3 v3 = Vec3(-1.0f,1.0f,-2.0f);
Vec3 v4 = Vec3(1.0f,-1.0f,-1.0f);
Vec3 v5 = Vec3(1.0f,-1.0f,-2.0f);
Vec3 v6 = Vec3(1.0f,1.0f,-2.0f);
Vec3 v7 = Vec3(1.0f,1.0f,-1.0f);
Vec3 point_0 = Vec3();
Figure* figurelist[12];
//sphere
figurelist[0]=new Sphere(Vec3(-0.2f,0.3f,-1.5f),0.3f,Vec3(1.000f, 0.196f, 0.000f));
figurelist[1]=new Sphere(Vec3(0.5f,-0.3f,-1.3f),0.4f,Vec3(0.054f, 0.172f, 0.847f));
//floor
figurelist[2]=new Triangle(v1,v0,v2,Vec3(0.752f, 0.713f, 0.823f));
figurelist[3]=new Triangle(v2,v3,v1,Vec3(0.752f, 0.713f, 0.823f));
//left
figurelist[4]=new Triangle(v5,v1,v0,Vec3(0.749f, 0.105f, 0.101f));
figurelist[5]=new Triangle(v0,v4,v5,Vec3(0.749f, 0.105f, 0.101f));
//back
figurelist[6]=new Triangle(v5,v1,v3,Vec3(0.925f, 0.639f, 0.454f));
figurelist[7]=new Triangle(v3,v6,v5,Vec3(0.925f, 0.639f, 0.454f));
//right
figurelist[8]=new Triangle(v7,v6,v3,Vec3(0.415f, 0.733f, 0.164f));
figurelist[9]=new Triangle(v3,v2,v7,Vec3(0.415f, 0.733f, 0.164f));
//top
figurelist[10]=new Triangle(v5,v6,v7,Vec3(0.925f, 0.639f, 0.454f));
figurelist[11]=new Triangle(v7,v4,v5,Vec3(0.925f, 0.639f, 0.454f));
int wResolution = 640;
int hResolution = 480;
// #rows = hResolution, #cols = wResolution
Image<Colour> image(hResolution, wResolution);
Vec3 llc= Vec3(-1.0,-1.0,-1.0);
Vec3 urc = Vec3(1.0,1.0,-1.0);
Vec3 CameraPos = Vec3(0,0,0);
Vec3 sphere_amient(0.960, 0.968, 0.811);
for (int row = 0; row < image.rows(); ++row) {
for (int col = 0; col < image.cols(); ++col) {
float u = float(row+0.5)/float(image.rows());
float v = float(col+0.5)/float(image.cols());
Vec3 PointPos = Vec3(llc(0) + u * (urc.x() - llc.x()), llc.y() + v * (urc.y() - llc.y()), -1);
Vec3 direction=(PointPos-CameraPos).normalized();
float minT = INFINITY;
int figureHit = -1;
float t0=0.0;
for (int k =0;k<sizeof (figurelist)/sizeof (figurelist[0]);k++){
bool hit = figurelist[k]->intersection(&t0,CameraPos,direction);
if(hit && t0<minT){
minT = t0;
figureHit = k;
}
if(figureHit != -1){
Vec3 p0 = CameraPos+minT*direction;
Vec3 lightSource=Vec3(2.0f,0.0f,-1.0f);
float lightIntensity=0.7f;
Vec3 diffuseColour(0.0f, 0.392f, 0.0f);
Vec3 specularColour(0.0,0.0,0.0);
float intensity = 0;
//ambient Colour for shadows
Vec3 AmbientColour = figurelist[figureHit]->cl.cross(Vec3(0.1f, 0.1f, 0.1f));
//Diffuse Lightning
Vec3 light_direction = (lightSource-p0).normalized();
Vec3 Normal = Vec3(figurelist[figureHit]->calculateNormal(p0,&intensity,&diffuseColour,&specularColour)).normalized();
float diffuse_term =std::max(0.0f,light_direction.dot(Normal));
Vec3 diffuse = (diffuseColour*lightIntensity*diffuse_term);
//Specular Highlights
Vec3 e = (p0-CameraPos).normalized();
Vec3 R = (e+light_direction).normalized();
float dot2 = std::max(0.0f,R.dot(Normal));
Vec3 specular = specularColour*lightIntensity*pow(dot2,intensity);
Vec3 shadow_direction = p0-light_direction;
float bias = 0.001f;
Vec3 p_shadow = p0+Normal;
//For hard shadows
int lightHit = -1;
for ( int i=0;i<sizeof (figurelist)/sizeof (figurelist[0]);i++){
bool lightRayHit = figurelist[i]->intersection(&t0,p_shadow,shadow_direction);
if(lightRayHit && t0<minT){
minT = t0;
lightHit = i;
}
}
if(lightHit != -1){
image(row,col) = AmbientColour;
}
else{
image(row,col) = [enter image description here][1]specular+diffuse;
}
}
else {
image(row,col)=white();
}
}
}
}
bmpwrite("../../out.bmp", image);
imshow(image);
return EXIT_SUCCESS;
}
Attached is the output image i am getting. Here image after applying shadow tracing:
And the original image without shadows:
Upvotes: 0
Views: 69
Reputation: 32587
This should be the problem:
Vec3 shadow_direction = p0-light_direction;
p0
is a position, light_direction
is a direction, hence, the result is a position
. But you are using it as a direction. Instead do:
Vec3 shadow_direction = -light_direction;
Also
float bias = 0.001f;
Vec3 p_shadow = p0+Normal;
was probably meant to be
Vec3 p_shadow = p0 + bias * Normal;
Upvotes: 1