Files
2026-02-02 04:50:13 +01:00

1434 lines
43 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/graphics/Renderer3D.h"
#include "hpl1/debug.h"
#include "hpl1/engine/graphics/GPUProgram.h"
#include "hpl1/engine/graphics/LowLevelGraphics.h"
#include "hpl1/engine/graphics/MeshCreator.h"
#include "hpl1/engine/graphics/RenderList.h"
#include "hpl1/engine/graphics/Renderable.h"
#include "hpl1/engine/graphics/RendererPostEffects.h"
#include "hpl1/engine/graphics/Texture.h"
#include "hpl1/engine/graphics/VertexBuffer.h"
#include "hpl1/engine/math/BoundingVolume.h"
#include "hpl1/engine/math/Math.h"
#include "hpl1/engine/resources/GpuProgramManager.h"
#include "hpl1/engine/resources/Resources.h"
#include "hpl1/engine/resources/TextureManager.h"
#include "hpl1/engine/resources/low_level_resources.h"
#include "hpl1/engine/scene/Camera3D.h"
#include "hpl1/engine/scene/Entity3D.h"
#include "hpl1/engine/scene/Light3D.h"
#include "hpl1/engine/scene/RenderableContainer.h"
#include "hpl1/engine/scene/World3D.h"
#include "hpl1/engine/system/low_level_system.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// RENDER SETTINGS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cRenderSettings::cRenderSettings() {
mbFogActive = false;
mfFogStart = 5.0f;
mfFogEnd = 5.0f;
mFogColor = cColor(1, 1);
mbFogCulling = false;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cRenderer3D::cRenderer3D(iLowLevelGraphics *apLowLevelGraphics, cResources *apResources,
cMeshCreator *apMeshCreator, cRenderList *apRenderList) {
Hpl1::logInfo(Hpl1::kDebugGraphics, "%s", "Creating Renderer3D\n");
mpLowLevelGraphics = apLowLevelGraphics;
mpLowLevelResources = apResources->GetLowLevel();
mpResources = apResources;
mpMeshCreator = apMeshCreator;
mpSkyBoxTexture = NULL;
mbAutoDestroySkybox = false;
mbSkyBoxActive = false;
mSkyBoxColor = cColor(1, 1);
mRenderSettings.mAmbientColor = cColor(0, 1);
mpRenderList = apRenderList;
mDebugFlags = 0;
mbLog = false;
mfRenderTime = 0;
mbRefractionUsed = true;
mvVtxRect.resize(4);
mvVtxRect[0] = cVertex(cVector3f(0, 0, 0), cVector2f(0, 1), cColor(1, 1));
mvVtxRect[1] = cVertex(cVector3f(1, 0, 0), cVector2f(1, 1), cColor(1, 1));
mvVtxRect[2] = cVertex(cVector3f(1, 1, 0), cVector2f(1, 0), cColor(1, 1));
mvVtxRect[3] = cVertex(cVector3f(0, 1, 40), cVector2f(0, 0), cColor(1, 1));
// Set up render settings.
mRenderSettings.mpLowLevel = mpLowLevelGraphics;
mRenderSettings.mbLog = false;
mRenderSettings.mShowShadows = eRendererShowShadows_All;
mRenderSettings.mpTempIndexArray = hplNewArray(unsigned int, 60000);
Hpl1::logInfo(Hpl1::kDebugGraphics, "%s", "Load Renderer3D gpu programs:\n");
cGpuProgramManager *pProgramManager = apResources->GetGpuProgramManager();
mRenderSettings.extrudeProgram = pProgramManager->CreateProgram("hpl1_ShadowExtrude", "hpl1_ShadowExtrude");
///////////////////////////////////
// Load diffuse program, for stuff like query rendering
_diffuseProgram = pProgramManager->CreateProgram("hpl1_Diffuse_Color", "hpl1_Diffuse_Color");
///////////////////////////////////
// Fog Vertex Program Init
_solidFogProgram = pProgramManager->CreateProgram("hpl1_Fog_Solid", "hpl1_Fog_Solid");
///////////////////////////////////
// Fog Texture Init
Log("Creating fog textures:");
unsigned char *pFogArray = hplNewArray(unsigned char, 256 * 2);
// Solid
Log("Solid");
iTexture *pTex = mpLowLevelGraphics->CreateTexture("FogLinearSolid",
false, eTextureType_Normal, eTextureTarget_1D);
for (int i = 0; i < 256; ++i) {
pFogArray[i * 2 + 0] = 255;
// pFogArray[i*2 + 0] = 255 - (unsigned char)i;
pFogArray[i * 2 + 1] = 255 - (unsigned char)i;
}
if (pTex) {
pTex->CreateFromArray(pFogArray, 2, cVector3l(256, 1, 1));
pTex->SetWrapR(eTextureWrap_ClampToEdge);
pTex->SetWrapS(eTextureWrap_ClampToEdge);
pTex->SetWrapT(eTextureWrap_ClampToEdge);
}
mpFogLinearSolidTexture = pTex;
// Additive
Log("Additive ");
pTex = mpLowLevelGraphics->CreateTexture("FogLinearAdd",
false, eTextureType_Normal, eTextureTarget_1D);
for (int i = 0; i < 256; ++i) {
pFogArray[i * 2 + 0] = (unsigned char)i;
pFogArray[i * 2 + 1] = (unsigned char)i;
}
if (pTex) {
pTex->CreateFromArray(pFogArray, 2, cVector3l(256, 1, 1));
pTex->SetWrapR(eTextureWrap_ClampToEdge);
pTex->SetWrapS(eTextureWrap_ClampToEdge);
}
mpFogLinearAddTexture = pTex;
// Alpha
Log("Alpha ");
pTex = mpLowLevelGraphics->CreateTexture("FogLinearAlpha",
false, eTextureType_Normal, eTextureTarget_1D);
for (int i = 0; i < 256; ++i) {
pFogArray[i * 2 + 0] = 255;
pFogArray[i * 2 + 1] = (unsigned char)i;
}
if (pTex) {
pTex->CreateFromArray(pFogArray, 2, cVector3l(256, 1, 1));
pTex->SetWrapR(eTextureWrap_ClampToEdge);
pTex->SetWrapS(eTextureWrap_ClampToEdge);
}
mpFogLinearAlphaTexture = pTex;
hplDeleteArray(pFogArray);
Log("\n");
/////////////////////////////////////////////
// Create Refraction programs
mbRefractionAvailable = true;
_refractProgram = pProgramManager->CreateProgram("hpl1_refract", "hpl1_refract");
_refractSpecProgram = pProgramManager->CreateProgram("hpl1_refract", "hpl1_refract_special");
if (!_refractProgram || !_refractSpecProgram) {
mbRefractionAvailable = false;
Hpl1::logInfo(Hpl1::kDebugGraphics, "%s", "refraction will not be supported");
}
/////////////////////////////////////////////
// Create sky box graphics.
Log("init sky box\n");
InitSkyBox();
Log("Renderer3D created\n");
}
//-----------------------------------------------------------------------
cRenderer3D::~cRenderer3D() {
hplDeleteArray(mRenderSettings.mpTempIndexArray);
if (mRenderSettings.extrudeProgram)
mpResources->GetGpuProgramManager()->Destroy(mRenderSettings.extrudeProgram);
if (_diffuseProgram)
mpResources->GetGpuProgramManager()->Destroy(_diffuseProgram);
if (_solidFogProgram)
mpResources->GetGpuProgramManager()->Destroy(_solidFogProgram);
if (_refractProgram)
mpResources->GetGpuProgramManager()->Destroy(_refractProgram);
if (_refractSpecProgram)
mpResources->GetGpuProgramManager()->Destroy(_refractSpecProgram);
if (mpSkyBox)
hplDelete(mpSkyBox);
if (mpSkyBoxTexture && mbAutoDestroySkybox) {
mpResources->GetTextureManager()->Destroy(mpSkyBoxTexture);
}
if (mpFogLinearSolidTexture)
hplDelete(mpFogLinearSolidTexture);
if (mpFogLinearAddTexture)
hplDelete(mpFogLinearAddTexture);
if (mpFogLinearAlphaTexture)
hplDelete(mpFogLinearAlphaTexture);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cRenderSettings::Clear() {
mlLastShadowAlgo = 0;
mbDepthTest = true;
mAlphaMode = eMaterialAlphaMode_Solid;
mBlendMode = eMaterialBlendMode_None;
mChannelMode = eMaterialChannelMode_RGBA;
gpuProgram = nullptr;
mbVertexUseLight = false;
mpSector = NULL;
mbUsesLight = false;
mbUsesEye = false;
mbMatrixWasNULL = false;
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
mpTexture[i] = NULL;
mTextureBlend[i] = eMaterialBlendMode_None;
}
mpVtxBuffer = NULL;
}
void cRenderSettings::Reset(iLowLevelGraphics *apLowLevel) {
if (gpuProgram)
gpuProgram->UnBind();
if (mpVtxBuffer)
mpVtxBuffer->UnBind();
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
if (mpTexture[i]) {
apLowLevel->SetTexture(i, NULL);
// mpLowLevelGraphics->SetTextureParam(eTextureParam_ColorOp1,eTextureOp_Color);
// mpLowLevelGraphics->SetTextureParam(eTextureParam_ColorFunc, eTextureFunc_Modulate);
}
}
Clear();
}
//-----------------------------------------------------------------------
eRendererShowShadows cRenderer3D::GetShowShadows() {
return mRenderSettings.mShowShadows;
}
void cRenderer3D::SetShowShadows(eRendererShowShadows aState) {
mRenderSettings.mShowShadows = aState;
}
//-----------------------------------------------------------------------
void cRenderer3D::UpdateRenderList(cWorld3D *apWorld, cCamera3D *apCamera, float afFrameTime) {
// Clear all objects to be rendereded
mpRenderList->Clear();
// Set some variables
mpRenderList->SetFrameTime(afFrameTime);
mpRenderList->SetCamera(apCamera);
// Set the frustum
mRenderSettings.mpFrustum = apCamera->GetFrustum();
// Setup fog BV
if (mRenderSettings.mbFogActive && mRenderSettings.mbFogCulling) {
// This is because the fog line is a straight line infront of the camera.
float fCornerDist = (mRenderSettings.mfFogEnd * 2.0f) /
cos(apCamera->GetFOV() * apCamera->GetAspect() * 0.5f);
mFogBV.SetSize(fCornerDist);
mFogBV.SetPosition(apCamera->GetPosition());
}
// Add all objects to be rendered
apWorld->GetRenderContainer()->GetVisible(mRenderSettings.mpFrustum, mpRenderList);
// Compile an optimized render list.
mpRenderList->Compile();
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderWorld(cWorld3D *apWorld, cCamera3D *apCamera, float afFrameTime) {
mfRenderTime += afFrameTime;
//////////////////////////////
// Setup render settings and logging
if (mDebugFlags & eRendererDebugFlag_LogRendering) {
mbLog = true;
mRenderSettings.mbLog = true;
} else if (mbLog) {
mbLog = false;
mRenderSettings.mbLog = false;
}
mRenderSettings.mDebugFlags = mDebugFlags;
/////////////////////////////////
// Set up rendering
BeginRendering(apCamera);
mRenderSettings.Clear();
////////////////////////////
// Render Z
// mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_E);
mpLowLevelGraphics->SetColorWriteActive(true, true, true, true);
mRenderSettings.mChannelMode = eMaterialChannelMode_RGBA;
// mpLowLevelGraphics->SetColorWriteActive(false, false, false,false);
// mRenderSettings.mChannelMode = eMaterialChannelMode_Z;
// Set the ambient color
mpLowLevelGraphics->SetActiveTextureUnit(0);
mpLowLevelGraphics->SetTextureEnv(eTextureParam_ColorFunc, eTextureFunc_Modulate);
mpLowLevelGraphics->SetTextureEnv(eTextureParam_ColorSource0, eTextureSource_Texture);
mpLowLevelGraphics->SetTextureEnv(eTextureParam_ColorSource1, eTextureSource_Constant);
// mpLowLevelGraphics->SetTextureEnv(eTextureParam_AlphaSource1,eTextureSource_Constant);
mpLowLevelGraphics->SetTextureConstantColor(mRenderSettings.mAmbientColor);
if (mbLog)
Log("Rendering ZBuffer:\n");
RenderZ(apCamera);
// reset parameters.
mpLowLevelGraphics->SetTextureEnv(eTextureParam_ColorSource1, eTextureSource_Previous);
// mpLowLevelGraphics->SetTextureEnv(eTextureParam_AlphaSource1,eTextureSource_Previous);
////////////////////////////
// Render Occlusion Queries
mpLowLevelGraphics->SetColorWriteActive(false, false, false, false);
mRenderSettings.mChannelMode = eMaterialChannelMode_Z;
if (mbLog)
Log("Rendering Occlusion Queries:\n");
mpLowLevelGraphics->SetDepthWriteActive(false);
RenderOcclusionQueries(apCamera);
////////////////////////////
// Render lighting
mRenderSettings.mChannelMode = eMaterialChannelMode_RGBA;
mpLowLevelGraphics->SetColorWriteActive(true, true, true, true);
mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_Equal);
if (mbLog)
Log("Rendering Lighting:\n");
RenderLight(apCamera);
////////////////////////////
// Render Diffuse
if (mbLog)
Log("Rendering Diffuse:\n");
RenderDiffuse(apCamera);
////////////////////////////
// Render fog
if (mbLog)
Log("Rendering fog:\n");
RenderFog(apCamera);
////////////////////////////
// Render sky box
mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_LessOrEqual);
////////////////////////////
if (mbLog)
Log("Rendering Skybox:\n");
RenderSkyBox(apCamera);
// Render transparent
if (mbLog)
Log("Rendering Transperant:\n");
RenderTrans(apCamera);
mRenderSettings.Reset(mpLowLevelGraphics);
////////////////////////////
// Render debug
RenderDebug(apCamera);
mpLowLevelGraphics->SetDepthWriteActive(true);
}
//-----------------------------------------------------------------------
void cRenderer3D::SetSkyBox(iTexture *apTexture, bool abAutoDestroy) {
if (mpSkyBoxTexture && mbAutoDestroySkybox) {
mpResources->GetTextureManager()->Destroy(mpSkyBoxTexture);
}
mbAutoDestroySkybox = abAutoDestroy;
mpSkyBoxTexture = apTexture;
if (mpSkyBoxTexture) {
mpSkyBoxTexture->SetWrapS(eTextureWrap_ClampToEdge);
mpSkyBoxTexture->SetWrapT(eTextureWrap_ClampToEdge);
}
}
void cRenderer3D::SetSkyBoxActive(bool abX) {
mbSkyBoxActive = abX;
}
void cRenderer3D::SetSkyBoxColor(const cColor &aColor) {
if (mSkyBoxColor == aColor)
return;
mSkyBoxColor = aColor;
float *pColors = mpSkyBox->GetArray(eVertexFlag_Color0);
int lNum = mpSkyBox->GetVertexNum();
for (int i = 0; i < lNum; ++i) {
pColors[0] = mSkyBoxColor.r;
pColors[1] = mSkyBoxColor.g;
pColors[2] = mSkyBoxColor.b;
pColors[3] = mSkyBoxColor.a;
pColors += 4;
}
mpSkyBox->UpdateData(eVertexFlag_Color0, false);
}
//-----------------------------------------------------------------------
void cRenderer3D::SetFogActive(bool abX) {
if (_solidFogProgram)
mRenderSettings.mbFogActive = abX;
}
void cRenderer3D::SetFogStart(float afX) {
mRenderSettings.mfFogStart = afX;
}
void cRenderer3D::SetFogEnd(float afX) {
mRenderSettings.mfFogEnd = afX;
}
//-----------------------------------------------------------------------
void cRenderer3D::FetchOcclusionQueries() {
if (mbLog)
Log("Fetching Occlusion Queries Result:\n");
// With depth test
cOcclusionQueryObjectIterator it = mpRenderList->GetQueryIterator();
while (it.HasNext()) {
cOcclusionQueryObject *pObject = it.Next();
// LogUpdate("Query: %d!\n",pObject->mpQuery);
while (pObject->mpQuery->FetchResults() == false)
;
if (mbLog)
Log(" Query: %d SampleCount: %d\n", pObject->mpQuery,
pObject->mpQuery->GetSampleCount());
}
if (mbLog)
Log("Done fetching queries\n");
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cRenderer3D::BeginRendering(cCamera3D *apCamera) {
//////////////////////////////////////////////////
/////Setup for clearing the screen
// turn of scissor test.
mpLowLevelGraphics->SetScissorActive(false);
mpLowLevelGraphics->SetClearColor(cColor(0, 0));
mpLowLevelGraphics->SetClearColorActive(true);
mpLowLevelGraphics->SetClearDepthActive(true);
mpLowLevelGraphics->SetClearDepth(1);
mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_LessOrEqual);
mpLowLevelGraphics->SetClearStencilActive(false);
mpLowLevelGraphics->ClearScreen();
//////////////////////////////////////////////////
// Cull and depth mode.
mpLowLevelGraphics->SetCullActive(true);
mpLowLevelGraphics->SetCullMode(eCullMode_CounterClockwise);
mpLowLevelGraphics->SetDepthTestActive(true);
mpLowLevelGraphics->SetMatrix(eMatrix_Projection, apCamera->GetProjectionMatrix());
mpLowLevelGraphics->SetColor(cColor(1, 1, 1, 1));
mRenderSettings.mpCamera = apCamera;
for (int i = 0; i < MAX_TEXTUREUNITS; ++i)
mpLowLevelGraphics->SetTexture(i, NULL);
}
//-----------------------------------------------------------------------
void cRenderer3D::InitSkyBox() {
mpSkyBox = mpMeshCreator->CreateSkyBoxVertexBuffer(1);
}
//-----------------------------------------------------------------------
static void clearTextures(uint start, cRenderSettings &rendererSettings, iLowLevelGraphics *lowLevelGfx) {
for (uint i = start; i < MAX_TEXTUREUNITS; ++i) {
if (rendererSettings.mpTexture[i]) {
lowLevelGfx->SetTexture(i, nullptr);
rendererSettings.mpTexture[i] = nullptr;
}
}
}
void cRenderer3D::RenderFog(cCamera3D *apCamera) {
if (mRenderSettings.mbFogActive == false || !_solidFogProgram)
return;
clearTextures(0, mRenderSettings, mpLowLevelGraphics);
//////////////////////////////////
// Set fog program
if (mRenderSettings.gpuProgram)
mRenderSettings.gpuProgram->UnBind();
mRenderSettings.gpuProgram = nullptr;
_solidFogProgram->Bind();
_solidFogProgram->SetColor3f("fogColor", mRenderSettings.mFogColor);
_solidFogProgram->SetFloat("fogStart", mRenderSettings.mfFogStart);
_solidFogProgram->SetFloat("fogEnd", mRenderSettings.mfFogEnd);
//////////////////////////////////
// Blend mode
mpLowLevelGraphics->SetBlendActive(true);
// mpLowLevelGraphics->SetBlendFunc(eBlendFunc_One,eBlendFunc_Zero);
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_SrcAlpha, eBlendFunc_OneMinusSrcAlpha);
mRenderSettings.mBlendMode = eMaterialBlendMode_LastEnum;
//////////////////////////////////////
// Texture
mpLowLevelGraphics->SetTexture(0, mpFogLinearSolidTexture);
mRenderSettings.mpTexture[0] = mpFogLinearSolidTexture;
//////////////////////////////////
// Render objects
cMotionBlurObjectIterator it = mpRenderList->GetMotionBlurIterator();
while (it.HasNext()) {
iRenderable *pObject = it.Next();
cMatrixf *pMtx = pObject->GetModelMatrix(apCamera);
//////////////////
// Non static models
if (pMtx) {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, cMath::MatrixMul(apCamera->GetViewMatrix(),
*pMtx));
_solidFogProgram->SetMatrixf("worldViewProj", eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
}
//////////////////
// NULL Model view matrix (static)
else {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
_solidFogProgram->SetMatrixf("worldViewProj", eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
}
pObject->GetVertexBuffer()->Bind();
pObject->GetVertexBuffer()->Draw();
pObject->GetVertexBuffer()->UnBind();
}
_solidFogProgram->UnBind();
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderSkyBox(cCamera3D *apCamera) {
if (mbSkyBoxActive == false)
return;
Hpl1::logInfo(Hpl1::kDebugRenderer, "%s\n", "Drawing skybox");
if (mRenderSettings.gpuProgram) {
mRenderSettings.gpuProgram->UnBind();
mRenderSettings.gpuProgram = nullptr;
}
if (mRenderSettings.mpVtxBuffer) {
mRenderSettings.mpVtxBuffer->UnBind();
mRenderSettings.mpVtxBuffer = NULL;
if (mbLog)
Log(" Setting Vertex Buffer: NULL\n");
}
clearTextures(1, mRenderSettings, mpLowLevelGraphics);
mRenderSettings.mbMatrixWasNULL = false;
cMatrixf mtxSky = cMatrixf::Identity;
// Calculate the size of the sky box need to just touch the far clip plane.
float fFarClip = apCamera->GetFarClipPlane();
float fSide = fFarClip / sqrt(3) * 0.95f;
mtxSky.m[0][0] = fSide;
mtxSky.m[1][1] = fSide;
mtxSky.m[2][2] = fSide;
mtxSky = cMath::MatrixMul(mtxSky, apCamera->GetViewMatrix());
mtxSky.SetTranslation(0);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxSky);
mpLowLevelGraphics->SetTexture(0, mpSkyBoxTexture);
mRenderSettings.mpTexture[0] = mpSkyBoxTexture;
mpLowLevelGraphics->SetBlendActive(false);
mRenderSettings.mBlendMode = eMaterialBlendMode_Replace;
mpSkyBox->Bind();
mpSkyBox->Draw();
mpSkyBox->UnBind();
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderZ(cCamera3D *apCamera) {
cRenderNode *pNode = mpRenderList->GetRootNode(eRenderListDrawType_Normal,
eMaterialRenderType_Z, 0);
mRenderSettings.mpLight = NULL;
pNode->Render(&mRenderSettings);
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderOcclusionQueries(cCamera3D *apCamera) {
#if 0
//////////////////////////////////////////////////
// Reset any vertex buffers,fragment or vertex programs.
if (mRenderSettings.mpFragmentProgram)
mRenderSettings.mpFragmentProgram->UnBind();
mRenderSettings.mpFragmentProgram = NULL;
#endif
////////////////////////////
// Vertex program
if (mRenderSettings.gpuProgram != _diffuseProgram) {
if (mRenderSettings.gpuProgram)
mRenderSettings.gpuProgram->UnBind();
mRenderSettings.gpuProgram = _diffuseProgram;
_diffuseProgram->Bind();
Hpl1::logInfo(Hpl1::kDebugGraphics, "%s", "binding Rendered3D::_diffuseProgram");
}
////////////////////////
// Reset texture unit 0
mpLowLevelGraphics->SetTexture(0, NULL);
mRenderSettings.mpTexture[0] = NULL;
////////////////////////
// Keep track of what has been set
iVertexBuffer *pPrevBuffer = mRenderSettings.mpVtxBuffer;
cMatrixf *pPrevMatrix = NULL;
bool bFirstRound = true;
bool bPrevDepthTest = true;
//////////////////////////////////
// Iterate the query objects
cOcclusionQueryObjectIterator it = mpRenderList->GetQueryIterator();
while (it.HasNext()) {
cOcclusionQueryObject *pObject = it.Next();
/*if(pObject->mbDepthTest) {
mpLowLevelGraphics->SetColorWriteActive(true, true,true,true);
mRenderSettings.mChannelMode = eMaterialChannelMode_RGBA;
}
else {
mpLowLevelGraphics->SetColorWriteActive(false, false, false, false);
mRenderSettings.mChannelMode = eMaterialChannelMode_Z;
}*/
/////////////////////
// Set depth test
if (bPrevDepthTest != pObject->mbDepthTest) {
// mpLowLevelGraphics->SetDepthTestActive(pObject->mbDepthTest);
if (pObject->mbDepthTest)
mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_LessOrEqual);
else
mpLowLevelGraphics->SetDepthTestFunc(eDepthTestFunc_Always);
bPrevDepthTest = pObject->mbDepthTest;
if (mbLog)
Log(" Setting depth test %d\n", pObject->mbDepthTest ? 1 : 0);
}
/////////////////////
// Set matrix
if (pPrevMatrix != pObject->mpMatrix || bFirstRound) {
if (pObject->mpMatrix) {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, cMath::MatrixMul(apCamera->GetViewMatrix(), *pObject->mpMatrix));
} else {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
}
pPrevMatrix = pObject->mpMatrix;
// Set the vertex program matrix.
if (_diffuseProgram)
_diffuseProgram->SetMatrixf("worldViewProj", eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
if (mbLog)
Log(" Setting matrix %d\n", pObject->mpMatrix);
}
/////////////////////
// Set Vertex buffer and draw
if (pPrevBuffer != pObject->mpVtxBuffer) {
if (pPrevBuffer)
pPrevBuffer->UnBind();
pObject->mpVtxBuffer->Bind();
pPrevBuffer = pObject->mpVtxBuffer;
if (mbLog)
Log(" Setting vtx buffer %d\n", pObject->mpVtxBuffer);
}
pObject->mpQuery->Begin();
pObject->mpVtxBuffer->Draw();
pObject->mpQuery->End();
if (mbLog)
Log(" Render with query: %d\n", pObject->mpQuery);
bFirstRound = false;
}
mRenderSettings.mpVtxBuffer = pPrevBuffer;
// mpLowLevelGraphics->FlushRendering();
// if(bPrevDepthTest==false)
// mpLowLevelGraphics->SetDepthTestActive(true);
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderLight(cCamera3D *apCamera) {
if (mDebugFlags & eRendererDebugFlag_DisableLighting)
return;
cLight3DIterator lightIt = mpRenderList->GetLightIt();
int lLightCount = 0;
while (lightIt.HasNext()) {
if (lLightCount >= MAX_NUM_OF_LIGHTS)
break;
iLight3D *pLight = lightIt.Next();
if (mpRenderList->GetLightObjects(lLightCount) == 0) {
lLightCount++;
continue;
}
if (mbLog)
Log("-----Light %s/%d ------\n", pLight->GetName().c_str(), (size_t)pLight);
cRenderNode *pNode = mpRenderList->GetRootNode(eRenderListDrawType_Normal,
eMaterialRenderType_Light, lLightCount);
if (pLight->BeginDraw(&mRenderSettings, mpLowLevelGraphics)) {
pNode->Render(&mRenderSettings);
}
pLight->EndDraw(&mRenderSettings, mpLowLevelGraphics);
lLightCount++;
}
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderDiffuse(cCamera3D *apCamera) {
cRenderNode *pNode = mpRenderList->GetRootNode(eRenderListDrawType_Normal,
eMaterialRenderType_Diffuse, 0);
mRenderSettings.mpLight = NULL;
pNode->Render(&mRenderSettings);
}
//-----------------------------------------------------------------------
/*void cRenderer3D::RenderTrans(cCamera3D *apCamera)
{
cRenderNode* pNode = mpRenderList->GetRootNode(eRenderListDrawType_Trans,
eMaterialRenderType_Diffuse, 0);
mRenderSettings.mpLight = NULL;
pNode->Render(&mRenderSettings);
}*/
void cRenderer3D::RenderTrans(cCamera3D *apCamera) {
mpLowLevelGraphics->SetColorWriteActive(true, true, true, true);
mpLowLevelGraphics->SetDepthWriteActive(false);
bool bLog = mRenderSettings.mbLog;
iTexture *vTextures[MAX_TEXTUREUNITS];
/*for(int i=0;i<MAX_TEXTUREUNITS;i++)
{
mpLowLevelGraphics->SetTexture(i,NULL);
mRenderSettings.mpTexture[i] = NULL;
}*/
/*cVector3f vForward = */ apCamera->GetForward();
//////////////////////////////////
// Iterate the query objects
cTransperantObjectIterator it = mpRenderList->GetTransperantIterator();
while (it.HasNext()) {
iRenderable *pObject = it.Next();
if (bLog)
Log(" Rendering '%s'\n", pObject->GetName().c_str());
/*if(pObject->GetIsOneSided())
{
cVector3f vNormal;
if(pObject->GetModelMatrix(apCamera))
{
vNormal = cMath::MatrixMul(pObject->GetWorldMatrix().GetRotation(), pObject->GetOneSidedNormal());
vNormal = cMath::MatrixMul(apCamera->GetViewMatrix().GetRotation(), vNormal);
}
else
{
vNormal = cMath::MatrixMul(apCamera->GetViewMatrix().GetRotation(), pObject->GetOneSidedNormal());
}
if(cMath::Vector3Dot(vNormal, cVector3f(0,0,1)) < -0.5f)
{
continue;
}
}*/
/////////////////////////////////////////
// Get all data needed
iMaterial *pMaterial = pObject->GetMaterial();
bool bDepthTest = pMaterial->GetDepthTest();
eMaterialAlphaMode alphaMode = pMaterial->GetAlphaMode(eMaterialRenderType_Diffuse, 0, NULL);
eMaterialBlendMode blendMode = pMaterial->GetBlendMode(eMaterialRenderType_Diffuse, 0, NULL);
for (int i = 0; i < MAX_TEXTUREUNITS; ++i)
vTextures[i] = pMaterial->GetTexture(i, eMaterialRenderType_Diffuse, 0, NULL);
iVertexBuffer *pVtxBuffer = pObject->GetVertexBuffer();
cMatrixf *pModelMatrix = pObject->GetModelMatrix(apCamera);
cMatrixf *pInvModelMatrix = pObject->GetInvModelMatrix();
iTexture *pRefraction = pMaterial->GetTexture(eMaterialTexture_Refraction);
if (mRenderSettings.mbDepthTest != bDepthTest) {
mpLowLevelGraphics->SetDepthTestActive(bDepthTest);
mRenderSettings.mbDepthTest = bDepthTest;
if (bLog)
Log(" Set depth test %d\n", bDepthTest);
}
/////////////////////////////////////////
// Refraction Rendering
if (mbRefractionAvailable && pRefraction && mbRefractionUsed) {
if (bLog)
Log(" Start render refraction\n");
if (bLog)
Log(" Unbind vtx buffer, vtx program and frag program\n");
if (mRenderSettings.mpVtxBuffer)
mRenderSettings.mpVtxBuffer->UnBind();
if (mRenderSettings.gpuProgram)
mRenderSettings.gpuProgram->UnBind();
/////////////////////////////////////
// Alpha and blend mode
mRenderSettings.mAlphaMode = eMaterialAlphaMode_Solid;
mpLowLevelGraphics->SetAlphaTestActive(false);
mRenderSettings.mBlendMode = eMaterialBlendMode_None;
mpLowLevelGraphics->SetBlendActive(false);
//////////////////////////////
// Get Screen Clip space
cVector2f vScreenSizeFloat = mpLowLevelGraphics->GetScreenSize();
cVector2l vScreenSize((int)mpLowLevelGraphics->GetScreenSize().x,
(int)mpLowLevelGraphics->GetScreenSize().y);
iTexture *pScreen = mpPostEffects->GetFreeScreenTexture();
// Get the cliprect objects bounding volume
cRect2l clipRect;
int lScale = cMath::Abs((int)pMaterial->GetValue()) + 1;
bool bHasClipRect = cMath::GetClipRectFromBV(clipRect, *pObject->GetBoundingVolume(),
apCamera->GetViewMatrix(), apCamera->GetProjectionMatrix(),
apCamera->GetNearClipPlane(), vScreenSize);
if (bHasClipRect) {
clipRect.x -= lScale;
if (clipRect.x < 0) {
clipRect.w += clipRect.x;
clipRect.x = 0;
}
clipRect.y -= lScale;
if (clipRect.y < 0) {
clipRect.h += clipRect.y;
clipRect.y = 0;
}
clipRect.w += lScale * 2;
if (clipRect.w + clipRect.x > vScreenSize.x)
clipRect.w = vScreenSize.x - clipRect.x;
clipRect.h += lScale * 2;
if (clipRect.h + clipRect.y > vScreenSize.y)
clipRect.h = vScreenSize.y - clipRect.y;
}
//////////////////////////////
// Render to alpha if water, (shitty test this is...)
if (pMaterial->GetRefractionSkipsStandardTrans()) {
if (bLog)
Log(" Render alpha to screen\n");
// NULL all textuer
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
if (mRenderSettings.mpTexture[i] != NULL) {
mpLowLevelGraphics->SetTexture(i, NULL);
mRenderSettings.mpTexture[i] = NULL;
if (bLog)
Log(" Set texture[%d] NULL\n", i);
}
}
// Only write to alpha
mpLowLevelGraphics->SetColorWriteActive(false, false, false, true);
////////////////////////////////////////////////
// Clear alpha using 2D quad.
mpLowLevelGraphics->SetOrthoProjection(mpLowLevelGraphics->GetScreenSize(), -1000, 1000);
mpLowLevelGraphics->SetIdentityMatrix(eMatrix_ModelView);
if (bHasClipRect) {
cVector2f vOffset = cVector2f((float)clipRect.x, (float)clipRect.y);
cVector2f vSize = cVector2f((float)clipRect.w, (float)clipRect.h);
mvVtxRect[0].pos = cVector3f(vOffset.x, vOffset.y, 0);
mvVtxRect[1].pos = cVector3f(vOffset.x + vSize.x, vOffset.y, 0);
mvVtxRect[2].pos = cVector3f(vOffset.x + vSize.x, vOffset.y + vSize.y, 0);
mvVtxRect[3].pos = cVector3f(vOffset.x, vOffset.y + vSize.y, 0);
} else {
mvVtxRect[0].pos = cVector3f(0, 0, 0);
mvVtxRect[1].pos = cVector3f(vScreenSizeFloat.x, 0, 0);
mvVtxRect[2].pos = cVector3f(vScreenSizeFloat.x, vScreenSizeFloat.y, 0);
mvVtxRect[3].pos = cVector3f(0, vScreenSizeFloat.y, 0);
}
for (int i = 0; i < 4; ++i)
mvVtxRect[i].col.a = 0;
mpLowLevelGraphics->DrawQuad(mvVtxRect);
// Set back to ordinary projection...
mpLowLevelGraphics->SetMatrix(eMatrix_Projection, apCamera->GetProjectionMatrix());
// Set Model matrix
if (pModelMatrix) {
cMatrixf mtxModel = cMath::MatrixMul(apCamera->GetViewMatrix(), *pModelMatrix);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxModel);
mRenderSettings.mbMatrixWasNULL = false;
} else {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
mRenderSettings.mbMatrixWasNULL = true;
}
pVtxBuffer->Bind();
if (bLog)
Log(" Drawing vtx buffer %d\n", pVtxBuffer);
pVtxBuffer->Draw();
pVtxBuffer->UnBind();
// Reset stuff
mpLowLevelGraphics->SetColorWriteActive(true, true, true, true);
}
//////////////////////////////
// Copy Screen To Texture
if (bHasClipRect) {
cVector2l vOffset = cVector2l(clipRect.x, clipRect.y);
cVector2l vSize = cVector2l(clipRect.w, clipRect.h);
/*Log(" ScreenSize: %d:%d Offset: %d:%d Size: %d:%d Scale: %d\n",vScreenSize.x,vScreenSize.y,
vOffset.x,vOffset.y,
vSize.x, vSize.y,
lScale);*/
mpLowLevelGraphics->CopyContextToTexure(pScreen, vOffset, vSize, vOffset);
if (bLog)
Log(" Copy clipped screen texture\n");
} else {
mpLowLevelGraphics->CopyContextToTexure(pScreen, 0, vScreenSize);
if (bLog)
Log(" Copy full screen screen texture\n");
}
//////////////////////////////
// Set up programs
bool bSpecial = false;
if (pMaterial->GetTexture(eMaterialTexture_Specular) != NULL &&
pMaterial->GetRefractionDiffuseTexture() == eMaterialTexture_Diffuse) {
bSpecial = true;
if (bLog)
Log(" Special = true\n");
}
iGpuProgram *refractProgram = pMaterial->getRefractionProgram();
if (!refractProgram) {
if (bSpecial)
refractProgram = _refractSpecProgram;
else
refractProgram = _refractProgram;
}
mRenderSettings.gpuProgram = refractProgram;
refractProgram->Bind();
Hpl1::logInfo(Hpl1::kDebugRenderer, "Binding gpu program '%s'", refractProgram->GetName().c_str());
/////////////////////////////////////
// Vertex shader
mRenderSettings.mbMatrixWasNULL = false;
// Model matrix
if (pModelMatrix) {
cMatrixf mtxModel = cMath::MatrixMul(apCamera->GetViewMatrix(), *pModelMatrix);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxModel);
mRenderSettings.mbMatrixWasNULL = false;
} else {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
mRenderSettings.mbMatrixWasNULL = true;
}
refractProgram->SetMatrixf("worldViewProj",
eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
// Eye position
if (pMaterial->GetRefractionUsesEye()) {
if (pModelMatrix) {
cVector3f vLocalEye = cMath::MatrixMul(*pInvModelMatrix, apCamera->GetEyePosition());
refractProgram->SetVec3f("EyePos", vLocalEye);
} else {
refractProgram->SetVec3f("EyePos", apCamera->GetEyePosition());
}
}
/////////////////////////////////////
// Fragment shader
refractProgram->SetVec2f("screenSize", mpLowLevelGraphics->GetScreenSize());
if (bSpecial) {
refractProgram->SetFloat("t", mfRenderTime * pRefraction->GetFrameTime());
} else if (pMaterial->GetRefractionUsesTime()) {
refractProgram->SetFloat("t", mfRenderTime);
}
refractProgram->SetFloat("scale", pMaterial->GetValue());
////////////////////////////////////
// Textures
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
// float fTime;
iTexture *pTex = NULL;
switch (i) {
case 0:
pTex = pScreen;
break;
case 1:
pTex = pRefraction;
break;
case 2:
if (bSpecial) {
pTex = pMaterial->GetTexture(eMaterialTexture_Specular);
} else if (pMaterial->GetRefractionUsesDiffuse()) {
pTex = pMaterial->GetTexture(pMaterial->GetRefractionDiffuseTexture());
}
}
if (mRenderSettings.mpTexture[i] != pTex) {
mpLowLevelGraphics->SetTexture(i, pTex);
mRenderSettings.mpTexture[i] = pTex;
if (bLog) {
if (pTex)
Log(" Set texture[%d] %s (%d)\n", i, pTex->GetName().c_str(), pTex);
else
Log(" Set texture[%d] NULL\n", i);
}
}
}
/////////////////////////////////////
// Draw
if (bLog)
Log(" Drawing vtx buffer %d\n", pVtxBuffer);
pVtxBuffer->Bind();
pVtxBuffer->Draw();
pVtxBuffer->UnBind();
mRenderSettings.mpVtxBuffer = pVtxBuffer;
if (pMaterial->GetRefractionSkipsStandardTrans() || pMaterial->GetTexture(eMaterialTexture_Diffuse) == NULL) {
if (bLog)
Log(" Skipping normal trans rendering!\n");
continue;
}
}
/////////////////////////////////////////////////
// Alpha mode
if (alphaMode != mRenderSettings.mAlphaMode) {
mRenderSettings.mAlphaMode = alphaMode;
if (alphaMode == eMaterialAlphaMode_Solid) {
mpLowLevelGraphics->SetAlphaTestActive(false);
if (bLog)
Log(" Set alpha test off!\n");
} else {
mpLowLevelGraphics->SetAlphaTestActive(true);
mpLowLevelGraphics->SetAlphaTestFunc(eAlphaTestFunc_GreaterOrEqual, 0.6f);
if (bLog)
Log(" Set alpha test on!\n");
}
}
/////////////////////////////////////////////////
// Blend mode
if (blendMode != mRenderSettings.mBlendMode) {
mRenderSettings.mBlendMode = blendMode;
if (blendMode == eMaterialBlendMode_None) {
mpLowLevelGraphics->SetBlendActive(false);
if (bLog)
Log(" Set blend mode off!\n");
} else {
mpLowLevelGraphics->SetBlendActive(true);
switch (blendMode) {
case eMaterialBlendMode_Add:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_One, eBlendFunc_One);
if (bLog)
Log(" Set blend mode one-one!\n");
break;
case eMaterialBlendMode_Replace:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_One, eBlendFunc_Zero);
if (bLog)
Log(" Set blend mode one-zero!\n");
break;
case eMaterialBlendMode_Mul:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_Zero, eBlendFunc_SrcColor);
if (bLog)
Log(" Set blend mode zero-srccolor!\n");
break;
case eMaterialBlendMode_MulX2:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_DestColor, eBlendFunc_SrcColor);
if (bLog)
Log(" Set blend mode destcolor-srccolor!\n");
break;
case eMaterialBlendMode_Alpha:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_SrcAlpha, eBlendFunc_OneMinusSrcAlpha);
if (bLog)
Log(" Set blend mode srcalpha-oneminussrcalpha!\n");
break;
case eMaterialBlendMode_DestAlphaAdd:
mpLowLevelGraphics->SetBlendFunc(eBlendFunc_DestAlpha, eBlendFunc_One);
if (bLog)
Log(" Set blend mode destalpha-one!\n");
break;
default:
break;
}
}
}
iGpuProgram *gpuProgram = pMaterial->getGpuProgram(eMaterialRenderType_Diffuse, 0, nullptr);
iMaterialProgramSetup *gpuProgramSetup = pMaterial->getGpuProgramSetup(eMaterialRenderType_Diffuse, 0, NULL);
if (gpuProgram != mRenderSettings.gpuProgram) {
if (mRenderSettings.gpuProgram)
mRenderSettings.gpuProgram->UnBind();
mRenderSettings.gpuProgram = gpuProgram;
if (gpuProgram) {
gpuProgram->Bind();
if (gpuProgramSetup)
gpuProgramSetup->Setup(gpuProgram, &mRenderSettings);
mRenderSettings.gpuProgramSetup = gpuProgramSetup;
mRenderSettings.mbMatrixWasNULL = false;
}
}
/////////////////////////////////////////////////
// Texture
for (int i = 0; i < MAX_TEXTUREUNITS; i++) {
if (mRenderSettings.mpTexture[i] != vTextures[i]) {
mpLowLevelGraphics->SetTexture(i, vTextures[i]);
mRenderSettings.mpTexture[i] = vTextures[i];
if (bLog) {
if (vTextures[i])
Log(" Set texture[%d] %s (%d)\n", i, vTextures[i]->GetName().c_str(), vTextures[i]);
else
Log(" Set texture[%d] NULL\n", i);
}
}
}
/////////////////////////////////////////////////
// Vertex buffer
if (pVtxBuffer != mRenderSettings.mpVtxBuffer) {
if (mRenderSettings.mpVtxBuffer)
mRenderSettings.mpVtxBuffer->UnBind();
mRenderSettings.mpVtxBuffer = pVtxBuffer;
if (pVtxBuffer)
pVtxBuffer->Bind();
if (bLog)
Log(" Set vtx buffer %d\n", pVtxBuffer);
}
/////////////////////////////////////////////////
// Matrix
// It is a normal matrix
bool bSetVtxProgMatrix = false;
if (pModelMatrix) {
cMatrixf mtxModel = cMath::MatrixMul(apCamera->GetViewMatrix(), *pModelMatrix);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxModel);
mRenderSettings.mbMatrixWasNULL = false;
bSetVtxProgMatrix = true;
}
// NULL matrix
else if (mRenderSettings.mbMatrixWasNULL == false) {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
mRenderSettings.mbMatrixWasNULL = true;
bSetVtxProgMatrix = true;
}
if (mRenderSettings.gpuProgram && bSetVtxProgMatrix) {
// Might be quicker if this is set directly
mRenderSettings.gpuProgram->SetMatrixf("worldViewProj",
eGpuProgramMatrix_ViewProjection,
eGpuProgramMatrixOp_Identity);
if (mRenderSettings.gpuProgramSetup) {
mRenderSettings.gpuProgramSetup->SetupMatrix(pModelMatrix, &mRenderSettings);
}
}
///////////////////////////////////////////
/// Draw
if (bLog)
Log("Draw\n");
pVtxBuffer->Draw();
}
if (mRenderSettings.mpVtxBuffer)
mRenderSettings.mpVtxBuffer->UnBind();
if (mRenderSettings.gpuProgram)
mRenderSettings.gpuProgram->UnBind();
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderDebug(cCamera3D *apCamera) {
if (mDebugFlags) {
mpLowLevelGraphics->SetDepthWriteActive(false);
// Render Debug for objects
cRenderableIterator objectIt = mpRenderList->GetObjectIt();
while (objectIt.HasNext()) {
iRenderable *pObject = objectIt.Next();
RenderDebugObject(apCamera, pObject, NULL, 0, NULL, eMaterialRenderType_Diffuse, NULL);
}
// Render debug for lights.
if (mDebugFlags & eRendererDebugFlag_DrawLightBoundingBox) {
mpLowLevelGraphics->SetDepthTestActive(false);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
cLight3DIterator lightIt = mpRenderList->GetLightIt();
while (lightIt.HasNext()) {
iLight3D *pLight = lightIt.Next();
cBoundingVolume *pBV = pLight->GetBoundingVolume();
cColor Col = pLight->GetDiffuseColor();
mpLowLevelGraphics->DrawSphere(pLight->GetWorldPosition(), 0.1f, Col);
mpLowLevelGraphics->DrawBoxMaxMin(pBV->GetMax(), pBV->GetMin(), Col);
}
mpLowLevelGraphics->SetDepthTestActive(true);
}
mpLowLevelGraphics->SetDepthWriteActive(true);
}
}
//-----------------------------------------------------------------------
void cRenderer3D::RenderDebugObject(cCamera3D *apCamera, iRenderable *&apObject, iMaterial *apPrevMat,
int alPrevMatId, iVertexBuffer *apPrevVtxBuff,
eMaterialRenderType aRenderType, iLight3D *apLight) {
iVertexBuffer *pVtxBuffer = apObject->GetVertexBuffer();
if (mDebugFlags & eRendererDebugFlag_DrawBoundingBox) {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
cBoundingVolume *pBV = apObject->GetBoundingVolume();
mpLowLevelGraphics->DrawBoxMaxMin(pBV->GetMax(), pBV->GetMin(), cColor(1, 1.0f, 1.0f, 1));
}
if (mDebugFlags & eRendererDebugFlag_DrawBoundingSphere) {
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, apCamera->GetViewMatrix());
cBoundingVolume *pBV = apObject->GetBoundingVolume();
mpLowLevelGraphics->DrawSphere(pBV->GetWorldCenter(), pBV->GetRadius(), cColor(1, 1.0f, 1.0f, 1));
}
cMatrixf mtxModel;
cMatrixf *pModelMtx = apObject->GetModelMatrix(apCamera);
if (pModelMtx)
mtxModel = cMath::MatrixMul(apCamera->GetViewMatrix(), *pModelMtx);
else
mtxModel = cMath::MatrixMul(apCamera->GetViewMatrix(), cMatrixf::Identity);
mpLowLevelGraphics->SetMatrix(eMatrix_ModelView, mtxModel);
// Draw the debug graphics for the object.
for (int i = 0; i < pVtxBuffer->GetVertexNum(); i++) {
cVector3f vPos = pVtxBuffer->GetVector3(eVertexFlag_Position, i);
if (mDebugFlags & eRendererDebugFlag_DrawNormals) {
cVector3f vNormal = pVtxBuffer->GetVector3(eVertexFlag_Normal, i);
mpLowLevelGraphics->DrawLine(vPos, vPos + (vNormal * 0.1f), cColor(0.5f, 0.5f, 1, 1));
}
if (mDebugFlags & eRendererDebugFlag_DrawTangents) {
cVector3f vTan = pVtxBuffer->GetVector4(eVertexFlag_Texture1, i);
mpLowLevelGraphics->DrawLine(vPos, vPos + (vTan * 0.2f), cColor(1, 0.0f, 0.0f, 1));
}
}
}
//-----------------------------------------------------------------------
} // namespace hpl