CGI/exercise1/src/Viewer.cpp

276 lines
7.5 KiB
C++
Raw Normal View History

2018-10-17 08:22:24 +00:00
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
2018-09-06 12:35:43 +00:00
// Copyright (C) CGV TU Dresden - All Rights Reserved
#include "Viewer.h"
#include <nanogui/window.h>
#include <nanogui/layout.h>
#include <nanogui/checkbox.h>
#include <gui/SliderHelper.h>
#include <iostream>
2018-10-17 08:22:24 +00:00
#include <fstream>
2018-09-06 12:35:43 +00:00
#include "glsl.h"
Viewer::Viewer()
: AbstractViewer("CG1 Exercise 1")
2018-10-17 08:22:24 +00:00
{
2018-09-06 12:35:43 +00:00
SetupGUI();
CreateShaders();
CreateVertexBuffers();
2018-10-17 11:00:47 +00:00
view_uniform_id = glGetUniformLocation(program_id, "view");
proj_uniform_id = glGetUniformLocation(program_id, "proj");
2018-10-17 14:39:10 +00:00
julia_m_id = glGetUniformLocation(program_id, "m");
julia_c_id = glGetUniformLocation(program_id, "c");
2018-09-06 12:35:43 +00:00
modelViewMatrix.setIdentity();
projectionMatrix.setIdentity();
camera().FocusOnBBox(nse::math::BoundingBox<float, 3>(Eigen::Vector3f(-1, -1, -1), Eigen::Vector3f(1, 1, 1)));
}
void Viewer::SetupGUI()
{
auto mainWindow = SetupMainWindow();
//Create GUI elements for the various options
chkHasDepthTesting = new nanogui::CheckBox(mainWindow, "Perform Depth Testing");
chkHasDepthTesting->setChecked(true);
chkHasFaceCulling = new nanogui::CheckBox(mainWindow, "Perform backface Culling");
chkHasFaceCulling->setChecked(true);
sldJuliaCX = nse::gui::AddLabeledSliderWithDefaultDisplay(mainWindow, "JuliaC.X", std::make_pair(-1.0f, 1.0f), 0.45f, 2);
sldJuliaCY = nse::gui::AddLabeledSliderWithDefaultDisplay(mainWindow, "JuliaC.Y", std::make_pair(-1.0f, 1.0f), -0.3f, 2);
sldJuliaZoom = nse::gui::AddLabeledSliderWithDefaultDisplay(mainWindow, "Julia Zoom", std::make_pair(0.01f, 10.0f), 1.0f, 2);
performLayout();
}
// Create and define the vertex array and add a number of vertex buffers
void Viewer::CreateVertexBuffers()
{
/*** Begin of task 1.2.3 ***
Fill the positions-array and your color array with 12 rows, each
containing 4 entries, to define a tetrahedron. */
// Define 3 vertices for one face
GLfloat positions[] = {
2018-10-17 14:39:10 +00:00
-1, -1, -1, 1, // 1
1, -1, 1, 1, // 6
-1, 1, 1, 1, // 8
2018-10-17 11:00:47 +00:00
2018-10-17 14:39:10 +00:00
-1, -1, -1, 1, // 1
1, 1, -1, 1, // 3
1, -1, 1, 1, // 6
2018-10-17 11:00:47 +00:00
2018-10-17 14:39:10 +00:00
-1, -1, -1, 1, // 1
-1, 1, 1, 1, // 8
1, 1, -1, 1, // 3
2018-10-17 11:00:47 +00:00
2018-10-17 14:39:10 +00:00
1, 1, -1, 1, // 3
-1, 1, 1, 1, // 8
1, -1, 1, 1, // 6
2018-10-17 11:00:47 +00:00
};
2018-09-06 12:35:43 +00:00
2018-10-17 08:55:20 +00:00
GLfloat colors[] = {
2018-10-17 11:00:47 +00:00
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
0, 1, 0, 1,
2018-10-17 14:39:10 +00:00
0, 1, 0, 1,
0, 1, 0, 1,
2018-10-17 11:00:47 +00:00
0, 0, 1, 1,
2018-10-17 14:39:10 +00:00
0, 0, 1, 1,
0, 0, 1, 1,
1, 1, 0, 1,
1, 1, 0, 1,
1, 1, 0, 1,
2018-10-17 08:55:20 +00:00
};
2018-10-17 08:22:24 +00:00
// Generate the vertex array
2018-09-06 12:35:43 +00:00
glGenVertexArrays(1, &vertex_array_id);
glBindVertexArray(vertex_array_id);
// Generate a position buffer to be appended to the vertex array
glGenBuffers(1, &position_buffer_id);
// Bind the buffer for subsequent settings
glBindBuffer(GL_ARRAY_BUFFER, position_buffer_id);
// Supply the position data
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
// The buffer shall now be linked to the shader attribute
2018-10-17 08:22:24 +00:00
// "in_position". First, get the location of this attribute in
2018-09-06 12:35:43 +00:00
// the shader program
GLuint vid = glGetAttribLocation(program_id, "in_position");
2018-09-06 12:35:43 +00:00
// Enable this vertex attribute array
glEnableVertexAttribArray(vid);
// Set the format of the data to match the type of "in_position"
glVertexAttribPointer(vid, 4, GL_FLOAT, GL_FALSE, 0, 0);
/*** Begin of task 1.2.2 (a) ***
Create another buffer that will store color information. This works nearly
similar to the code above that creates the position buffer. Store the buffer
id into the variable "color_buffer_id" and bind the color buffer to the
shader variable "in_color".
/*** End of task 1.2.2 (a) ***/
2018-10-17 08:55:20 +00:00
glGenBuffers(1, &color_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
GLuint cid = glGetAttribLocation(program_id, "in_color");
glEnableVertexAttribArray(cid);
glVertexAttribPointer(cid, 4, GL_FLOAT, GL_FALSE, 0, 0);
2018-09-06 12:35:43 +00:00
// Unbind the vertex array to leave OpenGL in a clean state
glBindVertexArray(0);
}
2018-10-17 08:22:24 +00:00
inline std::string loadShaderText(const char *path)
2018-09-06 12:35:43 +00:00
{
2018-10-17 08:22:24 +00:00
std::ifstream is(path);
std::string s_save;
2018-09-06 12:35:43 +00:00
2018-10-17 08:22:24 +00:00
if (is.is_open())
2018-09-06 12:35:43 +00:00
{
2018-10-17 08:22:24 +00:00
s_save.assign(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>());
2018-09-06 12:35:43 +00:00
}
2018-10-17 08:22:24 +00:00
else
{
std::cout << "could not open " << path << std::endl;
}
is.close();
return s_save;
}
inline GLuint loadShader(const char *path, GLenum shadertype)
{
std::string s_source = loadShaderText(path);
if (s_source.empty())
return 0;
const char *c_source = s_source.c_str();
GLuint shader = glCreateShader(shadertype);
glShaderSource(shader, 1, (const char **)&c_source, NULL);
glCompileShader(shader);
GLint shaderCompiled = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE)
{
GLint log_length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
char *log = new char[log_length];
glGetShaderInfoLog(shader, (GLsizei)log_length, NULL, log);
std::cout << "error compiling shader( " << path << " ): " << std::endl
<< log << std::endl;
delete[] log;
glDeleteShader(shader);
shader = 0;
}
return shader;
2018-09-06 12:35:43 +00:00
}
// Read, Compile and link the shader codes to a shader program
void Viewer::CreateShaders()
{
2018-10-17 08:22:24 +00:00
const char *vs = "exercise1/glsl/shader.vert";
const char *fs = "exercise1/glsl/shader.frag";
vertex_shader_id = loadShader(vs, GL_VERTEX_SHADER);
fragment_shader_id = loadShader(fs, GL_FRAGMENT_SHADER);
if ((vertex_shader_id == 0) || (fragment_shader_id == 0))
{
std::cout << "error creating shader" << std::endl;
abort();
}
2018-09-06 12:35:43 +00:00
2018-10-17 08:22:24 +00:00
program_id = glCreateProgram();
glAttachShader(program_id, vertex_shader_id);
glAttachShader(program_id, fragment_shader_id);
glLinkProgram(program_id);
2018-09-06 12:35:43 +00:00
/*** Begin of task 1.2.1 ***
Use the appropriate OpenGL commands to create a shader object for
the vertex shader, set the source code and let it compile. Store the
ID of this shader object in the variable "vertex_shader_id". Repeat
for the fragment shader. Store the ID in the variable "fragment_shader_id.
Finally, create a shader program with its handle stored in "program_id",
attach both shader objects and link them. For error checking, you can
use the method "CheckShaderCompileStatus()" after the call to glCompileShader().
*/
/*** End of task 1.2.1 ***/
}
void Viewer::drawContents()
{
Eigen::Vector2f juliaC(sldJuliaCX->value(), sldJuliaCY->value());
float juliaZoom = sldJuliaZoom->value();
//Get the transform matrices
camera().ComputeCameraMatrices(modelViewMatrix, projectionMatrix);
// If has_faceculling is set then enable backface culling
// and disable it otherwise
if (chkHasFaceCulling->checked())
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
// If has_depthtesting is set then enable depth testing
// and disable it otherwise
if (chkHasDepthTesting->checked())
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
// Activate the shader program
glUseProgram(program_id);
/*** Begin of task 1.2.4 (b) ***
Set the shader variables for the modelview and projection matrix.
First, find the location of these variables using glGetUniformLocation and
then set them with the command glUniformMatrix4fv.
*/
2018-10-17 11:00:47 +00:00
glUniformMatrix4fv(view_uniform_id, 1, false, modelViewMatrix.data());
glUniformMatrix4fv(proj_uniform_id, 1, false, projectionMatrix.data());
2018-10-17 14:39:10 +00:00
glUniform1f(julia_m_id, juliaZoom);
glUniform2fv(julia_c_id, 1, juliaC.data());
2018-10-17 08:22:24 +00:00
// Bind the vertex array
2018-09-06 12:35:43 +00:00
glBindVertexArray(vertex_array_id);
// Draw the bound vertex array. Start at element 0 and draw 3 vertices
2018-10-17 11:00:47 +00:00
glDrawArrays(GL_TRIANGLES, 0, 12);
2018-09-06 12:35:43 +00:00
/*** End of task 1.2.4 (b) ***/
2018-10-17 08:22:24 +00:00
2018-09-06 12:35:43 +00:00
// Unbind the vertex array
glBindVertexArray(0);
// Deactivate the shader program
glUseProgram(0);
}