Added Renderer::DrawFullscreenQuad

Made [Color|Texture]Background use a new shader-based algorithm


Former-commit-id: cfd319b33712c270726eb697e258d61db2ca6835
This commit is contained in:
Lynix 2013-06-27 12:54:20 +02:00
parent 1a6e55881b
commit 984ade783a
5 changed files with 232 additions and 143 deletions

View File

@ -10,11 +10,13 @@
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Color.hpp> #include <Nazara/Core/Color.hpp>
#include <Nazara/Graphics/AbstractBackground.hpp> #include <Nazara/Graphics/AbstractBackground.hpp>
#include <Nazara/Renderer/Shader.hpp>
class NAZARA_API NzColorBackground : public NzAbstractBackground class NAZARA_API NzColorBackground : public NzAbstractBackground
{ {
public: public:
NzColorBackground(const NzColor& color = NzColor::Black); NzColorBackground(const NzColor& color = NzColor::Black);
~NzColorBackground();
void Draw(const NzScene* scene) const; void Draw(const NzScene* scene) const;
@ -25,6 +27,7 @@ class NAZARA_API NzColorBackground : public NzAbstractBackground
private: private:
NzColor m_color; NzColor m_color;
NzShaderRef m_shader;
}; };
#endif // NAZARA_COLORBACKGROUND_HPP #endif // NAZARA_COLORBACKGROUND_HPP

View File

@ -41,7 +41,7 @@ class NAZARA_API NzRenderer
static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); 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 DrawPrimitives(nzPrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount);
static void DrawPrimitivesInstanced(unsigned int instanceCount, 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); static void Enable(nzRendererParameter parameter, bool enable);

View File

@ -2,21 +2,111 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/ColorBackground.hpp> #include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Graphics/ColorBackGround.hpp>
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/ShaderBuilder.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
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<NzShader> 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) : NzColorBackground::NzColorBackground(const NzColor& color) :
m_color(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 void NzColorBackground::Draw(const NzScene* scene) const
{ {
NazaraUnused(scene); NazaraUnused(scene);
NzRenderer::SetClearColor(m_color); static NzRenderStates states;
NzRenderer::Clear(nzRendererClear_Color);
m_shader->SendColor(s_colorLocation, m_color);
NzRenderer::SetRenderStates(states);
NzRenderer::SetShader(m_shader);
NzRenderer::DrawFullscreenQuad();
} }
nzBackgroundType NzColorBackground::GetBackgroundType() const nzBackgroundType NzColorBackground::GetBackgroundType() const
@ -33,3 +123,4 @@ void NzColorBackground::SetColor(const NzColor& color)
{ {
m_color = color; m_color = color;
} }

View File

@ -2,32 +2,123 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Graphics/TextureBackground.hpp> #include <Nazara/Graphics/TextureBackground.hpp>
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp> #include <Nazara/Renderer/ShaderBuilder.hpp>
#include <memory>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
NzTextureBackground::NzTextureBackground(NzTexture* texture) : namespace
m_texture(texture)
{ {
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<NzShader> 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 void NzTextureBackground::Draw(const NzScene* scene) const
{ {
NazaraUnused(scene); NazaraUnused(scene);
const NzRenderTarget* target = NzRenderer::GetTarget(); static NzRenderStates states;
NzRectui viewport = NzRenderer::GetViewport();
// Sous forme de flottants pour la division flottante m_shader->SendInteger(s_textureLocation, 0);
float width = static_cast<float>(target->GetWidth());
float height = static_cast<float>(target->GetHeight());
NzVector2f uv0(viewport.x/width, viewport.y/height);
NzVector2f uv1((viewport.x+viewport.width)/width, (viewport.y+viewport.height)/height);
NzRenderer::SetRenderStates(states);
NzRenderer::SetShader(m_shader);
NzRenderer::SetTexture(0, m_texture); 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 nzBackgroundType NzTextureBackground::GetBackgroundType() const

View File

@ -74,7 +74,7 @@ namespace
std::vector<TextureUnit> s_textureUnits; std::vector<TextureUnit> s_textureUnits;
GLuint s_currentVAO = 0; GLuint s_currentVAO = 0;
NzBuffer* s_instancingBuffer = nullptr; NzBuffer* s_instancingBuffer = nullptr;
NzVertexBuffer* s_quadBuffer = nullptr; NzVertexBuffer* s_fullscreenQuadBuffer = nullptr;
NzMatrix4f s_matrix[totalMatrixCount]; NzMatrix4f s_matrix[totalMatrixCount];
NzRenderStates s_states; NzRenderStates s_states;
NzVector2ui s_targetSize; NzVector2ui s_targetSize;
@ -329,125 +329,18 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive
glBindVertexArray(0); 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 SetIndexBuffer(nullptr);
if (NzContext::GetCurrent() == nullptr) SetVertexBuffer(s_fullscreenQuadBuffer);
{
NazaraError("No active context");
return;
}
#endif
#if NAZARA_RENDERER_SAFE if (!EnsureStateUpdate())
if (unit >= s_textureUnits.size())
{ {
NazaraError("Texture unit out of range (" + NzString::Number(unit) + " >= " + NzString::Number(s_textureUnits.size()) + ')'); NazaraError("Failed to update states");
return; return;
} }
if (!s_textureUnits[unit].texture) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
{
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);
}
} }
void NzRenderer::Enable(nzRendererParameter parameter, bool enable) void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
@ -732,19 +625,15 @@ bool NzRenderer::Initialize()
s_vertexBuffer = nullptr; s_vertexBuffer = nullptr;
s_updateFlags = (Update_Matrices | Update_Shader | Update_VAO); s_updateFlags = (Update_Matrices | Update_Shader | Update_VAO);
NzVertexElement elements[2]; NzVertexElement element;
elements[0].offset = 0; element.offset = 0;
elements[0].type = nzElementType_Float3; element.type = nzElementType_Float2;
elements[0].usage = nzElementUsage_Position; element.usage = nzElementUsage_Position;
elements[1].offset = 3*sizeof(float);
elements[1].type = nzElementType_Float2;
elements[1].usage = nzElementUsage_TexCoord;
std::unique_ptr<NzVertexDeclaration> declaration(new NzVertexDeclaration); std::unique_ptr<NzVertexDeclaration> 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(); Uninitialize();
return false; return false;
@ -752,9 +641,25 @@ bool NzRenderer::Initialize()
declaration->SetPersistent(false); 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(); 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()) if (!NzMaterial::Initialize())
{ {
NazaraError("Failed to initialize materials"); NazaraError("Failed to initialize materials");
@ -1306,7 +1211,7 @@ void NzRenderer::Uninitialize()
NzTextureSampler::Uninitialize(); NzTextureSampler::Uninitialize();
// Libération des buffers // Libération des buffers
delete s_quadBuffer; delete s_fullscreenQuadBuffer;
if (s_instancingBuffer) if (s_instancingBuffer)
{ {
@ -1396,7 +1301,6 @@ bool NzRenderer::EnsureStateUpdate()
{ {
TextureUnit& unit = s_textureUnits[i]; TextureUnit& unit = s_textureUnits[i];
///FIXME: Cet appel ne fait-il pas redondance avec le rebinding des textures avant le return ?
if (!unit.textureUpdated) if (!unit.textureUpdated)
{ {
NzOpenGL::SetTextureUnit(i); NzOpenGL::SetTextureUnit(i);