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();
|
|
|
|
|
|
|
|
|
|
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[] = {
|
|
|
|
|
0, 1, 0, 1,
|
|
|
|
|
-1, -1, 0, 1,
|
2018-10-17 08:22:24 +00:00
|
|
|
|
1, -1, 0, 1};
|
2018-09-06 12:35:43 +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");
|
|
|
|
|
// 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) ***/
|
|
|
|
|
|
|
|
|
|
// 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 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
|
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|
|
|
|
|
|
|
|
|
/*** 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);
|
|
|
|
|
}
|