summaryrefslogtreecommitdiffstats
path: root/dev/a5-artrender/artrender_app.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dev/a5-artrender/artrender_app.cc')
-rw-r--r--dev/a5-artrender/artrender_app.cc296
1 files changed, 296 insertions, 0 deletions
diff --git a/dev/a5-artrender/artrender_app.cc b/dev/a5-artrender/artrender_app.cc
new file mode 100644
index 0000000..c99dc38
--- /dev/null
+++ b/dev/a5-artrender/artrender_app.cc
@@ -0,0 +1,296 @@
+/** CSci-4611 Assignment 5: Art Render
+ */
+
+#include "artrender_app.h"
+#include "config.h"
+
+#include <iostream>
+#include <sstream>
+
+
+
+using namespace std;
+
+ArtRenderApp::ArtRenderApp() : GraphicsApp(1024,768, "Art Render"),
+ shader_style_(0), current_model_(0), light_pos_(1.5, 1.5, 1.5),
+ diffuse_ramp_(GL_CLAMP_TO_EDGE), specular_ramp_(GL_CLAMP_TO_EDGE)
+{
+ // Define a search path for finding data files (images and shaders)
+ search_path_.push_back(".");
+ search_path_.push_back("./data");
+ search_path_.push_back("./shaders");
+ search_path_.push_back(DATA_DIR_INSTALL);
+ search_path_.push_back(DATA_DIR_BUILD);
+ search_path_.push_back(SHADERS_DIR_INSTALL);
+ search_path_.push_back(SHADERS_DIR_BUILD);
+
+ // NOTE: YOU CAN COMMENT OUT SOME OF THESE IF THE APP IS LOADING TOO SLOWLY
+ // THE MODEL_FILES ARRAY JUST NEEDS TO HOLD AT LEAST ONE MODEL.
+ // Also, compiling in Release mode will optimize the loading of text files a lot.
+ model_files_.push_back("bunny.obj");
+ model_files_.push_back("chamferedCube.obj");
+ model_files_.push_back("cow.obj");
+ model_files_.push_back("hippo.obj");
+ model_files_.push_back("maxplanck.obj");
+ model_files_.push_back("sphere.obj");
+ model_files_.push_back("teapot.obj");
+}
+
+
+ArtRenderApp::~ArtRenderApp() {
+}
+
+
+void ArtRenderApp::InitNanoGUI() {
+ // Setup the GUI window
+ nanogui::Window* window = new nanogui::Window(screen(), "Shading Style");
+ window->setPosition(Eigen::Vector2i(10, 10));
+ window->setSize(Eigen::Vector2i(200, 100));
+ window->setLayout(new nanogui::GroupLayout());
+
+ new nanogui::Label(window, "Dynamically Reload", "sans-bold");
+
+ nanogui::Button* btnReload = new nanogui::Button(window, "Reload Shaders and Textures");
+ btnReload->setCallback(std::bind(&ArtRenderApp::OnReloadBtnPressed, this));
+
+
+ new nanogui::Label(window, "Rendering Style", "sans-bold");
+
+ nanogui::Button* btnGouraud = new nanogui::Button(window, "Gouraud Shading");
+ btnGouraud->setCallback(std::bind(&ArtRenderApp::OnGouraudBtnPressed, this));
+
+ nanogui::Button* btnPhong = new nanogui::Button(window, "Phong Shading");
+ btnPhong->setCallback(std::bind(&ArtRenderApp::OnPhongBtnPressed, this));
+
+ nanogui::Button* btnArtsy = new nanogui::Button(window, "Artsy Shading");
+ btnArtsy->setCallback(std::bind(&ArtRenderApp::OnArtsyBtnPressed, this));
+
+
+ new nanogui::Label(window, "Model", "sans-bold");
+
+ for (int i = 0; i < model_files_.size(); i++) {
+ nanogui::Button* btn = new nanogui::Button(window, model_files_[i]);
+ btn->setCallback([this, i] { this->current_model_ = i; });
+ Mesh m;
+ m.LoadFromOBJ(Platform::FindFile(model_files_[i], search_path_));
+ meshes_.push_back(m);
+ EdgeMesh em;
+ em.CreateFromMesh(m);
+ edge_meshes_.push_back(em);
+ }
+ screen()->performLayout();
+}
+
+
+void ArtRenderApp::OnLeftMouseDown(const Point2 &pos) {
+ Point2 normalizedMousePos = PixelsToNormalizedDeviceCoords(pos);
+ float mouseZ = ReadZValueAtPixel(pos);
+ uni_cam_.OnButtonDown(normalizedMousePos, mouseZ);
+}
+
+
+void ArtRenderApp::OnLeftMouseDrag(const Point2 &pos, const Vector2 &delta) {
+ Point2 normalizedMousePos = PixelsToNormalizedDeviceCoords(pos);
+ uni_cam_.OnDrag(normalizedMousePos);
+}
+
+
+void ArtRenderApp::OnLeftMouseUp(const Point2 &pos) {
+ Point2 normalizedMousePos = PixelsToNormalizedDeviceCoords(pos);
+ uni_cam_.OnButtonUp(normalizedMousePos);
+}
+
+
+void ArtRenderApp::UpdateSimulation(double dt) {
+ uni_cam_.AdvanceAnimation(dt);
+}
+
+
+void ArtRenderApp::OnReloadBtnPressed() {
+ LoadShadersAndTextures();
+}
+
+void ArtRenderApp::OnGouraudBtnPressed() {
+ shader_style_ = 0;
+}
+
+void ArtRenderApp::OnPhongBtnPressed() {
+ shader_style_ = 1;
+}
+
+void ArtRenderApp::OnArtsyBtnPressed() {
+ shader_style_ = 2;
+}
+
+
+
+void ArtRenderApp::InitOpenGL() {
+ // Set up the camera in a good position to see the model
+ proj_matrix_ = Matrix4::Perspective(30, aspect_ratio(), 0.1f, 50.0f);
+ uni_cam_.set_view_matrix(Matrix4::LookAt(Point3(0,0,3), Point3(0,0,0), Vector3(0,1,0)));
+ glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
+
+ // Customize the lighting used for the quick shapes default shader to make the
+ // ambient really bright since we're using it to draw the yellow "light bulb"
+ // in the scene.
+ DefaultShader::LightProperties qs_light;
+ qs_light.ambient_intensity = Color(0.8f, 0.8f, 0.8f);
+ qs_light.diffuse_intensity = Color(0.4f, 0.4f, 0.4f);
+ qs_light.specular_intensity = Color(0.0f, 0.0f, 0.0f);
+ quick_shapes_.default_shader()->SetLight(0, qs_light);
+
+ LoadShadersAndTextures();
+}
+
+
+void ArtRenderApp::LoadShadersAndTextures() {
+ // (Re)loads and (re)compiles all of the shader programs text files. And, (re)loads the
+ // textures from file as well.
+
+ gouraud_shaderprog_.AddVertexShaderFromFile(Platform::FindFile("gouraud.vert", search_path_));
+ gouraud_shaderprog_.AddFragmentShaderFromFile(Platform::FindFile("gouraud.frag", search_path_));
+ gouraud_shaderprog_.LinkProgram();
+
+ phong_shaderprog_.AddVertexShaderFromFile(Platform::FindFile("phong.vert", search_path_));
+ phong_shaderprog_.AddFragmentShaderFromFile(Platform::FindFile("phong.frag", search_path_));
+ phong_shaderprog_.LinkProgram();
+
+ artsy_shaderprog_.AddVertexShaderFromFile(Platform::FindFile("artsy.vert", search_path_));
+ artsy_shaderprog_.AddFragmentShaderFromFile(Platform::FindFile("artsy.frag", search_path_));
+ artsy_shaderprog_.LinkProgram();
+
+ outline_shaderprog_.AddVertexShaderFromFile(Platform::FindFile("outline.vert", search_path_));
+ outline_shaderprog_.AddFragmentShaderFromFile(Platform::FindFile("outline.frag", search_path_));
+ outline_shaderprog_.LinkProgram();
+
+ // To try out different shading styles, you can replace diffuse.png and specular.png with
+ // some of the other texture files in the data/ directory.
+ diffuse_ramp_.InitFromFile(Platform::FindFile("diffuse.png", search_path_));
+ diffuse_ramp_.set_wrap_mode(GL_CLAMP_TO_EDGE);
+
+ specular_ramp_.InitFromFile(Platform::FindFile("specular.png", search_path_));
+ specular_ramp_.set_wrap_mode(GL_CLAMP_TO_EDGE);
+}
+
+
+void ArtRenderApp::DrawUsingOpenGL() {
+ // Just the identity matrix
+ Matrix4 model_matrix;
+
+ // Lighting parameters
+ static const Color Ia(0.3f, 0.3f, 0.3f, 1.0f);
+ static const Color Id(0.7f, 0.7f, 0.7f, 1.0f);
+ static const Color Is(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // Material parameters
+ static const Color ka(1.0f, 0.4f, 0.4f, 1.0f);
+ static const Color kd(1.0f, 0.4f, 0.4f, 1.0f);
+ static const Color ks(0.6f, 0.6f, 0.6f, 1.0f);
+ static const float s = 50.0f;
+
+ // Precompute items needed in the shader
+
+ // Light positions are usually defined in world space. For lighting calculations
+ // we need the position of the light in view space (a.k.a. eye space).
+ Point3 light_in_eye_space = uni_cam_.view_matrix() * light_pos_;
+
+ // The shader also needs these matrices
+ Matrix4 model_view_matrix = uni_cam_.view_matrix()*model_matrix;
+ Matrix4 normal_matrix = model_view_matrix.Inverse().Transpose();
+
+ // Make sure the default option to only draw front facing triangles is set
+ glEnable(GL_CULL_FACE);
+
+ if (shader_style_ == 0) {
+
+ // Render the current model's mesh using the Gouraud shader program
+ gouraud_shaderprog_.UseProgram();
+ gouraud_shaderprog_.SetUniform("model_view_matrix", model_view_matrix);
+ gouraud_shaderprog_.SetUniform("normal_matrix", normal_matrix);
+ gouraud_shaderprog_.SetUniform("proj_matrix", proj_matrix_);
+ gouraud_shaderprog_.SetUniform("ka", ka);
+ gouraud_shaderprog_.SetUniform("kd", kd);
+ gouraud_shaderprog_.SetUniform("ks", ks);
+ gouraud_shaderprog_.SetUniform("s", s);
+ gouraud_shaderprog_.SetUniform("light_in_eye_space", light_in_eye_space);
+ gouraud_shaderprog_.SetUniform("Ia", Ia);
+ gouraud_shaderprog_.SetUniform("Id", Id);
+ gouraud_shaderprog_.SetUniform("Is", Is);
+ meshes_[current_model_].Draw();
+ gouraud_shaderprog_.StopProgram();
+
+ }
+ if (shader_style_ == 1) {
+
+ // Render the current model's mesh using the Phong shader program
+ phong_shaderprog_.UseProgram();
+ phong_shaderprog_.SetUniform("model_view_matrix", model_view_matrix);
+ phong_shaderprog_.SetUniform("normal_matrix", normal_matrix);
+ phong_shaderprog_.SetUniform("proj_matrix", proj_matrix_);
+ phong_shaderprog_.SetUniform("ka", ka);
+ phong_shaderprog_.SetUniform("kd", kd);
+ phong_shaderprog_.SetUniform("ks", ks);
+ phong_shaderprog_.SetUniform("s", s);
+ phong_shaderprog_.SetUniform("light_in_eye_space", light_in_eye_space);
+ phong_shaderprog_.SetUniform("Ia", Ia);
+ phong_shaderprog_.SetUniform("Id", Id);
+ phong_shaderprog_.SetUniform("Is", Is);
+ meshes_[current_model_].Draw();
+ phong_shaderprog_.StopProgram();
+
+ }
+ else if (shader_style_ == 2) {
+
+ // Rendering using the Artsy shader programs
+
+ // Step 1: Use the toon shader to draw the object's mesh
+ artsy_shaderprog_.UseProgram();
+ artsy_shaderprog_.SetUniform("model_view_matrix", model_view_matrix);
+ artsy_shaderprog_.SetUniform("normal_matrix", normal_matrix);
+ artsy_shaderprog_.SetUniform("proj_matrix", proj_matrix_);
+ artsy_shaderprog_.SetUniform("ka", ka);
+ artsy_shaderprog_.SetUniform("kd", kd);
+ artsy_shaderprog_.SetUniform("ks", ks);
+ artsy_shaderprog_.SetUniform("s", s);
+ artsy_shaderprog_.SetUniform("light_in_eye_space", light_in_eye_space);
+ artsy_shaderprog_.SetUniform("Ia", Ia);
+ artsy_shaderprog_.SetUniform("Id", Id);
+ artsy_shaderprog_.SetUniform("Is", Is);
+ artsy_shaderprog_.BindTexture("diffuse_ramp", diffuse_ramp_);
+ artsy_shaderprog_.BindTexture("specular_ramp", specular_ramp_);
+ meshes_[current_model_].Draw();
+ artsy_shaderprog_.StopProgram();
+
+
+ // Step 2: Draw the silhouette edge using the edge mesh and outline shader
+
+ // Disable back face culling so OpenGL will draw both front and back facing triangles
+ glDisable(GL_CULL_FACE);
+
+ // Set the OpenGL polygon offset so it will draw triangles even if they
+ // exactly on top of another triangle
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(1, 1);
+
+ static const float thickness = 0.01f;
+
+ // Draw edge mesh
+ outline_shaderprog_.UseProgram();
+ outline_shaderprog_.SetUniform("modelViewMatrix", model_view_matrix);
+ outline_shaderprog_.SetUniform("normalMatrix", normal_matrix);
+ outline_shaderprog_.SetUniform("proj_matrix", proj_matrix_);
+ outline_shaderprog_.SetUniform("thickness", thickness);
+ edge_meshes_[current_model_].Draw();
+ outline_shaderprog_.StopProgram();
+
+ }
+
+ // Draw a little yellow sphere at the location of the light source
+ Matrix4 light_model = Matrix4::Translation(light_pos_ - Point3(0, 0, 0)) *
+ Matrix4::Scale(Vector3(0.1f, 0.1f, 0.1f));
+ quick_shapes_.DrawSphere(light_model, uni_cam_.view_matrix(), proj_matrix_, Color(1, 1, 0));
+
+ // Draw the UniCam widget when in rotation mode
+ uni_cam_.Draw(proj_matrix_);
+}
+