added exposure equations to avoid saturation; default exposure 1.0; added "exposure" keyword to global scene options in parser

git-svn-id: svn://anubis/fart/trunk@250 7f9b0f55-74a9-4bce-be96-3c2cd072584d
This commit is contained in:
Josh Holtrop 2010-06-25 04:05:34 +00:00
parent 8fb2492e0a
commit ef003f6100
6 changed files with 42 additions and 17 deletions

View File

@ -184,6 +184,12 @@ void Scene::processOptions(refptr<Node> 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();

View File

@ -1,6 +1,7 @@
#include "Scene.h"
#include <math.h> /* exp(), pow() */
#include <stdlib.h>
#include <string>
#include <vector>
#include <utility> /* pair */
@ -8,7 +9,8 @@
#include <algorithm> /* sort() */
#include <functional> /* binary_function */
#include <typeinfo> /* typeid operator support */
#include <math.h>
#include "Scene.h"
#include "BMP.h"
#include "util/Color.h"
#include "shapes/Shape.h"
@ -23,8 +25,9 @@ Scene::Scene(const map<string, const char *> & 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> 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;
}

View File

@ -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<Shape> > m_shapes;

View File

@ -96,6 +96,12 @@ class DiffuseNode : public VectorNode
DiffuseNode(refptr<Vector> vector) : VectorNode(vector) {}
};
class ExposureNode : public NumberNode
{
public:
ExposureNode(double d) : NumberNode(d) {}
};
class HeightNode : public IntegerNode
{
public:

View File

@ -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;

View File

@ -65,6 +65,7 @@ static refptr<Node> 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 {