diff --git a/main/Scene-load.cc b/main/Scene-load.cc index 8a9001c..b1fd18d 100644 --- a/main/Scene-load.cc +++ b/main/Scene-load.cc @@ -184,6 +184,12 @@ void Scene::processOptions(refptr node) { m_height = (*it)->getInteger(); } + else if ( typeid(**it) == typeid(ExposureNode) ) + { + m_exposure = (*it)->getNumber(); + if (m_exposure < 0.0) + m_exposure = 0.0; + } else if ( typeid(**it) == typeid(MultisampleNode) ) { m_multisample_level = (*it)->getInteger(); diff --git a/main/Scene.cc b/main/Scene.cc index e50dda7..f6fb123 100644 --- a/main/Scene.cc +++ b/main/Scene.cc @@ -1,6 +1,7 @@ -#include "Scene.h" +#include /* exp(), pow() */ #include + #include #include #include /* pair */ @@ -8,7 +9,8 @@ #include /* sort() */ #include /* binary_function */ #include /* typeid operator support */ -#include + +#include "Scene.h" #include "BMP.h" #include "util/Color.h" #include "shapes/Shape.h" @@ -23,8 +25,9 @@ Scene::Scene(const map & options, m_height = 600; m_multisample_level = 1; m_vfov = 60.0; - m_ambient_light = Color(0.2, 0.2, 0.2); + m_ambient_light = Color(0.1, 0.1, 0.1); m_max_depth = 10; + m_exposure = 1.0f; m_transforms.push(Transform()); load(filename); @@ -86,13 +89,25 @@ void Scene::renderPixel(int x, int y, unsigned char * pixel) } } + /* apply exposure formula so we aren't saturated */ + finalColor.r = 1.0f - + exp(-m_exposure * finalColor.r / m_multisample_level_squared); + finalColor.g = 1.0f - + exp(-m_exposure * finalColor.g / m_multisample_level_squared); + finalColor.b = 1.0f - + exp(-m_exposure * finalColor.b / m_multisample_level_squared); + +#if 0 + /* gamma correct */ + finalColor.r = pow(finalColor.r, 1 / 2.2); + finalColor.g = pow(finalColor.g, 1 / 2.2); + finalColor.b = pow(finalColor.b, 1 / 2.2); +#endif + /* take the average of all the samples as the final pixel value */ - pixel[BMP_RED] = (unsigned char) - (0xFF * finalColor.r / m_multisample_level_squared); - pixel[BMP_GREEN] = (unsigned char) - (0xFF * finalColor.g / m_multisample_level_squared); - pixel[BMP_BLUE] = (unsigned char) - (0xFF * finalColor.b / m_multisample_level_squared); + pixel[BMP_RED] = (unsigned char) (0xFF * finalColor.r); + pixel[BMP_GREEN] = (unsigned char) (0xFF * finalColor.g); + pixel[BMP_BLUE] = (unsigned char) (0xFF * finalColor.b); } Color Scene::traceRay(const Ray & ray) @@ -244,14 +259,6 @@ Color Scene::computePhong(const refptr material, } } - /* TODO: figure out better scaling */ - if (result.r > 1.0) - result.r = 1.0; - if (result.g > 1.0) - result.g = 1.0; - if (result.b > 1.0) - result.b = 1.0; - return result; } diff --git a/main/Scene.h b/main/Scene.h index 5b87ae1..62f38ff 100644 --- a/main/Scene.h +++ b/main/Scene.h @@ -77,6 +77,7 @@ class Scene double m_vfov; Color m_ambient_light; int m_max_depth; + double m_exposure; /* private data */ std::vector< refptr > m_shapes; diff --git a/parser/nodes.h b/parser/nodes.h index b3bf038..e55615f 100644 --- a/parser/nodes.h +++ b/parser/nodes.h @@ -96,6 +96,12 @@ class DiffuseNode : public VectorNode DiffuseNode(refptr vector) : VectorNode(vector) {} }; +class ExposureNode : public NumberNode +{ + public: + ExposureNode(double d) : NumberNode(d) {} +}; + class HeightNode : public IntegerNode { public: diff --git a/parser/parser.lex b/parser/parser.lex index b32abb0..b7f7c71 100644 --- a/parser/parser.lex +++ b/parser/parser.lex @@ -46,6 +46,7 @@ color return COLOR; cyl return CYL; define return DEFINE; diffuse return DIFFUSE; +exposure return EXPOSURE; height return HEIGHT; intersect return INTERSECT; light return LIGHT; diff --git a/parser/parser.yy b/parser/parser.yy index 839c75d..e570fb6 100644 --- a/parser/parser.yy +++ b/parser/parser.yy @@ -65,6 +65,7 @@ static refptr parsed_scene_node; %token CYL; %token DEFINE; %token DIFFUSE; +%token EXPOSURE; %token HEIGHT; %token INTERSECT; %token LIGHT; @@ -295,6 +296,9 @@ options_item: WIDTH DEC_NUMBER { | MAXDEPTH DEC_NUMBER { $$ = new MaxDepthNode($2->getInteger()); } + | EXPOSURE number { + $$ = new ExposureNode($2->getNumber()); + } ; plane: PLANE LCURLY plane_items RCURLY {