diff --git a/TODO.org b/TODO.org index cec92a9..fea407e 100644 --- a/TODO.org +++ b/TODO.org @@ -1,4 +1,4 @@ -* Features [12/20] +* Features [13/20] - [X] Perspective projection - [X] Ray-sphere intersection @@ -18,7 +18,7 @@ - [X] Phong shading - [X] Specular reflections - [X] Transmission - - [ ] Scene description input files (JSON) + - [X] Scene description input files (JSON) - [X] Indirect illumination - [ ] Glossy reflections - [X] Image based lighting @@ -106,79 +106,4 @@ l->m_diffuse = vec3(1.0f, 0.0f, 1.0f); vl.push_back(static_cast(l)); } - - void scene_2(vector
& vf, vector & vl, Environment * & e, Camera * c) { - Sphere * s; - Plane * p; - Disk * d; - PointLight * l; - - s = new Sphere(0.2f, 0.0f, -0.75f, 0.25f); - s->m_mat->m_diffuse = vec3(1.0f); - s->m_mat->m_rho = 0.2f; - vf.push_back(static_cast
(s)); - - p = new Plane(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(-2.0f, 0.0f, 0.0f), vec3(1.0f, 0.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(2.0f, 0.0f, 0.0f), vec3(-1.0f, 0.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 0.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, -1.0f, 0.0f)); - p->m_mat->m_diffuse = vec3(0.0f, 1.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 0.0f, -2.0f), vec3(0.0f, 0.0f, 1.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 0.0f, 1.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - p = new Plane(vec3(0.0f, 0.0f, 1.1f), vec3(0.0f, 0.0f, -1.0f)); - p->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - p->m_mat->m_specular = vec3(0.0f); - vf.push_back(static_cast
(p)); - - s = new Sphere(-0.5f, -0.5f, -1.5f, 0.5f); - s->m_mat->m_diffuse = vec3(0.0f); - s->m_mat->m_rho = 1.0f; - vf.push_back(static_cast
(s)); - - s = new Sphere(-0.5f, -0.5f, 0.6f, 0.5f); - s->m_mat->m_diffuse = vec3(1.0f, 1.0f, 0.0f); - s->m_mat->m_refract = true; - s->m_mat->m_ref_index = 1.33f; - vf.push_back(static_cast
(s)); - - d = new Disk(vec3(-0.25f, 1.0f, -1.0f), vec3(1.0f, 0.0f, 0.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.25f, 1.0f, -1.0f), vec3(-1.0f, 0.0f, 0.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.0f, 1.0f, -1.25f), vec3(0.0f, 0.0f, 1.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - d = new Disk(vec3(0.0f, 1.0f, -0.75f), vec3(0.0f, 0.0f, -1.0f), 0.25f); - d->m_mat->m_diffuse = vec3(1.0f); - vf.push_back(static_cast
(d)); - - l = new PointLight(); - l->m_position = vec3(0.0f, 0.9f, -1.0f); - l->m_diffuse = vec3(1.0f); - vl.push_back(static_cast(l)); - } - #+END_SRC diff --git a/output.png b/output.png index 6992842..a4f72ca 100644 Binary files a/output.png and b/output.png differ diff --git a/scene.cpp b/scene.cpp index e2a6bfb..ad54fe3 100644 --- a/scene.cpp +++ b/scene.cpp @@ -81,6 +81,14 @@ static const string GEO_TRN_KEY = "translation"; static const string GEO_SCL_KEY = "scaling"; static const string GEO_ROT_KEY = "rotation"; +static const string LGT_DIR_KEY = "direction"; +static const string LGT_CAT_KEY = "const_attenuation"; +static const string LGT_LAT_KEY = "linear_attenuation"; +static const string LGT_QAT_KEY = "quad_attenuation"; +static const string LGT_SPD_KEY = "spot_direction"; +static const string LGT_SPC_KEY = "spot_cutoff"; +static const string LGT_SPE_KEY = "spot_exponent"; + Scene::Scene(const char * file_name, int h, int w, float fov) throw(SceneError) { ostringstream oss; ifstream ifs(file_name, ios::in); @@ -120,13 +128,16 @@ Scene::Scene(const char * file_name, int h, int w, float fov) throw(SceneError) else if ((*it).name_ == DSK_KEY) m_figures.push_back(read_disk((*it).value_)); - else if ((*it).name_ == DLT_KEY) { + else if ((*it).name_ == DLT_KEY) + m_lights.push_back(read_light((*it).value_, DIRECTIONAL)); - } else if ((*it).name_ == PLT_KEY) { + else if ((*it).name_ == PLT_KEY) + m_lights.push_back(read_light((*it).value_, POINT)); - } else if ((*it).name_ == SLT_KEY) { + else if ((*it).name_ == SLT_KEY) + m_lights.push_back(read_light((*it).value_, SPOT)); - } else + else cerr << "Unrecognized key \"" << (*it).name_ << "\" in the input file." << endl; } } catch (SceneError & e) { @@ -439,3 +450,52 @@ Figure * Scene::read_disk(Value &v) throw(SceneError) { return static_cast
(new Disk(position, normal, radius, mat)); } + +Light * Scene::read_light(Value & v, light_type_t t) throw(SceneError) { + vec3 position, diffuse = vec3(1.0f), specular = vec3(1.0f), spot_dir = vec3(0.0f, -1.0f, 0.0f); + float const_att = 1.0f, lin_att = 0.0f, quad_att = 0.0f, spot_cutoff = 45.0f, spot_exp = 0.0f; + Object lght_obj = v.get_value(); + + try { + for (Object::iterator it = lght_obj.begin(); it != lght_obj.end(); it++) { + if ((*it).name_ == FIG_POS_KEY || (*it).name_ == LGT_DIR_KEY) + read_vector((*it).value_, position); + + else if((*it).name_ == MLT_DIF_KEY) + read_vector((*it).value_, diffuse); + + else if((*it).name_ == MLT_SPC_KEY) + read_vector((*it).value_, specular); + + else if((*it).name_ == LGT_SPD_KEY) + read_vector((*it).value_, spot_dir); + + else if ((*it).name_ == LGT_CAT_KEY) + const_att = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == LGT_LAT_KEY) + lin_att = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == LGT_QAT_KEY) + quad_att = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == LGT_SPC_KEY) + spot_cutoff = static_cast((*it).value_.get_value()); + + else if ((*it).name_ == LGT_SPE_KEY) + spot_exp = static_cast((*it).value_.get_value()); + } + } catch (SceneError & e) { + throw e; + } + + if (t == DIRECTIONAL) + return static_cast(new DirectionalLight(position, diffuse, specular)); + else if (t == POINT) + return static_cast(new PointLight(position, diffuse, specular, const_att, lin_att, quad_att)); + else if (t == SPOT) + return static_cast(new SpotLight(position, diffuse, specular, const_att, lin_att, quad_att, spot_cutoff, spot_exp, spot_dir)); + else + throw SceneError("Unknown light type."); + return NULL; +} diff --git a/scene.hpp b/scene.hpp index b43eb6c..03267fd 100644 --- a/scene.hpp +++ b/scene.hpp @@ -19,6 +19,8 @@ using std::vector; using std::runtime_error; using json_spirit::Value; +typedef enum LIGHT_TYPE { DIRECTIONAL, POINT, SPOT } light_type_t; + class SceneError: public runtime_error { public: explicit SceneError(const string & what_arg): runtime_error(what_arg) { } @@ -39,9 +41,10 @@ private: void read_environment(Value & v) throw(SceneError); void read_camera(Value & v) throw(SceneError); Material * read_material(Value & v) throw(SceneError); - Figure * read_sphere(Value &v) throw(SceneError); - Figure * read_plane(Value &v) throw(SceneError); - Figure * read_disk(Value &v) throw(SceneError); + Figure * read_sphere(Value & v) throw(SceneError); + Figure * read_plane(Value & v) throw(SceneError); + Figure * read_disk(Value & v) throw(SceneError); + Light * read_light(Value & v, light_type_t t) throw(SceneError); }; #endif diff --git a/scenes/scene2.json b/scenes/scene2.json index 8d2f792..5e8000c 100644 --- a/scenes/scene2.json +++ b/scenes/scene2.json @@ -1,9 +1,12 @@ { + "point_light":{ + "position": [0.0, 0.9, -1.0] + }, + "sphere": { "position": [0.2, 0.0, -0.75], "radius": 0.25, "material": { - "emission": [10.0, 10.0, 10.0], "diffuse": [1.0, 1.0, 1.0], "rho": 0.2 }