engineer-thesis-WUT/Engine/engine/draw.cpp

333 lines
11 KiB
C++
Raw Normal View History

2023-03-12 16:24:48 +01:00
// "Copyright [2023] <Krzysztof Rudnicki>"
2022-09-05 20:17:25 +02:00
#ifndef DRAW_CPP
#define DRAW_CPP
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
2023-03-11 17:26:16 +01:00
#include <filesystem>
2023-03-12 17:32:42 +01:00
#include <utility>
#include "./draw.hpp"
#include "./renderLoop.hpp"
#include "./shaders.hpp"
#include "./constants.hpp"
#include "./misc.hpp"
#include "./shader.hpp"
#include "./textures.hpp"
#include "./stb_image.h"
drawFigureReturn drawFigure(const int whatToDraw) {
switch (whatToDraw) {
2022-09-10 13:40:58 +02:00
case 0:
2023-03-12 17:32:42 +01:00
return drawTriangleClass(
constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
2022-09-10 13:40:58 +02:00
case 1:
2023-03-12 17:32:42 +01:00
return drawSquare(
constants::SQUARE_VERTICES,
constants::SQUARE_VERTICES_SIZE,
constants::SQUARE_INDICES, constants::SQUARE_INDICES_SIZE,
constants::VERTEX_SHADER_SOURCE,
constants::FRAGMENT_SHADER_SOURCE);
2022-09-17 14:14:08 +02:00
case 2:
2023-03-12 17:32:42 +01:00
// Try to draw 2 triangles next to each other
// using glDrawArrays by adding more vertices to your data.
return drawTriangleClass(
constants::TRIANGLES_VERTICES,
constants::TRIANGLES_VERTICES_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
2022-09-17 14:14:08 +02:00
case 3:
2023-03-12 17:32:42 +01:00
drawTriangleClass(constants::TRIANGLE_ONE,
constants::TRIANGLE_ONE_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
// Now create the same 2 triangles
// using two different VAOs and VBOs for their data
return drawTriangleClass(
constants::TRIANGLE_TWO,
constants::TRIANGLE_TWO_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
case 4:
2023-03-12 17:32:42 +01:00
drawTriangleClass(constants::TRIANGLE_ONE,
constants::TRIANGLE_ONE_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
/*
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 drawTriangleClass(
constants::TRIANGLE_TWO,
constants::TRIANGLE_TWO_SIZE,
constants::VERTEX_SHADER_SOURCE_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_YELLOW_FILENAME);
case 5:
// Get color from vertex shader to fragment shader
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_COLOR_FILENAME,
constants::FRAGMENT_SHADER_COLOR_FROM_VERTEX_FILENAME);
case 6:
// set color from opengl code to uniform value in fragment shader
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_COLOR_FILENAME,
constants::FRAGMENT_SHADER_UNIFORMS_FILENAME);
2022-11-20 23:14:59 +01:00
case 7:
// set color from opengl code to uniform value in fragment shader
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_COLORS,
constants::TRIANGLE_COLORS_SIZE,
constants::VERTEX_SHADER_VERTICE_COLOR_FILENAME,
constants::FRAGMENT_SHADER_COLOR_FROM_VERTEX_FILENAME,
true);
2023-01-27 21:29:04 +01:00
case 8:
// upside down triangle
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_UPSIDE_DOWN_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME);
2023-01-27 21:29:04 +01:00
case 9:
{
// offset triangle
offsetsStruct offsets = offsetsStruct();
offsets.xOffset = 0.5f;
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_OFFSET_FILENAME,
constants::FRAGMENT_SHADER_SOURCE_FILENAME,
false,
false,
offsets);
2023-01-27 21:29:04 +01:00
}
2023-03-05 20:02:41 +01:00
case 10:
2023-03-12 17:32:42 +01:00
return drawTriangleClass(constants::TRIANGLE_VERTICES,
constants::TRIANGLE_VERTICES_SIZE,
constants::VERTEX_SHADER_TASK_THREE_FILENAME,
constants::FRAGMENT_SHADER_TASK_THREE_FILENAME);
case constants::MAX_DRAW_CALL:
return drawDebilMode(
constants::VERTEX_SHADER_TEXTURE_FILENAME,
constants::FRAGMENT_SHADER_TEXTURE_FILENAME,
constants::TEXTURE_VERTICES,
constants::TEXTURE_VERTICES_SIZE,
constants::TEXTURE_INDICES,
constants::TEXTURE_INDICES_SIZE);
2022-09-10 13:40:58 +02:00
default:
throw "No function for this draw call";
2022-09-07 18:54:59 +02:00
}
2022-09-05 20:17:25 +02:00
}
2023-03-12 17:32:42 +01:00
unsigned int getShaderProgram(
const char* vertexShaderSource,
const char* fragmentShaderSource) {
const std::pair<unsigned int, unsigned int> shaders =
compileShaders(vertexShaderSource, fragmentShaderSource);
2022-12-11 18:49:16 +01:00
if (shaders.first == 0 || shaders.second == 0)
return 0;
2023-03-12 17:32:42 +01:00
const unsigned int shaderProgram =
linkShaderObjectsShaderProgram(shaders.first, shaders.second);
2022-12-11 18:49:16 +01:00
if (shaderProgram == 0)
return 0;
return shaderProgram;
}
2023-01-27 21:29:04 +01:00
void setOffsets(Shader shader, const offsetsStruct offsets) {
shader.setFloat("xOffset", offsets.xOffset);
shader.setFloat("yOffset", offsets.yOffset);
shader.setFloat("zOffset", offsets.zOffset);
}
2023-03-12 17:32:42 +01:00
drawFigureReturn drawTriangleClass(
const float triangleVertices[],
const size_t triangleVerticesSize,
const char* vertexPath,
const char* fragmentPath,
const bool colorIncluded,
const bool textureIncluded,
const offsetsStruct offsets) {
2023-01-27 21:29:04 +01:00
// In your CPP file:
// ======================
// float offset = 0.5f;
2022-11-20 23:14:59 +01:00
Shader ourShader(vertexPath, fragmentPath);
ourShader.use();
2023-01-27 21:29:04 +01:00
setOffsets(ourShader, offsets);
2023-03-12 17:32:42 +01:00
const unsigned int vertexBufferObject =
copyVerticesMemory(
triangleVertices,
triangleVerticesSize,
GL_ARRAY_BUFFER);
2022-11-20 23:14:59 +01:00
const unsigned int vertexArrayObject = generateBindVAO();
2023-03-12 17:32:42 +01:00
copyVerticesArray(
vertexBufferObject,
triangleVertices,
triangleVerticesSize,
GL_ARRAY_BUFFER);
2022-11-20 23:14:59 +01:00
// set vertex attribute pointers
2023-03-05 20:02:41 +01:00
configureVertexAttribute(colorIncluded, textureIncluded);
2023-03-12 17:32:42 +01:00
doDrawArrays(
ourShader.ID,
vertexArrayObject,
GL_TRIANGLES,
0,
triangleVerticesSize);
2023-03-11 19:08:15 +01:00
drawFigureReturn newReturn;
newReturn.success = 0;
newReturn.VAO = vertexArrayObject;
newReturn.VBO = vertexBufferObject;
newReturn.EBO = 0;
return newReturn;
2022-11-20 23:14:59 +01:00
}
2023-03-12 17:32:42 +01:00
drawFigureReturn drawSquare(
const float squareVertices[],
const size_t squareVerticesSize,
const unsigned int squareIndices[],
const size_t squareIndicesSize,
const char* vertexShaderSource,
const char* fragmentShaderSource,
const bool colorIncluded,
const bool textureIncluded,
const offsetsStruct offsets) {
const unsigned int shaderProgram =
getShaderProgram(vertexShaderSource, fragmentShaderSource);
2023-03-12 16:24:48 +01:00
drawFigureReturn newReturn = drawFigureReturn();
2023-03-11 19:08:15 +01:00
if (shaderProgram == 0) {
newReturn.success = -1;
return newReturn;
}
2022-09-07 18:54:59 +02:00
const unsigned int VAO = generateBindVAO();
2023-03-11 16:58:17 +01:00
copyVerticesMemory(squareVertices, squareVerticesSize, GL_ARRAY_BUFFER);
2023-03-12 17:32:42 +01:00
copyVerticesMemory(
squareIndices,
squareIndicesSize,
GL_ELEMENT_ARRAY_BUFFER);
2022-09-05 20:17:25 +02:00
2022-09-07 18:54:59 +02:00
// set vertex attribute pointers
2023-03-11 16:58:17 +01:00
configureVertexAttribute(colorIncluded, textureIncluded);
2022-09-05 20:17:25 +02:00
2023-03-12 17:32:42 +01:00
doDrawElements(
shaderProgram,
VAO,
GL_TRIANGLES,
GL_UNSIGNED_INT,
squareIndicesSize);
2023-03-11 19:08:15 +01:00
newReturn.success = 0;
newReturn.VAO = VAO;
return newReturn;
2023-01-18 17:51:24 +01:00
}
2023-03-12 17:32:42 +01:00
drawFigureReturn drawDebilMode(
const char* vertexPath,
const char* fragmentPath,
const float vertices[],
const size_t verticesSize,
const unsigned int indices[],
const size_t indicesSize) {
2023-03-11 16:58:17 +01:00
// https://stackoverflow.com/questions/33883609/opengl-linker-error-linking-with-uncompiled-shader
2023-03-12 17:32:42 +01:00
Shader ourShader(
constants::VERTEX_SHADER_TEXTURE_FILENAME,
constants::FRAGMENT_SHADER_TEXTURE_FILENAME);
2023-03-11 17:26:16 +01:00
2023-03-11 19:08:15 +01:00
unsigned int VAO = generateBindVAO();
2023-03-12 17:32:42 +01:00
unsigned int VBO = copyVerticesMemory(
vertices,
verticesSize,
GL_ARRAY_BUFFER);
unsigned int EBO = copyVerticesMemory(indices,
indicesSize,
GL_ELEMENT_ARRAY_BUFFER);
2023-03-11 17:26:16 +01:00
2023-03-11 19:08:15 +01:00
configureVertexAttribute(true, true);
2023-03-11 17:26:16 +01:00
2023-03-12 16:24:48 +01:00
unsigned int texture1 = loadAndCreateTexture("assets/container.png", true);
2023-03-12 17:32:42 +01:00
unsigned int texture2 = loadAndCreateTexture(
"assets/awesomeface.png",
false);
2023-03-11 17:26:16 +01:00
2023-03-12 17:32:42 +01:00
ourShader.use(); // don't forget to activate/use
// the shader before setting uniforms!
// set it via the texture class
2023-03-12 14:46:56 +01:00
ourShader.setInt("texture1", 0);
ourShader.setInt("texture2", 1);
2023-03-12 14:46:56 +01:00
activateAndBindTextures(texture1, GL_TEXTURE0);
activateAndBindTextures(texture2, GL_TEXTURE1);
2023-03-11 19:08:15 +01:00
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
2023-03-11 19:08:15 +01:00
drawFigureReturn newReturn;
newReturn.success = 0;
newReturn.VAO = VAO;
newReturn.VBO = VBO;
newReturn.EBO = EBO;
return newReturn;
2023-03-11 16:58:17 +01:00
}
2023-03-12 17:32:42 +01:00
void doDrawElements(
const unsigned int shaderProgram,
const unsigned int vertexArrayObject,
const GLenum drawArrayMode,
const GLenum drawType,
const int numberOfElementsToDraw) {
glUseProgram(shaderProgram);
2022-09-05 20:17:25 +02:00
glBindVertexArray(vertexArrayObject);
glDrawElements(drawArrayMode, numberOfElementsToDraw, drawType, 0);
glBindVertexArray(0);
2022-09-07 18:54:59 +02:00
}
2022-09-05 20:17:25 +02:00
2023-03-12 17:32:42 +01:00
void updateUniformColor(
const unsigned int shaderProgram,
const GLchar* uniformName) {
// update the uniform color
2023-03-12 17:32:42 +01:00
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
// query the location of our uniform
const int vertexColorLocation =
glGetUniformLocation(shaderProgram, uniformName);
// if glGetUniformLocation returns -1 it could not find the location
if (vertexColorLocation != -1) {
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.
*/
}
}
2023-03-12 17:32:42 +01:00
void doDrawArrays(
const unsigned int shaderProgram,
const unsigned int vertexArrayObject,
const GLenum drawArrayMode,
const int firstIndex,
const unsigned int numberOfIndicesToBeRendered) {
2022-09-05 20:17:25 +02:00
// use shader program to render an object
glUseProgram(shaderProgram);
updateUniformColor(shaderProgram, "ourColor");
2022-09-05 20:17:25 +02:00
glBindVertexArray(vertexArrayObject);
// From left:
// primitive type we want to draw
2022-09-07 18:54:59 +02:00
// starting index of vertex array
2022-09-05 20:17:25 +02:00
// how many vertices we want to draw
glDrawArrays(drawArrayMode, firstIndex, numberOfIndicesToBeRendered);
}
2023-03-12 17:32:42 +01:00
#endif // #ifndef DRAW_CPP