From c42dd0b359e963643520508ab4f7dbfd4a73081e Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 15 May 2024 13:04:16 +0300 Subject: [PATCH 1/2] Add feature shaders light at C --- include/shader.h | 60 ++++++++++++++++++ src/shader.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 include/shader.h create mode 100644 src/shader.cpp diff --git a/include/shader.h b/include/shader.h new file mode 100644 index 0000000..3515c69 --- /dev/null +++ b/include/shader.h @@ -0,0 +1,60 @@ +#pragma once +//todo switch + +#include +#include +#include +#include + +class Shader +{ +public: + Shader() {}; + + void loadFromFiles(std::string vertexPath, std::string fragmentPath); + + void bind() + { + glUseProgram(id); + } + + void clear() + { + glDeleteProgram(id); + } + + GLuint getId() { return id; } + +protected: + + GLuint id = 0; + + GLuint createShaderFromMemory(const char *data, GLenum type); + std::string loadShaderSource(std::string source); + +}; + +class DrawBlocksShader : public Shader +{ +public: + void load(); + + void setProjectionMatrix(const glm::mat4 &mat); + void setModelViewMatrix(const glm::mat4 &mat); + void setPlayerPos(const glm::vec3 &pos); + void setTexture(int index); + void setPosition(int x, int y, int z); + void setTextureAtlasCoords(int x, int y); + void setAo(bool ao); + +private: + + GLint u_playerPos; + GLint u_modelView; + GLint u_projectionMatrix; + GLint u_texture; + GLint u_pos; + GLint u_atlas; + GLint u_ao; + +}; \ No newline at end of file diff --git a/src/shader.cpp b/src/shader.cpp new file mode 100644 index 0000000..d3ea9c3 --- /dev/null +++ b/src/shader.cpp @@ -0,0 +1,159 @@ +#include "shader.h" +#include +#include +#include "tools.h" +#include "log.h" + +void Shader::loadFromFiles(std::string vertexPath, std::string fragmentPath) +{ + std::string vertexSource = loadShaderSource(vertexPath); + auto vertexShaderId = createShaderFromMemory(vertexSource.c_str(), GL_VERTEX_SHADER); + + std::string fragmentSource = loadShaderSource(fragmentPath); + auto fragmentShaderId = createShaderFromMemory(fragmentSource.c_str(), GL_FRAGMENT_SHADER); + + id = glCreateProgram(); + + glAttachShader(id, vertexShaderId); + glAttachShader(id, fragmentShaderId); + + glLinkProgram(id); + + glDeleteShader(vertexShaderId); + glDeleteShader(fragmentShaderId); + + int info = 0; + glGetProgramiv(id, GL_LINK_STATUS, &info); + + if (info != GL_TRUE) + { + char *message = 0; + int l = 0; + + glGetProgramiv(id, GL_INFO_LOG_LENGTH, &l); + + message = new char[l]; + + glGetProgramInfoLog(id, l, &l, message); + + llog(ErrorLog(), message, "\n", "in:", vertexPath, "and:", fragmentPath); + + delete[] message; + } + + glValidateProgram(id); + +} + +GLuint Shader::createShaderFromMemory(const char *data, GLenum type) +{ + GLuint shaderID = glCreateShader(type); + + glShaderSource(shaderID, 1, &data, 0); + glCompileShader(shaderID); + + + int result = 0; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + + if (!result) + { + char *message = 0; + int l = 0; + + glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &l); + + if (l) + { + + message = new char[l]; + + glGetShaderInfoLog(shaderID, l, &l, message); + + message[l - 1] = 0; + + llog(ErrorLog(), message, "\n", "data:\n\n", data); + + delete[] message; + + } + + } + + return shaderID; +} + +std::string Shader::loadShaderSource(std::string source) +{ + std::ifstream f(source); + + if (!f.is_open()) + { + throw(std::string("err loading ") + source); + } + + //most vexing parse here yay love cpp + std::string ret{ std::istreambuf_iterator(f), {} }; + + return std::move(ret); +} + +void DrawBlocksShader::load() +{ + loadFromFiles(RESOURCES_PATH "vertex.vert", RESOURCES_PATH "fragment.frag"); + + permaAssertComment(id, "shader not found"); + + u_playerPos = glGetUniformLocation(id, "u_playerPos"); + u_modelView = glGetUniformLocation(id, "u_modelView"); + u_projectionMatrix = glGetUniformLocation(id, "u_projectionMatrix"); + u_texture = glGetUniformLocation(id, "u_texture"); + u_pos = glGetUniformLocation(id, "u_pos"); + u_atlas = glGetUniformLocation(id, "u_atlas"); + u_ao = glGetUniformLocation(id, "u_ao"); + + + if (u_projectionMatrix == -1) + { + llog(ErrorLog(), "projMat error\n"); + } + +} + +void DrawBlocksShader::setProjectionMatrix(const glm::mat4 &mat) +{ + glUniformMatrix4fv(u_projectionMatrix, 1, GL_FALSE, &(mat[0][0])); + +} + +void DrawBlocksShader::setModelViewMatrix(const glm::mat4 &mat) +{ + glUniformMatrix4fv(u_modelView, 1, GL_FALSE, &(mat[0][0])); + +} + +void DrawBlocksShader::setPlayerPos(const glm::vec3 &pos) +{ + glUniform3f(u_playerPos, pos.x, pos.y, pos.z); +} + +void DrawBlocksShader::setTexture(int index) +{ + glUniform1i(u_texture, index); +} + +void DrawBlocksShader::setPosition(int x, int y, int z) +{ + glUniform3i(u_pos, x, y, z); +} + +void DrawBlocksShader::setTextureAtlasCoords(int x, int y) +{ + glUniform2i(u_atlas, x, y); +} + + +void DrawBlocksShader::setAo(bool ao) +{ + glUniform1i(u_ao, ao); +} -- 2.40.1 From e69f222900db126e624d12fda93a12979f126333 Mon Sep 17 00:00:00 2001 From: Marina Date: Wed, 15 May 2024 13:04:44 +0300 Subject: [PATCH 2/2] Add feature sky at world --- include/skyBox.h | 31 ++++++ src/skyBox.cpp | 244 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 include/skyBox.h create mode 100644 src/skyBox.cpp diff --git a/include/skyBox.h b/include/skyBox.h new file mode 100644 index 0000000..1dedaf9 --- /dev/null +++ b/include/skyBox.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include + +class SkyBox +{ +public: + + void create(); + void clear(); + + void clearTexture(); + + + void loadTextures(const char *textures[]); + void loadTexturesFromCrossTexture(const char* texture); + + + void render(const glm::mat4 &viewProjection); + +private: + + GLuint cubemapTexture = 0; + Shader shader; + GLint u_cubeMap = -1; + GLint u_viewProjection = -1; + + GLuint vao = 0; + GLuint cubeBuffer = 0; +}; \ No newline at end of file diff --git a/src/skyBox.cpp b/src/skyBox.cpp new file mode 100644 index 0000000..077146f --- /dev/null +++ b/src/skyBox.cpp @@ -0,0 +1,244 @@ +#include "skyBox.h" +#include "stb_image/stb_image.h" +#include + +static float skyboxVertices[] = { + // positions + -1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + + -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f +}; + + +void SkyBox::create() +{ + shader.loadFromFiles(RESOURCES_PATH "skyBox.vert", RESOURCES_PATH "skyBox.frag"); + + u_cubeMap = glGetUniformLocation(shader.getId(), "u_cubeMap"); + u_viewProjection = glGetUniformLocation(shader.getId(), "u_viewProjection"); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + glGenBuffers(1, &cubeBuffer); + glBindBuffer(GL_ARRAY_BUFFER, cubeBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), skyboxVertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + glEnableVertexAttribArray(0); + + + glBindVertexArray(0); +} + +void SkyBox::clear() +{ + + +} + +void SkyBox::loadTextures(const char* textures[]) +{ + if(cubemapTexture) + { + clearTexture(); + } + + glGenTextures(1, &cubemapTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); + + int width, height, nrChannels; + unsigned char *data; + for (unsigned int i = 0; i < 6; i++) + { + stbi_set_flip_vertically_on_load(false); + + data = stbi_load(textures[i], &width, &height, &nrChannels, 0); + glTexImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data + ); + + stbi_image_free(data); + + } + + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + +} + + +void SkyBox::loadTexturesFromCrossTexture(const char *texture) +{ + if (cubemapTexture) + { + clearTexture(); + } + + glGenTextures(1, &cubemapTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); + + int width, height, nrChannels; + unsigned char *data; + + + stbi_set_flip_vertically_on_load(false); + data = stbi_load(texture, &width, &height, &nrChannels, 3); + + //right + //left + //top + //bottom + //front + //back + + auto getPixel = [&](int x, int y, unsigned char *data) + { + return (unsigned char*)(data + 3 * (x + y * width)); + }; + + glm::ivec2 paddings[6]; + glm::ivec2 immageRatio = {}; + + { + immageRatio = { 4, 3 }; + glm::ivec2 paddingscopy[6] = + { + { (width / 4) * 2, (height / 3) * 1, }, + { (width / 4) * 0, (height / 3) * 1, }, + { (width / 4) * 1, (height / 3) * 0, }, + { (width / 4) * 1, (height / 3) * 2, }, + { (width / 4) * 1, (height / 3) * 1, }, + { (width / 4) * 3, (height / 3) * 1, }, + }; + + memcpy(paddings, paddingscopy, sizeof(paddings)); + + } + + if (data) + { + for (unsigned int i = 0; i < 6; i++) + { + unsigned char *extractedData = new unsigned char[3 * + (width / immageRatio.x) * (height / immageRatio.y)]; + + int index = 0; + + int paddingX = paddings[i].x; + int paddingY = paddings[i].y; + + for (int j = 0; j < height / immageRatio.y; j++) + for (int i = 0; i < width / immageRatio.x; i++) + { + extractedData[index] = *getPixel(i + paddingX, j + paddingY, data); + extractedData[index + 1] = *(getPixel(i + paddingX, j + paddingY, data) + 1); + extractedData[index + 2] = *(getPixel(i + paddingX, j + paddingY, data) + 2); + + index += 3; + } + + glTexImage2D( + GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, GL_RGB, width / immageRatio.x, height / immageRatio.y, 0, + GL_RGB, GL_UNSIGNED_BYTE, extractedData + ); + + + + delete[] extractedData; + } + + stbi_image_free(data); + + } + else + { + throw(std::string("err loading ") + texture + "\n"); + } + + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + + + +} + + +void SkyBox::render(const glm::mat4 &viewProjection) +{ + + glDepthFunc(GL_LEQUAL); + //glDepthMask(GL_FALSE); + glBindVertexArray(vao); + shader.bind(); + + glUniform1i(u_cubeMap, 0); + glUniformMatrix4fv(u_viewProjection, 1, GL_FALSE, &viewProjection[0][0]); + + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); + glActiveTexture(GL_TEXTURE0); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + glBindVertexArray(0); + //glDepthMask(GL_TRUE); + glDepthFunc(GL_LESS); + +} + +void SkyBox::clearTexture() +{ + glDeleteTextures(1, &cubemapTexture); + cubemapTexture = 0; + +} -- 2.40.1