From 984ade783afc285b7bb57656ffe9a3dd8c39bb28 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 27 Jun 2013 12:54:20 +0200 Subject: [PATCH] Added Renderer::DrawFullscreenQuad Made [Color|Texture]Background use a new shader-based algorithm Former-commit-id: cfd319b33712c270726eb697e258d61db2ca6835 --- include/Nazara/Graphics/ColorBackground.hpp | 3 + include/Nazara/Renderer/Renderer.hpp | 2 +- src/Nazara/Graphics/ColorBackground.cpp | 97 +++++++++++- src/Nazara/Graphics/TextureBackground.cpp | 115 ++++++++++++-- src/Nazara/Renderer/Renderer.cpp | 158 ++++---------------- 5 files changed, 232 insertions(+), 143 deletions(-) diff --git a/include/Nazara/Graphics/ColorBackground.hpp b/include/Nazara/Graphics/ColorBackground.hpp index 5bfa55ab8..7d19e8318 100644 --- a/include/Nazara/Graphics/ColorBackground.hpp +++ b/include/Nazara/Graphics/ColorBackground.hpp @@ -10,11 +10,13 @@ #include #include #include +#include class NAZARA_API NzColorBackground : public NzAbstractBackground { public: NzColorBackground(const NzColor& color = NzColor::Black); + ~NzColorBackground(); void Draw(const NzScene* scene) const; @@ -25,6 +27,7 @@ class NAZARA_API NzColorBackground : public NzAbstractBackground private: NzColor m_color; + NzShaderRef m_shader; }; #endif // NAZARA_COLORBACKGROUND_HPP diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index b3a4dae6e..0f6c9bd9d 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -41,7 +41,7 @@ class NAZARA_API NzRenderer static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); static void DrawPrimitives(nzPrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); static void DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); - NAZARA_DEPRECATED("Don't use this or you will have cancer") static void DrawTexture(unsigned int unit, const NzRectf& rect, const NzVector2f& uv0, const NzVector2f& uv1, float z = 0.f); + static void DrawFullscreenQuad(); static void Enable(nzRendererParameter parameter, bool enable); diff --git a/src/Nazara/Graphics/ColorBackground.cpp b/src/Nazara/Graphics/ColorBackground.cpp index bdcc5b760..a803886c6 100644 --- a/src/Nazara/Graphics/ColorBackground.cpp +++ b/src/Nazara/Graphics/ColorBackground.cpp @@ -2,21 +2,111 @@ // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include +#include #include +#include +#include #include +namespace +{ + NzShader* BuildShader() + { + const char* fragmentSource110 = + "#version 110\n" + "uniform vec4 Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Color;\n" + "}\n"; + + const char* fragmentSource140 = + "#version 140\n" + "out vec4 RenderTarget0;\n" + "uniform vec4 Color;\n" + "void main()\n" + "{\n" + " RenderTarget0 = Color;\n" + "}\n"; + + const char* vertexSource110 = + "#version 110\n" + "attribute vec2 VertexPosition;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(VertexPosition, 0.0, 1.0);\n" + "}\n"; + + const char* vertexSource140 = + "#version 140\n" + "in vec2 VertexPosition;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(VertexPosition, 0.0, 1.0);\n" + "}\n"; + + ///TODO: Remplacer ça par des ShaderNode + std::unique_ptr shader(new NzShader(nzShaderLanguage_GLSL)); + shader->SetPersistent(false); + + bool useGLSL140 = (NzOpenGL::GetVersion() >= 310); + + if (!shader->Load(nzShaderType_Fragment, (useGLSL140) ? fragmentSource140 : fragmentSource110)) + { + NazaraError("Failed to load fragment shader"); + return nullptr; + } + + if (!shader->Load(nzShaderType_Vertex, (useGLSL140) ? vertexSource140 : vertexSource110)) + { + NazaraError("Failed to load vertex shader"); + return nullptr; + } + + if (!shader->Compile()) + { + NazaraError("Failed to compile shader"); + return nullptr; + } + + return shader.release(); + } + + static NzShader* s_shader = nullptr; + static unsigned int s_colorLocation; +} + NzColorBackground::NzColorBackground(const NzColor& color) : m_color(color) { + if (!s_shader) + { + s_shader = BuildShader(); + s_colorLocation = s_shader->GetUniformLocation("Color"); + } + + m_shader = s_shader; +} + +NzColorBackground::~NzColorBackground() +{ + if (m_shader.Reset()) + s_shader = nullptr; } void NzColorBackground::Draw(const NzScene* scene) const { NazaraUnused(scene); - NzRenderer::SetClearColor(m_color); - NzRenderer::Clear(nzRendererClear_Color); + static NzRenderStates states; + + m_shader->SendColor(s_colorLocation, m_color); + + NzRenderer::SetRenderStates(states); + NzRenderer::SetShader(m_shader); + + NzRenderer::DrawFullscreenQuad(); } nzBackgroundType NzColorBackground::GetBackgroundType() const @@ -33,3 +123,4 @@ void NzColorBackground::SetColor(const NzColor& color) { m_color = color; } + diff --git a/src/Nazara/Graphics/TextureBackground.cpp b/src/Nazara/Graphics/TextureBackground.cpp index 67a851ec3..e1e3986a7 100644 --- a/src/Nazara/Graphics/TextureBackground.cpp +++ b/src/Nazara/Graphics/TextureBackground.cpp @@ -2,32 +2,123 @@ // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include -#include +#include +#include #include -NzTextureBackground::NzTextureBackground(NzTexture* texture) : -m_texture(texture) +namespace { + NzShader* BuildShader() + { + const char* fragmentSource110 = + "#version 110\n" + "varying vec2 vTexCoord;\n" + "uniform sampler2D Texture;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture(Texture, vTexCoord);\n" + "}\n"; + + const char* fragmentSource140 = + "#version 140\n" + "in vec2 vTexCoord;\n" + "out vec4 RenderTarget0;\n" + "uniform sampler2D Texture;\n" + "void main()\n" + "{\n" + " RenderTarget0 = texture(Texture, vTexCoord);\n" + "}\n"; + + const char* vertexSource110 = + "#version 110\n" + "attribute vec2 VertexPosition;\n" + "varying vec2 vTexCoord;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(VertexPosition, 0.0, 1.0);\n" + " vTexCoord = vec2((VertexPosition.x + 1.0)*0.5, (VertexPosition.y + 1.0)*0.5);\n" + "}\n"; + + const char* vertexSource140 = + "#version 140\n" + "in vec2 VertexPosition;\n" + "out vec2 vTexCoord;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(VertexPosition, 0.0, 1.0);\n" + " vTexCoord = vec2((VertexPosition.x + 1.0)*0.5, (VertexPosition.y + 1.0)*0.5);\n" + "}\n"; + + ///TODO: Remplacer ça par des ShaderNode + std::unique_ptr shader(new NzShader(nzShaderLanguage_GLSL)); + shader->SetPersistent(false); + + bool useGLSL140 = (NzOpenGL::GetVersion() >= 310); + + if (!shader->Load(nzShaderType_Fragment, (useGLSL140) ? fragmentSource140 : fragmentSource110)) + { + NazaraError("Failed to load fragment shader"); + return nullptr; + } + + if (!shader->Load(nzShaderType_Vertex, (useGLSL140) ? vertexSource140 : vertexSource110)) + { + NazaraError("Failed to load vertex shader"); + return nullptr; + } + + if (!shader->Compile()) + { + NazaraError("Failed to compile shader"); + return nullptr; + } + + return shader.release(); + } + + static NzShader* s_shader = nullptr; + static unsigned int s_textureLocation; +} + +NzTextureBackground::NzTextureBackground() +{ + if (!s_shader) + { + s_shader = BuildShader(); + s_textureLocation = s_shader->GetUniformLocation("Texture"); + } + + m_shader = s_shader; +} + +NzTextureBackground::NzTextureBackground(NzTexture* texture) : +NzTextureBackground() +{ + m_texture = texture; +} + +NzTextureBackground::~NzTextureBackground() +{ + if (m_shader.Reset()) + s_shader = nullptr; } void NzTextureBackground::Draw(const NzScene* scene) const { NazaraUnused(scene); - const NzRenderTarget* target = NzRenderer::GetTarget(); - NzRectui viewport = NzRenderer::GetViewport(); + static NzRenderStates states; - // Sous forme de flottants pour la division flottante - float width = static_cast(target->GetWidth()); - float height = static_cast(target->GetHeight()); - - NzVector2f uv0(viewport.x/width, viewport.y/height); - NzVector2f uv1((viewport.x+viewport.width)/width, (viewport.y+viewport.height)/height); + m_shader->SendInteger(s_textureLocation, 0); + NzRenderer::SetRenderStates(states); + NzRenderer::SetShader(m_shader); NzRenderer::SetTexture(0, m_texture); - NzRenderer::DrawTexture(0, NzRectf(0.f, 0.f, width, height), uv0, uv1, 1.f); + + NzRenderer::DrawFullscreenQuad(); } nzBackgroundType NzTextureBackground::GetBackgroundType() const diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 99434624a..f54d7a7a3 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -74,7 +74,7 @@ namespace std::vector s_textureUnits; GLuint s_currentVAO = 0; NzBuffer* s_instancingBuffer = nullptr; - NzVertexBuffer* s_quadBuffer = nullptr; + NzVertexBuffer* s_fullscreenQuadBuffer = nullptr; NzMatrix4f s_matrix[totalMatrixCount]; NzRenderStates s_states; NzVector2ui s_targetSize; @@ -329,125 +329,18 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive glBindVertexArray(0); } -void NzRenderer::DrawTexture(unsigned int unit, const NzRectf& rect, const NzVector2f& uv0, const NzVector2f& uv1, float z) +void NzRenderer::DrawFullscreenQuad() { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif + SetIndexBuffer(nullptr); + SetVertexBuffer(s_fullscreenQuadBuffer); - #if NAZARA_RENDERER_SAFE - if (unit >= s_textureUnits.size()) + if (!EnsureStateUpdate()) { - NazaraError("Texture unit out of range (" + NzString::Number(unit) + " >= " + NzString::Number(s_textureUnits.size()) + ')'); + NazaraError("Failed to update states"); return; } - if (!s_textureUnits[unit].texture) - { - NazaraError("No texture at unit #" + NzString::Number(unit)); - return; - } - - if (z < 0.f || z > 1.f) - { - NazaraError("Z must be in range [0..1] (Got " + NzString::Number(z) + ')'); - return; - } - #endif - - const NzTexture* texture = s_textureUnits[unit].texture; - - if (glDrawTexture) - { - float xCorrect = 2.f/s_targetSize.x; - float yCorrect = 2.f/s_targetSize.y; - - NzVector2f coords[2] = - { - {rect.x, rect.y}, - {rect.x+rect.width, rect.y+rect.height} - }; - - for (unsigned int i = 0; i < 2; ++i) - { - coords[i].x *= xCorrect; - coords[i].x -= 1.f; - - coords[i].y *= yCorrect; - coords[i].y -= 1.f; - } - - const NzTextureSampler& sampler = s_textureUnits[unit].sampler; - GLuint samplerId; - if (s_useSamplerObjects) - samplerId = sampler.GetOpenGLID(); - else - { - sampler.Apply(texture); - samplerId = 0; - } - - glDrawTexture(texture->GetOpenGLID(), samplerId, - coords[0].x, coords[0].y, coords[1].x, coords[1].y, - z, - uv0.x, 1.f-uv0.y, uv1.x, 1.f-uv1.y); // Inversion des UV sur Y - } - else - { - ///FIXME: Remplacer cette immondice (Code fonctionnel mais à vomir) - // Ce code est horrible mais la version optimisée demanderait des fonctionnalités pas encore implémentées, à venir... - - float vertices[4*(3 + 2)] = - { - rect.x, rect.y, z, - uv0.x, uv0.y, - - rect.x+rect.width, rect.y, z, - uv1.x, uv0.y, - - rect.x, rect.y+rect.height, z, - uv0.x, uv1.y, - - rect.x+rect.width, rect.y+rect.height, z, - uv1.x, uv1.y - }; - - if (!s_quadBuffer->Fill(vertices, 0, 4, true)) - { - NazaraError("Failed to fill vertex buffer"); - return; - } - - const NzShader* oldShader = s_shader; - const NzVertexBuffer* oldBuffer = s_vertexBuffer; - - const NzShader* shader = NzShaderBuilder::Get(nzShaderFlags_DiffuseMapping | nzShaderFlags_FlipUVs); - shader->SendTexture(shader->GetUniformLocation("MaterialDiffuseMap"), texture); - - bool faceCulling = IsEnabled(nzRendererParameter_FaceCulling); - Enable(nzRendererParameter_FaceCulling, false); - SetShader(shader); - SetVertexBuffer(s_quadBuffer); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states"); - return; - } - - shader->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldViewProj], NzMatrix4f::Ortho(0.f, s_targetSize.x, 0.f, s_targetSize.y, 0.f)); - - glDrawArrays(NzOpenGL::PrimitiveMode[nzPrimitiveMode_TriangleStrip], 0, 4); - - // Restauration - Enable(nzRendererParameter_FaceCulling, faceCulling); - SetShader(oldShader); - SetVertexBuffer(oldBuffer); - } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } void NzRenderer::Enable(nzRendererParameter parameter, bool enable) @@ -732,19 +625,15 @@ bool NzRenderer::Initialize() s_vertexBuffer = nullptr; s_updateFlags = (Update_Matrices | Update_Shader | Update_VAO); - NzVertexElement elements[2]; - elements[0].offset = 0; - elements[0].type = nzElementType_Float3; - elements[0].usage = nzElementUsage_Position; - - elements[1].offset = 3*sizeof(float); - elements[1].type = nzElementType_Float2; - elements[1].usage = nzElementUsage_TexCoord; + NzVertexElement element; + element.offset = 0; + element.type = nzElementType_Float2; + element.usage = nzElementUsage_Position; std::unique_ptr declaration(new NzVertexDeclaration); - if (!declaration->Create(elements, 2)) + if (!declaration->Create(&element, 1)) { - NazaraError("Failed to create quad declaration"); + NazaraError("Failed to create fullscreen quad declaration"); Uninitialize(); return false; @@ -752,9 +641,25 @@ bool NzRenderer::Initialize() declaration->SetPersistent(false); - s_quadBuffer = new NzVertexBuffer(declaration.get(), 4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + s_fullscreenQuadBuffer = new NzVertexBuffer(declaration.get(), 4, nzBufferStorage_Hardware, nzBufferUsage_Static); declaration.release(); + float vertices[4*2] = + { + -1.f, -1.f, + 1.f, -1.f, + -1.f, 1.f, + 1.f, 1.f, + }; + + if (!s_fullscreenQuadBuffer->Fill(vertices, 0, 4)) + { + NazaraError("Failed to fill fullscreen quad buffer"); + Uninitialize(); + + return false; + } + if (!NzMaterial::Initialize()) { NazaraError("Failed to initialize materials"); @@ -1306,7 +1211,7 @@ void NzRenderer::Uninitialize() NzTextureSampler::Uninitialize(); // Libération des buffers - delete s_quadBuffer; + delete s_fullscreenQuadBuffer; if (s_instancingBuffer) { @@ -1396,7 +1301,6 @@ bool NzRenderer::EnsureStateUpdate() { TextureUnit& unit = s_textureUnits[i]; - ///FIXME: Cet appel ne fait-il pas redondance avec le rebinding des textures avant le return ? if (!unit.textureUpdated) { NzOpenGL::SetTextureUnit(i);