#ifndef DRAW_CPP #define DRAW_CPP #include #include #include #include #include "draw.hpp" #include "renderLoop.hpp" #include "shaders.hpp" #include "constants.hpp" #include "misc.hpp" int drawFigure(const int whatToDraw) { switch (whatToDraw) { case 0: return drawTriangle(constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE, false); case 1: return drawSquare(constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE); case 2: // Try to draw 2 triangles next to each other using glDrawArrays by adding more vertices to your data. return drawTriangle(constants::TRIANGLES_VERTICES, constants::TRIANGLES_VERTICES_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE, false); case 3: // Now create the same 2 triangles using two different VAOs and VBOs for their data return (drawTriangle(constants::TRIANGLE_ONE, constants::TRIANGLE_ONE_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE, false) == -1 || drawTriangle(constants::TRIANGLE_TWO, constants::TRIANGLE_TWO_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE, false) == -1); case 4: // Create two shader programs where the second program uses a different fragment shader that outputs the color yellow; draw both triangles again where one outputs the color yellow return (drawTriangle(constants::TRIANGLE_ONE, constants::TRIANGLE_ONE_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE, false) == -1 || drawTriangle(constants::TRIANGLE_TWO, constants::TRIANGLE_TWO_SIZE, constants::VERTEX_SHADER_SOURCE, constants::FRAGMENT_SHADER_SOURCE_YELLOW, false) == -1); case 5: // Get color from vertex shader to fragment shader return drawTriangle(constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, constants::VERTEX_SHADER_COLOR, constants::FRAGMENT_SHADER_COLOR_FROM_VERTEX, false); case 6: // set color from opengl code to uniform value in fragment shader return drawTriangle(constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, constants::VERTEX_SHADER_COLOR, constants::FRAGMENT_SHADER_UNIFORMS, false); case constants::MAX_DRAW_CALL: // set color from opengl code to uniform value in fragment shader return drawTriangle(constants::TRIANGLE_COLORS, constants::TRIANGLE_COLORS_SIZE, constants::VERTEX_SHADER_VERTICE_COLOR, constants::FRAGMENT_SHADER_COLOR_FROM_VERTEX, true); default: throw "No function for this draw call"; } } int drawSquare(const char* vertexShaderSource, const char* fragmentShaderSource) { const std::pair shaders = compileShaders(vertexShaderSource, fragmentShaderSource); if (shaders.first == 0 || shaders.second == 0) return -1; const unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second); if (shaderProgram == 0) return -1; const unsigned int VAO = generateBindVAO(); copyVerticesMemory(constants::SQUARE_VERTICES, constants::SQUARE_VERTICES_SIZE, GL_ARRAY_BUFFER); copyVerticesMemory(constants::SQUARE_INDICES, constants::SQUARE_INDICES_SIZE, GL_ELEMENT_ARRAY_BUFFER); // set vertex attribute pointers configureVertexAttribute(false); doDrawElements(shaderProgram, VAO, GL_TRIANGLES, GL_UNSIGNED_INT, std::size(constants::SQUARE_INDICES)); return 0; } void doDrawElements(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const GLenum drawType, const int numberOfElementsToDraw) { glUseProgram(shaderProgram); glBindVertexArray(vertexArrayObject); glDrawElements(drawArrayMode, numberOfElementsToDraw, drawType, 0); glBindVertexArray(0); } int drawTriangle(const float triangleVertices[], const size_t triangleVerticesSize, const char* vertexShaderSource, const char* fragmentShaderSource, const bool colorIncluded) { const unsigned int vertexBufferObject = copyVerticesMemory(triangleVertices, triangleVerticesSize, GL_ARRAY_BUFFER); const std::pair shaders = compileShaders(vertexShaderSource, fragmentShaderSource); if (shaders.first == 0 || shaders.second == 0) return -1; const unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second); if (shaderProgram == 0) return -1; const unsigned int vertexArrayObject = generateBindVAO(); copyVerticesArray(vertexBufferObject, triangleVertices, triangleVerticesSize, GL_ARRAY_BUFFER); // set vertex attribute pointers configureVertexAttribute(colorIncluded); doDrawArrays(shaderProgram, vertexArrayObject, GL_TRIANGLES, 0, triangleVerticesSize); return 0; } void updateUniformColor(const unsigned int shaderProgram, const GLchar* uniformName) { // update the uniform color const float timeValue = glfwGetTime(); // retrieve running time const float greenValue = sin(timeValue) / 2.0f + 0.5f; // vary the color from 0.0 to 1.0 using sin const int vertexColorLocation = glGetUniformLocation(shaderProgram, uniformName); // query the location of our uniform if(vertexColorLocation != -1) // if glGetUniformLocation returns -1 it could not find the location { glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); /* we set the uniform value using glUniform4f 4f means that it expects 4 floats few of possible postfixes: f: the function expects a float as its value. i: the function expects an int as its value. ui: the function expects an unsigned int as its value. 3f: the function expects 3 floats as its value. fv: the function expects a float vector/array as its value. */ } } void doDrawArrays(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const int firstIndex, const unsigned int numberOfIndicesToBeRendered) { // use shader program to render an object glUseProgram(shaderProgram); updateUniformColor(shaderProgram, "ourColor"); glBindVertexArray(vertexArrayObject); // From left: // primitive type we want to draw // starting index of vertex array // how many vertices we want to draw glDrawArrays(drawArrayMode, firstIndex, numberOfIndicesToBeRendered); } #endif