From 1a4412c5b19520d58001e47dc5e580183c507d5a Mon Sep 17 00:00:00 2001 From: EmaMaker Date: Mon, 10 Apr 2023 00:21:49 +0200 Subject: [PATCH] renderer: initial texture support via ArrayTextures totally stolen textures from minecraft --- include/chunkmesher.hpp | 2 +- include/intervalmap.hpp | 2 +- shaders/shader-texture.fs | 44 +++++++++++++++++++ shaders/shader-texture.vs | 22 ++++++++++ src/chunkgenerator.cpp | 2 +- src/chunkmesher.cpp | 89 +++++++++++++++++++++++--------------- src/main.cpp | 2 +- src/renderer.cpp | 31 +++++++++++-- textures/cobblestone.png | Bin 0 -> 265 bytes textures/dirt.png | Bin 0 -> 266 bytes textures/grass_top.png | Bin 0 -> 633 bytes 11 files changed, 151 insertions(+), 43 deletions(-) create mode 100644 shaders/shader-texture.fs create mode 100644 shaders/shader-texture.vs create mode 100644 textures/cobblestone.png create mode 100644 textures/dirt.png create mode 100644 textures/grass_top.png diff --git a/include/chunkmesher.hpp b/include/chunkmesher.hpp index 5f50b98..5533568 100644 --- a/include/chunkmesher.hpp +++ b/include/chunkmesher.hpp @@ -17,7 +17,7 @@ namespace chunkmesher{ void draw(Chunk::Chunk* chunk, glm::mat4 model); void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, - glm::vec3 bottomRight, glm::vec3 normal, Block block, bool backFace); + glm::vec3 bottomRight, glm::vec3 normal, Block block, int dim, bool backFace); } diff --git a/include/intervalmap.hpp b/include/intervalmap.hpp index f5d1f9d..6f7222b 100644 --- a/include/intervalmap.hpp +++ b/include/intervalmap.hpp @@ -39,7 +39,7 @@ public: treemap[end] = end_prev_entry->second; // A little optimization: delete next key if it is of the same value of the end key - if(end_next_entry->second == treemap[end]) treemap.erase(end_next_entry); + //if(end_next_entry->second == treemap[end]) treemap.erase(end_next_entry); } // insert the start key. Replaces whatever value is already there. Do not place if the element before is of the same value diff --git a/shaders/shader-texture.fs b/shaders/shader-texture.fs new file mode 100644 index 0000000..6da90fc --- /dev/null +++ b/shaders/shader-texture.fs @@ -0,0 +1,44 @@ +#version 330 core + +out vec4 FragColor; + +in vec3 vNormal; +in vec3 vTexCoord; +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; + +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); + + // Blinn-Phong lighting + // Ambient + vec3 ambient = lightColor*vColor; + + // Diffuse + float diff = max(dot(normal, lightDir), 0.0); + vec3 diffuse = vColor * diff; + + // Blinn Specular + vec3 viewDir = normalize(viewPos - FragPos); + vec3 halfwayDir = normalize(lightDir + viewDir); + float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0); + vec3 specular = lightColor * vColor * spec; + + // Final color + vec3 color = ambient * ambientStrength + diffuse * diffuseStrength + specular * specularStrength; + FragColor.rgb = color; +} diff --git a/shaders/shader-texture.vs b/shaders/shader-texture.vs new file mode 100644 index 0000000..6c00ad8 --- /dev/null +++ b/shaders/shader-texture.vs @@ -0,0 +1,22 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec3 aTexCoord; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +out vec3 vNormal; +out vec3 vTexCoord; +out vec3 FragPos; + +void main() +{ + vTexCoord = aTexCoord; + vNormal = mat3(transpose(inverse(model))) * aNormal; + + FragPos = vec3(model*vec4(aPos, 1.0)); + gl_Position = projection * view * model * vec4(aPos, 1.0); +} diff --git a/src/chunkgenerator.cpp b/src/chunkgenerator.cpp index 9cf6111..c80a0c6 100644 --- a/src/chunkgenerator.cpp +++ b/src/chunkgenerator.cpp @@ -23,7 +23,7 @@ void generateNoise3D(Chunk::Chunk *chunk); void generateChunk(Chunk::Chunk *chunk) { - generateNoise3D(chunk); + generateNoise(chunk); } Block block; diff --git a/src/chunkmesher.cpp b/src/chunkmesher.cpp index 82b56f4..b3d4e56 100755 --- a/src/chunkmesher.cpp +++ b/src/chunkmesher.cpp @@ -152,7 +152,7 @@ void mesh(Chunk::Chunk* chunk) 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], backFace); + mask[n], dim, backFace); } for (l = 0; l < h; ++l) @@ -205,7 +205,7 @@ void sendtogpu(Chunk::Chunk* chunk) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk->EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, chunk->indices.size() * sizeof(GLuint), &(chunk->indices[0]), GL_STATIC_DRAW); - // color attribute + // texcoords attribute glBindBuffer(GL_ARRAY_BUFFER, chunk->colorBuffer); glBufferData(GL_ARRAY_BUFFER, chunk->colors.size() * sizeof(GLfloat), &(chunk->colors[0]), GL_STATIC_DRAW); @@ -228,7 +228,7 @@ void sendtogpu(Chunk::Chunk* chunk) } void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight, - glm::vec3 bottomRight, glm::vec3 normal, Block block, bool backFace) + glm::vec3 bottomRight, glm::vec3 normal, Block block, int dim, bool backFace) { chunk->vertices.push_back(bottomLeft.x); @@ -259,6 +259,56 @@ void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec chunk->vertices.push_back(normal.y); chunk->vertices.push_back(normal.z); + // texcoords + if(dim == 0){ + chunk->colors.push_back(0); + chunk->colors.push_back(0); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(bottomRight.z - bottomLeft.z)); + chunk->colors.push_back(abs(bottomRight.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topLeft.z - bottomLeft.z)); + chunk->colors.push_back(abs(topLeft.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topRight.z - bottomLeft.z)); + chunk->colors.push_back(abs(topRight.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + }else if(dim == 1){ + chunk->colors.push_back(0); + chunk->colors.push_back(0); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(bottomRight.z - bottomLeft.z)); + chunk->colors.push_back(abs(bottomRight.x - bottomLeft.x)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topLeft.z - bottomLeft.z)); + chunk->colors.push_back(abs(topLeft.x - bottomLeft.x)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topRight.z - bottomLeft.z)); + chunk->colors.push_back(abs(topRight.x - bottomLeft.x)); + chunk->colors.push_back(((int)block) - 2); + }else{ + chunk->colors.push_back(0); + chunk->colors.push_back(0); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(bottomRight.x - bottomLeft.x)); + chunk->colors.push_back(abs(bottomRight.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topLeft.x - bottomLeft.x)); + chunk->colors.push_back(abs(topLeft.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + + chunk->colors.push_back(abs(topRight.x - bottomLeft.x)); + chunk->colors.push_back(abs(topRight.y - bottomLeft.y)); + chunk->colors.push_back(((int)block) - 2); + } if (backFace) { @@ -279,38 +329,5 @@ void quad(Chunk::Chunk* chunk, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec chunk->indices.push_back(chunk->vIndex + 2); } chunk->vIndex += 4; - - // ugly switch case for colors - GLfloat r, g, b; - switch (block) - { - case Block::STONE: - r = 0.588f; - g = 0.588f; - b = 0.588f; - break; - case Block::GRASS: - r = 0.05f; - g = 0.725f; - b = 0.0f; - break; - case Block::DIRT: - r = 0.152f; - g = 0.056f; - b = 0.056f; - break; - default: - r = 0.0f; - g = 0.0f; - b = 0.0f; - break; - } - - for (int i = 0; i < 4; i++) - { - chunk->colors.push_back(r); - chunk->colors.push_back(g); - chunk->colors.push_back(b); - } } }; diff --git a/src/main.cpp b/src/main.cpp index 448003e..d4fe9d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,7 +81,7 @@ int main() lastFPSFrame = currentFrame; } - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClearColor(0.431f, 0.694f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Input processing diff --git a/src/renderer.cpp b/src/renderer.cpp index 1bb2057..b2450a8 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1,15 +1,39 @@ +#include "renderer.hpp" + #include "chunkmanager.hpp" #include "chunkmesher.hpp" -#include "renderer.hpp" #include "globals.hpp" +#include "stb_image.h" + namespace renderer{ Shader* theShader; + GLuint chunkTexture; Shader* getRenderShader() { return theShader; } void init(){ - theShader = new Shader{"shaders/shader.vs", "shaders/shader.fs"}; + // Create Shader + theShader = new Shader{"shaders/shader-texture.vs", "shaders/shader-texture.fs"}; + + // Create 3d array texture + constexpr int layerCount = 3; + glGenTextures(1, &chunkTexture); + glBindTexture(GL_TEXTURE_2D_ARRAY, chunkTexture); + + int width, height, nrChannels; + unsigned char *texels = stbi_load("textures/cobblestone.png", &width, &height, &nrChannels, 0); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, width, height, layerCount, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texels); + unsigned char *texels1 = stbi_load("textures/dirt.png", &width, &height, &nrChannels, 0); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 1, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, texels1); + unsigned char *texels2 = stbi_load("textures/grass_top.png", &width, &height, &nrChannels, 0); + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, width, height, 1, GL_RGB, GL_UNSIGNED_BYTE, texels2); + + glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_REPEAT); } void render(){ @@ -22,6 +46,8 @@ namespace renderer{ int chunkY=static_cast(cameraPos.y) / CHUNK_SIZE; int chunkZ=static_cast(cameraPos.z) / CHUNK_SIZE; + theShader->use(); + theShader->setVec3("viewPos", cameraPos); for(int i = 0; i < chunks_volume; i++) { Chunk::Chunk* c = chunkmanager::getChunks().at(chunkmanager::calculateIndex(chunkmanager::getChunksIndices()[i][0] + chunkX, chunkmanager::getChunksIndices()[i][1] + chunkY, chunkmanager::getChunksIndices()[i][2] + chunkZ)); @@ -55,7 +81,6 @@ namespace renderer{ if(c->getState(Chunk::CHUNK_STATE_MESH_LOADED) && c->vIndex > 0) { // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // wireframe mode - theShader->use(); theShader->setMat4("model", model); theShader->setMat4("view", theCamera.getView()); theShader->setMat4("projection", theCamera.getProjection()); diff --git a/textures/cobblestone.png b/textures/cobblestone.png new file mode 100644 index 0000000000000000000000000000000000000000..80fa3a83f228bee9fcb132a0d5f34d2bc6da1d38 GIT binary patch literal 265 zcmV+k0rvihP)DY;#22M^*(uo#%Svfs#D}TMr%gT0ETKB8izL_GXWxq(=HDBxj1H*mL>`y(X P00000NkvXXu0mjfB?5D{ literal 0 HcmV?d00001 diff --git a/textures/dirt.png b/textures/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..617d353e0d67a14a2952b2a98375eb8a50b97d79 GIT binary patch literal 266 zcmV+l0rmcgP)7w`V=NDEI+d2EruJ8Nt`?O29*Y((K z=DVK`tGLh7MTtz%ds&v@Ga&DZ$;xQ1!Z)iihj}Hm*4l8eo1~Im3;+ie&}VWdpbDk0 z+*Vd{tJH?~A!2frcub(;r0KIVImhR2X8sP4PM&T#KQlJngXEsPNu_c;# zj2A0tbfmyB_f1S^g6x^QT2YWaZ|9A0rZL;l$|NdG{#j@PkUL`URB(A|ju9BN2CqZ0*2Lvm$NhX`==|8vas^a_b z{f8ezM{RA=&ROwL!?NnOL*L<^)LBqP01bVWrwoL)KN>D-4J1pn~Qa?L|W*C-}2cD;oP*NJT~0w4g}&MC79Y_}qy^Qy}5^p)Q}G$u!VelBTYTS4n> z<*;>F7}AZeBmeUHw`pS+DD-43JU&k5*B{>89dIkA3pg{p7_1A%RxCat{Ca=c8{e1uKXRNh)wW+u*mnSa@mpOF-mZ-OpJInJ8 zTI9x)8uRU$0iijQiK`mIPuKnLf4B3!U6VEznwpZDLr=RJR?SJ?zGg29>I4P T)HuKG00000NkvXXu0mjftdcDi literal 0 HcmV?d00001