diff --git a/source/client/graphics/ChunkRenderer.cpp b/source/client/graphics/ChunkRenderer.cpp index aa8ad1f1..f596d62e 100644 --- a/source/client/graphics/ChunkRenderer.cpp +++ b/source/client/graphics/ChunkRenderer.cpp @@ -34,26 +34,9 @@ #include "Texture.hpp" ChunkRenderer::ChunkRenderer(const TextureAtlas &textureAtlas) : m_textureAtlas(textureAtlas) { - m_renderDistance = bgfx::createUniform("u_renderDistance", bgfx::UniformType::Vec4); - m_fogColor = bgfx::createUniform("u_fogColor", bgfx::UniformType::Vec4); - m_mipLevel = bgfx::createUniform("u_mipLevel", bgfx::UniformType::Vec4); -} - -ChunkRenderer::~ChunkRenderer() { - if (bgfx::isValid(m_mipLevel)) { - bgfx::destroy(m_mipLevel); - m_mipLevel.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_fogColor)) { - bgfx::destroy(m_fogColor); - m_fogColor.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_renderDistance)) { - bgfx::destroy(m_renderDistance); - m_renderDistance.idx = bgfx::kInvalidHandle; - } + m_renderDistance.init("u_renderDistance", bgfx::UniformType::Vec4); + m_fogColor.init("u_fogColor", bgfx::UniformType::Vec4); + m_mipLevel.init("u_mipLevel", bgfx::UniformType::Vec4); } inline static bool bbIntersects(const glm::vec3 &a0, const glm::vec3 &a1, const glm::vec3 &b0, const glm::vec3 &b1) { @@ -297,25 +280,15 @@ void ChunkRenderer::drawChunks(RenderTarget &target, RenderStates states, const bgfx::setViewMode(states.view, bgfx::ViewMode::DepthDescending); - float renderDistance[4] = {(float)Config::renderDistance * CHUNK_WIDTH, 0.f, 0.f, 0.f}; - bgfx::setUniform(m_renderDistance, renderDistance); + m_renderDistance.setValue(Config::renderDistance * CHUNK_WIDTH); - if (currentSky) { - float fogColor[4] = { - currentSky->fogColor().r, - currentSky->fogColor().g, - currentSky->fogColor().b, - currentSky->fogColor().a - }; - bgfx::setUniform(m_fogColor, fogColor); - } + if (currentSky) + m_fogColor.setValue(currentSky->fogColor()); for (u8 layer = 0 ; layer < ChunkMeshLayer::Count ; ++layer) { - float mipLevel[4] = {0.f, - (layer == ChunkMeshLayer::NoMipMap || layer == ChunkMeshLayer::Flora) - ? 0.f : (float)Config::mipmapLevels, - 0.f, 0.f - }; + float maxMipLevel = 0.f; + if (layer == ChunkMeshLayer::NoMipMap || layer == ChunkMeshLayer::Flora) + maxMipLevel = Config::mipmapLevels; if (layer == ChunkMeshLayer::Flora || layer == ChunkMeshLayer::Liquid) states.isCullFaceEnabled = false; @@ -326,7 +299,7 @@ void ChunkRenderer::drawChunks(RenderTarget &target, RenderStates states, const std::size_t verticesCount = std::get<0>(it)->getVerticesCount(layer); if (verticesCount == 0) continue; - bgfx::setUniform(m_mipLevel, mipLevel); + m_mipLevel.setValue(0.f, maxMipLevel); target.beginDrawing(states); @@ -345,4 +318,3 @@ void ChunkRenderer::drawChunks(RenderTarget &target, RenderStates states, const } } } - diff --git a/source/client/graphics/ChunkRenderer.hpp b/source/client/graphics/ChunkRenderer.hpp index 9f619fa1..d295cdf0 100644 --- a/source/client/graphics/ChunkRenderer.hpp +++ b/source/client/graphics/ChunkRenderer.hpp @@ -30,6 +30,7 @@ #include #include "RenderStates.hpp" +#include "ShaderUniform.hpp" #include "Sky.hpp" #include "TextureAtlas.hpp" @@ -45,7 +46,6 @@ class ChunkRenderer { public: ChunkRenderer(const TextureAtlas &textureAtlas); - ~ChunkRenderer(); void draw(RenderTarget &target, RenderStates states, const ChunkMap &chunks, Camera &camera, const Sky *currentSky) const; @@ -60,9 +60,9 @@ class ChunkRenderer { OnChunkDeletionRequestedCallback m_onChunkDeletionRequested; OnMeshingRequestedCallback m_onMeshingRequested; - bgfx::UniformHandle m_renderDistance = BGFX_INVALID_HANDLE; - bgfx::UniformHandle m_fogColor = BGFX_INVALID_HANDLE; - bgfx::UniformHandle m_mipLevel = BGFX_INVALID_HANDLE; + ShaderUniform m_renderDistance; + ShaderUniform m_fogColor; + ShaderUniform m_mipLevel; }; #endif // CHUNKRENDERER_HPP_ diff --git a/source/client/graphics/Framebuffer.cpp b/source/client/graphics/Framebuffer.cpp index 6d071766..617dcce2 100644 --- a/source/client/graphics/Framebuffer.cpp +++ b/source/client/graphics/Framebuffer.cpp @@ -51,11 +51,11 @@ Framebuffer::Framebuffer() { m_vbo.init(quad, sizeof(quad)); - m_colorTextureSampler = bgfx::createUniform("s_colorTexture", bgfx::UniformType::Sampler); - m_depthTextureSampler = bgfx::createUniform("s_depthTexture", bgfx::UniformType::Sampler); + m_colorTextureSampler.init("s_colorTexture", bgfx::UniformType::Sampler); + m_depthTextureSampler.init("s_depthTexture", bgfx::UniformType::Sampler); - m_effectTypeUniform = bgfx::createUniform("u_effectType", bgfx::UniformType::Vec4); - m_depthFogColorUniform = bgfx::createUniform("u_depthFogColor", bgfx::UniformType::Vec4); + m_effectTypeUniform.init("u_effectType", bgfx::UniformType::Vec4); + m_depthFogColorUniform.init("u_depthFogColor", bgfx::UniformType::Vec4); } Framebuffer::Framebuffer(u16 width, u16 height) : Framebuffer() { @@ -95,26 +95,6 @@ void Framebuffer::free() { bgfx::destroy(m_handle); m_handle.idx = bgfx::kInvalidHandle; } - - if (bgfx::isValid(m_depthFogColorUniform)) { - bgfx::destroy(m_depthFogColorUniform); - m_depthFogColorUniform.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_effectTypeUniform)) { - bgfx::destroy(m_effectTypeUniform); - m_effectTypeUniform.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_depthTextureSampler)) { - bgfx::destroy(m_depthTextureSampler); - m_depthTextureSampler.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_colorTextureSampler)) { - bgfx::destroy(m_colorTextureSampler); - m_colorTextureSampler.idx = bgfx::kInvalidHandle; - } } void Framebuffer::loadShader(const std::string &name) { @@ -127,19 +107,12 @@ void Framebuffer::prepareDraw() const { } void Framebuffer::draw() const { - bgfx::setTexture(0, m_colorTextureSampler, m_textures[0]); - bgfx::setTexture(1, m_depthTextureSampler, m_textures[1]); + bgfx::setTexture(0, m_colorTextureSampler.handle(), m_textures[0]); + bgfx::setTexture(1, m_depthTextureSampler.handle(), m_textures[1]); - float effectType[4] = {(float)GameConfig::currentScreenEffect, GameConfig::fogDepth, 0.f, 0.f}; - bgfx::setUniform(m_effectTypeUniform, effectType); + m_effectTypeUniform.setValue(GameConfig::currentScreenEffect, GameConfig::fogDepth); - float fogColor[4] = { - GameConfig::fogColor.r, - GameConfig::fogColor.g, - GameConfig::fogColor.b, - GameConfig::fogColor.a, - }; - bgfx::setUniform(m_depthFogColorUniform, fogColor); + m_depthFogColorUniform.setValue(GameConfig::fogColor); m_vbo.enable(); diff --git a/source/client/graphics/Framebuffer.hpp b/source/client/graphics/Framebuffer.hpp index 94af65df..fd9ae02a 100644 --- a/source/client/graphics/Framebuffer.hpp +++ b/source/client/graphics/Framebuffer.hpp @@ -28,6 +28,7 @@ #define FRAMEBUFFER_HPP_ #include "Shader.hpp" +#include "ShaderUniform.hpp" #include "Texture.hpp" #include "VertexBuffer.hpp" @@ -49,11 +50,11 @@ class Framebuffer : public gk::NonCopyable { void draw() const; private: - bgfx::UniformHandle m_colorTextureSampler = BGFX_INVALID_HANDLE; - bgfx::UniformHandle m_depthTextureSampler = BGFX_INVALID_HANDLE; + ShaderUniform m_colorTextureSampler; + ShaderUniform m_depthTextureSampler; - bgfx::UniformHandle m_effectTypeUniform = BGFX_INVALID_HANDLE; - bgfx::UniformHandle m_depthFogColorUniform = BGFX_INVALID_HANDLE; + ShaderUniform m_effectTypeUniform; + ShaderUniform m_depthFogColorUniform; bgfx::TextureHandle m_textures[2] = {BGFX_INVALID_HANDLE, BGFX_STATE_BLEND_INV_SRC_ALPHA}; diff --git a/source/client/graphics/ShaderUniform.cpp b/source/client/graphics/ShaderUniform.cpp new file mode 100644 index 00000000..a77ab37c --- /dev/null +++ b/source/client/graphics/ShaderUniform.cpp @@ -0,0 +1,80 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#include + +#include "ShaderUniform.hpp" + +ShaderUniform::ShaderUniform(ShaderUniform &&shaderUniform) { + m_handle = shaderUniform.m_handle; + shaderUniform.m_handle.idx = bgfx::kInvalidHandle; +} + +ShaderUniform::~ShaderUniform() { + free(); +} + +ShaderUniform &ShaderUniform::operator=(ShaderUniform &&shaderUniform) { + m_handle = shaderUniform.m_handle; + shaderUniform.m_handle.idx = bgfx::kInvalidHandle; + + return *this; +} + +void ShaderUniform::init(const char *uniformName, bgfx::UniformType::Enum type, uint16_t num) { + if (bgfx::isValid(m_handle)) + throw EXCEPTION("Trying to reuse an uniform named", (m_name ? m_name : "?"), "with name", (uniformName ? uniformName : "?")); + + m_name = uniformName; + m_handle = bgfx::createUniform(m_name, type, num); +} + +void ShaderUniform::free() { + if (bgfx::isValid(m_handle)) + bgfx::destroy(m_handle); +} + +void ShaderUniform::setValue(float x, float y, float z, float w) const { + float value[4] = {x, y, z, w}; + bgfx::setUniform(m_handle, value); +} + +void ShaderUniform::setValue(const gk::Color &color, bool needsRounding) const { + if (!needsRounding) { + float value[4] = {color.r, color.g, color.b, color.a}; + bgfx::setUniform(m_handle, value); + } + else { + float value[4] = { + color.r255() / 255.f, + color.g255() / 255.f, + color.b255() / 255.f, + color.a255() / 255.f + }; + + bgfx::setUniform(m_handle, value); + } +} diff --git a/source/client/graphics/ShaderUniform.hpp b/source/client/graphics/ShaderUniform.hpp new file mode 100644 index 00000000..0645d48d --- /dev/null +++ b/source/client/graphics/ShaderUniform.hpp @@ -0,0 +1,60 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md) + * + * This file is part of OpenMiner. + * + * OpenMiner is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * OpenMiner is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenMiner; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * ===================================================================================== + */ +#ifndef SHADERUNIFORM_HPP_ +#define SHADERUNIFORM_HPP_ + +#include + +#include + +namespace gk { + class Color; +} + +class ShaderUniform : public gk::NonCopyable { + public: + ShaderUniform() = default; + ShaderUniform(ShaderUniform &&); + ~ShaderUniform(); + + ShaderUniform &operator=(ShaderUniform &&); + + void init(const char *uniformName, bgfx::UniformType::Enum type, uint16_t num = 1); + void free(); + + void setValue(float x, float y = 0.f, float z = 0.f, float w = 0.f) const; + void setValue(const gk::Color &color, bool needsRounding = false) const; + + const bgfx::UniformHandle &handle() const { return m_handle; } + + private: + const char *m_name = nullptr; + + bgfx::UniformHandle m_handle = BGFX_INVALID_HANDLE; +}; + +#endif // SHADERUNIFORM_HPP_ diff --git a/source/client/states/GameState.cpp b/source/client/states/GameState.cpp index a67a087c..f47c67c1 100644 --- a/source/client/states/GameState.cpp +++ b/source/client/states/GameState.cpp @@ -63,24 +63,12 @@ GameState::GameState() m_keyboardHandler = dynamic_cast(gk::GamePad::getInputHandler()); - m_skyColor = bgfx::createUniform("u_skyColor", bgfx::UniformType::Vec4); - m_sunlightIntensity = bgfx::createUniform("u_sunlightIntensity", bgfx::UniformType::Vec4); + m_skyColor.init("u_skyColor", bgfx::UniformType::Vec4); + m_sunlightIntensity.init("u_sunlightIntensity", bgfx::UniformType::Vec4); m_fbo.init(Config::screenWidth, Config::screenHeight); } -GameState::~GameState() { - if (bgfx::isValid(m_sunlightIntensity)) { - bgfx::destroy(m_sunlightIntensity); - m_sunlightIntensity.idx = bgfx::kInvalidHandle; - } - - if (bgfx::isValid(m_skyColor)) { - bgfx::destroy(m_skyColor); - m_skyColor.idx = bgfx::kInvalidHandle; - } -} - void GameState::init() { m_world.setEventHandler(*m_eventHandler); @@ -227,31 +215,25 @@ void GameState::onGuiScaleChanged(const GuiScaleChangedEvent &event) { void GameState::draw(RenderTarget &target, RenderStates states) const { if (m_world.sky()) { + gk::Color color = m_world.sky()->color(); + float sunlightIntensity = 1.f; + if (m_world.sky()->daylightCycleSpeed() > 0.f) { float time = GameTime::getCurrentTime(0, m_world.sky()->daylightCycleSpeed()); - const gk::Color &color = GameTime::getSkyColorFromTime(*m_world.sky(), time); - - u32 iColor = (color.r255() << 24) | (color.g255() << 16) | (color.b255() << 8) | color.a255(); - bgfx::setViewClear(BgfxView::Sky, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, iColor); - - float colorPtr[4] = {color.r255() / 255.f, color.g255() / 255.f, color.b255() / 255.f, color.a255() / 255.f}; - bgfx::setUniform(m_skyColor, colorPtr); - - float sunlightIntensity[4] = {GameTime::getSunlightIntensityFromTime(time), 0, 0, 0}; - bgfx::setUniform(m_sunlightIntensity, sunlightIntensity); + color = GameTime::getSkyColorFromTime(*m_world.sky(), time); + sunlightIntensity = GameTime::getSunlightIntensityFromTime(time); } - else { - const gk::Color &color = m_world.sky()->color(); - u32 iColor = (color.r255() << 24) | (color.g255() << 16) | (color.b255() << 8) | color.a255(); - bgfx::setViewClear(BgfxView::Sky, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, iColor); + u32 iColor = (color.r255() << 24) + | (color.g255() << 16) + | (color.b255() << 8) + | color.a255(); - float colorPtr[4] = {color.r255() / 255.f, color.g255() / 255.f, color.b255() / 255.f, color.a255() / 255.f}; - bgfx::setUniform(m_skyColor, colorPtr); + bgfx::setViewClear(BgfxView::Sky, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, iColor); - float sunlightIntensity[4] = {1.f, 0.f, 0.f, 0.f}; - bgfx::setUniform(m_sunlightIntensity, &sunlightIntensity); - } + m_skyColor.setValue(color, true); + + m_sunlightIntensity.setValue(sunlightIntensity); } states.shader = &m_shader; diff --git a/source/client/states/GameState.hpp b/source/client/states/GameState.hpp index 2d06e022..d6880131 100644 --- a/source/client/states/GameState.hpp +++ b/source/client/states/GameState.hpp @@ -40,6 +40,7 @@ #include "KeyboardHandler.hpp" #include "PlayerBox.hpp" #include "Registry.hpp" +#include "ShaderUniform.hpp" #include "Skybox.hpp" class RenderTarget; @@ -48,7 +49,6 @@ class TextureAtlas; class GameState : public DrawableState { public: GameState(); - ~GameState() override; void init() override; void onStateInactive() override; @@ -103,8 +103,8 @@ class GameState : public DrawableState { Skybox m_skybox{m_camera, m_world}; - bgfx::UniformHandle m_skyColor = BGFX_INVALID_HANDLE; - bgfx::UniformHandle m_sunlightIntensity = BGFX_INVALID_HANDLE; + ShaderUniform m_skyColor; + ShaderUniform m_sunlightIntensity; }; #endif // GAMESTATE_HPP_