PrimeWorldEditor/Core/CRenderer.cpp

351 lines
9.5 KiB
C++

#include "CRenderer.h"
#include "CDrawUtil.h"
#include "CGraphics.h"
#include "CResCache.h"
#include <Common/AnimUtil.h>
#include <Common/CTransform4f.h>
#include <Resource/factory/CTextureDecoder.h>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <gtx/transform.hpp>
// ************ STATIC MEMBER INITIALIZATION ************
u32 CRenderer::sNumRenderers = 0;
// ************ INITIALIZATION ************
CRenderer::CRenderer()
{
mOptions = eEnableUVScroll | eEnableBackfaceCull;
mBloomMode = eNoBloom;
mDrawGrid = true;
mInitialized = false;
mContextIndex = -1;
mOpaqueBucket.SetSortType(CRenderBucket::FrontToBack);
mTransparentBucket.SetSortType(CRenderBucket::BackToFront);
sNumRenderers++;
}
CRenderer::~CRenderer()
{
sNumRenderers--;
if (sNumRenderers == 0)
{
CGraphics::Shutdown();
CDrawUtil::Shutdown();
}
}
void CRenderer::Init()
{
if (!mInitialized)
{
CVector4f ClearVec = mClearColor.ToVector4f();
glClearColor(ClearVec.x, ClearVec.y, ClearVec.z, ClearVec.w);
mContextIndex = CGraphics::GetContextIndex();
mInitialized = true;
}
}
// ************ GETTERS/SETTERS ************
bool CRenderer::IsUVAnimationOn()
{
return ((mOptions & eUVScroll) != 0);
}
void CRenderer::ToggleBackfaceCull(bool b)
{
if (b) mOptions |= eEnableBackfaceCull;
else mOptions &= ~eEnableBackfaceCull;
}
void CRenderer::ToggleUVAnimation(bool b)
{
if (b) mOptions |= eEnableUVScroll;
else mOptions &= ~eEnableUVScroll;
}
void CRenderer::ToggleGrid(bool b)
{
mDrawGrid = b;
}
void CRenderer::ToggleOccluders(bool b)
{
if (b) mOptions |= eEnableOccluders;
else mOptions &= ~eEnableOccluders;
}
void CRenderer::ToggleAlphaDisabled(bool b)
{
if (b) mOptions |= eNoAlpha;
else mOptions &= ~eNoAlpha;
}
void CRenderer::SetBloom(EBloomMode BloomMode)
{
mBloomMode = BloomMode;
if (BloomMode != eNoBloom)
mOptions |= eEnableBloom;
else
mOptions &= ~eEnableBloom;
}
void CRenderer::SetFont(CFont *pFont)
{
}
void CRenderer::SetClearColor(CColor Clear)
{
mClearColor = Clear;
CVector4f ClearVec = Clear.ToVector4f();
ClearVec.w = 0.f;
glClearColor(ClearVec.x, ClearVec.y, ClearVec.z, ClearVec.w);
}
void CRenderer::SetViewportSize(u32 Width, u32 Height)
{
mViewportWidth = Width;
mViewportHeight = Height;
mBloomHScale = ((float) Width / 640);
mBloomVScale = ((float) Height / 528);
mBloomWidth = (u32) (320 * mBloomHScale);
mBloomHeight = (u32) (224 * mBloomVScale);
mBloomHScale = 1.f / mBloomHScale;
mBloomVScale = 1.f / mBloomVScale;
}
// ************ RENDER ************
void CRenderer::RenderBuckets(CCamera& Camera)
{
if (!mInitialized) Init();
mSceneFramebuffer.Bind();
// Set backface culling
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
else glDisable(GL_CULL_FACE);
// Render scene to texture
glDepthRange(0.f, 1.f);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
mOpaqueBucket.Draw(mOptions);
mOpaqueBucket.Clear();
mTransparentBucket.Sort(Camera);
mTransparentBucket.Draw(mOptions);
mTransparentBucket.Clear();
}
void CRenderer::RenderBloom()
{
// Check to ensure bloom is enabled
if (mBloomMode == eNoBloom) return;
// Setup
static const float skHOffset[6] = { -0.008595f, -0.005470f, -0.002345f,
0.002345f, 0.005470f, 0.008595f };
static const float skVOffset[6] = { -0.012275f, -0.007815f, -0.003350f,
0.003350f, 0.007815f, 0.012275f };
static const CColor skTintColors[6] = { CColor((u8) 17, 17, 17, 255),
CColor((u8) 53, 53, 53, 255),
CColor((u8) 89, 89, 89, 255),
CColor((u8) 89, 89, 89, 255),
CColor((u8) 53, 53, 53, 255),
CColor((u8) 17, 17, 17, 255) };
float BloomWidth = (mBloomMode == eBloom ? mBloomWidth : mViewportWidth);
float BloomHeight = (mBloomMode == eBloom ? mBloomHeight : mViewportHeight);
float BloomHScale = (mBloomMode == eBloom ? mBloomHScale : 0);
float BloomVScale = (mBloomMode == eBloom ? mBloomVScale : 0);
glDisable(GL_DEPTH_TEST);
glViewport(0, 0, BloomWidth, BloomHeight);
glClearColor(0.f, 0.f, 0.f, 0.f);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
CGraphics::SetIdentityMVP();
CGraphics::UpdateMVPBlock();
// Pass 1: Alpha-blend the scene texture on a black background
mBloomFramebuffers[0].Resize(BloomWidth, BloomHeight);
mBloomFramebuffers[0].Bind();
glClear(GL_COLOR_BUFFER_BIT);
CDrawUtil::UseTextureShader();
glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
mSceneFramebuffer.Texture()->Bind(0);
CDrawUtil::DrawSquare();
// Pass 2: Horizontal blur
mBloomFramebuffers[1].Resize(BloomWidth, BloomHeight);
mBloomFramebuffers[1].Bind();
CDrawUtil::UseTextureShader(CColor::skGray);
glBlendFunc(GL_ONE, GL_ZERO);
mBloomFramebuffers[0].Texture()->Bind(0);
CDrawUtil::DrawSquare();
for (u32 iPass = 0; iPass < 6; iPass++)
{
CDrawUtil::UseTextureShader(skTintColors[iPass]);
CVector3f Translate(skHOffset[iPass] * BloomHScale, 0.f, 0.f);
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Translate).ToMatrix4f();
CGraphics::UpdateMVPBlock();
glBlendFunc(GL_ONE, GL_ONE);
CDrawUtil::DrawSquare();
}
// Pass 3: Vertical blur
mBloomFramebuffers[2].Resize(BloomWidth, BloomHeight);
mBloomFramebuffers[2].Bind();
glClear(GL_COLOR_BUFFER_BIT);
CDrawUtil::UseTextureShader(CColor::skGray);
glBlendFunc(GL_ONE, GL_ZERO);
mBloomFramebuffers[1].Texture()->Bind(0);
CDrawUtil::DrawSquare();
for (u32 iPass = 0; iPass < 6; iPass++)
{
CDrawUtil::UseTextureShader(skTintColors[iPass]);
CVector3f Translate(0.f, skVOffset[iPass] * BloomVScale, 0.f);
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(Translate).ToMatrix4f();
CGraphics::UpdateMVPBlock();
glBlendFunc(GL_ONE, GL_ONE);
CDrawUtil::DrawSquare();
}
// Render result onto main scene framebuffer
mSceneFramebuffer.Bind();
glViewport(0, 0, mViewportWidth, mViewportHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
CGraphics::SetIdentityMVP();
CGraphics::UpdateMVPBlock();
CDrawUtil::UseTextureShader();
glBlendFunc(GL_ONE, GL_ONE);
mBloomFramebuffers[2].Texture()->Bind(0);
CDrawUtil::DrawSquare();
if (mBloomMode == eBloomMaps)
{
// Bloom maps are in the framebuffer alpha channel.
// White * dst alpha = bloom map colors
CDrawUtil::UseColorShader(CColor::skWhite);
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
CDrawUtil::DrawSquare();
}
// Clean up
glEnable(GL_DEPTH_TEST);
}
void CRenderer::RenderSky(CModel *pSkyboxModel, CVector3f CameraPosition)
{
if (!mInitialized) Init();
if (!pSkyboxModel) return;
glEnable(GL_CULL_FACE);
CTransform4f ModelMtx;
ModelMtx.Translate(CameraPosition);
CGraphics::sMVPBlock.ModelMatrix = ModelMtx.ToMatrix4f();
CGraphics::sVertexBlock.COLOR0_Amb = CVector4f(1.f, 1.f, 1.f, 1.f);
CGraphics::sPixelBlock.TevColor = CVector4f(1.f, 1.f, 1.f, 1.f);
CGraphics::sNumLights = 0;
CGraphics::UpdateMVPBlock();
CGraphics::UpdateVertexBlock();
CGraphics::UpdatePixelBlock();
CGraphics::UpdateLightBlock();
glDepthRange(1.f, 1.f);
pSkyboxModel->Draw(mOptions, 0);
}
void CRenderer::AddOpaqueMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command)
{
SRenderablePtr ptr;
ptr.pRenderable = pRenderable;
ptr.Asset = AssetID;
ptr.AABox = AABox;
ptr.Command = Command;
mOpaqueBucket.Add(ptr);
}
void CRenderer::AddTransparentMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command)
{
SRenderablePtr ptr;
ptr.pRenderable = pRenderable;
ptr.Asset = AssetID;
ptr.AABox = AABox;
ptr.Command = Command;
mTransparentBucket.Add(ptr);
}
void CRenderer::BeginFrame()
{
if (!mInitialized) Init();
CGraphics::SetActiveContext(mContextIndex);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mDefaultFramebuffer);
mSceneFramebuffer.Resize(mViewportWidth, mViewportHeight);
mSceneFramebuffer.Bind();
glViewport(0, 0, mViewportWidth, mViewportHeight);
InitFramebuffer();
}
void CRenderer::EndFrame()
{
// Render result to screen
glBindFramebuffer(GL_FRAMEBUFFER, mDefaultFramebuffer);
InitFramebuffer();
glViewport(0, 0, mViewportWidth, mViewportHeight);
CGraphics::SetIdentityMVP();
CGraphics::UpdateMVPBlock();
glDisable(GL_DEPTH_TEST);
CDrawUtil::UseTextureShader();
glBlendFunc(GL_ONE, GL_ZERO);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
mSceneFramebuffer.Texture()->Bind(0);
CDrawUtil::DrawSquare();
glEnable(GL_DEPTH_TEST);
gDrawCount = 0;
}
void CRenderer::ClearDepthBuffer()
{
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
}
// ************ PRIVATE ************
void CRenderer::InitFramebuffer()
{
CVector4f Clear = mClearColor.ToVector4f();
Clear.w = 0.f;
glClearColor(Clear.x, Clear.y, Clear.z, Clear.w);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
u32 gDrawCount;