diff --git a/main/Scene-load.cc b/main/Scene-load.cc index ebb0353..e63fa7c 100644 --- a/main/Scene-load.cc +++ b/main/Scene-load.cc @@ -202,6 +202,10 @@ void Scene::processOptions(refptr node) { setAmbientLight(Color((*it)->getVector())); } + else if ( typeid(**it) == typeid(AmbientOcclusionNode) ) + { + m_ambient_occlusion_level = (*it)->getInteger(); + } } } diff --git a/main/Scene.cc b/main/Scene.cc index 37a350e..bd97bd8 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -30,6 +30,7 @@ Scene::Scene(const map & options, m_ambient_light = Color(0.2, 0.2, 0.2); m_max_depth = 10; m_exposure = 1.0f; + m_ambient_occlusion_level = 0; m_transforms.push(Transform()); load(filename); @@ -215,8 +216,12 @@ Color Scene::computePhong(const refptr material, const Vector & surfacePoint, const Vector & surfaceNormal) { - Color result = m_ambient_light * material->getAmbientColor() - * calculateAmbientOcclusion(Ray(surfacePoint, surfaceNormal).shift(1e-7)); + Color result = m_ambient_light * material->getAmbientColor(); + if (m_ambient_occlusion_level > 0) + { + result *= calculateAmbientOcclusion( + Ray(surfacePoint, surfaceNormal).shift(1e-7)); + } Vector viewDirection = -viewRay.getDirection(); double shininess = material->getShininess(); @@ -327,7 +332,8 @@ Color Scene::calculateLightContribution(const Ray & toLight, Color Scene::calculateAmbientOcclusion(const Ray & surfaceNormal) { Color result(1, 1, 1); - const int nISteps = 30, nJSteps = 15; + const int nISteps = m_ambient_occlusion_level * 6; + const int nJSteps = nISteps / 2; int nRays = 0; Vector perpX = surfaceNormal.getDirection().getPerpendicular().normalize(); Vector perpY = (surfaceNormal.getDirection() * perpX).normalize(); diff --git a/main/Scene.h b/main/Scene.h index f068523..d95e64b 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -37,6 +37,7 @@ class Scene int getWidth() { return m_width; } int getHeight() { return m_height; } int getMultisampleLevel() { return m_multisample_level; } + int getAmbientOcclusionLevel() { return m_ambient_occlusion_level; } double getVFOV() { return m_vfov; } protected: @@ -79,6 +80,7 @@ class Scene Color m_ambient_light; int m_max_depth; double m_exposure; + int m_ambient_occlusion_level; /* private data */ std::vector< refptr > m_shapes; diff --git a/main/fart.cc b/main/fart.cc index 3087655..320131e 100644 --- a/main/fart.cc +++ b/main/fart.cc @@ -187,6 +187,7 @@ int main(int argc, char * argv[]) cout << " Width: " << width << endl; cout << " Height: " << height << endl; cout << " Multisample Level: " << scene.getMultisampleLevel() << endl; + cout << " Ambient Occlusion Level: " << scene.getAmbientOcclusionLevel() << endl; cout << " Vertical Field of View: " << scene.getVFOV() << endl; cout << "----------------------------------------" << endl; } diff --git a/parser/nodes.h b/parser/nodes.h index a1687d9..4144f4c 100644 --- a/parser/nodes.h +++ b/parser/nodes.h @@ -68,6 +68,12 @@ class AmbientNode : public VectorNode AmbientNode(refptr vector) : VectorNode(vector) {} }; +class AmbientOcclusionNode : public IntegerNode +{ + public: + AmbientOcclusionNode(int i) : IntegerNode(i) {} +}; + class BoxNode : public Node { public: diff --git a/parser/parser.lex b/parser/parser.lex index 4f56684..5ed4437 100644 --- a/parser/parser.lex +++ b/parser/parser.lex @@ -40,6 +40,7 @@ -?[0-9]*\.[0-9]+ *yylval = new NumberNode(atof(yytext)); return REAL_NUMBER; ambient return AMBIENT; +ambient_occlusion return AMBIENT_OCCLUSION; box return BOX; camera return CAMERA; color return COLOR; diff --git a/parser/parser.yy b/parser/parser.yy index f0d58d8..ee42281 100644 --- a/parser/parser.yy +++ b/parser/parser.yy @@ -59,6 +59,7 @@ static refptr parsed_scene_node; %token REAL_NUMBER; %token AMBIENT; +%token AMBIENT_OCCLUSION; %token BOX; %token CAMERA; %token COLOR; @@ -314,6 +315,9 @@ options_item: WIDTH DEC_NUMBER { | AMBIENT vector { $$ = new AmbientNode($2->getVector()); } + | AMBIENT_OCCLUSION DEC_NUMBER { + $$ = new AmbientOcclusionNode($2->getInteger()); + } ; plane: PLANE LCURLY plane_items RCURLY { diff --git a/scenes/ambient_occlusion.fart b/scenes/ambient_occlusion.fart new file mode 100644 index 0000000..81c6400 --- /dev/null +++ b/scenes/ambient_occlusion.fart @@ -0,0 +1,41 @@ + +scene +{ + options + { + multisample 3 + width 800 + height 600 + ambient_occlusion 5 + } + + camera + { + position <2, -3, 2> + look_at <0, 0, 1> + up <0, 0, 1> + } + + light + { + position <200, -10, 50> + } + + define material white + { + color <1, 1, 1> + } + + sphere + { + radius 1 + material white + translate <0, 0, 1> + } + + plane + { + position <0, 0, 1>, 0 + material white + } +} diff --git a/vim/syntax/fart.vim b/vim/syntax/fart.vim index 9e0371f..f61220f 100644 --- a/vim/syntax/fart.vim +++ b/vim/syntax/fart.vim @@ -10,7 +10,7 @@ endif syn case match -syn keyword fartKeywords ambient color define diffuse exposure height jitter look_at material max_depth multisample options position radius reflectance rotate scale shininess size specular translate transparency union up vfov width +syn keyword fartKeywords ambient ambient_occlusion color define diffuse exposure height jitter look_at material max_depth multisample options position radius reflectance rotate scale shininess size specular translate transparency union up vfov width syn keyword fartObjects box camera cyl intersect light plane scene sphere subtract union syn match fartNumber "\(^\|\W\)\@<=[+-]\=\(\d\+\)\=\.\=\d\+\([eE][+-]\=\d\+\)\="