diff --git a/include/chunk.hpp b/include/chunk.hpp index e29f226..17f29fb 100644 --- a/include/chunk.hpp +++ b/include/chunk.hpp @@ -56,7 +56,7 @@ namespace Chunk std::unique_ptr getBlocksArray(int* len) { return (this->blocks.toArray(len)); } public: - GLuint VAO{0}, VBO{0}, EBO{0}, colorBuffer{0}, numTriangles{0}; + GLuint VAO{0}, VBO{0}, extentsBuffer{0}, texinfoBuffer{0}, numVertices{0}; std::atomic unload_timer{0}; private: diff --git a/include/chunkmesher.hpp b/include/chunkmesher.hpp index ab5ea3e..ff8a79a 100644 --- a/include/chunkmesher.hpp +++ b/include/chunkmesher.hpp @@ -18,8 +18,8 @@ namespace chunkmesher{ GLuint numVertices{0}; std::vector vertices; - std::vector colors; - std::vector indices; + std::vector extents; + std::vector texinfo; }; oneapi::tbb::concurrent_queue& getMeshDataQueue(); diff --git a/include/shader.hpp b/include/shader.hpp index 1fcb277..09f8ae7 100644 --- a/include/shader.hpp +++ b/include/shader.hpp @@ -19,31 +19,38 @@ public: unsigned int ID; // constructor generates the shader on the fly // ------------------------------------------------------------------------ - Shader(const char *vertexPath, const char *fragmentPath) + Shader(const char* geometryPath, const char *vertexPath, const char *fragmentPath) { // 1. retrieve the vertex/fragment source code from filePath std::string vertexCode; std::string fragmentCode; + std::string geometryCode; std::ifstream vShaderFile; std::ifstream fShaderFile; + std::ifstream gShaderFile; // ensure ifstream objects can throw exceptions: vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); + gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { // open files vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); - std::stringstream vShaderStream, fShaderStream; + gShaderFile.open(geometryPath); + std::stringstream vShaderStream, fShaderStream, gShaderStream; // read file's buffer contents into streams vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); + gShaderStream << gShaderFile.rdbuf(); // close file handlers vShaderFile.close(); fShaderFile.close(); + gShaderFile.close(); // convert stream into string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); + geometryCode = gShaderStream.str(); } catch (std::ifstream::failure &e) { @@ -51,8 +58,9 @@ public: } const char *vShaderCode = vertexCode.c_str(); const char *fShaderCode = fragmentCode.c_str(); + const char *gShaderCode = geometryCode.c_str(); // 2. compile shaders - unsigned int vertex, fragment; + unsigned int vertex, fragment, geometry; // vertex shader vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vShaderCode, NULL); @@ -63,15 +71,23 @@ public: glShaderSource(fragment, 1, &fShaderCode, NULL); glCompileShader(fragment); checkCompileErrors(fragment, "FRAGMENT"); + // geometry shader + geometry = glCreateShader(GL_GEOMETRY_SHADER); + glShaderSource(geometry, 1, &gShaderCode, NULL); + glCompileShader(geometry); + checkCompileErrors(geometry, "GEOMETRY"); + // shader Program ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); + glAttachShader(ID, geometry); glLinkProgram(ID); checkCompileErrors(ID, "PROGRAM"); // delete the shaders as they're linked into our program now and no longer necessary glDeleteShader(vertex); glDeleteShader(fragment); + glDeleteShader(geometry); } // activate the shader // ------------------------------------------------------------------------ diff --git a/shaders/shader-texture.fs b/shaders/shader-texture.fs index 6da90fc..cd854e3 100644 --- a/shaders/shader-texture.fs +++ b/shaders/shader-texture.fs @@ -2,29 +2,31 @@ out vec4 FragColor; -in vec3 vNormal; -in vec3 vTexCoord; +in vec3 TexCoord; +in vec3 Normal; in vec3 FragPos; vec3 lightColor = vec3(1.0); vec3 lightDir = -normalize(vec3(0.0, 100.0, 0.0) - vec3(32.0)); -float ambientStrength = 0.4; -float diffuseStrength = 0.45; -float specularStrength = 0.05; +float ambientStrength = 0.1; +float diffuseStrength = 0.8; +float specularStrength = 0.1; uniform vec3 viewPos; uniform float u_time; uniform sampler2DArray textureArray; -void main(){ - vec3 vColor = vec3(texture(textureArray, vTexCoord)); - - // offset the normal a tiny bit, so that the color of faces opposing lightDir is not completely - // flat - vec3 normal = normalize(vNormal); +float gamma = 2.2; - // Blinn-Phong lighting +void main(){ + // Load the texture + // anti-gamma-correction of the texture. Without this it would be gamma corrected twice! + vec3 vColor = pow(texture(textureArray, TexCoord).rgb, vec3(gamma)); + + vec3 normal = normalize(Normal); + + /* Start of Blinn-Phong lighting */ // Ambient vec3 ambient = lightColor*vColor; @@ -40,5 +42,5 @@ void main(){ // Final color vec3 color = ambient * ambientStrength + diffuse * diffuseStrength + specular * specularStrength; - FragColor.rgb = color; + FragColor.rgb = pow(color, vec3(1.0/gamma)); } diff --git a/shaders/shader-texture.gs b/shaders/shader-texture.gs new file mode 100644 index 0000000..fc1e602 --- /dev/null +++ b/shaders/shader-texture.gs @@ -0,0 +1,80 @@ +#version 330 core + +layout (points) in; +layout (triangle_strip, max_vertices = 4) out; + +in VS_OUT{ + vec3 Extents; + vec3 Normal; + float BlockType; +} gs_in[]; + +out vec3 TexCoord; +out vec3 Normal; +out vec3 FragPos; + +uniform mat4 view; +uniform mat4 projection; + +void main(){ + Normal = gs_in[0].Normal; + + TexCoord = vec3(0.0, 0.0, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position; + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + if(gs_in[0].Extents.x == 0){ + TexCoord = vec3(0.0, gs_in[0].Extents.z, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, gs_in[0].Extents.z, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(gs_in[0].Extents.y, 0.0, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(0.0, gs_in[0].Extents.y, 0.0, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(gs_in[0].Extents.y, gs_in[0].Extents.z, gs_in[0].BlockType); + } + else if(gs_in[0].Extents.y == 0){ + TexCoord = vec3(0.0, gs_in[0].Extents.z, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, gs_in[0].Extents.z, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(gs_in[0].Extents.x, 0.0, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(gs_in[0].Extents.x, 0.0, 0.0, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(gs_in[0].Extents.x, gs_in[0].Extents.z, gs_in[0].BlockType); + } + else{ + TexCoord = vec3(gs_in[0].Extents.x, 0.0, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(gs_in[0].Extents.x, 0.0, 0.0, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(0.0, gs_in[0].Extents.y, gs_in[0].BlockType); + gl_Position = gl_in[0].gl_Position + vec4(0.0, gs_in[0].Extents.y, 0.0, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + TexCoord = vec3(gs_in[0].Extents.x, gs_in[0].Extents.y, gs_in[0].BlockType); + } + + gl_Position = gl_in[0].gl_Position + vec4(gs_in[0].Extents, 0.0); + FragPos = vec3(gl_Position); + gl_Position = projection * view * gl_Position; + EmitVertex(); + + EndPrimitive(); +} diff --git a/shaders/shader-texture.vs b/shaders/shader-texture.vs index 6c00ad8..9c97c8a 100644 --- a/shaders/shader-texture.vs +++ b/shaders/shader-texture.vs @@ -1,22 +1,27 @@ #version 330 core layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec3 aTexCoord; +layout (location = 1) in vec3 aExtents; +layout (location = 2) in vec2 aInfo; uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; -out vec3 vNormal; -out vec3 vTexCoord; -out vec3 FragPos; +out VS_OUT { + vec3 Extents; + vec3 Normal; + float BlockType; +} vs_out; void main() { - vTexCoord = aTexCoord; - vNormal = mat3(transpose(inverse(model))) * aNormal; + //vNormal = mat3(transpose(inverse(model))) * aNormal; + vs_out.Extents = aExtents; + vs_out.BlockType = aInfo.y; - FragPos = vec3(model*vec4(aPos, 1.0)); - gl_Position = projection * view * model * vec4(aPos, 1.0); + if(aExtents.x == 0) vs_out.Normal = vec3(1.0 - 2*aInfo.x, 0.0, 0.0); + else if(aExtents.y == 0) vs_out.Normal = vec3(0.0, 1.0 - 2*aInfo.x, 0.0); + else vs_out.Normal = vec3(0.0, 0.0, 1.0 - 2*aInfo.x); + vs_out.Normal = mat3(transpose(inverse(model))) * vs_out.Normal; + + gl_Position = model * vec4(aPos, 1.0); } diff --git a/src/chunk.cpp b/src/chunk.cpp index 66feb49..b14fffc 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -28,18 +28,17 @@ namespace Chunk void Chunk::createBuffers(){ glGenVertexArrays(1, &(this->VAO)); - glGenBuffers(1, &(this->colorBuffer)); glGenBuffers(1, &(this->VBO)); - glGenBuffers(1, &(this->EBO)); + glGenBuffers(1, &(this->extentsBuffer)); + glGenBuffers(1, &(this->texinfoBuffer)); } void Chunk::deleteBuffers(){ - glDeleteBuffers(1, &(this->colorBuffer)); - glDeleteBuffers(1, &(this->VBO)); - glDeleteBuffers(1, &(this->EBO)); + glDeleteBuffers(1, &(this->VBO)); + glDeleteBuffers(1, &(this->extentsBuffer)); + glDeleteBuffers(1, &(this->texinfoBuffer)); glDeleteVertexArrays(1, &(this->VAO)); - } Block Chunk::getBlock(int x, int y, int z) diff --git a/src/chunkmanager.cpp b/src/chunkmanager.cpp index 077f52a..05ed813 100644 --- a/src/chunkmanager.cpp +++ b/src/chunkmanager.cpp @@ -115,8 +115,8 @@ namespace chunkmanager if(x > 1023 || y > 1023 || z > 1023) continue; const uint32_t index = calculateIndex(x, y, z); - delete n; chunks.erase(index); + //delete n; nUnloaded++; } } diff --git a/src/chunkmesher.cpp b/src/chunkmesher.cpp index 3fcc324..4ddb2bb 100755 --- a/src/chunkmesher.cpp +++ b/src/chunkmesher.cpp @@ -41,8 +41,8 @@ void mesh(Chunk::Chunk* chunk) mesh_data->numVertices = 0; mesh_data->chunk = chunk; mesh_data->vertices.clear(); - mesh_data->indices.clear(); - mesh_data->colors.clear(); + mesh_data->extents.clear(); + mesh_data->texinfo.clear(); // Abort if chunk is empty if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)){ @@ -179,13 +179,19 @@ void mesh(Chunk::Chunk* chunk) dv[2] = 0; dv[v] = h; - quad(mesh_data, glm::vec3(x[0], x[1], x[2]), - glm::vec3(x[0] + du[0], x[1] + du[1], x[2] + du[2]), - glm::vec3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], - x[2] + du[2] + dv[2]), - glm::vec3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), - glm::vec3(backFace ? q[0] : -q[0], backFace ? q[1] : -q[1], backFace ? q[2] : -q[2] ), - mask[n], dim, backFace); + // bottom left + mesh_data->vertices.push_back(x[0]); //bottomLeft.x + mesh_data->vertices.push_back(x[1]); //bottomLeft.y + mesh_data->vertices.push_back(x[2]); //bottomLeft.z + + // extents, use normals for now + mesh_data->extents.push_back(du[0] + dv[0]); + mesh_data->extents.push_back(du[1] + dv[1]); + mesh_data->extents.push_back(du[2] + dv[2]); + + mesh_data->texinfo.push_back(backFace ? 0.0 : 1.0); + mesh_data->texinfo.push_back((int)(mask[n]) - 2); + mesh_data->numVertices++; } for (l = 0; l < h; ++l) @@ -228,143 +234,36 @@ void sendtogpu(MeshData* mesh_data) // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(mesh_data->chunk->VAO); + // position attribute glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->VBO); glBufferData(GL_ARRAY_BUFFER, mesh_data->vertices.size() * sizeof(GLfloat), &(mesh_data->vertices[0]), GL_STATIC_DRAW); - - // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); // normal attribute - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void *)(3* - sizeof(float))); + glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->extentsBuffer); + glBufferData(GL_ARRAY_BUFFER, mesh_data->extents.size() * sizeof(GLfloat), &(mesh_data->extents[0]), GL_STATIC_DRAW); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)(0)); glEnableVertexAttribArray(1); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh_data->chunk->EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh_data->indices.size() * sizeof(GLuint), &(mesh_data->indices[0]), GL_STATIC_DRAW); - // texcoords attribute - glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->colorBuffer); - glBufferData(GL_ARRAY_BUFFER, mesh_data->colors.size() * sizeof(GLfloat), &(mesh_data->colors[0]), GL_STATIC_DRAW); - + glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->texinfoBuffer); + glBufferData(GL_ARRAY_BUFFER, mesh_data->texinfo.size() * sizeof(GLfloat), &(mesh_data->texinfo[0]), GL_STATIC_DRAW); glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); glBindVertexArray(0); // save the number of indices of the mesh, it is needed later for drawing - mesh_data->chunk->numTriangles = (GLuint)(mesh_data->indices.size()); + mesh_data->chunk->numVertices = (GLuint)(mesh_data->numVertices); // once data has been sent to the GPU, it can be cleared from system RAM mesh_data->vertices.clear(); - mesh_data->indices.clear(); - mesh_data->colors.clear(); + mesh_data->extents.clear(); + mesh_data->texinfo.clear(); } // mark the chunk mesh has loaded on GPU mesh_data->chunk->setState(Chunk::CHUNK_STATE_MESH_LOADED, true); } - -void quad(MeshData* mesh_data, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, - glm::vec3 bottomRight, glm::vec3 normal, Block block, int dim, bool backFace) -{ - mesh_data->vertices.push_back(bottomLeft.x); - mesh_data->vertices.push_back(bottomLeft.y); - mesh_data->vertices.push_back(bottomLeft.z); - mesh_data->vertices.push_back(normal.x); - mesh_data->vertices.push_back(normal.y); - mesh_data->vertices.push_back(normal.z); - - mesh_data->vertices.push_back(bottomRight.x); - mesh_data->vertices.push_back(bottomRight.y); - mesh_data->vertices.push_back(bottomRight.z); - mesh_data->vertices.push_back(normal.x); - mesh_data->vertices.push_back(normal.y); - mesh_data->vertices.push_back(normal.z); - - mesh_data->vertices.push_back(topLeft.x); - mesh_data->vertices.push_back(topLeft.y); - mesh_data->vertices.push_back(topLeft.z); - mesh_data->vertices.push_back(normal.x); - mesh_data->vertices.push_back(normal.y); - mesh_data->vertices.push_back(normal.z); - - mesh_data->vertices.push_back(topRight.x); - mesh_data->vertices.push_back(topRight.y); - mesh_data->vertices.push_back(topRight.z); - mesh_data->vertices.push_back(normal.x); - mesh_data->vertices.push_back(normal.y); - mesh_data->vertices.push_back(normal.z); - - // texcoords - if(dim == 0){ - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(bottomRight.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(bottomRight.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topLeft.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(topLeft.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topRight.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(topRight.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - }else if(dim == 1){ - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(bottomRight.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(bottomRight.x - bottomLeft.x)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topLeft.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(topLeft.x - bottomLeft.x)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topRight.z - bottomLeft.z)); - mesh_data->colors.push_back(abs(topRight.x - bottomLeft.x)); - mesh_data->colors.push_back(((int)block) - 2); - }else{ - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(0); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(bottomRight.x - bottomLeft.x)); - mesh_data->colors.push_back(abs(bottomRight.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topLeft.x - bottomLeft.x)); - mesh_data->colors.push_back(abs(topLeft.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - - mesh_data->colors.push_back(abs(topRight.x - bottomLeft.x)); - mesh_data->colors.push_back(abs(topRight.y - bottomLeft.y)); - mesh_data->colors.push_back(((int)block) - 2); - } - - if (backFace) - { - mesh_data->indices.push_back(mesh_data->numVertices + 2); - mesh_data->indices.push_back(mesh_data->numVertices); - mesh_data->indices.push_back(mesh_data->numVertices + 1); - mesh_data->indices.push_back(mesh_data->numVertices + 1); - mesh_data->indices.push_back(mesh_data->numVertices + 3); - mesh_data->indices.push_back(mesh_data->numVertices + 2); - } - else - { - mesh_data->indices.push_back(mesh_data->numVertices + 2); - mesh_data->indices.push_back(mesh_data->numVertices + 3); - mesh_data->indices.push_back(mesh_data->numVertices + 1); - mesh_data->indices.push_back(mesh_data->numVertices + 1); - mesh_data->indices.push_back(mesh_data->numVertices); - mesh_data->indices.push_back(mesh_data->numVertices + 2); - } - mesh_data->numVertices += 4; -} }; diff --git a/src/main.cpp b/src/main.cpp index fdb4efa..8769986 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,7 +58,8 @@ int main() glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetCursorPosCallback(window, mouse_callback); glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); //GL_BACK GL_CCW by default + //glEnable(GL_FRAMEBUFFER_SRGB); //gamma correction done in fragment shader + //glEnable(GL_CULL_FACE); //GL_BACK GL_CCW by default std::cout << "Using GPU: " << glGetString(GL_VENDOR) << " " << glGetString(GL_RENDERER) << "\n"; diff --git a/src/renderer.cpp b/src/renderer.cpp index 7fb41a5..6df7c4a 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -23,7 +23,7 @@ namespace renderer{ void init(){ // Create Shader - theShader = new Shader{"shaders/shader-texture.vs", "shaders/shader-texture.fs"}; + theShader = new Shader{"shaders/shader-texture.gs", "shaders/shader-texture.vs", "shaders/shader-texture.fs"}; // Create 3d array texture constexpr int layerCount = 3; @@ -96,14 +96,14 @@ namespace renderer{ if (!out) { - if(c->numTriangles > 0) + if(c->numVertices > 0) { theShader->setMat4("model", model); theShader->setMat4("view", theCamera.getView()); theShader->setMat4("projection", theCamera.getProjection()); glBindVertexArray(c->VAO); - glDrawElements(GL_TRIANGLES, c->numTriangles , GL_UNSIGNED_INT, 0); + glDrawArrays(GL_POINTS, 0, c->numVertices); glBindVertexArray(0); } } diff --git a/textures/oak_log.png b/textures/oak_log.png new file mode 100644 index 0000000..842ffab Binary files /dev/null and b/textures/oak_log.png differ