summaryrefslogtreecommitdiff
path: root/hw6/src/compoundShader.cpp
diff options
context:
space:
mode:
author53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
committer53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
commitdb072ad4dc181eca5a1458656b130beb43f475bf (patch)
treea3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/compoundShader.cpp
downloadcsci427-db072ad4dc181eca5a1458656b130beb43f475bf.tar.xz
csci427-db072ad4dc181eca5a1458656b130beb43f475bf.zip
Diffstat (limited to 'hw6/src/compoundShader.cpp')
-rw-r--r--hw6/src/compoundShader.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/hw6/src/compoundShader.cpp b/hw6/src/compoundShader.cpp
new file mode 100644
index 0000000..6456fdc
--- /dev/null
+++ b/hw6/src/compoundShader.cpp
@@ -0,0 +1,141 @@
+/******************************************************************/
+/* This file is part of the homework assignments for CSCI-427/527 */
+/* at The College of William & Mary and authored by Pieter Peers. */
+/* No part of this file, whether altered or in original form, can */
+/* be distributed or used outside the context of CSCI-427/527 */
+/* without consent of either the College of William & Mary or */
+/* Pieter Peers. */
+/******************************************************************/
+
+#include <algorithm>
+#include "compoundShader.h"
+#include "random_number.h"
+#include <iostream> // DEBUG
+
+//////////////////
+// Constructors //
+//////////////////
+compoundShader::compoundShader(const std::vector<std::shared_ptr<const shader_base>>& shader_list)
+ : shader_base()
+{
+ _compound = shader_list;
+}
+
+
+/////////////
+// Methods //
+/////////////
+color compoundShader::shade(const intersectionPoint& ip, const vec3d& light_dir) const
+{
+ color result(0.0f, 0.0f, 0.0f);
+ for_each(_compound.begin(), _compound.end(), [&](const std::shared_ptr<const shader_base>& shader)
+ {
+ result += shader->shade(ip, light_dir);
+ });
+
+ // Done.
+ return result;
+}
+
+
+color compoundShader::reflectance(const intersectionPoint& ip, const vec3d& light_dir) const
+{
+ color result(0.0f, 0.0f, 0.0f);
+ for_each(_compound.begin(), _compound.end(), [&](const std::shared_ptr<const shader_base>& shader)
+ {
+ result += shader->reflectance(ip, light_dir);
+ });
+
+ // Done.
+ return result;
+}
+
+
+brdfSample compoundShader::sample(const intersectionPoint& ip, float r1, float r2) const
+{
+ // santiy check
+ if(_compound.empty()) return brdfSample();
+
+ // initialize
+ auto currentCompound = _compound.begin();
+ float pdf = 1.0f;
+
+ // HW6: implement importance sampling of BRDF, where you select
+ // a BRDF propertional to their relative reflectivity.
+ // For example, if the compound shader has two BRDFs with
+ // an reflectivity of 20% and 40%, then the likelihood that
+ // the second BRDF is sampled is twice that of the first BRDF.
+ // Practically, you need to point the 'currentCompound' to the BRDF
+ // you want sample, and set 'pdf' to the PDF of the selection.
+ // Modifies: nothing
+ // Returns: brdfSample
+
+ float cdf = 0.0f;
+ float choice = random_float(1.0f) * reflectivity(ip);
+
+ // compute cdf until it exceeds choice probability and select that compound
+ while (currentCompound < _compound.end() && choice >= cdf) {
+ pdf = (**currentCompound).reflectivity(ip);
+ cdf += pdf;
+ currentCompound++;
+ }
+
+ // move currentCompound back to selection
+ currentCompound--;
+
+ // generate sample (do not remove -- this line will produce the correct
+ // result if currentCompound and pdf are set correctly).
+ return (*currentCompound)->sample(ip, r1, r2) * pdf;
+}
+
+
+float compoundShader::reflectivity(const intersectionPoint& ip) const
+{
+ // return sum of reflectivity
+ float total_reflectivity = 0.0f;
+ for_each(_compound.begin(), _compound.end(), [&](const std::shared_ptr<const shader_base>& shader)
+ {
+ total_reflectivity += shader->reflectivity(ip);
+ });
+
+ // Done.
+ return total_reflectivity;
+}
+
+
+color compoundShader::emittance(const intersectionPoint& ip) const
+{
+ // return total sum of emittance
+ color total_emittance;
+ for_each(_compound.begin(), _compound.end(), [&](const std::shared_ptr<const shader_base>& shader)
+ {
+ total_emittance += shader->emittance(ip);
+ });
+
+ // Done.
+ return total_emittance;
+}
+
+
+shaderProperties compoundShader::properties(const intersectionPoint& ip) const
+{
+ // if any component has a property set, then set it for the compound
+ shaderProperties result(false, false);
+ for(unsigned int i=0; i < _compound.size(); i++)
+ result |= _compound[i]->properties(ip);
+
+ // Done.
+ return result;
+}
+
+
+void compoundShader::_print(std::ostream& s) const
+{
+ s << "Compound Shader (" << _compound.size() << " components): {";
+ for(unsigned int i=0; i < _compound.size(); i++)
+ {
+ s << *_compound[i];
+ if(i != _compound.size()-1) s << ", ";
+ }
+ s << "}";
+}