From ea2cc97169f90d049c0c073bce93a87391254688 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 22 Mar 2013 11:15:17 +0100 Subject: [PATCH] Added Texture backgrounds Former-commit-id: 8aa98a9b8bee5fbf1b5eefa958a7b9095b784cf5 --- include/Nazara/2D/TextureBackground.hpp | 30 +++++ include/Nazara/Renderer/Renderer.hpp | 1 + src/Nazara/2D/TextureBackground.cpp | 44 +++++++ src/Nazara/Renderer/Renderer.cpp | 167 ++++++++++++++++++++++-- 4 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 include/Nazara/2D/TextureBackground.hpp create mode 100644 src/Nazara/2D/TextureBackground.cpp diff --git a/include/Nazara/2D/TextureBackground.hpp b/include/Nazara/2D/TextureBackground.hpp new file mode 100644 index 000000000..dbfa4b65f --- /dev/null +++ b/include/Nazara/2D/TextureBackground.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2013 Jérôme Leclercq +// This file is part of the "Nazara Engine - 2D Module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_TEXTUREBACKGROUND_HPP +#define NAZARA_TEXTUREBACKGROUND_HPP + +#include +#include +#include + +class NAZARA_API NzTextureBackground : public NzBackground +{ + public: + NzTextureBackground(NzTexture* texture); + + void Draw() const; + + nzBackgroundType GetBackgroundType() const; + NzTexture* GetTexture() const; + + void SetTexture(NzTexture* texture); + + private: + NzTextureRef m_texture; +}; + +#endif // NAZARA_TEXTUREBACKGROUND_HPP diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 5431c150d..c2bc6833e 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -40,6 +40,7 @@ class NAZARA_API NzRenderer static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount); static void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount); static void DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, 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 Enable(nzRendererParameter parameter, bool enable); diff --git a/src/Nazara/2D/TextureBackground.cpp b/src/Nazara/2D/TextureBackground.cpp new file mode 100644 index 000000000..c41cbd866 --- /dev/null +++ b/src/Nazara/2D/TextureBackground.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2013 Jérôme Leclercq +// This file is part of the "Nazara Engine - 2D Module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +NzTextureBackground::NzTextureBackground(NzTexture* texture) : +m_texture(texture) +{ +} + +void NzTextureBackground::Draw() const +{ + const NzRenderTarget* target = NzRenderer::GetTarget(); + NzRectui viewport = NzRenderer::GetViewport(); + + // Sous forme de flottants pour la division flottante + float width = target->GetWidth(); + float height = target->GetHeight(); + + NzVector2f uv0(viewport.x/width, viewport.y/height); + NzVector2f uv1((viewport.x+viewport.width)/width, (viewport.y+viewport.height)/height); + + NzRenderer::SetTexture(0, m_texture); + NzRenderer::DrawTexture(0, NzRectf(0.f, 0.f, width, height), uv0, uv1, 1.f); +} + +nzBackgroundType NzTextureBackground::GetBackgroundType() const +{ + return nzBackgroundType_Texture; +} + +NzTexture* NzTextureBackground::GetTexture() const +{ + return m_texture; +} + +void NzTextureBackground::SetTexture(NzTexture* texture) +{ + m_texture = texture; +} diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 38d3faf41..62de34dc6 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -61,7 +61,9 @@ namespace std::map s_vaos; std::vector s_textureUnits; NzBuffer* s_instancingBuffer = nullptr; + NzVertexBuffer* s_quadBuffer = nullptr; NzMatrix4f s_matrix[totalMatrixCount]; + NzVector2ui s_targetSize; nzBlendFunc s_srcBlend; nzBlendFunc s_dstBlend; nzFaceCulling s_faceCulling; @@ -308,6 +310,130 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive glDrawArraysInstanced(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount, instanceCount); } +void NzRenderer::DrawTexture(unsigned int unit, const NzRectf& rect, const NzVector2f& uv0, const NzVector2f& uv1, float z) +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + #if NAZARA_RENDERER_SAFE + if (unit >= s_textureUnits.size()) + { + NazaraError("Texture unit out of range (" + NzString::Number(unit) + " >= " + NzString::Number(s_textureUnits.size()) + ')'); + 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(true)) + { + NazaraError("Failed to update states"); + return; + } + + shader->SendMatrix(shader->GetUniformLocation("WorldViewProjMatrix"), NzMatrix4f::Ortho(0.f, s_targetSize.x, 0.f, s_targetSize.y, 0.f)); + + glDrawArrays(NzOpenGL::PrimitiveType[nzPrimitiveType_TriangleStrip], 0, 4); + + // Restauration + Enable(nzRendererParameter_FaceCulling, faceCulling); + SetShader(oldShader); + SetVertexBuffer(oldBuffer); + + s_matrixUpdated[nzMatrixCombination_WorldViewProj] = false; + s_vaoUpdated = false; + } +} + void NzRenderer::Enable(nzRendererParameter parameter, bool enable) { #ifdef NAZARA_DEBUG @@ -611,6 +737,28 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer) s_vertexBuffer = nullptr; s_vertexDeclaration = nullptr; + 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; + + NzVertexDeclaration* declaration = new NzVertexDeclaration; + if (!declaration->Create(elements, 2)) + { + NazaraError("Failed to create quad declaration"); + Uninitialize(); + + return false; + } + + declaration->SetPersistent(false, false); + + s_quadBuffer = new NzVertexBuffer(declaration, 4, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + if (initializeDebugDrawer && !NzDebugDrawer::Initialize()) NazaraWarning("Failed to initialize debug drawer"); // Non-critique @@ -1086,6 +1234,7 @@ bool NzRenderer::SetTarget(const NzRenderTarget* target) } s_target = target; + s_targetSize.Set(target->GetWidth(), target->GetHeight()); } return true; @@ -1101,18 +1250,18 @@ void NzRenderer::SetTexture(nzUInt8 unit, const NzTexture* texture) } #endif - if (!texture) // Pas besoin de mettre à jour s'il n'y a pas de texture - return; - if (s_textureUnits[unit].texture != texture) { s_textureUnits[unit].texture = texture; s_textureUnits[unit].textureUpdated = false; - if (s_textureUnits[unit].sampler.UseMipmaps(texture->HasMipmaps())) - s_textureUnits[unit].samplerUpdated = false; + if (texture) + { + if (s_textureUnits[unit].sampler.UseMipmaps(texture->HasMipmaps())) + s_textureUnits[unit].samplerUpdated = false; - s_textureUnits[unit].updated = false; + s_textureUnits[unit].updated = false; + } } } @@ -1144,7 +1293,7 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) } #endif - if (s_vertexBuffer != vertexBuffer) + if (vertexBuffer && s_vertexBuffer != vertexBuffer) { s_vertexBuffer = vertexBuffer; @@ -1214,7 +1363,9 @@ void NzRenderer::Uninitialize() NzShaderBuilder::Uninitialize(); NzTextureSampler::Uninitialize(); - // Libération du buffer d'instancing + // Libération des buffers + delete s_quadBuffer; + if (s_instancingBuffer) { delete s_instancingBuffer;