// This source code is property of the Computer Graphics and Visualization // chair of the TU Dresden. Do not distribute! // Copyright (C) CGV TU Dresden - All Rights Reserved #include "Viewer.h" #include #include #include #include #include #include #include "glsl.h" using namespace nse::gui; Viewer::Viewer() : AbstractViewer("CG1 Exercise 1") { SetupGUI(); CreateShaders(); CreateVertexBuffers(); view_uniform_id = glGetUniformLocation(program_id, "view"); proj_uniform_id = glGetUniformLocation(program_id, "proj"); julia_m_id = glGetUniformLocation(program_id, "m"); julia_c_id = glGetUniformLocation(program_id, "c"); julia_pos_id = glGetUniformLocation(program_id, "julia_positions"); modelViewMatrix.setIdentity(); projectionMatrix.setIdentity(); camera().FocusOnBBox(nse::math::BoundingBox(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); point1X = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point1.X", std::make_pair(-1.0f, 1.0f), 0.0f, 2); point1Y = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point1.Y", std::make_pair(-1.0f, 1.0f), 0.0f, 2); point2X = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point2.X", std::make_pair(-1.0f, 1.0f), -1.0f, 2); point2Y = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point2.Y", std::make_pair(-1.0f, 1.0f), -1.0f, 2); point3X = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point3.X", std::make_pair(-1.0f, 1.0f), 1.0f, 2); point3Y = AddLabeledSliderWithDefaultDisplay(mainWindow, "Point3.Y", std::make_pair(-1.0f, 1.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[] = { -1, -1, -1, 1, // 1 1, -1, 1, 1, // 6 -1, 1, 1, 1, // 8 -1, -1, -1, 1, // 1 1, 1, -1, 1, // 3 1, -1, 1, 1, // 6 -1, -1, -1, 1, // 1 -1, 1, 1, 1, // 8 1, 1, -1, 1, // 3 1, 1, -1, 1, // 3 -1, 1, 1, 1, // 8 1, -1, 1, 1, // 6 }; GLfloat colors[] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, }; // Generate the vertex array 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 // "in_position". First, get the location of this attribute in // 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) ***/ 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); // Unbind the vertex array to leave OpenGL in a clean state glBindVertexArray(0); } inline std::string loadShaderText(const char *path) { std::ifstream is(path); std::string s_save; if (is.is_open()) { s_save.assign(std::istreambuf_iterator(is), std::istreambuf_iterator()); } 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; } // Read, Compile and link the shader codes to a shader program void Viewer::CreateShaders() { 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(); } program_id = glCreateProgram(); glAttachShader(program_id, vertex_shader_id); glAttachShader(program_id, fragment_shader_id); glLinkProgram(program_id); /*** 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); // create uniform buffer for julia_positions float julia_positions[6] = { point1X->value(), point1Y->value(), point2X->value(), point2Y->value(), point3X->value(), point3Y->value() }; // 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. */ glUniformMatrix4fv(view_uniform_id, 1, false, modelViewMatrix.data()); glUniformMatrix4fv(proj_uniform_id, 1, false, projectionMatrix.data()); glUniform1f(julia_m_id, juliaZoom); glUniform2fv(julia_c_id, 1, juliaC.data()); glUniform2fv(julia_pos_id, 6, julia_positions); // Bind the vertex array glBindVertexArray(vertex_array_id); // Draw the bound vertex array. Start at element 0 and draw 3 vertices glDrawArrays(GL_TRIANGLES, 0, 12); /*** End of task 1.2.4 (b) ***/ // Unbind the vertex array glBindVertexArray(0); // Deactivate the shader program glUseProgram(0); }