diff --git a/CMakeLists.txt b/CMakeLists.txt index c13aa74..e3aedd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,12 @@ target_link_libraries(tracey_ex4 tracey) add_executable(tracey_ex5 ex5.cpp) target_link_libraries(tracey_ex5 tracey) +add_executable(tracey_ex6 ex6.cpp) +target_link_libraries(tracey_ex6 tracey) +if("${CMAKE_CURRENT_LIST_DIR}/renderer/superrenderer.cpp" IN_LIST renderer_src) + add_definitions(-DSUPERRENDERER_FOUND) +endif() + diff --git a/common/texture.cpp b/common/texture.cpp index e3fa49a..b83eac4 100644 --- a/common/texture.cpp +++ b/common/texture.cpp @@ -55,7 +55,7 @@ Color Texture::color(float u, float v, bool interpolate) const { if (!interpolate) { color = this->getPixelAt(int(roundf(u * this->width())), int(roundf(v * this->height()))); } else { - // We will use bilinear filtering in the future, but for now we do a simple color look-up + // IMPLEMENT bilinear interpolation color = this->getPixelAt(int(roundf(u * this->width())), int(roundf(v * this->height()))); } return color; diff --git a/ex6.cpp b/ex6.cpp new file mode 100644 index 0000000..1bd5b59 --- /dev/null +++ b/ex6.cpp @@ -0,0 +1,89 @@ +#include +#include + +#include "camera/perspectivecamera.h" + +#include "scene/fastscene.h" + +#include "primitive/sphere.h" + +#include "renderer/simplerenderer.h" +#ifdef SUPERRENDERER_FOUND +#include "renderer/superrenderer.h" +#endif + +#include "shader/materialshader.h" + +#include "light/ambientlight.h" +#include "light/pointlight.h" +#include "light/spotlight.h" + +int main() { + FastScene scene; + scene.setEnvironmentMap(std::make_shared("data/TychoSkymapII.t5_04096x02048.png")); + + // Set up the camera + PerspectiveCamera camera; + camera.setPosition(Vector3d(0.0f, -0.2f, 0.0f)); + camera.setForwardDirection(normalized(Vector3d(-1.0f, -0.15f, 0.6f))); + camera.setUpDirection(normalized(Vector3d(0.0f, -1.0f, 0.0f))); + camera.setFovAngle(90.0f); + + // Add the earth + auto earthDiffuse = std::make_shared("data/earth_diffuse.ppm"); + auto earthSpecular = std::make_shared("data/earth_specular.ppm"); + auto earthNormal = std::make_shared("data/earth_normal.ppm"); + auto earthClouds = std::make_shared("data/earth_clouds.ppm"); + auto earthCloudShader = std::make_shared(); + earthCloudShader->setDiffuseMap(earthClouds); + earthCloudShader->setAlphaMap(earthClouds); + earthCloudShader->setDiffuseCoefficient(0.9f); + earthCloudShader->setSpecularCoefficient(0.1f); + auto earthShader = std::make_shared(); + earthShader->setDiffuseMap(earthDiffuse); + earthShader->setDiffuseCoefficient(0.5f); + earthShader->setSpecularMap(earthSpecular); + earthShader->setSpecularCoefficient(0.5f); + earthShader->setShininessExponent(15.0f); + earthShader->setNormalMap(earthNormal); + scene.add(std::make_shared(Vector3d(-50.0f, 0.0f, 60.0f), 20.0f, earthShader)); + scene.add(std::make_shared(Vector3d(-50.0f, 0.0f, 60.0f), 20.05f, earthCloudShader)); + + // Add the spaceship + auto spaceshipDiffuse = std::make_shared("data/space_frigate_6_diffuse.ppm"); + auto spaceshipSpecular = std::make_shared("data/space_frigate_6_specular.ppm"); + auto spaceshipNormal = std::make_shared("data/space_frigate_6_normal.ppm"); + auto spaceshipReflection = std::make_shared("data/space_frigate_6_specular.ppm"); + auto spaceshipShader = std::make_shared(); + spaceshipShader->setDiffuseMap(spaceshipDiffuse); + spaceshipShader->setDiffuseCoefficient(0.75f); + spaceshipShader->setSpecularMap(spaceshipSpecular); + spaceshipShader->setNormalMap(spaceshipNormal); + spaceshipShader->setNormalCoefficient(0.8f); + spaceshipShader->setSpecularCoefficient(0.25f); + spaceshipShader->setShininessExponent(30.0f); + spaceshipShader->setReflectionMap(spaceshipReflection); + spaceshipShader->setReflectance(0.75f); + + scene.addObj("data/space_frigate_6.obj", Vector3d(-1.0f, 1.0f, 1.0f) / 20.0f, Vector3d(-1.3f, -0.3f, 0.7f), + spaceshipShader); + + // Add lights + scene.add(std::make_shared(Vector3d(0.0f, 0.0f, 30.0f), 1000.0f)); + scene.add(std::make_shared(0.3f)); + + // build the tree + scene.buildTree(); + + // Render the scene + SimpleRenderer renderer; + renderer.renderImage(scene, camera, 1024, 768).save("result.png"); + +#ifdef SUPERRENDERER_FOUND + SuperRenderer sr; + sr.setSuperSamplingFactor(4); + sr.renderImage(scene, camera, 1024, 768).save("result_super.png"); +#endif + + return 0; +} diff --git a/shader/materialshader.cpp b/shader/materialshader.cpp new file mode 100644 index 0000000..f126a54 --- /dev/null +++ b/shader/materialshader.cpp @@ -0,0 +1,28 @@ +#include "light/light.h" +#include "scene/scene.h" +#include "shader/materialshader.h" +#include + +Vector3d tangentToWorldSpace(const Vector3d &surfaceNormal, const Vector3d &surfaceTangent, const Vector3d &surfaceBitangent, const Vector3d &textureNormal) { + return textureNormal.x * surfaceTangent + textureNormal.y * surfaceBitangent + textureNormal.z * surfaceNormal; +} + +MaterialShader::MaterialShader() : opacity(1.0f), normalCoefficient(1.0f), diffuseCoefficient(0.5f), reflectance(0.0f), specularCoefficient(0.5f), shininessExponent(8) {} + +Color MaterialShader::shade(Scene const &scene, Ray const &ray) const { + Color fragmentColor; + + // IMPLEMENT ME + + // (Normal Map) Calculate the new normal vector + + // (Diffuse-/Specular Map) Accumulate the light over all light sources + + // (Reflection Map) Calculate the reflectance, create a reflection ray + + // (Alpha Map) Calculate the opacity, create a background ray + + return fragmentColor; +} + +bool MaterialShader::isTransparent() const { return this->opacity < 1.0f || this->alphaMap; } diff --git a/shader/materialshader.h b/shader/materialshader.h new file mode 100644 index 0000000..c83c02b --- /dev/null +++ b/shader/materialshader.h @@ -0,0 +1,49 @@ +#ifndef MATERIALSHADER_H +#define MATERIALSHADER_H + +#include "common/texture.h" +#include "shader/shader.h" +#include + +class MaterialShader : public Shader { + +public: + // Constructor + MaterialShader(); + + // Set + void setAlphaMap(std::shared_ptr const &alphaMap) { this->alphaMap = alphaMap; } + void setOpacity(float opacity) { this->opacity = opacity; } + void setNormalMap(std::shared_ptr const &normalMap) { this->normalMap = normalMap; } + void setNormalCoefficient(float normalCoefficient) { this->normalCoefficient = normalCoefficient; } + void setDiffuseMap(std::shared_ptr const &diffuseMap) { this->diffuseMap = diffuseMap; } + void setDiffuseCoefficient(float diffuseCoefficient) { this->diffuseCoefficient = diffuseCoefficient; } + void setSpecularMap(std::shared_ptr const &specularMap) { this->specularMap = specularMap; } + void setSpecularCoefficient(float specularCoefficient) { this->specularCoefficient = specularCoefficient; } + void setShininessExponent(float shininessExponent) { this->shininessExponent = shininessExponent; } + void setReflectionMap(std::shared_ptr const &reflectionMap) { this->reflectionMap = reflectionMap; } + void setReflectance(float reflectance) { this->reflectance = reflectance; } + + // Shader functions + Color shade(Scene const &scene, Ray const &ray) const override; + bool isTransparent() const override; + +private: + std::shared_ptr alphaMap; + float opacity; + + std::shared_ptr normalMap; + float normalCoefficient; + + std::shared_ptr diffuseMap; + float diffuseCoefficient; + + std::shared_ptr reflectionMap; + float reflectance; + + std::shared_ptr specularMap; + float specularCoefficient; + float shininessExponent; +}; + +#endif