From edfefd1898ed78174b5fbe1c1e198b456a47237a Mon Sep 17 00:00:00 2001 From: UIS Date: Sun, 8 Nov 2020 21:18:18 +0300 Subject: [PATCH] Refactor renderer --- cwd/assets/altcraft/shaders/face.json | 2 +- cwd/assets/altcraft/shaders/frag/face.fs | 50 +++-- cwd/assets/altcraft/shaders/vert/face.vs | 85 ++++---- src/AssetManager.cpp | 61 +++--- src/AssetManager.hpp | 11 +- src/Framebuffer.cpp | 3 +- src/Game.cpp | 2 +- src/GameState.cpp | 2 - src/ModLoader.cpp | 7 +- src/Render.cpp | 42 ++-- src/Render.hpp | 2 +- src/RendererEntity.cpp | 4 +- src/RendererSection.cpp | 244 +++++++++-------------- src/RendererSection.hpp | 27 ++- src/RendererSectionData.cpp | 67 +++++-- src/RendererSectionData.hpp | 10 +- src/RendererWorld.cpp | 41 ++-- src/Shader.cpp | 7 +- src/Shader.hpp | 6 +- src/TextureAtlas.cpp | 19 +- src/TextureAtlas.hpp | 9 +- 21 files changed, 334 insertions(+), 367 deletions(-) diff --git a/cwd/assets/altcraft/shaders/face.json b/cwd/assets/altcraft/shaders/face.json index 840e6708..7e165dba 100644 --- a/cwd/assets/altcraft/shaders/face.json +++ b/cwd/assets/altcraft/shaders/face.json @@ -8,4 +8,4 @@ "MinLightLevel", "GlobalTime" ] -} \ No newline at end of file +} diff --git a/cwd/assets/altcraft/shaders/frag/face.fs b/cwd/assets/altcraft/shaders/frag/face.fs index 98b389a4..e1517459 100644 --- a/cwd/assets/altcraft/shaders/frag/face.fs +++ b/cwd/assets/altcraft/shaders/frag/face.fs @@ -1,48 +1,44 @@ #version 330 core +precision lowp float; + +in vec2 UvPosition; +flat in uint Layer; in VS_OUT { - vec2 UvPosition; - vec3 Texture; - vec3 Color; - vec2 Light; + flat float Light; + flat vec3 Color; } fs_in; uniform sampler2DArray textureAtlas; -uniform float DayTime; -uniform float MinLightLevel; + vec3 rgb2hsv(vec3 c) { - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } vec3 hsv2rgb(vec3 c) { - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } void main() { - vec4 color = texture(textureAtlas,fs_in.Texture); - if (color.a < 0.3) - discard; + vec4 color = texture(textureAtlas, vec3(UvPosition, Layer)); + if (color.a < 0.3) + discard; - vec3 hsvColor = rgb2hsv(color.xyz); - hsvColor+=fs_in.Color; + vec3 hsvColor = rgb2hsv(color.xyz); + hsvColor+=fs_in.Color; color = vec4(hsv2rgb(hsvColor),1); - float light = fs_in.Light.x / 15.0; - float skyLight = (fs_in.Light.y / 15.0) * DayTime; - - float faceLight = clamp(light + skyLight,MinLightLevel,1.0); - - color = vec4(color.rgb * faceLight, color.a); + color.rgb *= fs_in.Light; gl_FragColor = color; -} \ No newline at end of file +} diff --git a/cwd/assets/altcraft/shaders/vert/face.vs b/cwd/assets/altcraft/shaders/vert/face.vs index 30ae0d73..588a0c04 100644 --- a/cwd/assets/altcraft/shaders/vert/face.vs +++ b/cwd/assets/altcraft/shaders/vert/face.vs @@ -1,47 +1,56 @@ #version 330 core +precision mediump float; +precision mediump int; -layout (location = 0) in vec3 position; -layout (location = 2) in vec2 UvCoordinates; -layout (location = 7) in vec4 Texture; -layout (location = 8) in mat4 model; -layout (location = 12) in vec3 color; -layout (location = 13) in vec2 light; -layout (location = 14) in float TextureLayer; -layout (location = 15) in float TextureFrames; +uniform float GlobalTime; +uniform float DayTime; +uniform float MinLightLevel; +uniform mat4 projView; + +//Per quad info + +//xx yy ww hh 4*2=8 +//p h l f 4*1=4 //12 +//T(L1){Uu} (L2){Vv} 2*2=4 //16 + +layout(location = 0) in uvec2 qinfo; +layout(location = 1) in vec2 uv; +layout(location = 2) in vec3 positions[4]; +//3 +//4 +//5 +layout(location = 6) in uvec4 utex; +layout(location = 7) in uvec4 phlf; + +out vec2 UvPosition; +flat out uint Layer; out VS_OUT { - vec2 UvPosition; - vec3 Texture; - vec3 Color; - vec2 Light; + flat float Light; + flat vec3 Color; } vs_out; -uniform float GlobalTime; -uniform mat4 projView; +//Intel SNB: VS vec4 shader: 55 instructions. 0 loops. 196 cycles. 0:0 spills:fills, 1 sends. Compacted 880 to 864 bytes (2%) -vec3 TransformTextureCoord(vec4 TextureAtlasCoords, vec2 UvCoords, float Layer) { - float x = TextureAtlasCoords.x; - float y = TextureAtlasCoords.y; -// float w = TextureAtlasCoords.z; - float h = TextureAtlasCoords.w; - vec2 transformed = vec2(x, 1 - y - h) + UvCoords * TextureAtlasCoords.zw; - return vec3(transformed.x, transformed.y, Layer); -} +void main() { + gl_Position = projView * vec4(positions[gl_VertexID], 1.0); + + vec4 subUV = vec4( + uvec4(qinfo, qinfo >> uint(5)) & uint(0x1F) + ) / 16.0; + + vec4 tex = vec4(utex) / 1024.0; + float frames = float(phlf.w); + tex.w /= frames; + tex.y += trunc(mod(GlobalTime * 4.0f, frames)) * tex.w; + + tex.xy += subUV.xy * tex.zw; + tex.zw = (subUV.zw-subUV.xy) * tex.zw; + + UvPosition = tex.xy + tex.zw*uv; + Layer = phlf.z; -void main() -{ - vec4 sourcePosition = vec4(position,1.0f); - gl_Position = projView * model * sourcePosition; - - vec4 texturePos = Texture; - float frameHeight = texturePos.w / TextureFrames; - float currentFrame = mod(GlobalTime * 4.0f, TextureFrames); - currentFrame = trunc(currentFrame); - texturePos.w = frameHeight; - texturePos.y = texturePos.y + currentFrame * frameHeight; - - vs_out.UvPosition = UvCoordinates; - vs_out.Texture = TransformTextureCoord(texturePos,UvCoordinates,TextureLayer); - vs_out.Color = color; - vs_out.Light = light; + vec2 light = vec2((qinfo >> uint(10)) & uint(0xF)) / 15.0; + vs_out.Light = clamp(light.x + (light.y * DayTime), MinLightLevel, 1.0); + vs_out.Color = vec3(0.275, 0.63, 0.1) * (qinfo.x>>14); } diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index af6fb94d..fdfb13b9 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -101,6 +101,7 @@ void LoadTextures() { data.data = std::move(textureAsset->textureData); data.width = textureAsset->realWidth; data.height = textureAsset->realHeight; + data.frames = textureAsset->frames; textureData.push_back(data); textureAsset->id = id++; }); @@ -257,17 +258,20 @@ void ParseBlockModels() { break; } parsedFace.transform = faceTransform; - TextureCoord texture; - unsigned int textureFrames = 1; + uint16_t textureId, frames; textureName = face.second.texture; if (model.Textures.empty()) { - texture = AssetManager::GetTexture("minecraft/textures/error"); - } - else { + AssetTreeNode *node = AssetManager::GetAssetByAssetName("/minecraft/textures/error"); + AssetTexture *assetTexture = nullptr; + if (node && node->type == AssetTreeNode::ASSET_TEXTURE) + assetTexture = reinterpret_cast(node->asset.get()); + textureId = assetTexture->id; + frames = assetTexture->frames; + } else { while (textureName[0] == '#') { textureName.erase(0, 1); auto textureIt = model.Textures.find(textureName); - textureName = textureIt != model.Textures.end() ? textureIt->second : "minecraft/textures/error"; + textureName = textureIt != model.Textures.end() ? textureIt->second : "error"; } textureName.insert(0, "/minecraft/textures/"); AssetTreeNode *node = AssetManager::GetAssetByAssetName(textureName); @@ -275,37 +279,24 @@ void ParseBlockModels() { if (node && node->type == AssetTreeNode::ASSET_TEXTURE) assetTexture = reinterpret_cast(node->asset.get()); - texture = atlas->GetTexture(assetTexture->id); - textureFrames = assetTexture->frames; - - if (!(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,16,0,16 }) && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,0,0 }) - && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,16,16 })) { - double x = face.second.uv.x1; - double y = face.second.uv.x1; - double w = face.second.uv.x2 - face.second.uv.x1; - double h = face.second.uv.y2 - face.second.uv.y1; - x /= 16.0; - y /= 16.0; - w /= 16.0; - h /= 16.0; - double X = texture.x; - double Y = texture.y; - double W = texture.w; - double H = texture.h; - - texture.x = X + x * W; - texture.y = Y + y * H; - texture.w = w * W; - texture.h = h * H; - } + textureId = assetTexture->id; + frames = assetTexture->frames; } - parsedFace.texture = glm::vec4{ texture.x,texture.y,texture.w,texture.h }; - parsedFace.layer = texture.layer; - parsedFace.frames = textureFrames; + TextureCoord tc = atlas->GetTexture(textureId); + parsedFace.x = tc.pixelX; + parsedFace.y = tc.pixelY; + parsedFace.w = tc.pixelW; + parsedFace.h = tc.pixelH; + parsedFace.layer = tc.layer; + + parsedFace.frames = frames; + parsedFace.textureId = textureId; + parsedFace.Uu = (face.second.uv.x2<<5)|face.second.uv.x1; + parsedFace.Vv = (face.second.uv.y2<<5)|face.second.uv.y1; if (face.second.tintIndex) - parsedFace.color = glm::vec3(0.275, 0.63, 0.1); + parsedFace.tint = true; else - parsedFace.color = glm::vec3(0, 0, 0); + parsedFace.tint = false; model.parsedFaces.push_back(parsedFace); } @@ -411,7 +402,7 @@ AssetTreeNode *AssetManager::GetAssetByAssetName(const std::string & assetName) return node; } -GLuint AssetManager::GetTextureAtlasId() +GLuint AssetManager::GetTextureAtlasId() noexcept { return atlas->GetRawTextureId(); } diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 33b9ebcc..000adcfb 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -39,10 +39,11 @@ static const Vector FaceDirectionVector[] = { struct ParsedFace { FaceDirection visibility; glm::mat4 transform; - glm::vec4 texture; - float layer; - float frames; - glm::vec3 color; + uint16_t textureId; + uint16_t Uu, Vv;//10-bit + uint16_t x, y, w, h; + uint8_t layer, frames; + bool tint; }; struct BlockFaces { @@ -197,7 +198,7 @@ namespace AssetManager { Asset *GetAssetPtr(const std::string &assetName); AssetTreeNode *GetAssetByAssetName(const std::string &assetName); - GLuint GetTextureAtlasId(); + GLuint GetTextureAtlasId() noexcept; TextureCoord GetTexture(const std::string &assetName); } diff --git a/src/Framebuffer.cpp b/src/Framebuffer.cpp index 03866331..f4963e0f 100644 --- a/src/Framebuffer.cpp +++ b/src/Framebuffer.cpp @@ -82,8 +82,7 @@ void Framebuffer::Activate() { void Framebuffer::RenderTo(Framebuffer &target) { OPTICK_EVENT(); - glBindFramebuffer(GL_FRAMEBUFFER, target.fbo); - glViewport(0, 0, target.width, target.height); + target.Clear(); AssetTreeNode *fbo = AssetManager::GetAssetByAssetName("/altcraft/shaders/fbo"); if (fbo->type == AssetTreeNode::ASSET_SHADER) reinterpret_cast(fbo->asset.get())->shader->Activate(); diff --git a/src/Game.cpp b/src/Game.cpp index d2fb1c33..9708f521 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -107,7 +107,7 @@ void InitEvents() { } if (message[0] == '!') message = message.substr(1); - auto packet = std::static_pointer_cast(std::make_shared(message)); + auto packet = std::static_pointer_cast(std::make_shared(message)); PUSH_EVENT("SendPacket",packet); }); diff --git a/src/GameState.cpp b/src/GameState.cpp index 885238b9..c4a5a53e 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -305,8 +305,6 @@ void GameState::UpdatePacket(std::shared_ptr ptr) { auto packet = std::static_pointer_cast(ptr); Entity &entity = world.GetEntity(packet->EntityId); entity.pos = entity.pos + Entity::DecodeDeltaPos(packet->DeltaX, packet->DeltaY, packet->DeltaZ); - if (entity.entityId != 0) - LOG(INFO) << "M: " << packet->EntityId; break; } diff --git a/src/ModLoader.cpp b/src/ModLoader.cpp index c8578b3d..09a1e476 100644 --- a/src/ModLoader.cpp +++ b/src/ModLoader.cpp @@ -176,11 +176,6 @@ void ModLoader::ParseAssetBlockModel(AssetTreeNode &node) noexcept { nlohmann::json modelData = nlohmann::json::parse(node.data); BlockModel model; - if (node.name == "button") { - int a = 15; - a++; - } - if (modelData.find("parent") != modelData.end()) { std::string parentName = modelData["parent"].get(); parentName = parentName.substr(parentName.find('/') + 1); @@ -266,6 +261,8 @@ void ModLoader::ParseAssetBlockModel(AssetTreeNode &node) noexcept { uv.x2 = face["uv"][2]; uv.y2 = face["uv"][3]; faceData.uv = uv; + } else { + faceData.uv = {0, 0, 16, 16}; } FaceDirection cullface = FaceDirection::none; diff --git a/src/Render.cpp b/src/Render.cpp index bcfe71f8..b775827d 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -59,7 +59,7 @@ Render::Render(unsigned int windowWidth, unsigned int windowHeight, SDL_GL_SetSwapInterval(0); framebuffer->Resize(renderState.WindowWidth * fieldResolutionScale, renderState.WindowHeight * fieldResolutionScale); - LOG(INFO) << "Supported threads: " << std::thread::hardware_concurrency(); + LOG(INFO) << "Supported threads: " << std::thread::hardware_concurrency(); } Render::~Render() { @@ -127,14 +127,16 @@ void Render::InitGlew() { SDL_GL_GetDrawableSize(window, &width, &height); glViewport(0, 0, width, height); glClearColor(0.8,0.8,0.8, 1.0f); - glEnable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_MULTISAMPLE); glCheckError(); if (glActiveTexture == nullptr) { throw std::runtime_error("GLEW initialization failed with unknown reason"); @@ -142,11 +144,11 @@ void Render::InitGlew() { } void Render::PrepareToRendering() { - //TextureAtlas texture + //Bind TextureAtlas glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_ARRAY, AssetManager::GetTextureAtlasId()); - ImGui_ImplSdlGL3_Init(window); + ImGui_ImplSdlGL3_Init(window); int width, height; SDL_GL_GetDrawableSize(window, &width, &height); @@ -178,19 +180,17 @@ void Render::UpdateKeyboard() { void Render::RenderFrame() { OPTICK_EVENT(); - framebuffer->Clear(); - Framebuffer::GetDefault().Clear(); - - if (renderWorld) - framebuffer->Activate(); - if (isWireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - if (renderWorld) - world->Render(renderState); - if (isWireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - if (renderWorld) + + if (renderWorld) { + framebuffer->Clear(); + if (isWireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + world->Render(renderState); + if (isWireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); framebuffer->RenderTo(Framebuffer::GetDefault()); + } else + Framebuffer::GetDefault().Clear(); RenderGui(); diff --git a/src/Render.hpp b/src/Render.hpp index 8e2e2335..10882b46 100644 --- a/src/Render.hpp +++ b/src/Render.hpp @@ -28,7 +28,7 @@ class Render { std::map isKeyPressed; bool HasFocus=true; float sensetivity = 0.1f; - bool isWireframe = false; + bool isWireframe = false; std::unique_ptr framebuffer; std::vector chatMessages; EventListener listener; diff --git a/src/RendererEntity.cpp b/src/RendererEntity.cpp index 62aac449..ab77a7ff 100644 --- a/src/RendererEntity.cpp +++ b/src/RendererEntity.cpp @@ -136,8 +136,6 @@ void RendererEntity::Render(RenderState& renderState, const World *world) { entityShader = reinterpret_cast(entityAsset->asset.get())->shader.get(); entityShader->SetUniform("model", model); entityShader->SetUniform("color", entity.renderColor); - glCheckError(); - glDrawArrays(GL_LINES, 0, 24); - glCheckError(); + glDrawArrays(GL_LINES, 0, 24); } diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp index 6c7e8112..0a0c3845 100644 --- a/src/RendererSection.cpp +++ b/src/RendererSection.cpp @@ -3,128 +3,72 @@ #include #include "Utility.hpp" -#include "Renderer.hpp" +#include "Render.hpp" #include "RendererSectionData.hpp" -const GLfloat vertices[] = { - 0, 0, 0, - 1, 0, 1, - 1, 0, 0, - - 0, 0, 0, - 0, 0, 1, - 1, 0, 1, -}; - -const GLfloat uv_coords[] = { - 0.0f, 0.0f, - 1.0f, 1.0f, - 0.0f, 1.0f, - - 0.0f, 0.0f, - 1.0f, 0.0f, - 1.0f, 1.0f, +static const GLfloat uv_coords[] = { + 0.f, 0.f, + 1.f, 0.f, + 0.f, 1.f, + 1.f, 1.f }; -const GLuint magicUniqueConstant = 88375; -GLuint RendererSection::VboVertices = magicUniqueConstant; -GLuint RendererSection::VboUvs = magicUniqueConstant; +GLuint RendererSection::VboUvs = 0; RendererSection::RendererSection(const RendererSectionData &data) { OPTICK_EVENT(); - if (VboVertices == magicUniqueConstant) { - glGenBuffers(1, &VboVertices); - glGenBuffers(1, &VboUvs); - - //Cube vertices - glBindBuffer(GL_ARRAY_BUFFER, VboVertices); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - //Cube UVs - glBindBuffer(GL_ARRAY_BUFFER, VboUvs); - glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW); - - LOG(INFO) << "Created VBOs with vertices (" << VboVertices << ") and UVs (" << VboUvs - << ") for faces"; - } - - glGenVertexArrays(1, &Vao); - - glGenBuffers(VBOCOUNT, Vbo); - - glBindVertexArray(Vao); - { - //Cube vertices - GLuint VertAttribPos = 0; - glBindBuffer(GL_ARRAY_BUFFER, VboVertices); - glVertexAttribPointer(VertAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(VertAttribPos); - - //Cube UVs - GLuint UvAttribPos = 2; - glBindBuffer(GL_ARRAY_BUFFER, VboUvs); - glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(UvAttribPos); - - //Textures - GLuint textureAttribPos = 7; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]); - glVertexAttribPointer(textureAttribPos, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(textureAttribPos); - glVertexAttribDivisor(textureAttribPos, 1); - glCheckError(); - - //TextureLayers - GLuint layerAttribPos = 14; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[LAYERS]); - glVertexAttribPointer(layerAttribPos, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(layerAttribPos); - glVertexAttribDivisor(layerAttribPos, 1); - glCheckError(); - - //TextureFrames - GLuint framesAttribPos = 15; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[FRAMES]); - glVertexAttribPointer(framesAttribPos, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(framesAttribPos); - glVertexAttribDivisor(framesAttribPos, 1); - glCheckError(); - - //Blocks models - GLuint matAttribPos = 8; - size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat); - glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); - glVertexAttribPointer(matAttribPos + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); - glVertexAttribPointer(matAttribPos + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(1 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(matAttribPos + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(2 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(matAttribPos + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(3 * 4 * sizeof(GLfloat))); - glEnableVertexAttribArray(matAttribPos + 0); - glEnableVertexAttribArray(matAttribPos + 1); - glEnableVertexAttribArray(matAttribPos + 2); - glEnableVertexAttribArray(matAttribPos + 3); - glVertexAttribDivisor(matAttribPos + 0, 1); - glVertexAttribDivisor(matAttribPos + 1, 1); - glVertexAttribDivisor(matAttribPos + 2, 1); - glVertexAttribDivisor(matAttribPos + 3, 1); - - //Color - GLuint colorAttribPos = 12; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[COLORS]); - glVertexAttribPointer(colorAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(colorAttribPos); - glVertexAttribDivisor(colorAttribPos, 1); - - //Light - GLuint lightAttribPos = 13; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[LIGHTS]); - glVertexAttribPointer(lightAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(lightAttribPos); - glVertexAttribDivisor(lightAttribPos, 1); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - glBindVertexArray(0); - glCheckError(); + if (!VboUvs) { + glGenBuffers(1, &VboUvs); + + glBindBuffer(GL_ARRAY_BUFFER, VboUvs); + glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW); + } + glGenBuffers(BUFCOUNT, buffers); + glGenVertexArrays(1, &vertexarray); + { + glBindVertexArray(vertexarray); + + glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFQUAD]); + GLuint TexAttribPos = 6; + glVertexAttribIPointer(TexAttribPos, 4, GL_UNSIGNED_SHORT, 4 * 4, 0); + glEnableVertexAttribArray(TexAttribPos); + glVertexAttribDivisor(TexAttribPos, 1); + + GLuint QuadAttribPos = 0; + glVertexAttribIPointer(QuadAttribPos, 2, GL_UNSIGNED_SHORT, 4 * 4, reinterpret_cast(3 * 4)); + glEnableVertexAttribArray(QuadAttribPos); + glVertexAttribDivisor(QuadAttribPos, 1); + + GLuint PhlfAttribPos = 7; + glVertexAttribIPointer(PhlfAttribPos, 4, GL_UNSIGNED_BYTE, 4 * 4, reinterpret_cast(2 * 4)); + glEnableVertexAttribArray(PhlfAttribPos); + glVertexAttribDivisor(PhlfAttribPos, 1); + + glBindBuffer(GL_ARRAY_BUFFER, VboUvs); + GLuint UvAttribPos = 1; + glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); + glEnableVertexAttribArray(UvAttribPos); + + //Vertices + glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFVERTS]); + GLuint PositionsAttribPos = 2; + glVertexAttribPointer(PositionsAttribPos+0, 3, GL_FLOAT, GL_FALSE, 3 * 4 * sizeof(GLfloat), 0); + glVertexAttribPointer(PositionsAttribPos+1, 3, GL_FLOAT, GL_FALSE, 3 * 4 * sizeof(GLfloat), reinterpret_cast(3 * 1 * sizeof(GLfloat))); + glVertexAttribPointer(PositionsAttribPos+2, 3, GL_FLOAT, GL_FALSE, 3 * 4 * sizeof(GLfloat), reinterpret_cast(3 * 2 * sizeof(GLfloat))); + glVertexAttribPointer(PositionsAttribPos+3, 3, GL_FLOAT, GL_FALSE, 3 * 4 * sizeof(GLfloat), reinterpret_cast(3 * 3 * sizeof(GLfloat))); + glEnableVertexAttribArray(PositionsAttribPos+0); + glEnableVertexAttribArray(PositionsAttribPos+1); + glEnableVertexAttribArray(PositionsAttribPos+2); + glEnableVertexAttribArray(PositionsAttribPos+3); + glVertexAttribDivisor(PositionsAttribPos+0, 1); + glVertexAttribDivisor(PositionsAttribPos+1, 1); + glVertexAttribDivisor(PositionsAttribPos+2, 1); + glVertexAttribDivisor(PositionsAttribPos+3, 1); + + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glCheckError(); UpdateData(data); } @@ -134,32 +78,32 @@ RendererSection::RendererSection(RendererSection && other) { swap(*this, other); } -RendererSection::~RendererSection() { - if (Vao != 0) - glDeleteVertexArrays(1, &Vao); - - for (int i = 0; i < VBOCOUNT; i++) - if (Vbo[i] != 0) { - glBindBuffer(GL_ARRAY_BUFFER, Vbo[i]); - glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_STATIC_DRAW); - } - - glDeleteBuffers(VBOCOUNT, Vbo); +RendererSection::~RendererSection() { + if (buffers[0] != 0) { + glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); + glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_STATIC_DRAW);//??? + glDeleteBuffers(BUFCOUNT, buffers); + glDeleteVertexArrays(1, &vertexarray); + } } void swap(RendererSection & lhs, RendererSection & rhs) { - std::swap(lhs.Vbo, rhs.Vbo); - std::swap(lhs.Vao, rhs.Vao); + std::swap(lhs.buffers, rhs.buffers); + std::swap(lhs.vertexarray, rhs.vertexarray); + std::swap(lhs.bufsizes, rhs.bufsizes); std::swap(lhs.hash, rhs.hash); std::swap(lhs.numOfFaces, rhs.numOfFaces); std::swap(lhs.sectionPos, rhs.sectionPos); } -void RendererSection::Render(RenderState &renderState) { +void RendererSection::Render() { OPTICK_EVENT(); - renderState.SetActiveVao(Vao); - glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces); - glCheckError(); + if (numOfFaces == 0) + return; + //Bind vertices texture + glBindVertexArray(vertexarray); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, numOfFaces); } Vector RendererSection::GetPosition() { @@ -172,28 +116,28 @@ size_t RendererSection::GetHash() { void RendererSection::UpdateData(const RendererSectionData & data) { OPTICK_EVENT(); - glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]); - glBufferData(GL_ARRAY_BUFFER, data.textures.size() * sizeof(glm::vec4), data.textures.data(), GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, Vbo[LAYERS]); - glBufferData(GL_ARRAY_BUFFER, data.textureLayers.size() * 1* sizeof(GLfloat), data.textureLayers.data(), GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, Vbo[FRAMES]); - glBufferData(GL_ARRAY_BUFFER, data.textureFrames.size() * 1 * sizeof(GLfloat), data.textureFrames.data(), GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); - glBufferData(GL_ARRAY_BUFFER, data.models.size() * sizeof(glm::mat4), data.models.data(), GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, Vbo[COLORS]); - glBufferData(GL_ARRAY_BUFFER, data.colors.size() * sizeof(glm::vec3), data.colors.data(), GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, Vbo[LIGHTS]); - glBufferData(GL_ARRAY_BUFFER, data.lights.size() * sizeof(glm::vec2), data.lights.data(), GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFVERTS]); + glBufferData(GL_ARRAY_BUFFER, bufsizes[BUFVERTS], NULL, GL_STATIC_DRAW);//Orphan buffer + GLsizeiptr newSize = data.verts.size() * sizeof(glm::vec3); + if (newSize > bufsizes[BUFVERTS]) {//Reallocate + glBufferData(GL_ARRAY_BUFFER, newSize, data.verts.data(), GL_STATIC_DRAW); + bufsizes[BUFVERTS] = newSize; + } else + glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, data.verts.data()); + + glBindBuffer(GL_ARRAY_BUFFER, buffers[BUFQUAD]); + glBufferData(GL_ARRAY_BUFFER, bufsizes[BUFQUAD], NULL, GL_STATIC_DRAW);//Orphan buffer + newSize = data.quadInfo.size() * sizeof(uint32_t); + if (newSize > bufsizes[BUFQUAD]) {//Reallocate + glBufferData(GL_ARRAY_BUFFER, newSize, data.quadInfo.data(), GL_STATIC_DRAW); + bufsizes[BUFQUAD] = newSize; + } else + glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, data.quadInfo.data()); glBindBuffer(GL_ARRAY_BUFFER, 0); glCheckError(); - numOfFaces = data.textures.size(); + numOfFaces = data.verts.size()/4; sectionPos = data.sectionPos; hash = data.hash; } diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp index 29b5db13..e373cb5e 100644 --- a/src/RendererSection.hpp +++ b/src/RendererSection.hpp @@ -9,19 +9,16 @@ class RenderState; class RendererSectionData; class RendererSection { - enum Vbos { - MODELS = 0, - TEXTURES, - LAYERS, - FRAMES, - COLORS, - LIGHTS, - VBOCOUNT, - }; - GLuint Vao = { 0 }; - GLuint Vbo[VBOCOUNT] = { 0 }; + enum buffers { + BUFVERTS = 0, + BUFQUAD, + BUFCOUNT + }; + GLuint vertexarray = 0; + GLuint buffers[BUFCOUNT] = { 0 }; + GLsizeiptr bufsizes[BUFCOUNT] = { 0 }; - static GLuint VboVertices, VboUvs; + static GLuint VboUvs; size_t hash; Vector sectionPos; @@ -34,15 +31,15 @@ class RendererSection { ~RendererSection(); - void Render(RenderState &renderState); + void Render(); Vector GetPosition(); size_t GetHash(); - size_t numOfFaces; + size_t numOfFaces = 0; friend void swap(RendererSection &lhs, RendererSection &rhs); void UpdateData(const RendererSectionData &data); -}; \ No newline at end of file +}; diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index 3f99a23a..4e72bcd6 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -14,11 +14,17 @@ inline const BlockId& GetBlockId(int x, int y, int z, const std::array(&xy), + *whp=reinterpret_cast(&wh); + uint16_t *x=xyp, *y=xyp+1, *w=whp, *h=whp+1; + *x = face.x; + *y = face.y; + *w = face.w; + *h = face.h; + + uint8_t *P=reinterpret_cast(&phlf), + *H=P+1, *L=P+2, *F=P+3; + *P = (isp.z<<4)|isp.x; + *H = isp.y; + *L = face.layer; + *F = face.frames; + } + uint32_t TLUuLVv; + { + uint16_t *TLUu=reinterpret_cast(&TLUuLVv), *LVv=TLUu+1; + + *TLUu = (face.tint<<14) | (block<<10) | face.Uu; + *LVv = (sky<<10) | face.Vv; + } + + data.quadInfo.push_back(xy); + data.quadInfo.push_back(wh); + data.quadInfo.push_back(phlf); + data.quadInfo.push_back(TLUuLVv); } } @@ -111,8 +144,6 @@ RendererSectionData ParseSection(const SectionsData §ions) { data.hash = sections.section->GetHash(); data.sectionPos = sections.section->GetPosition(); - glm::mat4 baseOffset = glm::translate(glm::mat4(1.0), (sections.section->GetPosition() * 16).glm()), transform; - for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { @@ -122,20 +153,16 @@ RendererSectionData ParseSection(const SectionsData §ions) { Vector vec(x, y, z); - transform = glm::translate(baseOffset, vec.glm()); - BlockLightness light = sections.GetLight(vec); BlockLightness skyLight = sections.GetSkyLight(vec); BlockFaces *model = GetInternalBlockModel(block, idModels); - AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], light, skyLight); + AddFacesByBlockModel(data, *model, vec, data.sectionPos * 16, blockVisibility[y * 256 + z * 16 + x], light, skyLight); } } } - data.textures.shrink_to_fit(); - data.textureLayers.shrink_to_fit(); - data.models.shrink_to_fit(); - data.colors.shrink_to_fit(); + data.verts.shrink_to_fit(); + data.quadInfo.shrink_to_fit(); return data; } diff --git a/src/RendererSectionData.hpp b/src/RendererSectionData.hpp index 3388988f..8ddccb3e 100644 --- a/src/RendererSectionData.hpp +++ b/src/RendererSectionData.hpp @@ -31,13 +31,9 @@ struct SectionsData { }; struct RendererSectionData { - std::vector models; - std::vector textures; - std::vector textureLayers; - std::vector textureFrames; - std::vector colors; - std::vector lights; - size_t hash = 0; + std::vector verts; + std::vector quadInfo; + size_t hash = ~0; Vector sectionPos; bool forced = false; }; diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp index a2afc80e..a4b7edfa 100644 --- a/src/RendererWorld.cpp +++ b/src/RendererWorld.cpp @@ -127,7 +127,7 @@ void RendererWorld::ParseQeueueRemoveUnnecessary() { bool skip = false; for (size_t i = 0; i < RendererWorld::parsingBufferSize; i++) { - if (parsing[i].data.section && parsing[i].data.section->GetPosition() == vec && parsing[i].data.section->GetHash() == section.GetHash()) { + if (parsing[i].data.section && parsing[i].data.section->GetPosition() == vec && (parsing[i].renderer.hash == section.GetHash() || parsing[i].parsing)) { skip = true; break; } @@ -217,8 +217,10 @@ RendererWorld::RendererWorld() { return; } it->second.UpdateData(parsing[id].renderer); - } else - sections.emplace(std::make_pair(parsing[id].renderer.sectionPos, RendererSection(parsing[id].renderer))); + } else { + if (!parsing[id].renderer.quadInfo.empty()) + sections.emplace(std::make_pair(parsing[id].renderer.sectionPos, RendererSection(parsing[id].renderer))); + } parsing[id] = RendererWorld::SectionParsing(); }); @@ -358,11 +360,12 @@ void RendererWorld::Render(RenderState & renderState) { entityShader->SetUniform("projection", projection); entityShader->SetUniform("view", view); glCheckError(); - + renderState.SetActiveVao(RendererEntity::GetVao()); for (auto& it : entities) { it.Render(renderState, &GetGameState()->GetWorld()); } + glCheckError(); //Render selected block const SelectionStatus& selectionStatus = GetGameState()->GetSelectionStatus(); @@ -464,28 +467,32 @@ void RendererWorld::Render(RenderState & renderState) { blockShader->SetUniform("DayTime", mixLevel); blockShader->SetUniform("projView", projView); blockShader->SetUniform("GlobalTime", globalTime); - glCheckError(); + glCheckError(); Frustum frustum(projView); - size_t culledSections = sections.size(); + size_t culledSections = sections.size(); unsigned int renderedFaces = 0; - for (auto& section : sections) { + for (auto& section : sections) { + Vector pos = section.second.GetPosition() * 16; glm::vec3 point{ - section.second.GetPosition().x * 16 + 8, - section.second.GetPosition().y * 16 + 8, - section.second.GetPosition().z * 16 + 8 + pos.x + 8, + pos.y + 8, + pos.z + 8 }; bool isVisible = frustum.TestSphere(point, 16.0f); - - if (!isVisible) { - culledSections--; - continue; - } - section.second.Render(renderState); + + if (!isVisible) { + culledSections--; + continue; + } + + section.second.Render(); renderedFaces += section.second.numOfFaces; - } + } + glCheckError(); + glBindVertexArray(0); this->culledSections = culledSections; DebugInfo::renderFaces.store(renderedFaces, std::memory_order_relaxed); glCheckError(); diff --git a/src/Shader.cpp b/src/Shader.cpp index 08866e1f..7034c6ff 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -5,8 +5,9 @@ #include +#include "Utility.hpp" -GLuint Shader::GetUniformLocation(const std::string &name) { +GLint Shader::GetUniformLocation(const std::string &name) { auto it = uniforms.find(name); if (it == uniforms.end()) { LOG(ERROR) << "Accessed not existing uniform " << name; @@ -17,7 +18,7 @@ GLuint Shader::GetUniformLocation(const std::string &name) { Shader::Shader(const std::string &vertSource, const std::string &fragSource, const std::vector &uniformsNames) { - bool vertFailed = false, fragFailed = false, linkFailed = false, uniformsFailed = false; + bool vertFailed = false, fragFailed = false, linkFailed = false; const GLchar *vertSourcePtr = vertSource.c_str(); const GLchar *fragSourcePtr = fragSource.c_str(); @@ -70,7 +71,7 @@ Shader::Shader(const std::string &vertSource, const std::string &fragSource, con glUseProgram(program); for (auto &it : uniformsNames) { - GLuint location = glGetUniformLocation(program, it.c_str()); + GLint location = glGetUniformLocation(program, it.c_str()); if (location == -1) { glDeleteProgram(program); LOG(ERROR) << "Uniform name \"" << it << "\" not found in shader"; diff --git a/src/Shader.hpp b/src/Shader.hpp index 8e1ce9e5..89f922af 100644 --- a/src/Shader.hpp +++ b/src/Shader.hpp @@ -9,10 +9,9 @@ #include class Shader { - std::map uniforms; + std::map uniforms; GLuint program = 0; - GLuint GetUniformLocation(const std::string &name); public: Shader(const Shader &) = delete; @@ -25,6 +24,7 @@ class Shader { ~Shader(); void Activate(); + GLint GetUniformLocation(const std::string &name); inline void SetUniform(const std::string &name, int val) { glUniform1i(GetUniformLocation(name), val); @@ -49,4 +49,4 @@ class Shader { inline void SetUniform(const std::string &name, glm::mat4 val) { glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, glm::value_ptr(val)); } -}; \ No newline at end of file +}; diff --git a/src/TextureAtlas.cpp b/src/TextureAtlas.cpp index 406418f7..34adfc4a 100644 --- a/src/TextureAtlas.cpp +++ b/src/TextureAtlas.cpp @@ -16,8 +16,9 @@ TextureAtlas::TextureAtlas(std::vector &textures) { const int padding = 1; const int paddingLimit = 128; + size_t tsz = textures.size(); std::vector totalRects; - for (int i = 0; i < textures.size(); i++) { + for (size_t i = 0; i < tsz; i++) { stbrp_rect rect; rect.id = i; rect.x = 0; @@ -81,11 +82,15 @@ TextureAtlas::TextureAtlas(std::vector &textures) { } LOG(INFO) << "Texture atlas size is " << textureSize << "x" << textureSize << "x" << layer; + size_t texturesCount = textureCoords.size(); //OpenGL int mipLevelCount = 1; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + //Texture atlas + glGenTextures(1, this->textures); + + //Fill texture atlas + glBindTexture(GL_TEXTURE_2D_ARRAY, this->textures[0]); glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, textureSize, textureSize, layer+1); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -95,9 +100,9 @@ TextureAtlas::TextureAtlas(std::vector &textures) { glCheckError(); //Uploading texture data - for (int i = 0; i < textureCoords.size(); i++) { + for (size_t i = 0; i < texturesCount; i++) { size_t bytesPerLine = textureCoords[i].pixelW * 4; - for (int y = 0; y < textureCoords[i].pixelH / 2; y++) { + for (size_t y = 0; y < textureCoords[i].pixelH / 2; y++) { int invY = textureCoords[i].pixelH - y - 1; unsigned char *src = textures[i].data.data() + y * bytesPerLine; unsigned char *dst = textures[i].data.data() + invY * bytesPerLine; @@ -105,7 +110,7 @@ TextureAtlas::TextureAtlas(std::vector &textures) { std::swap(*(src + j), *(dst + j)); } } - glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, textureCoords[i].pixelX, textureSize - textureCoords[i].pixelY - textureCoords[i].pixelH, textureCoords[i].layer, + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, textureCoords[i].pixelX, textureCoords[i].pixelY, textureCoords[i].layer, textureCoords[i].pixelW, textureCoords[i].pixelH, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textures[i].data.data()); glCheckError(); } @@ -114,5 +119,5 @@ TextureAtlas::TextureAtlas(std::vector &textures) { } TextureAtlas::~TextureAtlas() { - glDeleteTextures(1, &texture); + glDeleteTextures(1, textures); } diff --git a/src/TextureAtlas.hpp b/src/TextureAtlas.hpp index 1e5c134f..a13ebaba 100644 --- a/src/TextureAtlas.hpp +++ b/src/TextureAtlas.hpp @@ -7,16 +7,17 @@ struct TextureData { std::vector data; //expected format RGBA8888 int width, height; + size_t frames; }; struct TextureCoord { double x, y, w, h; - int pixelX, pixelY, pixelW, pixelH; + unsigned int pixelX, pixelY, pixelW, pixelH; size_t layer; }; class TextureAtlas { - GLuint texture; + GLuint textures[1]; std::vector textureCoords; public: TextureAtlas(std::vector &textures); @@ -26,10 +27,10 @@ class TextureAtlas { ~TextureAtlas(); inline GLuint GetRawTextureId() { - return texture; + return textures[0]; } TextureCoord GetTexture(int id) { return textureCoords[id]; } -}; \ No newline at end of file +};