Skip to content

Commit

Permalink
add soft shadow and diffuse reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
evan69 committed May 24, 2016
1 parent b809263 commit cbf68b3
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 41 deletions.
1 change: 1 addition & 0 deletions all.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <opencv2\opencv.hpp>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "vector3.h"

Expand Down
26 changes: 13 additions & 13 deletions box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ Box::Box( BoundingBox& p_Box ) :
{
}

int Box::Intersect( Ray& p_Ray, float& p_Dist )
int Box::Intersect( Ray& p_Ray, double& p_Dist )
{
float dist[6];
double dist[6];
vector3 ip[6], d = p_Ray.getDirection(), o = p_Ray.getOrigin();
bool retval = MISS;
for ( int i = 0; i < 6; i++ ) dist[i] = -1;
vector3 v1 = m_Box.getPos(), v2 = m_Box.getPos() + getSize();
if (d.x)
{
float rc = 1.0f / d.x;
double rc = 1.0f / d.x;
dist[0] = (v1.x - o.x) * rc;
dist[3] = (v2.x - o.x) * rc;
}
if (d.y)
{
float rc = 1.0f / d.y;
double rc = 1.0f / d.y;
dist[1] = (v1.y - o.y) * rc;
dist[4] = (v2.y - o.y) * rc;
}
if (d.z)
{
float rc = 1.0f / d.z;
double rc = 1.0f / d.z;
dist[2] = (v1.z - o.z) * rc;
dist[5] = (v2.z - o.z) * rc;
}
Expand All @@ -57,15 +57,15 @@ int Box::Intersect( Ray& p_Ray, float& p_Dist )

vector3 Box::getNormal( vector3& p_Pos )
{
float dist[6];
dist[0] = (float)fabs( m_Box.getSize().x - m_Box.getPos().x );
dist[1] = (float)fabs( m_Box.getSize().x + m_Box.getSize().x - m_Box.getPos().x );
dist[2] = (float)fabs( m_Box.getSize().y - m_Box.getPos().y );
dist[3] = (float)fabs( m_Box.getSize().y + m_Box.getSize().y - m_Box.getPos().y );
dist[4] = (float)fabs( m_Box.getSize().z - m_Box.getPos().z );
dist[5] = (float)fabs( m_Box.getSize().z + m_Box.getSize().z - m_Box.getPos().z );
double dist[6];
dist[0] = (double)fabs( m_Box.getSize().x - m_Box.getPos().x );
dist[1] = (double)fabs( m_Box.getSize().x + m_Box.getSize().x - m_Box.getPos().x );
dist[2] = (double)fabs( m_Box.getSize().y - m_Box.getPos().y );
dist[3] = (double)fabs( m_Box.getSize().y + m_Box.getSize().y - m_Box.getPos().y );
dist[4] = (double)fabs( m_Box.getSize().z - m_Box.getPos().z );
dist[5] = (double)fabs( m_Box.getSize().z + m_Box.getSize().z - m_Box.getPos().z );
int best = 0;
float bdist = dist[0];
double bdist = dist[0];
for ( int i = 1 ; i < 6; i++ ) if (dist[i] < bdist)
{
bdist = dist[i];
Expand Down
6 changes: 3 additions & 3 deletions box.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ namespace HYF
class Box : public Primitive
{
public:
int GetType() { return BOX; }
int getType() { return BOX; }
Box();
Box( BoundingBox& p_Box );
int Intersect( Ray& p_Ray, float& p_Dist );
bool IntersectBox( BoundingBox& p_Box ) { return m_Box.Intersect( p_Box ); }
int Intersect( Ray& p_Ray, double& p_Dist );
bool H_IntersectBox( BoundingBox& p_Box ) { return m_Box.Intersect( p_Box ); }
vector3 getNormal( vector3& );
bool Contains( vector3& p_Pos ) { return m_Box.Contains( p_Pos ); }
vector3& getPos() { return m_Box.getPos(); }
Expand Down
1 change: 1 addition & 0 deletions function.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
2016.5.23 漫反射,高光,镜面反射,折射,opencv输出
2016.5.23 新增超采样
2016.5.24 新增简单包围盒
2016.5.24 新增软阴影、粗糙镜面反射
1 change: 1 addition & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Mat colorim(600,800,CV_8UC3);

int main()
{
srand(time(NULL));
HYF::Engine* tracer = new HYF::Engine();
tracer->getScene()->init();
tracer->setTarget();
Expand Down
2 changes: 1 addition & 1 deletion plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class PlanePrim : public Primitive
int Intersect( Ray& p_Ray, double& p_Dist );
bool H_IntersectBox( BoundingBox& );
vector3 getNormal( vector3& p_Pos ){return m_Plane.N;};
BoundingBox getAABB() { return BoundingBox(vector3(-10000,-10000,-10000),vector3(20000,20000,20000));}
BoundingBox getBoundingBox() { return BoundingBox(vector3(-10000,-10000,-10000),vector3(20000,20000,20000));}

private:
plane m_Plane;
Expand Down
5 changes: 4 additions & 1 deletion primitive.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@ class Material
void setSpecular( double p_Spec ) { m_Spec = p_Spec; }//高光
void setDiffuse( double p_Diff ) { m_Diff = p_Diff; }
void setReflection( double p_Refl ) { m_Refl = p_Refl; }
void setDiffRefl(double p_DiffRefl ) { m_DiffRefl = p_DiffRefl; }
void setRefraction( double p_Refr ) { m_Refr = p_Refr; }
void setRefr_Rate( double p_Refr_Rate ) { m_Refr_Rate = p_Refr_Rate; }
double getSpecular() { return m_Spec; }//高光
double getDiffuse() { return m_Diff; }//漫反射
double getReflection() { return m_Refl;}
double getDiffRefl() { return m_DiffRefl;}
double getRefraction() { return m_Refr;}
double getRefr_Rate() { return m_Refr_Rate;}
private:
Color m_Color;//材质颜色
double m_Refl;//反射系数
double m_DiffRefl;//漫镜面反射系数
double m_Diff;//漫反射系数
double m_Spec;//高光
double m_Refr;//透射率
Expand All @@ -50,7 +53,7 @@ class Primitive
virtual vector3 getNormal( vector3& p_Pos ) = 0;
virtual Color getColor() { return m_Material.getColor(); }
virtual void Light( bool p_Light ) { m_Light = p_Light; }
virtual BoundingBox getAABB() = 0;
virtual BoundingBox getBoundingBox() = 0;

bool IsLight() { return m_Light; }
void setName( char* p_Name );
Expand Down
94 changes: 80 additions & 14 deletions raytracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,23 @@ double Engine::calShade(Primitive* p_Light, vector3 p_pi, vector3& p_Dir)
{

//vector3 delta = vector3();
double shade = 1.0;
double shade = 0.0;
Primitive* prim = 0;
if(p_Light->getType() == Primitive::SPHERE)
{
int max_R = 3,max_C = 5;
//int max_R = 2,max_C = 1;
Sphere* light = (Sphere*)p_Light;
vector3 O = light->getCentre();
p_Dir = O - p_pi;
NORMALIZE(p_Dir);
double R = light->getRadius();
vector3 dir = O - p_pi;
double dist = LENGTH(dir);
NORMALIZE(dir);
if (FindNearest( Ray( p_pi + dir * EPS, dir), dist, prim ))
if (prim == p_Light)
shade += 1.0;
/*
for(int i = 0;i < max_R;++i)
for(int j = 0;j < max_C;++j)
{
Expand All @@ -229,14 +236,49 @@ double Engine::calShade(Primitive* p_Light, vector3 p_pi, vector3& p_Dir)
double dist = LENGTH(dir);
NORMALIZE(dir);
if (FindNearest( Ray( p_pi + dir * EPS, dir), dist, prim ))
if (prim == p_Light) shade += 1.0;
if (prim == p_Light) shade += (1.0 / (max_R * max_C));
}
shade = shade / (max_R * max_C);

*/
}
if(p_Light->getType() == Primitive::BOX)
else if(p_Light->getType() == Primitive::BOX)
{

//printf("box\n");
shade = 0.0;
int max_X = 10,max_Z = 10;
Box* light = (Box*)p_Light;
vector3 P = light->getPos();
vector3 size = light->getSize();
p_Dir = P + 0.5 * size - p_pi;
NORMALIZE(p_Dir);
for(int i = 0;i < max_X;++i)
for(int j = 0;j < max_Z;++j)
{
vector3 d = vector3(size.x / max_X,0.0,size.z / max_Z);
//printf("%llf,%llf,%llf\n",d.x,d.y,d.z);
vector3 pos = P + vector3(d.x * (i + (double)rand() / RAND_MAX),0.0,d.z * (j + (double)rand() / RAND_MAX));
//monte carlo
vector3 dir = pos - p_pi;
double dist = LENGTH(dir);
NORMALIZE(dir);
if (FindNearest( Ray( p_pi + dir * EPS, dir), dist, prim ))
if (prim == p_Light)
shade += (1.0 / (max_X * max_Z));
}
/*
shade = 0;
Box* b = (Box*)p_Light;
p_Dir = (b->getPos() + 0.5f * b->getSize()) - p_pi;
NORMALIZE( p_Dir );
for ( int x = 0; x < 3; x++ ) for ( int y = 0; y < 3; y++ )
{
vector3 lp( b->getPos().x + x, b->getPos().y, b->getPos().z + y );
vector3 dir = lp - p_pi;
double ldist = (double)LENGTH( dir );
dir *= 1.0f / ldist;
if (FindNearest( Ray( p_pi + dir * EPS, dir), ldist, prim ))
if (prim == p_Light) shade += 1.0f / 9;
}
*/
}
//printf("%llf\n",shade);
return shade;
Expand Down Expand Up @@ -264,8 +306,6 @@ Primitive* Engine::Runtracer( Ray& p_Ray, Color& p_Col, int p_Depth, double p_Re
}
*/
if (!(result = FindNearest( p_Ray, p_Dist, prim ))) return 0;
//result = FindNearest( p_Ray, p_Dist, prim );
//printf("%llf\n",p_Dist);
//计算一根光线Ray最近的交汇点和距离
// no hit, terminate ray
if (!prim) return 0;//光线不和任何物体相交
Expand Down Expand Up @@ -356,9 +396,35 @@ Primitive* Engine::Runtracer( Ray& p_Ray, Color& p_Col, int p_Depth, double p_Re
double refl = prim->getMaterial()->getReflection();
if (refl > 0.0)//镜面反射
{
float drefl = prim->getMaterial()->getDiffRefl();
vector3 N = prim->getNormal( pi );
vector3 R = p_Ray.getDirection() - 2.0 * DOT( p_Ray.getDirection(), N ) * N;
if (p_Depth < TRACEDEPTH)
if ((drefl > 0) && (p_Depth < 2))//粗糙镜面反射
{
vector3 component1 = vector3( R.z, 0.0, -R.x );
vector3 component2 = R.Cross( component1 );
NORMALIZE(component2);
int num = 20;
//refl *= m_SScale;
for ( int i = 0; i < num; i++ )
{
double x0,y0;
while(1)
{
x0 = (double)rand() / RAND_MAX * drefl;
y0 = (double)rand() / RAND_MAX * drefl;
if((x0 * x0 + y0 * y0) < (drefl * drefl))
break;
}
vector3 newR = R + component1 * x0 + component2 * y0;
NORMALIZE( newR );
double dist;
Color rcol( 0, 0, 0 );
Runtracer( Ray( pi + newR * EPS, newR ), rcol, p_Depth + 1, p_Refr_Rate, dist );
p_Col += refl * rcol * prim->getMaterial()->getColor() * (1.0 / (double)num);
}
}
else if (p_Depth < TRACEDEPTH)//光滑镜面反射
{
Color rcol( 0, 0, 0 );
double dist;
Expand Down Expand Up @@ -399,7 +465,7 @@ Primitive* Engine::Runtracer( Ray& p_Ray, Color& p_Col, int p_Depth, double p_Re
return prim;
}

//#define SUPERSAMPLING
#define SUPERSAMPLING
bool Engine::HYF_render(cv::Mat& colorim)
{
vector3 o( 0, 0, -5 );
Expand All @@ -415,7 +481,7 @@ bool Engine::HYF_render(cv::Mat& colorim)
for(double i = -1.0;i < 1.5;++i)
for(double j = -1.0;j < 1.5;++j)
{
vector3 dir = vector3( (1.0 * x + i / 3) / 100 - 3.0 , (1.0 * y + j / 3) / 100 - 3.0, 0 ) - o;
vector3 dir = vector3( (1.0 * x + i / 3) / 100 - 4.0 , (1.0 * y + j / 3) / 100 - 3.0, 0 ) - o;
NORMALIZE( dir );
Ray r( o, dir );
double dist;
Expand All @@ -427,7 +493,7 @@ bool Engine::HYF_render(cv::Mat& colorim)
//super sampling
#endif
#ifndef SUPERSAMPLING
vector3 dir = vector3( (1.0 * x) / 100 - 3.0 , (1.0 * y) / 100 - 3.0, 0 ) - o;
vector3 dir = vector3( (1.0 * x) / 100 - 4.0 , (1.0 * y) / 100 - 3.0, 0 ) - o;
NORMALIZE( dir );
Ray r( o, dir );
double dist;
Expand All @@ -441,7 +507,7 @@ bool Engine::HYF_render(cv::Mat& colorim)
if (blue > 255) blue = 255;
colorim.at<Vec3b>(m_Height - y - 1,x) = Vec3b(blue,green,red);
}
//printf("rendering %dth row...\n",y+1);
printf("rendering %dth row...\n",y+1);
//imshow("test",colorim);
//waitKey(0);
}
Expand Down
Loading

0 comments on commit cbf68b3

Please sign in to comment.