Added presentations from EVI 2017
This commit is contained in:
BIN
EVI - 2017/EVI 12/EVI_12 - Subsumption.pdf
Normal file
BIN
EVI - 2017/EVI 12/EVI_12 - Subsumption.pdf
Normal file
Binary file not shown.
140
EVI - 2017/EVI 12/Examples/Arbitrator.java
Normal file
140
EVI - 2017/EVI 12/Examples/Arbitrator.java
Normal file
@@ -0,0 +1,140 @@
|
||||
package lejos.robotics.subsumption;
|
||||
|
||||
|
||||
/**
|
||||
* Arbitrator controls which Behavior object will become active in
|
||||
* a behavior control system. Make sure to call start() after the
|
||||
* Arbitrator is instantiated.<br>
|
||||
* This class has three major responsibilities: <br>
|
||||
* 1. Determine the highest priority behavior that returns <b> true </b> to takeControl()<br>
|
||||
* 2. Suppress the active behavior if its priority is less than highest
|
||||
* priority. <br>
|
||||
* 3. When the action() method exits, call action() on the Behavior of highest priority.
|
||||
* <br> The Arbitrator assumes that a Behavior is no longer active when action() exits,
|
||||
* <br> therefore it will only call suppress() on the Behavior whose action() method is running.
|
||||
* <br> It can make consecutive calls of action() on the same Behavior.
|
||||
* <br> Requirements for a Behavior:
|
||||
* <br> When suppress() is called, terminate action() immediately.
|
||||
* <br> When action() exits, the robot is in a safe state (e.g. motors stopped)
|
||||
* @see Behavior
|
||||
* @author Roger Glassey
|
||||
*/
|
||||
public class Arbitrator
|
||||
{
|
||||
|
||||
private final int NONE = -1;
|
||||
private Behavior[] _behavior;
|
||||
// highest priority behavior that wants control ; set by start() usec by monitor
|
||||
private int _highestPriority = NONE;
|
||||
private int _active = NONE; // active behavior; set by montior, used by start();
|
||||
private boolean _returnWhenInactive;
|
||||
/**
|
||||
* Monitor is an inner class. It polls the behavior array to find the behavior of hightst
|
||||
* priority. If higher than the active behavior, it calls active.suppress()
|
||||
*/
|
||||
private Monitor monitor;
|
||||
|
||||
/**
|
||||
* Allocates an Arbitrator object and initializes it with an array of
|
||||
* Behavior objects. The index of a behavior in this array is its priority level, so
|
||||
* the behavior of the largest index has the highest the priority level.
|
||||
* The behaviors in an Arbitrator can not
|
||||
* be changed once the arbitrator is initialized.<BR>
|
||||
* <B>NOTE:</B> Once the Arbitrator is initialized, the method start() must be
|
||||
* called to begin the arbitration.
|
||||
* @param behaviorList an array of Behavior objects.
|
||||
* @param returnWhenInactive if <B>true</B>, the <B>start()</B> method returns when no Behavior is active.
|
||||
*/
|
||||
public Arbitrator(Behavior[] behaviorList, boolean returnWhenInactive)
|
||||
{
|
||||
_behavior = behaviorList;
|
||||
_returnWhenInactive = returnWhenInactive;
|
||||
monitor = new Monitor();
|
||||
monitor.setDaemon(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as Arbitrator(behaviorList, false) Arbitrator start() never exits
|
||||
* @param behaviorList An array of Behavior objects.
|
||||
*/
|
||||
public Arbitrator(Behavior[] behaviorList)
|
||||
{
|
||||
this(behaviorList, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method starts the arbitration of Behaviors and runs an endless loop. <BR>
|
||||
* Note: Arbitrator does not run in a separate thread. The start()
|
||||
* method will never return unless <br>1. no action() method is running and
|
||||
* <br>2. no behavior takeControl()
|
||||
* returns <B> true </B> and <br> 3. the <i>returnWhenInacative </i> flag is true,
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
monitor.start();
|
||||
while (_highestPriority == NONE)
|
||||
{
|
||||
Thread.yield();//wait for some behavior to take contro
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
synchronized (monitor)
|
||||
{
|
||||
if (_highestPriority != NONE)
|
||||
{
|
||||
_active = _highestPriority;
|
||||
|
||||
} else if (_returnWhenInactive)
|
||||
{// no behavior wants to run
|
||||
monitor.more = false;//9 shut down monitor thread
|
||||
return;
|
||||
}
|
||||
}// monotor released before action is called
|
||||
if (_active != NONE) //_highestPrioirty could be NONE
|
||||
{
|
||||
_behavior[_active].action();
|
||||
_active = NONE; // no active behavior at the moment
|
||||
}
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the highest priority behavior that returns <B>true </B> to takeControl();
|
||||
* If this priority is higher than the active behavior, it calls active.suppress().
|
||||
* If there is no active behavior, calls suppress() on the most recently acrive behavior.
|
||||
*/
|
||||
private class Monitor extends Thread
|
||||
{
|
||||
|
||||
boolean more = true;
|
||||
int maxPriority = _behavior.length - 1;
|
||||
|
||||
public void run()
|
||||
{
|
||||
while (more)
|
||||
{
|
||||
//FIND HIGHEST PRIORITY BEHAVIOR THAT WANTS CONTROL
|
||||
synchronized (this)
|
||||
{
|
||||
_highestPriority = NONE;
|
||||
for (int i = maxPriority; i >= 0; i--)
|
||||
{
|
||||
if (_behavior[i].takeControl())
|
||||
{
|
||||
_highestPriority = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int active = _active;// local copy: avoid out of bounds error in 134
|
||||
if (active != NONE && _highestPriority > active)
|
||||
{
|
||||
_behavior[active].suppress();
|
||||
}
|
||||
}// end synchronize block - main thread can run now
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
55
EVI - 2017/EVI 12/Examples/Behavior.java
Normal file
55
EVI - 2017/EVI 12/Examples/Behavior.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package lejos.robotics.subsumption;
|
||||
|
||||
|
||||
/**
|
||||
* The Behavior interface represents an object embodying a specific
|
||||
* behavior belonging to a robot. Each behavior must define three things: <BR>
|
||||
* 1) The circumstances to make this behavior seize control of the robot.
|
||||
* e.g. When the touch sensor determines the robot has collided with an object.<BR>
|
||||
* 2) The action to perform when this behavior takes control.
|
||||
* e.g. Back up and turn.<BR>
|
||||
* 3) A way to quickly exit from the action when the Arbitrator selects a higher
|
||||
* priority behavior to take control.
|
||||
* These are represented by defining the methods takeControl(), action(),
|
||||
* and suppress() respectively. <BR>
|
||||
* A behavior control system has one or more Behavior objects. When you have defined
|
||||
* these objects, create an array of them and use that array to initialize an
|
||||
* Arbitrator object.
|
||||
*
|
||||
* @see Arbitrator
|
||||
|
||||
* @version 0.9 May 2011
|
||||
*/
|
||||
public interface Behavior {
|
||||
|
||||
/**
|
||||
* The boolean return indicates if this behavior should seize control of the robot.
|
||||
* For example, a robot that reacts if a touch sensor is pressed: <BR>
|
||||
* public boolean takeControl() { <BR>
|
||||
* return touch.isPressed(); <BR>
|
||||
* } <BR>
|
||||
* @return boolean Indicates if this Behavior should seize control.
|
||||
*/
|
||||
public boolean takeControl();
|
||||
|
||||
/**
|
||||
* The code in action() represents the tasks the robot performs when this
|
||||
* behavior becomes active. It can be as complex as navigating around a
|
||||
* room, or as simple as playing a tune.<BR>
|
||||
* <B>The contract for implementing this method is:</B><BR>
|
||||
* If its task is is complete, the method returns.
|
||||
* It also <B> must </B> return promptly when the suppress() method
|
||||
* is called, for example by testing the boolean suppress flag. <br>
|
||||
* When this method exits, the robot is in a safe state for another behavior
|
||||
* to run its action() method
|
||||
*/
|
||||
public void action();
|
||||
|
||||
/**
|
||||
* The code in suppress() should cause the current behavior to exit. <BR>
|
||||
* <B>The contract for implementing this method is:</B><BR>
|
||||
* Exit quickly, for example, just set boolean flag.
|
||||
*/
|
||||
public void suppress();
|
||||
|
||||
}
|
120
EVI - 2017/EVI 12/Examples/SubsumpRobot.java
Normal file
120
EVI - 2017/EVI 12/Examples/SubsumpRobot.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package miky;
|
||||
import robocode.*;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* SubsumpRobot - a robot by (your name here)
|
||||
*/
|
||||
public class SubsumpRobot extends Robot {
|
||||
abstract class SubsumptionBehavior {
|
||||
public abstract boolean takeControl();
|
||||
public abstract void action();
|
||||
}
|
||||
|
||||
class WanderBehavior extends SubsumptionBehavior {
|
||||
public boolean takeControl() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void action() {
|
||||
ahead(200);
|
||||
if (Math.random() > 0.5)
|
||||
turnLeft(30.0);
|
||||
else
|
||||
turnRight(30.0);
|
||||
scan();
|
||||
}
|
||||
}
|
||||
|
||||
class MoveToRobotBehavior extends SubsumptionBehavior {
|
||||
public boolean takeControl() {
|
||||
return scannedRobot != null;
|
||||
}
|
||||
|
||||
public void action() {
|
||||
turnRight(scannedRobot.getBearing());
|
||||
ahead(50);
|
||||
}
|
||||
}
|
||||
|
||||
class FireBehavior extends SubsumptionBehavior {
|
||||
public boolean takeControl() {
|
||||
return scannedRobot != null && scannedRobot.getDistance() < 200;
|
||||
}
|
||||
|
||||
public void action() {
|
||||
fire(3);
|
||||
}
|
||||
}
|
||||
|
||||
class AvoidWallBehavior extends SubsumptionBehavior {
|
||||
public boolean takeControl() {
|
||||
return hitEvent != null;
|
||||
}
|
||||
|
||||
public void action() {
|
||||
hitEvent = null;
|
||||
scannedRobot = null;
|
||||
back(100);
|
||||
turnLeft(180.0);
|
||||
}
|
||||
}
|
||||
|
||||
private List<SubsumptionBehavior> behaviors;
|
||||
private ScannedRobotEvent scannedRobot;
|
||||
private Event hitEvent;
|
||||
|
||||
public SubsumpRobot() {
|
||||
super();
|
||||
hitEvent = null;
|
||||
scannedRobot = null;
|
||||
behaviors = new LinkedList<SubsumptionBehavior>();
|
||||
}
|
||||
|
||||
public void addBehavior(SubsumptionBehavior behavior) {
|
||||
behaviors.add(behavior);
|
||||
}
|
||||
|
||||
public void removeBehavior(SubsumptionBehavior behavior) {
|
||||
behaviors.remove(behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
* run: SubsumpRobot's default behavior
|
||||
*/
|
||||
public void run() {
|
||||
int behavior_index = 0;
|
||||
|
||||
// Add behaviors.
|
||||
behaviors.add(new AvoidWallBehavior());
|
||||
behaviors.add(new FireBehavior());
|
||||
behaviors.add(new MoveToRobotBehavior());
|
||||
behaviors.add(new WanderBehavior());
|
||||
|
||||
while(true) {
|
||||
for (SubsumptionBehavior b : behaviors) {
|
||||
if (b.takeControl()) {
|
||||
b.action();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onScannedRobot(ScannedRobotEvent e) {
|
||||
scannedRobot = e;
|
||||
}
|
||||
|
||||
public void onHitWall(HitWallEvent e) {
|
||||
hitEvent = e;
|
||||
}
|
||||
|
||||
public void onHitRobot(HitRobotEvent e) {
|
||||
hitEvent = e;
|
||||
}
|
||||
|
||||
public void onRobotDeath(RobotDeathEvent e) {
|
||||
scannedRobot = null;
|
||||
}
|
||||
}
|
BIN
EVI - 2017/EVI 21/EVI_21 - Raytracing.pdf
Normal file
BIN
EVI - 2017/EVI 21/EVI_21 - Raytracing.pdf
Normal file
Binary file not shown.
30
EVI - 2017/EVI 21/EVIray/Makefile
Normal file
30
EVI - 2017/EVI 21/EVIray/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
CXX = g++
|
||||
TARGET = ray
|
||||
OBJECTS = main.o sampling.o camera.o plane.o sphere.o \
|
||||
phong_brdf.o directional_light.o point_light.o \
|
||||
spot_light.o sphere_area_light.o scene.o tracer.o \
|
||||
path_tracer.o whitted_tracer.o
|
||||
DEPENDS = $(OBJECTS:.o=.d)
|
||||
CXXFLAGS = -std=c++11 -pedantic -Wall -DGLM_FORCE_RADIANS -DUSE_CPP11_RANDOM -fno-builtin
|
||||
LDLIBS = -lfreeimage -ljson_spirit
|
||||
|
||||
.PHONY: all
|
||||
all: CXXFLAGS += -O3 -DNDEBUG
|
||||
all: $(TARGET)
|
||||
|
||||
.PHONY: debug
|
||||
debug: CXXFLAGS += -g
|
||||
debug: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(CXX) -o $@ $^ $(CXXFLAGS) $(LDLIBS)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $*.cpp -o $*.o
|
||||
$(CXX) -MM $(CXXFLAGS) $*.cpp > $*.d
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(TARGET) $(OBJECTS) $(DEPENDS)
|
90
EVI - 2017/EVI 21/EVIray/area_light.hpp
Normal file
90
EVI - 2017/EVI 21/EVIray/area_light.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
#ifndef AREA_LIGHT_HPP
|
||||
#define AREA_LIGHT_HPP
|
||||
|
||||
#include "light.hpp"
|
||||
|
||||
using glm::length;
|
||||
using glm::normalize;
|
||||
using glm::dot;
|
||||
|
||||
class AreaLight: public Light {
|
||||
public:
|
||||
float m_const_att;
|
||||
float m_lin_att;
|
||||
float m_quad_att;
|
||||
Figure * m_figure;
|
||||
|
||||
AreaLight():
|
||||
Light(AREA),
|
||||
m_const_att(1.0),
|
||||
m_lin_att(0.0),
|
||||
m_quad_att(0.0),
|
||||
m_figure(NULL),
|
||||
m_last_sample(vec3()),
|
||||
m_n_at_last_sample(vec3())
|
||||
{ }
|
||||
|
||||
AreaLight(Figure * _f, float _c = 1.0, float _l = 0.0, float _q = 0.0):
|
||||
Light(AREA),
|
||||
m_const_att(_c),
|
||||
m_lin_att(_l),
|
||||
m_quad_att(_q),
|
||||
m_figure(_f),
|
||||
m_last_sample(vec3()),
|
||||
m_n_at_last_sample(vec3())
|
||||
{ }
|
||||
|
||||
virtual vec3 direction(vec3 point) const {
|
||||
return normalize(m_last_sample - point);
|
||||
}
|
||||
|
||||
virtual float distance(vec3 point) const {
|
||||
return length(m_last_sample - point);
|
||||
}
|
||||
|
||||
vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att, ln_dot_d, d2, g;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = normalize(direction(i_pos));
|
||||
ln_dot_d = dot(m_n_at_last_sample, l_dir);
|
||||
if (ln_dot_d > 0.0f) {
|
||||
d2 = distance(i_pos);
|
||||
d2 *= d2;
|
||||
g = ln_dot_d / d2;
|
||||
d = distance(i_pos);
|
||||
att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
return (att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_figure->m_mat->m_emission) * g) / m_figure->pdf();
|
||||
|
||||
} else
|
||||
return vec3(0.0f);
|
||||
}
|
||||
|
||||
vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att, ln_dot_d;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = normalize(direction(i_pos));
|
||||
ln_dot_d = dot(m_n_at_last_sample, l_dir);
|
||||
if (ln_dot_d > 0.0f) {
|
||||
d = distance(i_pos);
|
||||
att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
return (att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_figure->m_mat->m_emission, m.m_shininess)) / m_figure->pdf();
|
||||
|
||||
} else
|
||||
return vec3(0.0f);
|
||||
}
|
||||
|
||||
virtual vec3 normal_at_last_sample() {
|
||||
return m_n_at_last_sample;
|
||||
}
|
||||
|
||||
virtual vec3 sample_at_surface() = 0;
|
||||
|
||||
protected:
|
||||
vec3 m_last_sample;
|
||||
vec3 m_n_at_last_sample;
|
||||
};
|
||||
|
||||
#endif
|
19
EVI - 2017/EVI 21/EVIray/brdf.hpp
Normal file
19
EVI - 2017/EVI 21/EVIray/brdf.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#ifndef BRDF_HPP
|
||||
#define BRDF_HPP
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "ray.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class BRDF {
|
||||
public:
|
||||
virtual ~BRDF() { }
|
||||
|
||||
virtual vec3 diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_diff_color) const = 0;
|
||||
virtual vec3 specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_spec_color, float shininess) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
74
EVI - 2017/EVI 21/EVIray/camera.cpp
Normal file
74
EVI - 2017/EVI 21/EVIray/camera.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <glm/gtx/rotate_vector.hpp>
|
||||
|
||||
#include "camera.hpp"
|
||||
|
||||
using glm::vec4;
|
||||
using glm::rotate;
|
||||
using glm::radians;
|
||||
using glm::cross;
|
||||
|
||||
void Camera::reset() {
|
||||
// Recalculate look at and invert it.
|
||||
m_inv_view_matrix = inverse(lookAt(m_eye, m_look, m_up));
|
||||
}
|
||||
|
||||
void Camera::translate(vec3 t) {
|
||||
// Create a translation matrix.
|
||||
mat4 t_matrix = glm::translate(mat4(1.0f), t);
|
||||
|
||||
// Compute new eye and look at position (in homogeneous coordinates).
|
||||
vec4 new_eye = t_matrix * vec4(m_eye, 1.0f);
|
||||
vec4 new_look = t_matrix * vec4(m_look, 1.0f);
|
||||
|
||||
// Set new eye and look at.
|
||||
m_eye = vec3(new_eye.x, new_eye.y, new_eye.z);
|
||||
m_look = vec3(new_look.x, new_look.y, new_look.z);
|
||||
|
||||
// Recalculate the view matrix.
|
||||
reset();
|
||||
}
|
||||
|
||||
void Camera::pitch(float angle) {
|
||||
// Calculate view direction and left vector.
|
||||
vec3 view_dir = normalize(m_look - m_eye);
|
||||
vec3 left = cross(view_dir, m_up);
|
||||
|
||||
// Rotate the view direction.
|
||||
view_dir = rotate(view_dir, radians(angle), left);
|
||||
|
||||
// Rotate the up vector
|
||||
m_up = normalize(rotate(m_up, radians(angle), left));
|
||||
|
||||
// Compute new look at.
|
||||
m_look = m_eye + view_dir;
|
||||
|
||||
// Recalculate the view matrix.
|
||||
reset();
|
||||
}
|
||||
|
||||
void Camera::yaw(float angle) {
|
||||
// Compute and rotate the view direction.
|
||||
vec3 view_dir = rotate(normalize(m_look - m_eye), radians(angle), m_up);
|
||||
|
||||
// Compute new look at.
|
||||
m_look = m_eye + view_dir;
|
||||
|
||||
// Recalculate the view matrix.
|
||||
reset();
|
||||
}
|
||||
|
||||
void Camera::roll(float angle) {
|
||||
// Rotate the up vector.
|
||||
m_up = normalize(rotate(m_up, radians(angle), normalize(m_look - m_eye)));
|
||||
|
||||
// Recalculate the view matrix.
|
||||
reset();
|
||||
}
|
||||
|
||||
void Camera::view_to_world(Ray & r) const {
|
||||
vec4 dir = m_inv_view_matrix * vec4(r.m_direction, 0.0f);
|
||||
vec4 orig = m_inv_view_matrix * vec4(r.m_origin, 1.0f);
|
||||
|
||||
r.m_direction = vec3(dir.x, dir.y, dir.z);
|
||||
r.m_origin = vec3(orig.x, orig.y, orig.z);
|
||||
}
|
71
EVI - 2017/EVI 21/EVIray/camera.hpp
Normal file
71
EVI - 2017/EVI 21/EVIray/camera.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
#ifndef CAMERA_HPP
|
||||
#define CAMERA_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "ray.hpp"
|
||||
|
||||
using glm::mat4;
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
using glm::normalize;
|
||||
using glm::lookAt;
|
||||
using glm::inverse;
|
||||
|
||||
// Camera vector disposition:
|
||||
// up^
|
||||
// |
|
||||
// |
|
||||
// eye)-------->* look
|
||||
//
|
||||
class Camera {
|
||||
public:
|
||||
vec3 m_eye; // Eye position.
|
||||
vec3 m_look; // Look-up position.
|
||||
vec3 m_up; // Up vector.
|
||||
|
||||
Camera(vec3 _e = vec3(0.0f), vec3 _l = vec3(0.0f, 0.0f, -1.0f), vec3 _u = vec3(0.0f, 1.0f, 0.0f)):
|
||||
m_eye(_e),
|
||||
m_look(_l),
|
||||
m_up(normalize(_u)),
|
||||
m_inv_view_matrix(inverse(lookAt(_e, _l, normalize(_u))))
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Restores the view matrix undoing any transformation.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Translate the eye position.
|
||||
*/
|
||||
void translate(vec3 t);
|
||||
|
||||
/**
|
||||
* Rotate view direction around left vector (cross product of up vector and view direction).
|
||||
*/
|
||||
void pitch(float angle);
|
||||
|
||||
/**
|
||||
* Rotate view direction around up vector.
|
||||
*/
|
||||
void yaw(float angle);
|
||||
|
||||
/**
|
||||
* Rotate up vector around view direction.
|
||||
*/
|
||||
void roll(float angle);
|
||||
|
||||
/**
|
||||
* Apply the inverse view matrix to a ray to take it from view space to world space.
|
||||
*/
|
||||
void view_to_world(Ray & r) const;
|
||||
|
||||
private:
|
||||
// Inverse view matrix.
|
||||
mat4 m_inv_view_matrix;
|
||||
};
|
||||
|
||||
#endif
|
29
EVI - 2017/EVI 21/EVIray/directional_light.cpp
Normal file
29
EVI - 2017/EVI 21/EVIray/directional_light.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <limits>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "directional_light.hpp"
|
||||
|
||||
using std::numeric_limits;
|
||||
using glm::pi;
|
||||
using glm::reflect;
|
||||
using glm::dot;
|
||||
using glm::pow;
|
||||
using glm::max;
|
||||
|
||||
vec3 DirectionalLight::direction(vec3 point) const {
|
||||
return m_position;
|
||||
}
|
||||
|
||||
float DirectionalLight::distance(vec3 point) const {
|
||||
return numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
vec3 DirectionalLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
return m.m_brdf->diffuse(m_position, normal, r, i_pos, m_diffuse);
|
||||
}
|
||||
|
||||
vec3 DirectionalLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
return m.m_brdf->specular(m_position, normal, r, i_pos, m_specular, m.m_shininess);
|
||||
}
|
23
EVI - 2017/EVI 21/EVIray/directional_light.hpp
Normal file
23
EVI - 2017/EVI 21/EVIray/directional_light.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#ifndef DIRECTIONAL_LIGHT_HPP
|
||||
#define DIRECTIONAL_LIGHT_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "light.hpp"
|
||||
|
||||
using glm::normalize;
|
||||
|
||||
class DirectionalLight: public InfinitesimalLight {
|
||||
public:
|
||||
DirectionalLight(): InfinitesimalLight() { }
|
||||
|
||||
DirectionalLight(vec3 _p, vec3 _d, vec3 _s): InfinitesimalLight(normalize(_p), _d, _s) { }
|
||||
|
||||
virtual vec3 direction(vec3 point) const;
|
||||
virtual float distance(vec3 point) const;
|
||||
virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
};
|
||||
|
||||
#endif
|
26
EVI - 2017/EVI 21/EVIray/environment.hpp
Normal file
26
EVI - 2017/EVI 21/EVIray/environment.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#ifndef ENVIRONMENT_HPP
|
||||
#define ENVIRONMENT_HPP
|
||||
|
||||
#include <FreeImage.h>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "ray.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Environment {
|
||||
public:
|
||||
Environment(vec3 bckg = vec3(1.0f)): m_bckg_color(bckg) { }
|
||||
|
||||
~Environment() { }
|
||||
|
||||
vec3 get_color(Ray & r) {
|
||||
return m_bckg_color;
|
||||
}
|
||||
|
||||
private:
|
||||
vec3 m_bckg_color;
|
||||
};
|
||||
|
||||
#endif
|
38
EVI - 2017/EVI 21/EVIray/figure.hpp
Normal file
38
EVI - 2017/EVI 21/EVIray/figure.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#ifndef FIGURE_HPP
|
||||
#define FIGURE_HPP
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "ray.hpp"
|
||||
#include "material.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Figure {
|
||||
public:
|
||||
Material * m_mat;
|
||||
|
||||
Figure(Material * mat = NULL): m_inv_area(0.0f) {
|
||||
m_mat = mat == NULL ? new Material() : mat;
|
||||
}
|
||||
|
||||
virtual ~Figure() {
|
||||
delete m_mat;
|
||||
}
|
||||
|
||||
virtual float pdf() const {
|
||||
return m_inv_area;
|
||||
}
|
||||
|
||||
virtual bool intersect(Ray & r, float & t) const = 0;
|
||||
virtual vec3 normal_at_int(Ray & r, float & t) const = 0;
|
||||
virtual vec3 sample_at_surface() const = 0;
|
||||
|
||||
protected:
|
||||
float m_inv_area;
|
||||
|
||||
virtual void calculate_inv_area() = 0;
|
||||
};
|
||||
|
||||
#endif
|
54
EVI - 2017/EVI 21/EVIray/light.hpp
Normal file
54
EVI - 2017/EVI 21/EVIray/light.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#ifndef LIGHT_HPP
|
||||
#define LIGHT_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "figure.hpp"
|
||||
#include "material.hpp"
|
||||
#include "ray.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Light {
|
||||
public:
|
||||
typedef enum LIGHT_TYPE { INFINITESIMAL = 0, AREA } ltype_t;
|
||||
|
||||
vec3 m_position;
|
||||
vec3 m_diffuse;
|
||||
vec3 m_specular;
|
||||
|
||||
Light(): m_position(vec3(0.0f)), m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)) { }
|
||||
|
||||
Light(ltype_t _t): m_position(vec3(0.0f)), m_diffuse(vec3(1.0f)), m_specular(vec3(1.0f)), m_type(_t) { }
|
||||
|
||||
Light(vec3 _p, vec3 _d, vec3 _s, ltype_t _t): m_position(_p), m_diffuse(_d), m_specular(_s), m_type(_t) { }
|
||||
|
||||
virtual ~Light() { }
|
||||
|
||||
virtual ltype_t light_type() {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
virtual vec3 direction(vec3 point) const = 0;
|
||||
virtual float distance(vec3 point) const = 0;
|
||||
virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0;
|
||||
virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0;
|
||||
|
||||
protected:
|
||||
ltype_t m_type;
|
||||
};
|
||||
|
||||
class InfinitesimalLight: public Light {
|
||||
public:
|
||||
InfinitesimalLight(): Light(INFINITESIMAL) { }
|
||||
|
||||
InfinitesimalLight(vec3 _p, vec3 _d, vec3 _s): Light(_p, _d, _s, INFINITESIMAL) { }
|
||||
|
||||
virtual vec3 direction(vec3 point) const = 0;
|
||||
virtual float distance(vec3 point) const = 0;
|
||||
virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0;
|
||||
virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
375
EVI - 2017/EVI 21/EVIray/main.cpp
Normal file
375
EVI - 2017/EVI 21/EVIray/main.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <FreeImage.h>
|
||||
|
||||
#include "sampling.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "ray.hpp"
|
||||
#include "tracer.hpp"
|
||||
#include "path_tracer.hpp"
|
||||
#include "whitted_tracer.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace glm;
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Defines.
|
||||
////////////////////////////////////////////
|
||||
#define ANSI_BOLD_YELLOW "\x1b[1;33m"
|
||||
#define ANSI_RESET_STYLE "\x1b[m"
|
||||
#define MAX_W 1920
|
||||
#define MAX_H 1080
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Function prototypes.
|
||||
////////////////////////////////////////////
|
||||
static void print_usage(char ** const argv);
|
||||
static void parse_args(int argc, char ** const argv);
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Constants.
|
||||
////////////////////////////////////////////
|
||||
static const char * OUT_FILE = "output.png";
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Global variables.
|
||||
////////////////////////////////////////////
|
||||
typedef enum TRACERS { NONE, WHITTED, MONTE_CARLO } tracer_t;
|
||||
|
||||
static char * g_input_file = NULL; // Input scene file name.
|
||||
static char * g_out_file_name = NULL; // Output image file name.
|
||||
static int g_samples = 25; // Samples per pixel.
|
||||
static float g_fov = 45.0f; // Camera field of view.
|
||||
static int g_w = 640; // Image width.
|
||||
static int g_h = 480; // Image height.
|
||||
static float g_a_ratio = 640.0f / 480.0f; // Image aspect ratio.
|
||||
static vec3 image[MAX_H][MAX_W]; // Image.
|
||||
static tracer_t g_tracer = NONE; // Ray tracer to use.
|
||||
static unsigned int g_max_depth = 5; // Max recursion depth.
|
||||
static float g_gamma = 2.2f; // Gamma correction factor.
|
||||
static float g_exposure = 0.0f; // Exposure correction factor.
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Main function.
|
||||
////////////////////////////////////////////
|
||||
int main(int argc, char ** argv) {
|
||||
Ray r; // Primary ray.
|
||||
vec2 sample; // Pixel sample position.
|
||||
Tracer * tracer; // Tracer to use.
|
||||
uint64_t total; // Total of samples to calculate;
|
||||
uint64_t current = 0; // Samples calculated.
|
||||
FIBITMAP * input_bitmap;
|
||||
FIBITMAP * output_bitmap;
|
||||
FREE_IMAGE_FORMAT fif;
|
||||
BYTE * bits;
|
||||
FIRGBF *pixel;
|
||||
int pitch;
|
||||
Scene * scn;
|
||||
|
||||
// Parse command line arguments.
|
||||
parse_args(argc, argv);
|
||||
|
||||
// Initialize FreeImage.
|
||||
FreeImage_Initialise();
|
||||
|
||||
// Try to read a scene file.
|
||||
try {
|
||||
scn = new Scene(g_input_file);
|
||||
} catch (SceneError & e) {
|
||||
cout << e.what() << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Print run parameters.
|
||||
cout << "Rendering the input file: " << ANSI_BOLD_YELLOW << g_input_file << ANSI_RESET_STYLE << endl;
|
||||
cout << "The scene contains: " << endl;
|
||||
cout << " " << ANSI_BOLD_YELLOW << scn->m_figures.size() << ANSI_RESET_STYLE << (scn->m_figures.size() != 1 ? " figures." : " figure.") << endl;
|
||||
cout << " " << ANSI_BOLD_YELLOW << scn->m_lights.size() << ANSI_RESET_STYLE << " light " << (scn->m_lights.size() != 1 ? "sources." : "source.") << endl;
|
||||
cout << "Output image resolution is " << ANSI_BOLD_YELLOW << g_w << "x" << g_h << ANSI_RESET_STYLE << " pixels." << endl;
|
||||
cout << "Using " << ANSI_BOLD_YELLOW << g_samples << ANSI_RESET_STYLE << " samples per pixel." << endl;
|
||||
cout << "Maximum ray tree depth is " << ANSI_BOLD_YELLOW << g_max_depth << ANSI_RESET_STYLE << "." << endl;
|
||||
|
||||
// Create the tracer object.
|
||||
switch (g_tracer) {
|
||||
|
||||
// Basic recursive ray tracer.
|
||||
case WHITTED:
|
||||
cout << "Using " << ANSI_BOLD_YELLOW << "Whitted" << ANSI_RESET_STYLE << " ray tracing." << endl;
|
||||
tracer = static_cast<Tracer *>(new WhittedTracer(g_max_depth));
|
||||
break;
|
||||
|
||||
// Monte Carlo path tracer.
|
||||
case MONTE_CARLO:
|
||||
cout << "Using " << ANSI_BOLD_YELLOW << "Monte Carlo" << ANSI_RESET_STYLE << " path tracing." << endl;
|
||||
tracer = static_cast<Tracer *>(new PathTracer(g_max_depth));
|
||||
break;
|
||||
|
||||
// No tracer specified.
|
||||
default:
|
||||
cerr << "Must specify a ray tracer with \"-t\"." << endl;
|
||||
print_usage(argv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Generate the image.
|
||||
// First calculate the number of samples to compute.
|
||||
total = static_cast<uint64_t>(g_h) * static_cast<uint64_t>(g_w) * static_cast<uint64_t>(g_samples);
|
||||
cout << "Tracing a total of " << ANSI_BOLD_YELLOW << total << ANSI_RESET_STYLE << " primary rays:" << endl;
|
||||
|
||||
// Trace for every row of the image.
|
||||
for (int i = 0; i < g_h; i++) {
|
||||
// Trace for every column of the image.
|
||||
for (int j = 0; j < g_w; j++) {
|
||||
// Trace for every sample per pixel.
|
||||
for (int k = 0; k < g_samples; k++) {
|
||||
// Generate a pixel sample.
|
||||
sample = sample_pixel(i, j, g_w, g_h, g_a_ratio, g_fov);
|
||||
// Generate a primary ray.
|
||||
r = Ray(normalize(vec3(sample, -0.5f) - vec3(0.0f)), // The direction of the ray is towards the sample in the image plane.
|
||||
vec3(0.0f) // The origin of the ray is at the center of coordinates.
|
||||
);
|
||||
// Apply the inverse of the view matrix to take the primary ray from camera space to world space.
|
||||
scn->m_cam->view_to_world(r);
|
||||
// Trace the ray recursively.
|
||||
image[i][j] += tracer->trace_ray(r, scn, 0);
|
||||
// Add 1 to samples processed.
|
||||
current++;
|
||||
}
|
||||
// Average the samples for this pixel.
|
||||
image[i][j] /= g_samples;
|
||||
}
|
||||
cout << "\r" << ANSI_BOLD_YELLOW << current << ANSI_RESET_STYLE << " of " << ANSI_BOLD_YELLOW << total << ANSI_RESET_STYLE << " primary rays traced.";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
// Copy the pixels to the output bitmap.
|
||||
cout << "Saving output image." << endl;
|
||||
if (g_tracer == MONTE_CARLO) {
|
||||
// Allocate an HDR image.
|
||||
input_bitmap = FreeImage_AllocateT(FIT_RGBF, g_w, g_h, 96);
|
||||
|
||||
// Get image stride and pixels.
|
||||
pitch = FreeImage_GetPitch(input_bitmap);
|
||||
bits = (BYTE *)FreeImage_GetBits(input_bitmap);
|
||||
|
||||
// Fill every pixel of the temporary image with the traced image's.
|
||||
for (unsigned int y = 0; y < FreeImage_GetHeight(input_bitmap); y++) {
|
||||
pixel = (FIRGBF *)bits;
|
||||
for (unsigned int x = 0; x < FreeImage_GetWidth(input_bitmap); x++) {
|
||||
pixel[x].red = image[g_h - 1 - y][x].r;
|
||||
pixel[x].green = image[g_h - 1 - y][x].g;
|
||||
pixel[x].blue = image[g_h - 1 - y][x].b;
|
||||
}
|
||||
bits += pitch;
|
||||
}
|
||||
|
||||
// If the tracer is the monte carlo path tracer, apply a tone mapping operator to reduce image range.
|
||||
output_bitmap = FreeImage_ToneMapping(input_bitmap, FITMO_DRAGO03, g_gamma, g_exposure);
|
||||
|
||||
// Save the output image.
|
||||
fif = FreeImage_GetFIFFromFilename(g_out_file_name != NULL ? g_out_file_name : OUT_FILE);
|
||||
FreeImage_Save(fif, output_bitmap, g_out_file_name != NULL ? g_out_file_name : OUT_FILE);
|
||||
|
||||
// Release the bitmaps.
|
||||
FreeImage_Unload(input_bitmap);
|
||||
FreeImage_Unload(output_bitmap);
|
||||
|
||||
} else {
|
||||
// Allocate an RGB image.
|
||||
input_bitmap = FreeImage_Allocate(g_w, g_h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
|
||||
|
||||
// Get image stride and pixels.
|
||||
pitch = FreeImage_GetLine(input_bitmap) / FreeImage_GetWidth(input_bitmap);
|
||||
bits = (BYTE *)FreeImage_GetBits(input_bitmap);
|
||||
|
||||
// Fill every pixel of the temporary image with the traced image's.
|
||||
for (unsigned int y = 0; y < FreeImage_GetHeight(input_bitmap); y++) {
|
||||
bits = FreeImage_GetScanLine(input_bitmap, y);
|
||||
for (unsigned int x = 0; x < FreeImage_GetWidth(input_bitmap); x++) {
|
||||
bits[FI_RGBA_RED] = static_cast<BYTE>(image[g_h - 1 - y][x].r * 255.0f);
|
||||
bits[FI_RGBA_GREEN] = static_cast<BYTE>(image[g_h - 1 - y][x].g * 255.0f);
|
||||
bits[FI_RGBA_BLUE] = static_cast<BYTE>(image[g_h - 1 - y][x].b * 255.0f);
|
||||
bits += pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply gamma correction.
|
||||
FreeImage_AdjustGamma(input_bitmap, g_gamma);
|
||||
|
||||
// Save the output image.
|
||||
fif = FreeImage_GetFIFFromFilename(g_out_file_name != NULL ? g_out_file_name : OUT_FILE);
|
||||
FreeImage_Save(fif, input_bitmap, g_out_file_name != NULL ? g_out_file_name : OUT_FILE);
|
||||
|
||||
// Release the bitmaps.
|
||||
FreeImage_Unload(input_bitmap);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
if (g_out_file_name != NULL)
|
||||
free(g_out_file_name);
|
||||
|
||||
delete scn;
|
||||
delete tracer;
|
||||
|
||||
// Close FreeImage.
|
||||
FreeImage_DeInitialise();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Helper functions.
|
||||
////////////////////////////////////////////
|
||||
void print_usage(char ** const argv) {
|
||||
cerr << "USAGE: " << argv[0] << " [OPTIONS]... FILE" << endl;
|
||||
cerr << "Renders the scene specified by the scene file FILE." << endl << endl;
|
||||
cerr << "Mandatory options: " << endl;
|
||||
cerr << " -t\tRay tracing method to use. Valid values: " << endl;
|
||||
cerr << " \t" << ANSI_BOLD_YELLOW << "whitted" << ANSI_RESET_STYLE << " Classic Whitted ray tracing." << endl;
|
||||
cerr << " \t" << ANSI_BOLD_YELLOW << "monte_carlo" << ANSI_RESET_STYLE << " Monte Carlo path tracing." << endl;
|
||||
cerr << "Extra options:" << endl;
|
||||
cerr << " -o\tOutput image file name with extension." << endl;
|
||||
cerr << " \tDefaults to \"output.png\"." << endl;
|
||||
cerr << " -f\tField of view to use in degrees." << endl;
|
||||
cerr << " \tDefaults to 45.0 degrees." << endl;
|
||||
cerr << " -s\tNumber of samples per pixel." << endl;
|
||||
cerr << " \tDefaults to 25 samples." << endl;
|
||||
cerr << " -w\tImage size in pixels as \"WIDTHxHEIGHT\"." << endl;
|
||||
cerr << " \tDefaults to 640x480 pixels." << endl;
|
||||
cerr << " \tMinimum resolution is 1x1 pixels." << endl;
|
||||
cerr << " \tMaxmimum resolution is " << MAX_W << "x" << MAX_H << " pixels." << endl;
|
||||
cerr << " -r\tMaxmimum recursion depth." << endl;
|
||||
cerr << " \tDefaults to 5." << endl;
|
||||
cerr << " -g\tGamma correction value (>= 0)." << endl;
|
||||
cerr << " \tDefaults to 2.2" << endl;
|
||||
cerr << " -e\tExposure scale factor (in [-8, 8])." << endl;
|
||||
cerr << " \tDefaults to 0.0 (no correction)." << endl;
|
||||
}
|
||||
|
||||
void parse_args(int argc, char ** const argv) {
|
||||
int opt;
|
||||
int x_pos;
|
||||
|
||||
// Check command line arguments.
|
||||
if(argc == 1) {
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while((opt = getopt(argc, argv, "-:t:s:w:f:o:r:g:e:p:h:k:c:l:m:z:")) != -1) {
|
||||
switch (opt) {
|
||||
case 1:
|
||||
g_input_file = (char *)malloc((strlen(optarg) + 1) * sizeof(char));
|
||||
strcpy(g_input_file, optarg);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
g_gamma = atof(optarg);
|
||||
g_gamma = g_gamma < 0.0f ? 0.0f : g_gamma;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
g_exposure = atof(optarg);
|
||||
g_exposure = clamp(g_exposure, -8.0f, 8.0f);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (strcmp("whitted", optarg) == 0 )
|
||||
g_tracer = WHITTED;
|
||||
else if(strcmp("monte_carlo", optarg) == 0 || strcmp("montecarlo", optarg) == 0)
|
||||
g_tracer = MONTE_CARLO;
|
||||
else {
|
||||
cerr << "Invalid ray tracer: " << optarg << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
for (x_pos = 0; optarg[x_pos]; x_pos++)
|
||||
if (optarg[x_pos] == 'x')
|
||||
break;
|
||||
|
||||
if (optarg[x_pos] == '\0') {
|
||||
cerr << "Invalid screen resolution: " << optarg << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
optarg[x_pos] = '\0';
|
||||
g_w = atoi(optarg);
|
||||
g_h = atoi(&optarg[x_pos + 1]);
|
||||
if (g_w <= 0 || g_h <= 0 || g_w >= MAX_W || g_h >= MAX_H) {
|
||||
cerr << "Invalid screen resolution: " << optarg << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_a_ratio = static_cast<float>(g_w) / static_cast<float>(g_h);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 's':
|
||||
g_samples = atoi(optarg);
|
||||
if (g_samples <= 0) {
|
||||
cerr << "Samples per pixel must be a positive integer." << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
g_out_file_name = (char*)malloc((strlen(optarg) + 1) * sizeof(char));
|
||||
strcpy(g_out_file_name, optarg);
|
||||
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
g_fov = atof(optarg);
|
||||
if (g_fov < 1.0f) {
|
||||
cerr << "FoV must be greater than or equal to 1.0 degrees." << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
g_max_depth = static_cast<unsigned int>(abs(atoi(optarg)));
|
||||
if (g_max_depth == 0) {
|
||||
cerr << "Recursion depth must be a positive integer." << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ':':
|
||||
cerr << "Option \"-" << static_cast<char>(optopt) << "\" requires an argument." << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
cerr << "Unrecognized option: \"-" << static_cast<char>(optopt) << "\"." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_input_file == NULL) {
|
||||
cerr << "Must specify an input file." << endl;
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
56
EVI - 2017/EVI 21/EVIray/material.hpp
Normal file
56
EVI - 2017/EVI 21/EVIray/material.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#ifndef MATERIAL_HPP
|
||||
#define MATERIAL_HPP
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "brdf.hpp"
|
||||
#include "phong_brdf.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Material {
|
||||
public:
|
||||
vec3 m_emission; // Light emission color.
|
||||
vec3 m_diffuse; // Diffuse color.
|
||||
vec3 m_specular; // Specular reflection color.
|
||||
float m_rho; // Reflection coefficient.
|
||||
float m_shininess; // Shininess.
|
||||
float m_ref_index; // Refraction index.
|
||||
bool m_refract; // Refraction enabled.
|
||||
BRDF * m_brdf; // BRDF.
|
||||
|
||||
/**
|
||||
* Default material constructor.
|
||||
*/
|
||||
Material(BRDF * _brdf = NULL):
|
||||
m_emission(vec3(0.0f)),
|
||||
m_diffuse(vec3(1.0f)),
|
||||
m_specular(vec3(1.0f)),
|
||||
m_rho(0.0f),
|
||||
m_shininess(89.0f),
|
||||
m_ref_index(1.0f),
|
||||
m_refract(false)
|
||||
{
|
||||
m_brdf = _brdf != NULL ? _brdf : static_cast<BRDF *>(new PhongBRDF());
|
||||
}
|
||||
|
||||
~Material() {
|
||||
delete m_brdf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
Material(const Material & m) {
|
||||
m_diffuse = m.m_diffuse;
|
||||
m_specular = m.m_specular;
|
||||
m_rho = m.m_rho;
|
||||
m_shininess = m.m_shininess;
|
||||
m_ref_index = m.m_ref_index;
|
||||
m_refract = m.m_refract;
|
||||
m_brdf = m.m_brdf;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
BIN
EVI - 2017/EVI 21/EVIray/output.png
Normal file
BIN
EVI - 2017/EVI 21/EVIray/output.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 182 KiB |
159
EVI - 2017/EVI 21/EVIray/path_tracer.cpp
Normal file
159
EVI - 2017/EVI 21/EVIray/path_tracer.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#include <limits>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "path_tracer.hpp"
|
||||
#include "sampling.hpp"
|
||||
#include "area_light.hpp"
|
||||
|
||||
using std::numeric_limits;
|
||||
using namespace glm;
|
||||
|
||||
PathTracer::~PathTracer() { }
|
||||
|
||||
vec3 PathTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const {
|
||||
float t, _t;
|
||||
Figure * _f;
|
||||
vec3 n, color, i_pos, ref, sample, dir_diff_color, dir_spec_color, ind_color, amb_color;
|
||||
Ray mv_r, sr, rr;
|
||||
bool vis, is_area_light = false;
|
||||
float kr, r1, r2;
|
||||
AreaLight * al;
|
||||
|
||||
t = numeric_limits<float>::max();
|
||||
_f = NULL;
|
||||
|
||||
// Find the closest intersecting surface.
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
if (s->m_figures[f]->intersect(r, _t) && _t < t) {
|
||||
t = _t;
|
||||
_f = s->m_figures[f];
|
||||
}
|
||||
}
|
||||
|
||||
// If this ray intersects something:
|
||||
if (_f != NULL) {
|
||||
// Take the intersection point and the normal of the surface at that point.
|
||||
i_pos = r.m_origin + (t * r.m_direction);
|
||||
n = _f->normal_at_int(r, t);
|
||||
|
||||
is_area_light = false;
|
||||
// Check if the object is an area light;
|
||||
for (vector<Light *>::iterator it = s->m_lights.begin(); it != s->m_lights.end(); it++) {
|
||||
if ((*it)->light_type() == Light::AREA && static_cast<AreaLight *>(*it)->m_figure == _f)
|
||||
is_area_light = true;
|
||||
}
|
||||
|
||||
// If the object is an area light, return it's emission value.
|
||||
if (is_area_light) {
|
||||
return _f->m_mat->m_emission;
|
||||
|
||||
// Check if the material is not reflective/refractive.
|
||||
} else if (!_f->m_mat->m_refract) {
|
||||
// Calculate the direct lighting.
|
||||
for (size_t l = 0; l < s->m_lights.size(); l++) {
|
||||
// For every light source
|
||||
vis = true;
|
||||
|
||||
if (s->m_lights[l]->light_type() == Light::INFINITESIMAL) {
|
||||
// Cast a shadow ray to determine visibility.
|
||||
sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + (n * BIAS));
|
||||
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) {
|
||||
vis = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the shading model accounting for visibility.
|
||||
dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
|
||||
} else if (s->m_lights[l]->light_type() == Light::AREA) {
|
||||
// Cast a shadow ray towards a sample point on the surface of the light source.
|
||||
al = static_cast<AreaLight *>(s->m_lights[l]);
|
||||
al->sample_at_surface();
|
||||
sr = Ray(al->direction(i_pos), i_pos + (n * BIAS));
|
||||
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
// Avoid self-intersection with the light source.
|
||||
if (al->m_figure != s->m_figures[f]) {
|
||||
if (s->m_figures[f]->intersect(sr, _t) && _t < al->distance(i_pos)) {
|
||||
vis = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the shading model accounting for visibility.
|
||||
dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate indirect lighting contribution.
|
||||
if (rec_level < m_max_depth) {
|
||||
r1 = random01();
|
||||
r2 = random01();
|
||||
sample = sample_hemisphere(r1, r2);
|
||||
rotate_sample(sample, n);
|
||||
rr = Ray(normalize(sample), i_pos + (sample * BIAS));
|
||||
ind_color += r1 * trace_ray(rr, s, rec_level + 1) / PDF;
|
||||
}
|
||||
|
||||
// Calculate environment light contribution
|
||||
vis = true;
|
||||
|
||||
r1 = random01();
|
||||
r2 = random01();
|
||||
sample = sample_hemisphere(r1, r2);
|
||||
rotate_sample(sample, n);
|
||||
rr = Ray(normalize(sample), i_pos + (sample * BIAS));
|
||||
|
||||
// Cast a shadow ray to determine visibility.
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
if (s->m_figures[f]->intersect(rr, _t)) {
|
||||
vis = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
amb_color = vis ? s->m_env->get_color(rr) * max(dot(n, rr.m_direction), 0.0f) / PDF : vec3(0.0f);
|
||||
|
||||
// Add lighting.
|
||||
color += ((dir_diff_color + ind_color + amb_color) * (_f->m_mat->m_diffuse / pi<float>())) + (_f->m_mat->m_specular * dir_spec_color);
|
||||
|
||||
// Determine the specular reflection color.
|
||||
if (_f->m_mat->m_rho > 0.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
|
||||
color += _f->m_mat->m_rho * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (_f->m_mat->m_rho > 0.0f && rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
} else {
|
||||
// If the material has transmission enabled, calculate the Fresnel term.
|
||||
kr = fresnel(r.m_direction, n, r.m_ref_index, _f->m_mat->m_ref_index);
|
||||
|
||||
// Determine the specular reflection color.
|
||||
if (kr > 0.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
|
||||
color += kr * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
// Determine the transmission color.
|
||||
if (_f->m_mat->m_refract && kr < 1.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat->m_ref_index)), i_pos - n * BIAS, _f->m_mat->m_ref_index);
|
||||
color += (1.0f - kr) * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
}
|
||||
|
||||
// Return final color.
|
||||
return _f->m_mat->m_emission + color;
|
||||
|
||||
} else
|
||||
return s->m_env->get_color(r);
|
||||
}
|
18
EVI - 2017/EVI 21/EVIray/path_tracer.hpp
Normal file
18
EVI - 2017/EVI 21/EVIray/path_tracer.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#ifndef PATH_TRACER_HPP
|
||||
#define PATH_TRACER_HPP
|
||||
|
||||
#include "tracer.hpp"
|
||||
|
||||
class PathTracer: public Tracer {
|
||||
public:
|
||||
PathTracer(): Tracer() { }
|
||||
|
||||
PathTracer(unsigned int max_depth): Tracer(max_depth) { };
|
||||
|
||||
virtual ~PathTracer();
|
||||
|
||||
virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const;
|
||||
};
|
||||
|
||||
#endif
|
19
EVI - 2017/EVI 21/EVIray/phong_brdf.cpp
Normal file
19
EVI - 2017/EVI 21/EVIray/phong_brdf.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include "phong_brdf.hpp"
|
||||
|
||||
using glm::reflect;
|
||||
using glm::pow;
|
||||
using glm::max;
|
||||
using glm::dot;
|
||||
|
||||
vec3 PhongBRDF::diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_diff_color) const {
|
||||
float n_dot_l = max(dot(surface_normal, light_dir), 0.0f);
|
||||
return light_diff_color * n_dot_l;
|
||||
}
|
||||
|
||||
vec3 PhongBRDF::specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_spec_color, float shininess) const {
|
||||
vec3 ref = reflect(light_dir, surface_normal);
|
||||
float r_dot_l = pow(max(dot(ref, incident_ray.m_direction), 0.0f), shininess);
|
||||
return light_spec_color * r_dot_l;
|
||||
}
|
16
EVI - 2017/EVI 21/EVIray/phong_brdf.hpp
Normal file
16
EVI - 2017/EVI 21/EVIray/phong_brdf.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#ifndef PHONG_BRDF_HPP
|
||||
#define PHONG_BRDF_HPP
|
||||
|
||||
#include "brdf.hpp"
|
||||
|
||||
class PhongBRDF: public BRDF {
|
||||
public:
|
||||
PhongBRDF() { }
|
||||
virtual ~PhongBRDF() { }
|
||||
|
||||
virtual vec3 diffuse(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_diff_color) const;
|
||||
virtual vec3 specular(vec3 light_dir, vec3 surface_normal, Ray & incident_ray, vec3 intersection_point, vec3 light_spec_color, float shininess) const;
|
||||
};
|
||||
|
||||
#endif
|
29
EVI - 2017/EVI 21/EVIray/plane.cpp
Normal file
29
EVI - 2017/EVI 21/EVIray/plane.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "plane.hpp"
|
||||
|
||||
#define TOL 1e-6
|
||||
|
||||
using glm::abs;
|
||||
using glm::dot;
|
||||
|
||||
bool Plane::intersect(Ray & r, float & t) const {
|
||||
float d = dot(r.m_direction, m_normal);
|
||||
|
||||
if (abs(d) > TOL) {
|
||||
t = dot(m_normal, (m_point - r.m_origin)) / d;
|
||||
return t >= 0.0f;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vec3 Plane::normal_at_int(Ray & r, float & t) const {
|
||||
return vec3(m_normal);
|
||||
}
|
||||
|
||||
vec3 Plane::sample_at_surface() const {
|
||||
return vec3(0.0f);
|
||||
}
|
||||
|
||||
void Plane::calculate_inv_area() {
|
||||
m_inv_area = 0.0f;
|
||||
}
|
42
EVI - 2017/EVI 21/EVIray/plane.hpp
Normal file
42
EVI - 2017/EVI 21/EVIray/plane.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#ifndef PLANE_HPP
|
||||
#define PLANE_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "figure.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
using glm::normalize;
|
||||
|
||||
class Plane : public Figure {
|
||||
public:
|
||||
vec3 m_point;
|
||||
vec3 m_normal;
|
||||
|
||||
Plane(Material * mat = NULL): Figure(mat), m_point(vec3(0.0f)), m_normal(vec3(0.0f, 0.0f, 1.0f)) {
|
||||
calculate_inv_area();
|
||||
}
|
||||
|
||||
Plane(float x, float y, float z, float nx, float ny, float nz, Material * mat = NULL):
|
||||
Figure(mat),
|
||||
m_point(vec3(x, y, z)),
|
||||
m_normal(normalize(vec3(nx, ny, nz)))
|
||||
{
|
||||
calculate_inv_area();
|
||||
}
|
||||
|
||||
Plane(vec3 _p, vec3 _n, Material * mat = NULL): Figure(mat), m_point(_p), m_normal(normalize(_n)) { }
|
||||
|
||||
virtual ~Plane() { }
|
||||
|
||||
virtual bool intersect(Ray & r, float & t) const;
|
||||
virtual vec3 normal_at_int(Ray & r, float & t) const;
|
||||
virtual vec3 sample_at_surface() const;
|
||||
|
||||
protected:
|
||||
virtual void calculate_inv_area();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
42
EVI - 2017/EVI 21/EVIray/point_light.cpp
Normal file
42
EVI - 2017/EVI 21/EVIray/point_light.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "point_light.hpp"
|
||||
|
||||
using glm::pi;
|
||||
using glm::reflect;
|
||||
using glm::length;
|
||||
using glm::normalize;
|
||||
using glm::dot;
|
||||
using glm::pow;
|
||||
using glm::max;
|
||||
|
||||
vec3 PointLight::direction(vec3 point) const {
|
||||
return normalize(m_position - point);
|
||||
}
|
||||
|
||||
float PointLight::distance(vec3 point) const {
|
||||
return length(m_position - point);
|
||||
}
|
||||
|
||||
vec3 PointLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = direction(i_pos);
|
||||
d = distance(i_pos);
|
||||
att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
|
||||
return att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_diffuse);
|
||||
}
|
||||
|
||||
vec3 PointLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = direction(i_pos);
|
||||
d = distance(i_pos);
|
||||
att = 1.0f / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
|
||||
return att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_specular, m.m_shininess);
|
||||
}
|
23
EVI - 2017/EVI 21/EVIray/point_light.hpp
Normal file
23
EVI - 2017/EVI 21/EVIray/point_light.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#ifndef POINT_LIGHT_HPP
|
||||
#define POINT_LIGHT_HPP
|
||||
|
||||
#include "light.hpp"
|
||||
|
||||
class PointLight: public InfinitesimalLight {
|
||||
public:
|
||||
float m_const_att;
|
||||
float m_lin_att;
|
||||
float m_quad_att;
|
||||
|
||||
PointLight(): InfinitesimalLight(), m_const_att(1.0f), m_lin_att(0.0f), m_quad_att(0.0f) { }
|
||||
|
||||
PointLight(vec3 _p, vec3 _d, vec3 _s, float _c, float _l, float _q): InfinitesimalLight(_p, _d, _s), m_const_att(_c), m_lin_att(_l), m_quad_att(_q) { }
|
||||
|
||||
virtual vec3 direction(vec3 point) const;
|
||||
virtual float distance(vec3 point) const;
|
||||
virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
};
|
||||
|
||||
#endif
|
22
EVI - 2017/EVI 21/EVIray/ray.hpp
Normal file
22
EVI - 2017/EVI 21/EVIray/ray.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#ifndef RAY_HPP
|
||||
#define RAY_HPP
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Ray {
|
||||
public:
|
||||
vec3 m_direction;
|
||||
vec3 m_origin;
|
||||
float m_ref_index;
|
||||
|
||||
Ray(): m_direction(vec3(0.0f, 0.0f, -1.0f)), m_origin(vec3(0.0f)), m_ref_index(1.0f) { }
|
||||
Ray(float dx, float dy, float dz, float ox, float oy, float oz, float _r = 1.0f): m_direction(vec3(dx, dy, dz)),
|
||||
m_origin(vec3(ox, oy, oz)),
|
||||
m_ref_index(_r) { }
|
||||
Ray(vec3 _d, vec3 _o, float _r = 1.0f): m_direction(_d), m_origin(_o), m_ref_index(_r) { }
|
||||
};
|
||||
|
||||
#endif
|
108
EVI - 2017/EVI 21/EVIray/sampling.cpp
Normal file
108
EVI - 2017/EVI 21/EVIray/sampling.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifdef USE_CPP11_RANDOM
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#endif
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "sampling.hpp"
|
||||
|
||||
#ifdef USE_CPP11_RANDOM
|
||||
using std::uniform_real_distribution;
|
||||
using std::mt19937;
|
||||
using std::bind;
|
||||
#endif
|
||||
using glm::mat3;
|
||||
using glm::abs;
|
||||
using glm::normalize;
|
||||
using glm::cross;
|
||||
using glm::radians;
|
||||
using glm::pi;
|
||||
|
||||
const float PDF = (1.0f / (2.0f * pi<float>()));
|
||||
|
||||
static bool seeded = false;
|
||||
|
||||
#ifdef USE_CPP11_RANDOM
|
||||
static uniform_real_distribution<float> dist(0, 1);
|
||||
static mt19937 engine;
|
||||
static auto generator = bind(dist, engine);
|
||||
#endif
|
||||
|
||||
float random01() {
|
||||
if (!seeded) {
|
||||
#ifdef USE_CPP11_RANDOM
|
||||
engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
#else
|
||||
srand(time(NULL));
|
||||
#endif
|
||||
seeded = true;
|
||||
}
|
||||
#ifdef USE_CPP11_RANDOM
|
||||
return generator();
|
||||
#else
|
||||
return static_cast<float>(rand()) / RAND_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2 sample_pixel(int i, int j, float w, float h, float a_ratio, float fov) {
|
||||
float pxNDC;
|
||||
float pyNDC;
|
||||
float pxS;
|
||||
float pyS;
|
||||
pyNDC = (static_cast<float>(i) + random01()) / h;
|
||||
pyS = (1.0f - (2.0f * pyNDC)) * glm::tan(radians(fov / 2.0f));
|
||||
pxNDC = (static_cast<float>(j) + random01()) / w;
|
||||
pxS = (2.0f * pxNDC) - 1.0f;
|
||||
pxS *= a_ratio * glm::tan(radians(fov / 2.0f));
|
||||
|
||||
return vec2(pxS, pyS);
|
||||
}
|
||||
|
||||
/* Sampling functions pretty much taken from scratchapixel.com */
|
||||
void create_coords_system(const vec3 &n, vec3 &nt, vec3 &nb) {
|
||||
if (abs(n.x) > abs(n.y))
|
||||
nt = normalize(vec3(n.z, 0.0f, -n.x));
|
||||
else
|
||||
nt = normalize(vec3(0.0f, -n.z, n.y));
|
||||
nb = normalize(cross(n, nt));
|
||||
}
|
||||
|
||||
vec3 sample_hemisphere(const float r1, float r2) {
|
||||
float sin_t = glm::sqrt(1.0f - (r1 * r1));
|
||||
float phi = 2 * pi<float>() * r2;
|
||||
float x = sin_t * glm::cos(phi);
|
||||
float z = sin_t * glm::sin(phi);
|
||||
return vec3(x, r1, z);
|
||||
}
|
||||
|
||||
void rotate_sample(vec3 & sample, const vec3 & n) {
|
||||
vec3 nt, nb;
|
||||
mat3 rot_m;
|
||||
|
||||
create_coords_system(n, nt, nb);
|
||||
sample = vec3(sample.x * nb.x + sample.y * n.x + sample.z * nt.x,
|
||||
sample.x * nb.y + sample.y * n.y + sample.z * nt.y,
|
||||
sample.x * nb.z + sample.y * n.z + sample.z * nt.z);
|
||||
}
|
||||
|
||||
vec3 sample_sphere(const vec3 center, const float radius) {
|
||||
float theta;
|
||||
float u, sqrt1muu, x, y, z;
|
||||
|
||||
// Sampling formula from Wolfram Mathworld:
|
||||
// http://mathworld.wolfram.com/SpherePointPicking.html
|
||||
theta = random01()* (2.0f * pi<float>());
|
||||
u = (random01() * 2.0f) - 1.0f;
|
||||
sqrt1muu = glm::sqrt(1.0f - (u * u));
|
||||
x = radius * sqrt1muu * cos(theta);
|
||||
y = radius * sqrt1muu * sin(theta);
|
||||
z = radius * u;
|
||||
|
||||
return vec3(vec3(x, y, z) + center);
|
||||
}
|
20
EVI - 2017/EVI 21/EVIray/sampling.hpp
Normal file
20
EVI - 2017/EVI 21/EVIray/sampling.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#ifndef SAMPLING_HPP
|
||||
#define SAMPLING_HPP
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
|
||||
extern const float PDF;
|
||||
|
||||
extern float random01();
|
||||
extern vec2 sample_pixel(int i, int j, float w, float h, float a_ratio, float fov);
|
||||
extern void create_coords_system(const vec3 &n, vec3 &nt, vec3 &nb);
|
||||
extern vec3 sample_hemisphere(const float r1, float r2);
|
||||
extern void rotate_sample(vec3 & sample, const vec3 & n);
|
||||
extern vec3 sample_sphere(const vec3 center, const float radius);
|
||||
|
||||
#endif
|
442
EVI - 2017/EVI 21/EVIray/scene.cpp
Normal file
442
EVI - 2017/EVI 21/EVIray/scene.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <json_spirit_reader.h>
|
||||
|
||||
#include "scene.hpp"
|
||||
#include "brdf.hpp"
|
||||
#include "phong_brdf.hpp"
|
||||
#include "sphere.hpp"
|
||||
#include "plane.hpp"
|
||||
#include "directional_light.hpp"
|
||||
#include "point_light.hpp"
|
||||
#include "spot_light.hpp"
|
||||
#include "sphere_area_light.hpp"
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::ostringstream;
|
||||
using std::ifstream;
|
||||
using std::ios;
|
||||
using std::streamsize;
|
||||
using glm::vec3;
|
||||
using glm::normalize;
|
||||
using glm::cross;
|
||||
using json_spirit::read;
|
||||
using json_spirit::Error_position;
|
||||
using json_spirit::Object;
|
||||
using json_spirit::Array;
|
||||
|
||||
static const string ENV_KEY = "environment";
|
||||
static const string CAM_KEY = "camera";
|
||||
static const string SPH_KEY = "sphere";
|
||||
static const string PLN_KEY = "plane";
|
||||
static const string MSH_KEY = "mesh";
|
||||
static const string DLT_KEY = "directional_light";
|
||||
static const string PLT_KEY = "point_light";
|
||||
static const string SLT_KEY = "spot_light";
|
||||
static const string SAL_KEY = "sphere_area_light";
|
||||
static const string PAL_KEY = "planar_area_light";
|
||||
|
||||
static const string ENV_COL_KEY = "color";
|
||||
|
||||
static const string CAM_EYE_KEY = "eye";
|
||||
static const string CAM_CNT_KEY = "look";
|
||||
static const string CAM_LFT_KEY = "left";
|
||||
static const string CAM_UPV_KEY = "up";
|
||||
static const string CAM_RLL_KEY = "roll";
|
||||
static const string CAM_PTC_KEY = "pitch";
|
||||
static const string CAM_YAW_KEY = "yaw";
|
||||
|
||||
static const string FIG_POS_KEY = "position";
|
||||
static const string FIG_MAT_KEY = "material";
|
||||
static const string FIG_RAD_KEY = "radius";
|
||||
static const string FIG_NOR_KEY = "normal";
|
||||
|
||||
static const string PLN_PNT_KEY = "point";
|
||||
|
||||
static const string MLT_EMS_KEY = "emission";
|
||||
static const string MLT_DIF_KEY = "diffuse";
|
||||
static const string MLT_SPC_KEY = "specular";
|
||||
static const string MLT_RHO_KEY = "rho";
|
||||
static const string MLT_SHN_KEY = "shininess";
|
||||
static const string MLT_RFI_KEY = "ref_index";
|
||||
static const string MLT_BRF_KEY = "transmissive";
|
||||
static const string MLT_BRD_KEY = "brdf";
|
||||
|
||||
static const string BRD_PHN_KEY = "phong";
|
||||
|
||||
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) {
|
||||
ostringstream oss;
|
||||
ifstream ifs(file_name, ios::in);
|
||||
Value val;
|
||||
Object top_level;
|
||||
|
||||
m_cam = NULL;
|
||||
m_env = NULL;
|
||||
|
||||
if (ifs.is_open()) {
|
||||
try {
|
||||
read_or_throw(ifs, val);
|
||||
} catch (Error_position & e) {
|
||||
ifs.close();
|
||||
oss << "Failed to parse the input file: " << endl << "Reason: " << e.reason_ << endl << "Line: " << e.line_ << endl << "Column: " << e.column_;
|
||||
throw SceneError(oss.str());
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
|
||||
top_level = val.get_value<Object>();
|
||||
|
||||
try {
|
||||
for (Object::iterator it = top_level.begin(); it != top_level.end(); it++) {
|
||||
if ((*it).name_ == ENV_KEY)
|
||||
read_environment((*it).value_);
|
||||
|
||||
else if ((*it).name_ == CAM_KEY)
|
||||
read_camera((*it).value_);
|
||||
|
||||
else if ((*it).name_ == SPH_KEY)
|
||||
m_figures.push_back(read_sphere((*it).value_));
|
||||
|
||||
else if ((*it).name_ == PLN_KEY)
|
||||
m_figures.push_back(read_plane((*it).value_));
|
||||
|
||||
else if ((*it).name_ == DLT_KEY)
|
||||
m_lights.push_back(read_light((*it).value_, DIRECTIONAL));
|
||||
|
||||
else if ((*it).name_ == PLT_KEY)
|
||||
m_lights.push_back(read_light((*it).value_, POINT));
|
||||
|
||||
else if ((*it).name_ == SLT_KEY)
|
||||
m_lights.push_back(read_light((*it).value_, SPOT));
|
||||
|
||||
else if((*it).name_ == SAL_KEY)
|
||||
m_lights.push_back(read_area_light((*it).value_, SPHERE));
|
||||
|
||||
else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in the input file." << endl;
|
||||
}
|
||||
} catch (SceneError & e) {
|
||||
throw e;
|
||||
} catch (runtime_error & r) {
|
||||
throw SceneError("Type error in input file.");
|
||||
}
|
||||
|
||||
// If there were no camera and/or environment defined, create some default ones.
|
||||
if (m_cam == NULL)
|
||||
m_cam = new Camera();
|
||||
if (m_env == NULL)
|
||||
m_env = new Environment();
|
||||
|
||||
} else
|
||||
throw SceneError("Could not open the input file.");
|
||||
}
|
||||
|
||||
Scene::~Scene() {
|
||||
delete m_env;
|
||||
delete m_cam;
|
||||
|
||||
for (size_t i = 0; i < m_figures.size(); i++) {
|
||||
delete m_figures[i];
|
||||
}
|
||||
m_figures.clear();
|
||||
|
||||
for (size_t i = 0; i < m_lights.size(); i++) {
|
||||
delete m_lights[i];
|
||||
}
|
||||
m_lights.clear();
|
||||
}
|
||||
|
||||
void Scene::read_vector(Value & val, vec3 & vec) {
|
||||
Array a = val.get_value<Array>();
|
||||
|
||||
if (a.size() < 3)
|
||||
throw SceneError("Vector value must have 3 elements.");
|
||||
|
||||
vec = vec3(a[0].get_value<double>(), a[1].get_value<double>(), a[2].get_value<double>());
|
||||
}
|
||||
|
||||
void Scene::read_environment(Value & v) {
|
||||
string t_name = "";
|
||||
bool has_color = false;
|
||||
vec3 color = vec3(1.0f);
|
||||
Object env_obj = v.get_value<Object>();
|
||||
|
||||
for (Object::iterator it = env_obj.begin(); it != env_obj.end(); it++) {
|
||||
if ((*it).name_ == ENV_COL_KEY) {
|
||||
try {
|
||||
read_vector((*it).value_, color);
|
||||
} catch (SceneError & e) {
|
||||
throw e;
|
||||
}
|
||||
has_color = true;
|
||||
}
|
||||
|
||||
else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in environment." << endl;
|
||||
}
|
||||
|
||||
if (!has_color)
|
||||
throw SceneError("Environment must specify a color.");
|
||||
|
||||
m_env = new Environment(color);
|
||||
}
|
||||
|
||||
void Scene::read_camera(Value & v) {
|
||||
bool has_up = false, has_left = false, has_eye = false, has_look = false;
|
||||
vec3 eye, look, left, up, translation;
|
||||
float pitch = 0.0f, yaw = 0.0f, roll = 0.0f;
|
||||
Object cam_obj = v.get_value<Object>();
|
||||
|
||||
for (Object::iterator it = cam_obj.begin(); it != cam_obj.end(); it++) {
|
||||
if ((*it).name_ == CAM_EYE_KEY) {
|
||||
read_vector((*it).value_, eye);
|
||||
has_eye = true;
|
||||
|
||||
} else if ((*it).name_ == CAM_CNT_KEY) {
|
||||
read_vector((*it).value_, look);
|
||||
has_look = true;
|
||||
|
||||
} else if ((*it).name_ == CAM_LFT_KEY) {
|
||||
read_vector((*it).value_, left);
|
||||
has_left = true;
|
||||
|
||||
} else if ((*it).name_ == CAM_UPV_KEY) {
|
||||
read_vector((*it).value_, up);
|
||||
has_up = true;
|
||||
|
||||
} else if ((*it).name_ == GEO_TRN_KEY)
|
||||
read_vector((*it).value_, translation);
|
||||
|
||||
else if ((*it).name_ == CAM_RLL_KEY)
|
||||
roll = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == CAM_PTC_KEY)
|
||||
pitch = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == CAM_YAW_KEY)
|
||||
yaw = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in camera." << endl;
|
||||
}
|
||||
|
||||
if (!has_eye || !has_look)
|
||||
throw SceneError("Must specify an eye and look positions for the camera.");
|
||||
|
||||
if (has_up)
|
||||
m_cam = new Camera(eye, look, up);
|
||||
else if(!has_up && has_left) {
|
||||
up = cross(normalize(look - eye), left);
|
||||
m_cam = new Camera(eye, look, up);
|
||||
} else
|
||||
throw SceneError("Must specify either an up or left vector for the camera.");
|
||||
|
||||
m_cam->pitch(pitch);
|
||||
m_cam->yaw(yaw);
|
||||
m_cam->roll(roll);
|
||||
m_cam->translate(translation);
|
||||
}
|
||||
|
||||
Material * Scene::read_material(Value & v) {
|
||||
vec3 emission = vec3(0.0f), diffuse = vec3(1.0f), specular = vec3(1.0f);
|
||||
bool transmissive = false;
|
||||
float rho = 0.0f, ref_index = 1.0f, shininess = 89.0f;
|
||||
Material * mat = NULL;
|
||||
Object mat_obj = v.get_value<Object>();
|
||||
|
||||
for (Object::iterator it = mat_obj.begin(); it != mat_obj.end(); it++) {
|
||||
if ((*it).name_ == MLT_EMS_KEY) {
|
||||
read_vector((*it).value_, emission);
|
||||
|
||||
} 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_ == MLT_RHO_KEY) {
|
||||
rho = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
} else if ((*it).name_ == MLT_SHN_KEY) {
|
||||
shininess = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
} else if ((*it).name_ == MLT_RFI_KEY) {
|
||||
ref_index = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
} else if ((*it).name_ == MLT_BRF_KEY) {
|
||||
transmissive = (*it).value_.get_value<bool>();
|
||||
|
||||
} else if ((*it).name_ == MLT_BRD_KEY) {
|
||||
if ((*it).value_.get_value<string>() == BRD_PHN_KEY)
|
||||
mat = new Material(new PhongBRDF());
|
||||
else
|
||||
throw SceneError("Unrecognized BRDF in material.");
|
||||
|
||||
} else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in material." << endl;
|
||||
}
|
||||
|
||||
if (mat == NULL)
|
||||
mat = new Material();
|
||||
mat->m_emission = emission;
|
||||
mat->m_diffuse = diffuse;
|
||||
mat->m_specular = specular;
|
||||
mat->m_rho = rho;
|
||||
mat->m_ref_index = ref_index;
|
||||
mat->m_shininess = shininess;
|
||||
mat->m_refract = transmissive;
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
Figure * Scene::read_sphere(Value &v) {
|
||||
bool has_position = false, has_radius = false;
|
||||
vec3 position;
|
||||
float radius = 1.0f;
|
||||
Material * mat = NULL;
|
||||
Object sph_obj = v.get_value<Object>();
|
||||
|
||||
for (Object::iterator it = sph_obj.begin(); it != sph_obj.end(); it++) {
|
||||
if ((*it).name_ == FIG_POS_KEY) {
|
||||
read_vector((*it).value_, position);
|
||||
has_position = true;
|
||||
|
||||
} else if ((*it).name_ == FIG_MAT_KEY) {
|
||||
try {
|
||||
mat = read_material((*it).value_);
|
||||
} catch (SceneError & e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
} else if ((*it).name_ == FIG_RAD_KEY) {
|
||||
radius = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
if (radius <= 0.0f)
|
||||
throw SceneError("Sphere radius must be greater than 0.");
|
||||
|
||||
has_radius = true;
|
||||
|
||||
} else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in sphere." << endl;
|
||||
}
|
||||
|
||||
if (!has_position || !has_radius)
|
||||
throw SceneError("Sphere must specify a position and radius.");
|
||||
|
||||
return static_cast<Figure *>(new Sphere(position, radius, mat));
|
||||
}
|
||||
|
||||
Figure * Scene::read_plane(Value &v) {
|
||||
bool has_position = false, has_normal = false;
|
||||
vec3 position, normal = vec3(0.0f, 1.0f, 0.0f);
|
||||
Material * mat = NULL;
|
||||
Object pln_obj = v.get_value<Object>();
|
||||
|
||||
for (Object::iterator it = pln_obj.begin(); it != pln_obj.end(); it++) {
|
||||
if ((*it).name_ == FIG_POS_KEY || (*it).name_ == PLN_PNT_KEY) {
|
||||
read_vector((*it).value_, position);
|
||||
has_position = true;
|
||||
|
||||
} else if ((*it).name_ == FIG_MAT_KEY) {
|
||||
try {
|
||||
mat = read_material((*it).value_);
|
||||
} catch (SceneError & e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
} else if ((*it).name_ == FIG_NOR_KEY) {
|
||||
read_vector((*it).value_, normal);
|
||||
has_normal = true;
|
||||
|
||||
} else
|
||||
cerr << "Unrecognized key \"" << (*it).name_ << "\" in plane." << endl;
|
||||
}
|
||||
|
||||
if (!has_position || !has_normal)
|
||||
throw SceneError("Plane must specify a point and normal vector.");
|
||||
|
||||
return static_cast<Figure *>(new Plane(position, normal, mat));
|
||||
}
|
||||
|
||||
Light * Scene::read_light(Value & v, light_type_t t) {
|
||||
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<Object>();
|
||||
|
||||
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<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == LGT_LAT_KEY)
|
||||
lin_att = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == LGT_QAT_KEY)
|
||||
quad_att = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == LGT_SPC_KEY)
|
||||
spot_cutoff = static_cast<float>((*it).value_.get_value<double>());
|
||||
|
||||
else if ((*it).name_ == LGT_SPE_KEY)
|
||||
spot_exp = static_cast<float>((*it).value_.get_value<double>());
|
||||
}
|
||||
|
||||
if (t == DIRECTIONAL)
|
||||
return static_cast<Light *>(new DirectionalLight(position, diffuse, specular));
|
||||
else if (t == POINT)
|
||||
return static_cast<Light *>(new PointLight(position, diffuse, specular, const_att, lin_att, quad_att));
|
||||
else if (t == SPOT)
|
||||
return static_cast<Light *>(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;
|
||||
}
|
||||
|
||||
Light * Scene::read_area_light(Value & v, light_type_t t) {
|
||||
Sphere * s;
|
||||
SphereAreaLight * sal;
|
||||
Light * l;
|
||||
|
||||
if (t == SPHERE) {
|
||||
s = static_cast<Sphere *>(read_sphere(v));
|
||||
sal = new SphereAreaLight(s);
|
||||
m_figures.push_back(static_cast<Figure *>(s));
|
||||
l = static_cast<Light *>(sal);
|
||||
|
||||
} else
|
||||
throw SceneError("Unknown area light type");
|
||||
|
||||
return l;
|
||||
}
|
50
EVI - 2017/EVI 21/EVIray/scene.hpp
Normal file
50
EVI - 2017/EVI 21/EVIray/scene.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#ifndef SCENE_HPP
|
||||
#define SCENE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <json_spirit_value.h>
|
||||
|
||||
#include "camera.hpp"
|
||||
#include "figure.hpp"
|
||||
#include "light.hpp"
|
||||
#include "material.hpp"
|
||||
#include "environment.hpp"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::runtime_error;
|
||||
using json_spirit::Value;
|
||||
|
||||
class SceneError: public runtime_error {
|
||||
public:
|
||||
explicit SceneError(const string & what_arg): runtime_error(what_arg) { }
|
||||
};
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
typedef enum LIGHT_TYPE { DIRECTIONAL, POINT, SPOT, SPHERE, DISK, PLANE } light_type_t;
|
||||
|
||||
vector<Figure *> m_figures;
|
||||
vector<Light *> m_lights;
|
||||
Environment * m_env;
|
||||
Camera * m_cam;
|
||||
|
||||
Scene(const char * file_name, int h = 480, int w = 640, float fov = 90.0f);
|
||||
~Scene();
|
||||
|
||||
private:
|
||||
void read_vector(Value & val, vec3 & vec);
|
||||
void read_environment(Value & v);
|
||||
void read_camera(Value & v);
|
||||
Material * read_material(Value & v);
|
||||
Figure * read_sphere(Value & v);
|
||||
Figure * read_plane(Value & v);
|
||||
Light * read_light(Value & v, light_type_t t);
|
||||
Light * read_area_light(Value & v, light_type_t t);
|
||||
};
|
||||
|
||||
#endif
|
13
EVI - 2017/EVI 21/EVIray/scenes/furnace.json
Normal file
13
EVI - 2017/EVI 21/EVIray/scenes/furnace.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"environment": {
|
||||
"color": [1.0, 1.0, 1.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"radius": 1.0,
|
||||
"material": {
|
||||
"diffuse": [0.1, 0.1, 0.1]
|
||||
}
|
||||
}
|
||||
}
|
124
EVI - 2017/EVI 21/EVIray/scenes/scene1.json
Normal file
124
EVI - 2017/EVI 21/EVIray/scenes/scene1.json
Normal file
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"directional_light": {
|
||||
"direction": [1.0, 1.0, 1.0],
|
||||
"diffuse": [0.0, 1.0, 1.0]
|
||||
},
|
||||
|
||||
"directional_light": {
|
||||
"direction": [-1.0, 1.0, 1.0],
|
||||
"diffuse": [1.0, 1.0, 0.0]
|
||||
},
|
||||
|
||||
"directional_light": {
|
||||
"direction": [0.0, 1.0, -1.0],
|
||||
"diffuse": [1.0, 0.0, 1.0]
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [-0.0, -0.0, -0.5],
|
||||
"normal": [0.0, 0.0, 0.1],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"rho": 0.3,
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"point": [0.0, -1.5, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.5, 0.4]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.0, 1.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-1.0, 1.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.0, -1.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-1.0, -1.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"radius": 1.0,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-1.5, 0.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.3
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.5, 0.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.08,
|
||||
"transmissive": true,
|
||||
"ref_index": 1.1
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 1.5, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.5
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -1.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.1
|
||||
}
|
||||
},
|
||||
|
||||
"environment": {
|
||||
"color": [0.7, 0.4, 0.05]
|
||||
},
|
||||
|
||||
"camera": {
|
||||
"eye": [0.0, 0.0, 1.0],
|
||||
"look": [0.0, 0.0, -1.0],
|
||||
"up": [0.0, 1.0, 0.0]
|
||||
}
|
||||
}
|
98
EVI - 2017/EVI 21/EVIray/scenes/scene10.json
Normal file
98
EVI - 2017/EVI 21/EVIray/scenes/scene10.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"camera": {
|
||||
"eye": [0.0, 0.0, 1.0],
|
||||
"look": [0.0, 0.0, -1.0],
|
||||
"left": [-1.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"point_light": {
|
||||
"position": [0.0, 0.9, -1.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.4, -0.75, -0.65],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.75, -0.5, -1.5],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 0.0],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.0, -0.5, -1.1],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0],
|
||||
"transmissive": true
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [-2.0, 0.0, 0.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [2.0, 0.0, 0.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0],
|
||||
"transmissive": true,
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"normal": [0.0, -1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 1.0],
|
||||
"transmissive": true,
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"transmissive": true,
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, 1.1],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
127
EVI - 2017/EVI 21/EVIray/scenes/scene2.json
Normal file
127
EVI - 2017/EVI 21/EVIray/scenes/scene2.json
Normal file
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"point_light": {
|
||||
"position": [0.0, 0.9, -1.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.2, 0.0, -0.75],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.2
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.5, -0.5, -1.5],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 0.0],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.5, -0.5, 0.6],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [-0.25, 1.0, -1.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [0.25, 1.0, -1.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [0.0, 1.0, -1.25],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [0.0, 1.0, -0.75],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [-2.0, 0.0, 0.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [2.0, 0.0, 0.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"normal": [0.0, -1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, 1.1],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
52
EVI - 2017/EVI 21/EVIray/scenes/scene3.json
Normal file
52
EVI - 2017/EVI 21/EVIray/scenes/scene3.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"environment": {
|
||||
"texture": "textures/pisa.hdr",
|
||||
"light_probe": false
|
||||
},
|
||||
|
||||
"camera": {
|
||||
"eye": [0.0, 1.5, 1.0],
|
||||
"look": [0.0, 0.0, -2.0],
|
||||
"left": [-1.0, 0.0, 0.0],
|
||||
"translation": [1.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [2.0, 0.0, -2.0],
|
||||
"radius": 1.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"shininess": 128.0,
|
||||
"brdf": "heidrich-seidel"
|
||||
}
|
||||
},
|
||||
|
||||
"sphere":{
|
||||
"position": [-1.0, 0.0, -3.25],
|
||||
"radius": 1.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"sphere_area_light":{
|
||||
"position": [1.0, 0.0, -3.25],
|
||||
"radius": 1.5,
|
||||
"material": {
|
||||
"emission": [10.0, 10.0, 10.0],
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [1.0, -1.5, -3.25],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"radius": 3.0,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.5, 0.5],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
30
EVI - 2017/EVI 21/EVIray/scenes/scene4.json
Normal file
30
EVI - 2017/EVI 21/EVIray/scenes/scene4.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"environment": {
|
||||
"texture": "textures/pisa.hdr",
|
||||
"light_probe": false
|
||||
},
|
||||
|
||||
"camera": {
|
||||
"eye": [0.0, 1.0, 0.0],
|
||||
"look": [0.0, 0.0, -2.0],
|
||||
"up": [0.0, 1.0, 0.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"radius": 1.0,
|
||||
"material": {
|
||||
"diffuse": [0.5, 0.5, 0.5],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.5, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
42
EVI - 2017/EVI 21/EVIray/scenes/scene5.json
Normal file
42
EVI - 2017/EVI 21/EVIray/scenes/scene5.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"environment": {
|
||||
"color": [0.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere_area_light": {
|
||||
"position": [0.0, 1.4, -2.0],
|
||||
"radius": 0.05,
|
||||
"material": {
|
||||
"emission": [1.0, 1.0, 1.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.2],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
91
EVI - 2017/EVI 21/EVIray/scenes/scene6.json
Normal file
91
EVI - 2017/EVI 21/EVIray/scenes/scene6.json
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"sphere_area_light": {
|
||||
"position": [0.0, 1.0, -1.0],
|
||||
"radius": 0.15,
|
||||
"material": {
|
||||
"emission": [1.0, 1.0, 1.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [0.2, 0.0, -0.75],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.5, -0.5, -1.5],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 0.0],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.5, -0.5, 0.6],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [-2.0, 0.0, 0.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [2.0, 0.0, 0.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"normal": [0.0, -1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, 1.1],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
97
EVI - 2017/EVI 21/EVIray/scenes/scene7.json
Normal file
97
EVI - 2017/EVI 21/EVIray/scenes/scene7.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"camera": {
|
||||
"eye": [0.0, 0.0, 1.0],
|
||||
"look": [0.0, 0.0, -1.0],
|
||||
"left": [-1.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"sphere_area_light": {
|
||||
"position": [0.0, 0.7, -1.0],
|
||||
"radius": 0.15,
|
||||
"material": {
|
||||
"emission": [1.0, 1.0, 1.0]
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.4, -0.75, -0.65],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.75, -0.5, -1.5],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 0.0],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.0, -0.5, -1.1],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [-2.0, 0.0, 0.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [2.0, 0.0, 0.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"normal": [0.0, -1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, 1.1],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
39
EVI - 2017/EVI 21/EVIray/scenes/scene8.json
Normal file
39
EVI - 2017/EVI 21/EVIray/scenes/scene8.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"environment": {
|
||||
"color": [0.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"camera": {
|
||||
"eye": [2.0, 0.0, 0.0],
|
||||
"look": [-1.0, -0.5, 0.0],
|
||||
"left": [0.0, 0.0, 1.0],
|
||||
"translation": [1.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"sphere":{
|
||||
"position": [0.0, 0.0, 0.0],
|
||||
"radius": 1.0,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.25, 1.0],
|
||||
"rho": 0.2
|
||||
}
|
||||
},
|
||||
|
||||
"sphere_area_light":{
|
||||
"position": [0.0, 0.0, -15.0],
|
||||
"radius": 10.0,
|
||||
"material": {
|
||||
"emission": [10.0, 10.0, 10.0]
|
||||
}
|
||||
},
|
||||
|
||||
"disk": {
|
||||
"position": [0, -1.0, 0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"radius": 2.0,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
93
EVI - 2017/EVI 21/EVIray/scenes/scene9.json
Normal file
93
EVI - 2017/EVI 21/EVIray/scenes/scene9.json
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"camera": {
|
||||
"eye": [0.0, 0.0, 1.0],
|
||||
"look": [0.0, 0.0, -1.0],
|
||||
"left": [-1.0, 0.0, 0.0]
|
||||
},
|
||||
|
||||
"point_light": {
|
||||
"position": [0.0, 0.9, -1.0]
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.4, -0.75, -0.65],
|
||||
"radius": 0.25,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"rho": 0.4
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [-0.75, -0.5, -1.5],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 0.0],
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
|
||||
"sphere": {
|
||||
"position": [1.0, -0.5, -1.1],
|
||||
"radius": 0.5,
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"transmissive": true,
|
||||
"ref_index": 1.33
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, -1.0, 0.0],
|
||||
"normal": [0.0, 1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [-2.0, 0.0, 0.0],
|
||||
"normal": [1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [2.0, 0.0, 0.0],
|
||||
"normal": [-1.0, 0.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"normal": [0.0, -1.0, 0.0],
|
||||
"material": {
|
||||
"diffuse": [0.0, 1.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, -2.0],
|
||||
"normal": [0.0, 0.0, 1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 0.0, 1.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
},
|
||||
|
||||
"plane": {
|
||||
"position": [0.0, 0.0, 1.1],
|
||||
"normal": [0.0, 0.0, -1.0],
|
||||
"material": {
|
||||
"diffuse": [1.0, 1.0, 0.0],
|
||||
"specular": [0.0, 0.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
52
EVI - 2017/EVI 21/EVIray/sphere.cpp
Normal file
52
EVI - 2017/EVI 21/EVIray/sphere.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <iostream>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "sphere.hpp"
|
||||
#include "sampling.hpp"
|
||||
|
||||
using namespace glm;
|
||||
|
||||
bool Sphere::intersect(Ray & r, float & t) const {
|
||||
float t1, t2;
|
||||
float d;
|
||||
|
||||
float a = (r.m_direction.x * r.m_direction.x) +
|
||||
(r.m_direction.y * r.m_direction.y) +
|
||||
(r.m_direction.z * r.m_direction.z);
|
||||
|
||||
float b = (2 * r.m_direction.x * (r.m_origin.x - m_center.x)) +
|
||||
(2 * r.m_direction.y * (r.m_origin.y - m_center.y)) +
|
||||
(2 * r.m_direction.z * (r.m_origin.z - m_center.z));
|
||||
|
||||
float c = (m_center.x * m_center.x) +
|
||||
(m_center.y * m_center.y) +
|
||||
(m_center.z * m_center.z) +
|
||||
(r.m_origin.x * r.m_origin.x) +
|
||||
(r.m_origin.y * r.m_origin.y) +
|
||||
(r.m_origin.z * r.m_origin.z) -
|
||||
2 * ((m_center.x * r.m_origin.x) + (m_center.y * r.m_origin.y) + (m_center.z * r.m_origin.z)) - (m_radius * m_radius);
|
||||
|
||||
d = (b * b) - (4 * a * c);
|
||||
|
||||
if (d >= 0.0f) {
|
||||
t1 = (-b - sqrt(d)) / (2 * a);
|
||||
t2 = (-b + sqrt(d)) / (2 * a);
|
||||
t = t1 < t2 ? t1 : t2;
|
||||
return t >= 0.0f;
|
||||
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
vec3 Sphere::normal_at_int(Ray & r, float & t) const {
|
||||
vec3 i = vec3(r.m_origin + (t * r.m_direction));
|
||||
return normalize(vec3((i - m_center) / m_radius));
|
||||
}
|
||||
|
||||
vec3 Sphere::sample_at_surface() const {
|
||||
return sample_sphere(m_center, m_radius);
|
||||
}
|
||||
|
||||
void Sphere::calculate_inv_area() {
|
||||
m_inv_area = 1.0f / (4.0 * pi<float>() * (m_radius * m_radius));
|
||||
}
|
38
EVI - 2017/EVI 21/EVIray/sphere.hpp
Normal file
38
EVI - 2017/EVI 21/EVIray/sphere.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#ifndef SPHERE_HPP
|
||||
#define SPHERE_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "figure.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
|
||||
class Sphere : public Figure {
|
||||
public:
|
||||
vec3 m_center;
|
||||
float m_radius;
|
||||
|
||||
Sphere(Material * mat = NULL): Figure(mat), m_center(vec3(0.0f)), m_radius(0.5f) {
|
||||
calculate_inv_area();
|
||||
}
|
||||
|
||||
Sphere(float x, float y, float z, float r, Material * mat = NULL): Figure(mat), m_center(vec3(x, y, z)), m_radius(r) {
|
||||
calculate_inv_area();
|
||||
}
|
||||
|
||||
Sphere(vec3 _c, float r, Material * mat = NULL): Figure(mat), m_center(_c), m_radius(r) {
|
||||
calculate_inv_area();
|
||||
}
|
||||
|
||||
virtual ~Sphere() { }
|
||||
|
||||
virtual bool intersect(Ray & r, float & t) const;
|
||||
virtual vec3 normal_at_int(Ray & r, float & t) const;
|
||||
virtual vec3 sample_at_surface() const;
|
||||
|
||||
private:
|
||||
virtual void calculate_inv_area();
|
||||
};
|
||||
|
||||
#endif
|
8
EVI - 2017/EVI 21/EVIray/sphere_area_light.cpp
Normal file
8
EVI - 2017/EVI 21/EVIray/sphere_area_light.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "sphere_area_light.hpp"
|
||||
|
||||
vec3 SphereAreaLight::sample_at_surface() {
|
||||
Sphere * s = static_cast<Sphere *>(m_figure);
|
||||
m_last_sample = m_figure->sample_at_surface();
|
||||
m_n_at_last_sample = normalize(vec3((m_last_sample - s->m_center) / s->m_radius));
|
||||
return m_last_sample;
|
||||
}
|
15
EVI - 2017/EVI 21/EVIray/sphere_area_light.hpp
Normal file
15
EVI - 2017/EVI 21/EVIray/sphere_area_light.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#ifndef SPHERE_AREA_LIGHT_HPP
|
||||
#define SPHERE_AREA_LIGHT_HPP
|
||||
|
||||
#include "area_light.hpp"
|
||||
#include "sphere.hpp"
|
||||
|
||||
class SphereAreaLight: public AreaLight {
|
||||
public:
|
||||
SphereAreaLight(Sphere * _s, float _c = 1.0, float _l = 0.0, float _q = 0.0): AreaLight(static_cast<Figure *>(_s), _c, _l, _q) { }
|
||||
|
||||
virtual vec3 sample_at_surface();
|
||||
};
|
||||
|
||||
#endif
|
47
EVI - 2017/EVI 21/EVIray/spot_light.cpp
Normal file
47
EVI - 2017/EVI 21/EVIray/spot_light.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "spot_light.hpp"
|
||||
|
||||
using glm::pi;
|
||||
using glm::reflect;
|
||||
using glm::length;
|
||||
using glm::normalize;
|
||||
using glm::dot;
|
||||
using glm::pow;
|
||||
using glm::max;
|
||||
using glm::acos;
|
||||
using glm::radians;
|
||||
|
||||
vec3 SpotLight::diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att, spot_effect;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = direction(i_pos);
|
||||
d = distance(i_pos);
|
||||
spot_effect = dot(m_spot_dir, -l_dir);
|
||||
|
||||
if (acos(spot_effect) < radians(m_spot_cutoff)) {
|
||||
spot_effect = pow(spot_effect, m_spot_exponent);
|
||||
att = spot_effect / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
return att * m.m_brdf->diffuse(l_dir, normal, r, i_pos, m_diffuse);
|
||||
|
||||
} else
|
||||
return vec3(0.0f);
|
||||
}
|
||||
|
||||
vec3 SpotLight::specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const {
|
||||
float d, att, spot_effect;
|
||||
vec3 l_dir, ref;
|
||||
|
||||
l_dir = direction(i_pos);
|
||||
d = distance(i_pos);
|
||||
spot_effect = dot(m_spot_dir, -l_dir);
|
||||
|
||||
if (acos(spot_effect) < radians(m_spot_cutoff)) {
|
||||
spot_effect = pow(spot_effect, m_spot_exponent);
|
||||
att = spot_effect / (m_const_att + (m_lin_att * d) + (m_quad_att * (d * d)));
|
||||
return att * m.m_brdf->specular(l_dir, normal, r, i_pos, m_specular, m.m_shininess);
|
||||
} else
|
||||
return vec3(0.0f);
|
||||
}
|
39
EVI - 2017/EVI 21/EVIray/spot_light.hpp
Normal file
39
EVI - 2017/EVI 21/EVIray/spot_light.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#ifndef SPOT_LIGHT_HPP
|
||||
#define SPOT_LIGHT_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "point_light.hpp"
|
||||
|
||||
using glm::vec3;
|
||||
using glm::normalize;
|
||||
|
||||
class SpotLight: public PointLight {
|
||||
public:
|
||||
float m_spot_cutoff;
|
||||
float m_spot_exponent;
|
||||
vec3 m_spot_dir;
|
||||
|
||||
SpotLight(): PointLight(), m_spot_cutoff(45.0f), m_spot_exponent(0.0f), m_spot_dir(vec3(0.0f, -1.0f, 0.0f)) { }
|
||||
|
||||
SpotLight(vec3 _p,
|
||||
vec3 _d,
|
||||
vec3 _s,
|
||||
float _c,
|
||||
float _l,
|
||||
float _q,
|
||||
float _sco,
|
||||
float _se,
|
||||
vec3 _sd):
|
||||
PointLight(_p, _d, _s, _c, _l, _q),
|
||||
m_spot_cutoff(_sco),
|
||||
m_spot_exponent(_se),
|
||||
m_spot_dir(normalize(_sd))
|
||||
{ }
|
||||
|
||||
virtual vec3 diffuse(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
virtual vec3 specular(vec3 normal, Ray & r, vec3 i_pos, Material & m) const;
|
||||
};
|
||||
|
||||
#endif
|
26
EVI - 2017/EVI 21/EVIray/tracer.cpp
Normal file
26
EVI - 2017/EVI 21/EVIray/tracer.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "tracer.hpp"
|
||||
|
||||
using glm::dot;
|
||||
using glm::normalize;
|
||||
using glm::refract;
|
||||
|
||||
const float BIAS = 0.000001f;
|
||||
|
||||
const vec3 BCKG_COLOR = vec3(0.1f);
|
||||
|
||||
float Tracer::fresnel(const vec3 & i, const vec3 & n, const float ir1, const float ir2) const {
|
||||
float cos_t1 = dot(i, n);
|
||||
float cos_t2 = dot(normalize(refract(i, n, ir1 / ir2)), n);
|
||||
float cos_t2s = (cos_t2 * cos_t2);
|
||||
float omcos_t2s = 1.0f - cos_t2s;
|
||||
omcos_t2s = omcos_t2s < 0.0f ? 0.0f : omcos_t2s;
|
||||
float sin_t2 = (ir1 / ir2) * glm::sqrt(omcos_t2s);
|
||||
|
||||
if (sin_t2 >= 1.0f)
|
||||
return 1.0f;
|
||||
|
||||
float fr_par = ((ir2 * cos_t1) - (ir1 * cos_t2)) / ((ir2 * cos_t1) + (ir1 * cos_t2));
|
||||
float fr_per = ((ir1 * cos_t2) - (ir2 * cos_t1)) / ((ir1 * cos_t2) + (ir2 * cos_t1));
|
||||
|
||||
return ((fr_par * fr_par) + (fr_per * fr_per)) / 2.0f;
|
||||
}
|
45
EVI - 2017/EVI 21/EVIray/tracer.hpp
Normal file
45
EVI - 2017/EVI 21/EVIray/tracer.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#ifndef TRACER_HPP
|
||||
#define TRACER_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "ray.hpp"
|
||||
#include "scene.hpp"
|
||||
|
||||
using std::vector;
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
|
||||
// Intersection displacement bias.
|
||||
extern const float BIAS;
|
||||
|
||||
// Default background color.
|
||||
extern const vec3 BCKG_COLOR;
|
||||
|
||||
/**
|
||||
* Base class for ray tracers.
|
||||
*/
|
||||
class Tracer {
|
||||
public:
|
||||
unsigned int m_max_depth; // Max recursion depth.
|
||||
|
||||
Tracer(unsigned int max_depth = 5): m_max_depth(max_depth) { }
|
||||
|
||||
virtual ~Tracer() { }
|
||||
|
||||
/**
|
||||
* Recursively trace a ray into a scene, up until the max recursion depth.
|
||||
*/
|
||||
virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Fresnel law for refractions.
|
||||
*/
|
||||
float fresnel(const vec3 & i, const vec3 & n, const float ir1, const float ir2) const;
|
||||
};
|
||||
|
||||
#endif
|
125
EVI - 2017/EVI 21/EVIray/whitted_tracer.cpp
Normal file
125
EVI - 2017/EVI 21/EVIray/whitted_tracer.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include <glm/gtc/constants.hpp>
|
||||
|
||||
#include "whitted_tracer.hpp"
|
||||
#include "area_light.hpp"
|
||||
|
||||
using std::numeric_limits;
|
||||
using namespace glm;
|
||||
|
||||
WhittedTracer::~WhittedTracer() { }
|
||||
|
||||
vec3 WhittedTracer::trace_ray(Ray & r, Scene * s, unsigned int rec_level) const {
|
||||
float t, _t;
|
||||
Figure * _f;
|
||||
vec3 n, color, i_pos, ref, dir_diff_color, dir_spec_color;
|
||||
Ray mv_r, sr, rr;
|
||||
bool vis, is_area_light;
|
||||
float kr;
|
||||
AreaLight * al;
|
||||
|
||||
t = numeric_limits<float>::max();
|
||||
_f = NULL;
|
||||
|
||||
// Find the closest intersecting surface.
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
if (s->m_figures[f]->intersect(r, _t) && _t < t) {
|
||||
t = _t;
|
||||
_f = s->m_figures[f];
|
||||
}
|
||||
}
|
||||
|
||||
// If this ray intersects something:
|
||||
if (_f != NULL) {
|
||||
// Take the intersection point and the normal of the surface at that point.
|
||||
i_pos = r.m_origin + (t * r.m_direction);
|
||||
n = _f->normal_at_int(r, t);
|
||||
|
||||
is_area_light = false;
|
||||
// Check if the object is an area light;
|
||||
for (size_t l = 0; l < s->m_lights.size(); l++) {
|
||||
if (s->m_lights[l]->light_type() == Light::AREA && static_cast<AreaLight *>(s->m_lights[l])->m_figure == _f)
|
||||
is_area_light = true;
|
||||
}
|
||||
|
||||
// If the object is an area light, return it's emission value.
|
||||
if (is_area_light) {
|
||||
return clamp(_f->m_mat->m_emission, 0.0f, 1.0f);
|
||||
|
||||
// Check if the material is not reflective/refractive.
|
||||
} else if (!_f->m_mat->m_refract) {
|
||||
|
||||
// Calculate the direct lighting.
|
||||
for (size_t l = 0; l < s->m_lights.size(); l++) {
|
||||
// For every light source
|
||||
vis = true;
|
||||
|
||||
if (s->m_lights[l]->light_type() == Light::INFINITESIMAL) {
|
||||
// Cast a shadow ray to determine visibility.
|
||||
sr = Ray(s->m_lights[l]->direction(i_pos), i_pos + n * BIAS);
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
if (s->m_figures[f]->intersect(sr, _t) && _t < s->m_lights[l]->distance(i_pos)) {
|
||||
vis = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (s->m_lights[l]->light_type() == Light::AREA) {
|
||||
// Cast a shadow ray towards a sample point on the surface of the light source.
|
||||
al = static_cast<AreaLight *>(s->m_lights[l]);
|
||||
al->sample_at_surface();
|
||||
sr = Ray(al->direction(i_pos), i_pos + (n * BIAS));
|
||||
|
||||
for (size_t f = 0; f < s->m_figures.size(); f++) {
|
||||
// Avoid self-intersection with the light source.
|
||||
if (al->m_figure != s->m_figures[f]) {
|
||||
if (s->m_figures[f]->intersect(sr, _t) && _t < al->distance(i_pos)) {
|
||||
vis = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate the shading model accounting for visibility.
|
||||
dir_diff_color += vis ? s->m_lights[l]->diffuse(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
dir_spec_color += vis ? s->m_lights[l]->specular(n, r, i_pos, *_f->m_mat) : vec3(0.0f);
|
||||
}
|
||||
|
||||
color += (1.0f - _f->m_mat->m_rho) * ((dir_diff_color * (_f->m_mat->m_diffuse / pi<float>())) + (_f->m_mat->m_specular * dir_spec_color));
|
||||
|
||||
// Determine the specular reflection color.
|
||||
if (_f->m_mat->m_rho > 0.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
|
||||
color += _f->m_mat->m_rho * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (_f->m_mat->m_rho > 0.0f && rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
} else {
|
||||
// If the material has transmission enabled, calculate the Fresnel term.
|
||||
kr = fresnel(r.m_direction, n, r.m_ref_index, _f->m_mat->m_ref_index);
|
||||
|
||||
// Determine the specular reflection color.
|
||||
if (kr > 0.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(reflect(r.m_direction, n)), i_pos + n * BIAS);
|
||||
color += kr * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
// Determine the transmission color.
|
||||
if (_f->m_mat->m_refract && kr < 1.0f && rec_level < m_max_depth) {
|
||||
rr = Ray(normalize(refract(r.m_direction, n, r.m_ref_index / _f->m_mat->m_ref_index)), i_pos - n * BIAS, _f->m_mat->m_ref_index);
|
||||
color += (1.0f - kr) * trace_ray(rr, s, rec_level + 1);
|
||||
} else if (rec_level >= m_max_depth)
|
||||
return vec3(0.0f);
|
||||
|
||||
}
|
||||
|
||||
// Return final color.
|
||||
return clamp(_f->m_mat->m_emission + color, 0.0f, 1.0f);
|
||||
|
||||
} else
|
||||
return clamp(s->m_env->get_color(r), 0.0f, 1.0f);
|
||||
}
|
18
EVI - 2017/EVI 21/EVIray/whitted_tracer.hpp
Normal file
18
EVI - 2017/EVI 21/EVIray/whitted_tracer.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#ifndef WHITTED_TRACER_HPP
|
||||
#define WHITTED_TRACER_HPP
|
||||
|
||||
#include "tracer.hpp"
|
||||
|
||||
class WhittedTracer: public Tracer {
|
||||
public:
|
||||
WhittedTracer(): Tracer() { }
|
||||
|
||||
WhittedTracer(unsigned int max_depth): Tracer(max_depth) { };
|
||||
|
||||
virtual ~WhittedTracer();
|
||||
|
||||
virtual vec3 trace_ray(Ray & r, Scene * s, unsigned int rec_level) const;
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user