Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/renderer/SceneRenderer.cpp
Show First 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | struct Models | ||||
LitRenderModifierPtr ModShader; | LitRenderModifierPtr ModShader; | ||||
} Model; | } Model; | ||||
CShaderDefines globalContext; | CShaderDefines globalContext; | ||||
/** | /** | ||||
* Renders all non-alpha-blended models with the given context. | * Renders all non-alpha-blended models with the given context. | ||||
*/ | */ | ||||
void CallModelRenderers(const CShaderDefines& context, int cullGroup, int flags) | void CallModelRenderers( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, int cullGroup, int flags) | |||||
{ | { | ||||
CShaderDefines contextSkinned = context; | CShaderDefines contextSkinned = context; | ||||
if (g_RenderingOptions.GetGPUSkinning()) | if (g_RenderingOptions.GetGPUSkinning()) | ||||
{ | { | ||||
contextSkinned.Add(str_USE_INSTANCING, str_1); | contextSkinned.Add(str_USE_INSTANCING, str_1); | ||||
contextSkinned.Add(str_USE_GPU_SKINNING, str_1); | contextSkinned.Add(str_USE_GPU_SKINNING, str_1); | ||||
} | } | ||||
Model.NormalSkinned->Render(Model.ModShader, contextSkinned, cullGroup, flags); | Model.NormalSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags); | ||||
if (Model.NormalUnskinned != Model.NormalSkinned) | if (Model.NormalUnskinned != Model.NormalSkinned) | ||||
{ | { | ||||
CShaderDefines contextUnskinned = context; | CShaderDefines contextUnskinned = context; | ||||
contextUnskinned.Add(str_USE_INSTANCING, str_1); | contextUnskinned.Add(str_USE_INSTANCING, str_1); | ||||
Model.NormalUnskinned->Render(Model.ModShader, contextUnskinned, cullGroup, flags); | Model.NormalUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Renders all alpha-blended models with the given context. | * Renders all alpha-blended models with the given context. | ||||
*/ | */ | ||||
void CallTranspModelRenderers(const CShaderDefines& context, int cullGroup, int flags) | void CallTranspModelRenderers( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, int cullGroup, int flags) | |||||
{ | { | ||||
CShaderDefines contextSkinned = context; | CShaderDefines contextSkinned = context; | ||||
if (g_RenderingOptions.GetGPUSkinning()) | if (g_RenderingOptions.GetGPUSkinning()) | ||||
{ | { | ||||
contextSkinned.Add(str_USE_INSTANCING, str_1); | contextSkinned.Add(str_USE_INSTANCING, str_1); | ||||
contextSkinned.Add(str_USE_GPU_SKINNING, str_1); | contextSkinned.Add(str_USE_GPU_SKINNING, str_1); | ||||
} | } | ||||
Model.TranspSkinned->Render(Model.ModShader, contextSkinned, cullGroup, flags); | Model.TranspSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags); | ||||
if (Model.TranspUnskinned != Model.TranspSkinned) | if (Model.TranspUnskinned != Model.TranspSkinned) | ||||
{ | { | ||||
CShaderDefines contextUnskinned = context; | CShaderDefines contextUnskinned = context; | ||||
contextUnskinned.Add(str_USE_INSTANCING, str_1); | contextUnskinned.Add(str_USE_INSTANCING, str_1); | ||||
Model.TranspUnskinned->Render(Model.ModShader, contextUnskinned, cullGroup, flags); | Model.TranspUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
CSceneRenderer::CSceneRenderer() | CSceneRenderer::CSceneRenderer() | ||||
{ | { | ||||
m = std::make_unique<Internals>(); | m = std::make_unique<Internals>(); | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void CSceneRenderer::SetSimulation(CSimulation2* simulation) | void CSceneRenderer::SetSimulation(CSimulation2* simulation) | ||||
{ | { | ||||
// set current simulation context for terrain renderer | // set current simulation context for terrain renderer | ||||
m->terrainRenderer.SetSimulation(simulation); | m->terrainRenderer.SetSimulation(simulation); | ||||
} | } | ||||
void CSceneRenderer::RenderShadowMap(const CShaderDefines& context) | void CSceneRenderer::RenderShadowMap( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context) | |||||
{ | { | ||||
PROFILE3_GPU("shadow map"); | PROFILE3_GPU("shadow map"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render shadow map"); | OGL_SCOPED_DEBUG_GROUP("Render shadow map"); | ||||
CShaderDefines contextCast = context; | CShaderDefines contextCast = context; | ||||
contextCast.Add(str_MODE_SHADOWCAST, str_1); | contextCast.Add(str_MODE_SHADOWCAST, str_1); | ||||
m->shadow.BeginRender(); | m->shadow.BeginRender(); | ||||
const int cascadeCount = m->shadow.GetCascadeCount(); | const int cascadeCount = m->shadow.GetCascadeCount(); | ||||
ENSURE(0 <= cascadeCount && cascadeCount <= 4); | ENSURE(0 <= cascadeCount && cascadeCount <= 4); | ||||
for (int cascade = 0; cascade < cascadeCount; ++cascade) | for (int cascade = 0; cascade < cascadeCount; ++cascade) | ||||
{ | { | ||||
m->shadow.PrepareCamera(cascade); | m->shadow.PrepareCamera(cascade); | ||||
const int cullGroup = CULL_SHADOWS_CASCADE_0 + cascade; | const int cullGroup = CULL_SHADOWS_CASCADE_0 + cascade; | ||||
{ | { | ||||
PROFILE("render patches"); | PROFILE("render patches"); | ||||
glCullFace(GL_FRONT); | glCullFace(GL_FRONT); | ||||
glEnable(GL_CULL_FACE); | glEnable(GL_CULL_FACE); | ||||
m->terrainRenderer.RenderPatches(cullGroup); | m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup); | ||||
glCullFace(GL_BACK); | glCullFace(GL_BACK); | ||||
} | } | ||||
{ | { | ||||
PROFILE("render models"); | PROFILE("render models"); | ||||
m->CallModelRenderers(contextCast, cullGroup, MODELFLAG_CASTSHADOWS); | m->CallModelRenderers(deviceCommandContext, contextCast, cullGroup, MODELFLAG_CASTSHADOWS); | ||||
} | } | ||||
{ | { | ||||
PROFILE("render transparent models"); | PROFILE("render transparent models"); | ||||
// disable face-culling for two-sided models | // disable face-culling for two-sided models | ||||
glDisable(GL_CULL_FACE); | glDisable(GL_CULL_FACE); | ||||
m->CallTranspModelRenderers(contextCast, cullGroup, MODELFLAG_CASTSHADOWS); | m->CallTranspModelRenderers(deviceCommandContext, contextCast, cullGroup, MODELFLAG_CASTSHADOWS); | ||||
glEnable(GL_CULL_FACE); | glEnable(GL_CULL_FACE); | ||||
} | } | ||||
} | } | ||||
m->shadow.EndRender(); | m->shadow.EndRender(); | ||||
g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | ||||
} | } | ||||
void CSceneRenderer::RenderPatches(const CShaderDefines& context, int cullGroup) | void CSceneRenderer::RenderPatches( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, int cullGroup) | |||||
{ | { | ||||
PROFILE3_GPU("patches"); | PROFILE3_GPU("patches"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render patches"); | OGL_SCOPED_DEBUG_GROUP("Render patches"); | ||||
#if CONFIG2_GLES | #if CONFIG2_GLES | ||||
#warning TODO: implement wireface/edged rendering mode GLES | #warning TODO: implement wireface/edged rendering mode GLES | ||||
#else | #else | ||||
// switch on wireframe if we need it | // switch on wireframe if we need it | ||||
if (m_TerrainRenderMode == WIREFRAME) | if (m_TerrainRenderMode == WIREFRAME) | ||||
{ | { | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
} | } | ||||
#endif | #endif | ||||
// render all the patches, including blend pass | // render all the patches, including blend pass | ||||
const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities(); | const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities(); | ||||
m->terrainRenderer.RenderTerrainShader(context, cullGroup, | m->terrainRenderer.RenderTerrainShader(deviceCommandContext, context, cullGroup, | ||||
(capabilities.m_Shadows && g_RenderingOptions.GetShadows()) ? &m->shadow : 0); | (capabilities.m_Shadows && g_RenderingOptions.GetShadows()) ? &m->shadow : 0); | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
if (m_TerrainRenderMode == WIREFRAME) | if (m_TerrainRenderMode == WIREFRAME) | ||||
{ | { | ||||
// switch wireframe off again | // switch wireframe off again | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
else if (m_TerrainRenderMode == EDGED_FACES) | else if (m_TerrainRenderMode == EDGED_FACES) | ||||
{ | { | ||||
// edged faces: need to make a second pass over the data: | // edged faces: need to make a second pass over the data: | ||||
// first switch on wireframe | // first switch on wireframe | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
// setup some renderstate .. | // setup some renderstate .. | ||||
glActiveTextureARB(GL_TEXTURE0); | glActiveTextureARB(GL_TEXTURE0); | ||||
glLineWidth(2.0f); | glLineWidth(2.0f); | ||||
// render tiles edges | // render tiles edges | ||||
m->terrainRenderer.RenderPatches(cullGroup, CColor(0.5f, 0.5f, 1.0f, 1.0f)); | m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup, CColor(0.5f, 0.5f, 1.0f, 1.0f)); | ||||
glLineWidth(4.0f); | glLineWidth(4.0f); | ||||
// render outline of each patch | // render outline of each patch | ||||
m->terrainRenderer.RenderOutlines(cullGroup); | m->terrainRenderer.RenderOutlines(cullGroup); | ||||
// .. and restore the renderstates | // .. and restore the renderstates | ||||
glLineWidth(1.0f); | glLineWidth(1.0f); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
void CSceneRenderer::RenderModels(const CShaderDefines& context, int cullGroup) | void CSceneRenderer::RenderModels( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, int cullGroup) | |||||
{ | { | ||||
PROFILE3_GPU("models"); | PROFILE3_GPU("models"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render models"); | OGL_SCOPED_DEBUG_GROUP("Render models"); | ||||
int flags = 0; | int flags = 0; | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
if (m_ModelRenderMode == WIREFRAME) | if (m_ModelRenderMode == WIREFRAME) | ||||
{ | { | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
} | } | ||||
#endif | #endif | ||||
m->CallModelRenderers(context, cullGroup, flags); | m->CallModelRenderers(deviceCommandContext, context, cullGroup, flags); | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
if (m_ModelRenderMode == WIREFRAME) | if (m_ModelRenderMode == WIREFRAME) | ||||
{ | { | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
else if (m_ModelRenderMode == EDGED_FACES) | else if (m_ModelRenderMode == EDGED_FACES) | ||||
{ | { | ||||
CShaderDefines contextWireframe = context; | CShaderDefines contextWireframe = context; | ||||
contextWireframe.Add(str_MODE_WIREFRAME, str_1); | contextWireframe.Add(str_MODE_WIREFRAME, str_1); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
m->CallModelRenderers(contextWireframe, cullGroup, flags); | m->CallModelRenderers(deviceCommandContext, contextWireframe, cullGroup, flags); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
void CSceneRenderer::RenderTransparentModels(const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling) | void CSceneRenderer::RenderTransparentModels( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling) | |||||
{ | { | ||||
PROFILE3_GPU("transparent models"); | PROFILE3_GPU("transparent models"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render transparent models"); | OGL_SCOPED_DEBUG_GROUP("Render transparent models"); | ||||
int flags = 0; | int flags = 0; | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
// switch on wireframe if we need it | // switch on wireframe if we need it | ||||
Show All 9 Lines | #endif | ||||
CShaderDefines contextOpaque = context; | CShaderDefines contextOpaque = context; | ||||
contextOpaque.Add(str_ALPHABLEND_PASS_OPAQUE, str_1); | contextOpaque.Add(str_ALPHABLEND_PASS_OPAQUE, str_1); | ||||
CShaderDefines contextBlend = context; | CShaderDefines contextBlend = context; | ||||
contextBlend.Add(str_ALPHABLEND_PASS_BLEND, str_1); | contextBlend.Add(str_ALPHABLEND_PASS_BLEND, str_1); | ||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_OPAQUE) | if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_OPAQUE) | ||||
m->CallTranspModelRenderers(contextOpaque, cullGroup, flags); | m->CallTranspModelRenderers(deviceCommandContext, contextOpaque, cullGroup, flags); | ||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND) | if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND) | ||||
m->CallTranspModelRenderers(contextBlend, cullGroup, flags); | m->CallTranspModelRenderers(deviceCommandContext, contextBlend, cullGroup, flags); | ||||
if (disableFaceCulling) | if (disableFaceCulling) | ||||
glEnable(GL_CULL_FACE); | glEnable(GL_CULL_FACE); | ||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
if (m_ModelRenderMode == WIREFRAME) | if (m_ModelRenderMode == WIREFRAME) | ||||
{ | { | ||||
// switch wireframe off again | // switch wireframe off again | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
else if (m_ModelRenderMode == EDGED_FACES) | else if (m_ModelRenderMode == EDGED_FACES) | ||||
{ | { | ||||
CShaderDefines contextWireframe = contextOpaque; | CShaderDefines contextWireframe = contextOpaque; | ||||
contextWireframe.Add(str_MODE_WIREFRAME, str_1); | contextWireframe.Add(str_MODE_WIREFRAME, str_1); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
m->CallTranspModelRenderers(contextWireframe, cullGroup, flags); | m->CallTranspModelRenderers(deviceCommandContext, contextWireframe, cullGroup, flags); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
// SetObliqueFrustumClipping: change the near plane to the given clip plane (in world space) | // SetObliqueFrustumClipping: change the near plane to the given clip plane (in world space) | ||||
// Based on code from Game Programming Gems 5, from http://www.terathon.com/code/oblique.html | // Based on code from Game Programming Gems 5, from http://www.terathon.com/code/oblique.html | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | void CSceneRenderer::ComputeRefractionCamera(CCamera& camera, const CBoundingBoxAligned& scissor) const | ||||
camera.SetViewPort(vp); | camera.SetViewPort(vp); | ||||
camera.SetProjection(projection); | camera.SetProjection(projection); | ||||
CMatrix3D scaleMat; | CMatrix3D scaleMat; | ||||
scaleMat.SetScaling(g_Renderer.GetHeight() / static_cast<float>(std::max(1, g_Renderer.GetWidth())), 1.0f, 1.0f); | scaleMat.SetScaling(g_Renderer.GetHeight() / static_cast<float>(std::max(1, g_Renderer.GetWidth())), 1.0f, 1.0f); | ||||
camera.SetProjection(scaleMat * camera.GetProjection()); | camera.SetProjection(scaleMat * camera.GetProjection()); | ||||
} | } | ||||
// RenderReflections: render the water reflections to the reflection texture | // RenderReflections: render the water reflections to the reflection texture | ||||
void CSceneRenderer::RenderReflections(const CShaderDefines& context, const CBoundingBoxAligned& scissor) | void CSceneRenderer::RenderReflections( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, const CBoundingBoxAligned& scissor) | |||||
{ | { | ||||
PROFILE3_GPU("water reflections"); | PROFILE3_GPU("water reflections"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render water reflections"); | OGL_SCOPED_DEBUG_GROUP("Render water reflections"); | ||||
WaterManager& wm = m->waterManager; | WaterManager& wm = m->waterManager; | ||||
// Remember old camera | // Remember old camera | ||||
CCamera normalCamera = m_ViewCamera; | CCamera normalCamera = m_ViewCamera; | ||||
Show All 24 Lines | void CSceneRenderer::RenderReflections( | ||||
glClearColor(0.5f, 0.5f, 1.0f, 0.0f); | glClearColor(0.5f, 0.5f, 1.0f, 0.0f); | ||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
glFrontFace(GL_CW); | glFrontFace(GL_CW); | ||||
if (!g_RenderingOptions.GetWaterReflection()) | if (!g_RenderingOptions.GetWaterReflection()) | ||||
{ | { | ||||
m->skyManager.RenderSky(); | m->skyManager.RenderSky(deviceCommandContext); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Render terrain and models | // Render terrain and models | ||||
RenderPatches(context, CULL_REFLECTIONS); | RenderPatches(deviceCommandContext, context, CULL_REFLECTIONS); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderModels(context, CULL_REFLECTIONS); | RenderModels(deviceCommandContext, context, CULL_REFLECTIONS); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderTransparentModels(context, CULL_REFLECTIONS, TRANSPARENT, true); | RenderTransparentModels(deviceCommandContext, context, CULL_REFLECTIONS, TRANSPARENT, true); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
glFrontFace(GL_CCW); | glFrontFace(GL_CCW); | ||||
// Particles are always oriented to face the camera in the vertex shader, | // Particles are always oriented to face the camera in the vertex shader, | ||||
// so they don't need the inverted glFrontFace | // so they don't need the inverted glFrontFace | ||||
if (g_RenderingOptions.GetParticles()) | if (g_RenderingOptions.GetParticles()) | ||||
{ | { | ||||
RenderParticles(CULL_REFLECTIONS); | RenderParticles(deviceCommandContext, CULL_REFLECTIONS); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
glDisable(GL_SCISSOR_TEST); | glDisable(GL_SCISSOR_TEST); | ||||
// Reset old camera | // Reset old camera | ||||
m_ViewCamera = normalCamera; | m_ViewCamera = normalCamera; | ||||
g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | ||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||||
} | } | ||||
// RenderRefractions: render the water refractions to the refraction texture | // RenderRefractions: render the water refractions to the refraction texture | ||||
void CSceneRenderer::RenderRefractions(const CShaderDefines& context, const CBoundingBoxAligned &scissor) | void CSceneRenderer::RenderRefractions( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context, const CBoundingBoxAligned &scissor) | |||||
{ | { | ||||
PROFILE3_GPU("water refractions"); | PROFILE3_GPU("water refractions"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render water refractions"); | OGL_SCOPED_DEBUG_GROUP("Render water refractions"); | ||||
WaterManager& wm = m->waterManager; | WaterManager& wm = m->waterManager; | ||||
// Remember old camera | // Remember old camera | ||||
CCamera normalCamera = m_ViewCamera; | CCamera normalCamera = m_ViewCamera; | ||||
Show All 26 Lines | void CSceneRenderer::RenderRefractions( | ||||
// try binding the framebuffer | // try binding the framebuffer | ||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_RefractionFbo); | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wm.m_RefractionFbo); | ||||
glClearColor(1.0f, 0.0f, 0.0f, 0.0f); | glClearColor(1.0f, 0.0f, 0.0f, 0.0f); | ||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
// Render terrain and models | // Render terrain and models | ||||
RenderPatches(context, CULL_REFRACTIONS); | RenderPatches(deviceCommandContext, context, CULL_REFRACTIONS); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderModels(context, CULL_REFRACTIONS); | RenderModels(deviceCommandContext, context, CULL_REFRACTIONS); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderTransparentModels(context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE, false); | RenderTransparentModels(deviceCommandContext, context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE, false); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
glDisable(GL_SCISSOR_TEST); | glDisable(GL_SCISSOR_TEST); | ||||
// Reset old camera | // Reset old camera | ||||
m_ViewCamera = normalCamera; | m_ViewCamera = normalCamera; | ||||
g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | g_Renderer.SetViewport(m_ViewCamera.GetViewPort()); | ||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||||
} | } | ||||
void CSceneRenderer::RenderSilhouettes(const CShaderDefines& context) | void CSceneRenderer::RenderSilhouettes( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
const CShaderDefines& context) | |||||
{ | { | ||||
PROFILE3_GPU("silhouettes"); | PROFILE3_GPU("silhouettes"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render water silhouettes"); | OGL_SCOPED_DEBUG_GROUP("Render water silhouettes"); | ||||
CShaderDefines contextOccluder = context; | CShaderDefines contextOccluder = context; | ||||
contextOccluder.Add(str_MODE_SILHOUETTEOCCLUDER, str_1); | contextOccluder.Add(str_MODE_SILHOUETTEOCCLUDER, str_1); | ||||
CShaderDefines contextDisplay = context; | CShaderDefines contextDisplay = context; | ||||
Show All 14 Lines | void CSceneRenderer::RenderSilhouettes( | ||||
{ | { | ||||
PROFILE("render patches"); | PROFILE("render patches"); | ||||
// To prevent units displaying silhouettes when parts of their model | // To prevent units displaying silhouettes when parts of their model | ||||
// protrude into the ground, only occlude with the back faces of the | // protrude into the ground, only occlude with the back faces of the | ||||
// terrain (so silhouettes will still display when behind hills) | // terrain (so silhouettes will still display when behind hills) | ||||
glCullFace(GL_FRONT); | glCullFace(GL_FRONT); | ||||
m->terrainRenderer.RenderPatches(CULL_SILHOUETTE_OCCLUDER); | m->terrainRenderer.RenderPatches(deviceCommandContext, CULL_SILHOUETTE_OCCLUDER); | ||||
glCullFace(GL_BACK); | glCullFace(GL_BACK); | ||||
} | } | ||||
{ | { | ||||
PROFILE("render model occluders"); | PROFILE("render model occluders"); | ||||
m->CallModelRenderers(contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); | m->CallModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); | ||||
} | } | ||||
{ | { | ||||
PROFILE("render transparent occluders"); | PROFILE("render transparent occluders"); | ||||
m->CallTranspModelRenderers(contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); | m->CallTranspModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0); | ||||
} | } | ||||
glDepthFunc(GL_GEQUAL); | glDepthFunc(GL_GEQUAL); | ||||
glColorMask(1, 1, 1, 1); | glColorMask(1, 1, 1, 1); | ||||
// Since we can't sort, we'll use the stencil buffer to ensure we only draw | // Since we can't sort, we'll use the stencil buffer to ensure we only draw | ||||
// a pixel once (using the color of whatever model happens to be drawn first). | // a pixel once (using the color of whatever model happens to be drawn first). | ||||
glEnable(GL_BLEND); | |||||
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); | |||||
const float silhouetteAlpha = 0.75f; | |||||
glBlendColorEXT(0, 0, 0, silhouetteAlpha); | |||||
glEnable(GL_STENCIL_TEST); | glEnable(GL_STENCIL_TEST); | ||||
glStencilFunc(GL_NOTEQUAL, 1, (GLuint)-1); | glStencilFunc(GL_NOTEQUAL, 1, (GLuint)-1); | ||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | ||||
{ | { | ||||
PROFILE("render model casters"); | PROFILE("render model casters"); | ||||
m->CallModelRenderers(contextDisplay, CULL_SILHOUETTE_CASTER, 0); | m->CallModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0); | ||||
} | } | ||||
{ | { | ||||
PROFILE("render transparent casters"); | PROFILE("render transparent casters"); | ||||
m->CallTranspModelRenderers(contextDisplay, CULL_SILHOUETTE_CASTER, 0); | m->CallTranspModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0); | ||||
} | } | ||||
// Restore state | // Restore state | ||||
glDepthFunc(GL_LEQUAL); | glDepthFunc(GL_LEQUAL); | ||||
glDisable(GL_BLEND); | |||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||||
glBlendColorEXT(0, 0, 0, 0); | |||||
glDisable(GL_STENCIL_TEST); | glDisable(GL_STENCIL_TEST); | ||||
} | } | ||||
void CSceneRenderer::RenderParticles(int cullGroup) | void CSceneRenderer::RenderParticles( | ||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext, | |||||
int cullGroup) | |||||
{ | { | ||||
PROFILE3_GPU("particles"); | PROFILE3_GPU("particles"); | ||||
OGL_SCOPED_DEBUG_GROUP("Render particles"); | OGL_SCOPED_DEBUG_GROUP("Render particles"); | ||||
m->particleRenderer.RenderParticles(cullGroup); | m->particleRenderer.RenderParticles( | ||||
deviceCommandContext, cullGroup); | |||||
#if !CONFIG2_GLES | #if !CONFIG2_GLES | ||||
if (m_ModelRenderMode == EDGED_FACES) | if (m_ModelRenderMode == EDGED_FACES) | ||||
{ | { | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
m->particleRenderer.RenderParticles(true); | m->particleRenderer.RenderParticles( | ||||
deviceCommandContext, cullGroup, true); | |||||
m->particleRenderer.RenderBounds(cullGroup); | m->particleRenderer.RenderBounds(cullGroup); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
// RenderSubmissions: force rendering of any batched objects | // RenderSubmissions: force rendering of any batched objects | ||||
Show All 34 Lines | void CSceneRenderer::RenderSubmissions( | ||||
m->overlayRenderer.PrepareForRendering(); | m->overlayRenderer.PrepareForRendering(); | ||||
m->particleRenderer.PrepareForRendering(context); | m->particleRenderer.PrepareForRendering(context); | ||||
const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities(); | const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities(); | ||||
if (capabilities.m_Shadows && g_RenderingOptions.GetShadows()) | if (capabilities.m_Shadows && g_RenderingOptions.GetShadows()) | ||||
{ | { | ||||
RenderShadowMap(context); | RenderShadowMap(deviceCommandContext, context); | ||||
} | } | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
if (m->waterManager.m_RenderWater) | if (m->waterManager.m_RenderWater) | ||||
{ | { | ||||
if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater()) | if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater()) | ||||
{ | { | ||||
m->waterManager.UpdateQuality(); | m->waterManager.UpdateQuality(); | ||||
PROFILE3_GPU("water scissor"); | PROFILE3_GPU("water scissor"); | ||||
RenderReflections(context, waterScissor); | RenderReflections(deviceCommandContext, context, waterScissor); | ||||
if (g_RenderingOptions.GetWaterRefraction()) | if (g_RenderingOptions.GetWaterRefraction()) | ||||
RenderRefractions(context, waterScissor); | RenderRefractions(deviceCommandContext, context, waterScissor); | ||||
m->terrainRenderer.RenderWaterFoamOccluders(cullGroup); | m->terrainRenderer.RenderWaterFoamOccluders(deviceCommandContext, cullGroup); | ||||
} | } | ||||
} | } | ||||
CPostprocManager& postprocManager = g_Renderer.GetPostprocManager(); | CPostprocManager& postprocManager = g_Renderer.GetPostprocManager(); | ||||
if (g_RenderingOptions.GetPostProc()) | if (g_RenderingOptions.GetPostProc()) | ||||
{ | { | ||||
// We have to update the post process manager with real near/far planes | // We have to update the post process manager with real near/far planes | ||||
// that we use for the scene rendering. | // that we use for the scene rendering. | ||||
postprocManager.SetDepthBufferClipPlanes( | postprocManager.SetDepthBufferClipPlanes( | ||||
m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane() | m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane() | ||||
); | ); | ||||
postprocManager.Initialize(); | postprocManager.Initialize(); | ||||
postprocManager.CaptureRenderOutput(); | postprocManager.CaptureRenderOutput(); | ||||
} | } | ||||
{ | { | ||||
PROFILE3_GPU("clear buffers"); | PROFILE3_GPU("clear buffers"); | ||||
glClearColor(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]); | glClearColor(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]); | ||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||||
} | } | ||||
m->skyManager.RenderSky(); | m->skyManager.RenderSky(deviceCommandContext); | ||||
// render submitted patches and models | // render submitted patches and models | ||||
RenderPatches(context, cullGroup); | RenderPatches(deviceCommandContext, context, cullGroup); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// render debug-related terrain overlays | // render debug-related terrain overlays | ||||
ITerrainOverlay::RenderOverlaysBeforeWater(); | ITerrainOverlay::RenderOverlaysBeforeWater(deviceCommandContext); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// render other debug-related overlays before water (so they can be seen when underwater) | // render other debug-related overlays before water (so they can be seen when underwater) | ||||
m->overlayRenderer.RenderOverlaysBeforeWater(); | m->overlayRenderer.RenderOverlaysBeforeWater(); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderModels(context, cullGroup); | RenderModels(deviceCommandContext, context, cullGroup); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// render water | // render water | ||||
if (m->waterManager.m_RenderWater && g_Game && waterScissor.GetVolume() > 0) | if (m->waterManager.m_RenderWater && g_Game && waterScissor.GetVolume() > 0) | ||||
{ | { | ||||
if (m->waterManager.WillRenderFancyWater()) | if (m->waterManager.WillRenderFancyWater()) | ||||
{ | { | ||||
// Render transparent stuff, but only the solid parts that can occlude block water. | // Render transparent stuff, but only the solid parts that can occlude block water. | ||||
RenderTransparentModels(context, cullGroup, TRANSPARENT_OPAQUE, false); | RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_OPAQUE, false); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
m->terrainRenderer.RenderWater(context, cullGroup, &m->shadow); | m->terrainRenderer.RenderWater(deviceCommandContext, context, cullGroup, &m->shadow); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// Render transparent stuff again, but only the blended parts that overlap water. | // Render transparent stuff again, but only the blended parts that overlap water. | ||||
RenderTransparentModels(context, cullGroup, TRANSPARENT_BLEND, false); | RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_BLEND, false); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
m->terrainRenderer.RenderWater(context, cullGroup, &m->shadow); | m->terrainRenderer.RenderWater(deviceCommandContext, context, cullGroup, &m->shadow); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// Render transparent stuff, so it can overlap models/terrain. | // Render transparent stuff, so it can overlap models/terrain. | ||||
RenderTransparentModels(context, cullGroup, TRANSPARENT, false); | RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// render transparent stuff, so it can overlap models/terrain | // render transparent stuff, so it can overlap models/terrain | ||||
RenderTransparentModels(context, cullGroup, TRANSPARENT, false); | RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
// render debug-related terrain overlays | // render debug-related terrain overlays | ||||
ITerrainOverlay::RenderOverlaysAfterWater(deviceCommandContext, cullGroup); | ITerrainOverlay::RenderOverlaysAfterWater(deviceCommandContext, cullGroup); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// render some other overlays after water (so they can be displayed on top of water) | // render some other overlays after water (so they can be displayed on top of water) | ||||
m->overlayRenderer.RenderOverlaysAfterWater(); | m->overlayRenderer.RenderOverlaysAfterWater(deviceCommandContext); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
// particles are transparent so render after water | // particles are transparent so render after water | ||||
if (g_RenderingOptions.GetParticles()) | if (g_RenderingOptions.GetParticles()) | ||||
{ | { | ||||
RenderParticles(cullGroup); | RenderParticles(deviceCommandContext, cullGroup); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
if (g_RenderingOptions.GetPostProc()) | if (g_RenderingOptions.GetPostProc()) | ||||
{ | { | ||||
if (g_Renderer.GetPostprocManager().IsMultisampleEnabled()) | if (g_Renderer.GetPostprocManager().IsMultisampleEnabled()) | ||||
g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer(); | g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer(); | ||||
postprocManager.ApplyPostproc(); | postprocManager.ApplyPostproc(deviceCommandContext); | ||||
postprocManager.ReleaseRenderOutput(); | postprocManager.ReleaseRenderOutput(); | ||||
} | } | ||||
if (g_RenderingOptions.GetSilhouettes()) | if (g_RenderingOptions.GetSilhouettes()) | ||||
{ | { | ||||
RenderSilhouettes(context); | RenderSilhouettes(deviceCommandContext, context); | ||||
} | } | ||||
// render debug lines | // render debug lines | ||||
if (g_RenderingOptions.GetDisplayFrustum()) | if (g_RenderingOptions.GetDisplayFrustum()) | ||||
DisplayFrustum(); | DisplayFrustum(); | ||||
if (g_RenderingOptions.GetDisplayShadowsFrustum()) | if (g_RenderingOptions.GetDisplayShadowsFrustum()) | ||||
{ | { | ||||
m->shadow.RenderDebugBounds(); | m->shadow.RenderDebugBounds(); | ||||
m->shadow.RenderDebugTexture(); | m->shadow.RenderDebugTexture(deviceCommandContext); | ||||
} | } | ||||
m->silhouetteRenderer.RenderDebugOverlays(m_ViewCamera); | m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext, m_ViewCamera); | ||||
// render overlays that should appear on top of all other objects | // render overlays that should appear on top of all other objects | ||||
m->overlayRenderer.RenderForegroundOverlays(m_ViewCamera); | m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera); | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
} | } | ||||
void CSceneRenderer::EndFrame() | void CSceneRenderer::EndFrame() | ||||
{ | { | ||||
// empty lists | // empty lists | ||||
m->terrainRenderer.EndFrame(); | m->terrainRenderer.EndFrame(); | ||||
Show All 16 Lines | |||||
void CSceneRenderer::DisplayFrustum() | void CSceneRenderer::DisplayFrustum() | ||||
{ | { | ||||
#if CONFIG2_GLES | #if CONFIG2_GLES | ||||
#warning TODO: implement CSceneRenderer::DisplayFrustum for GLES | #warning TODO: implement CSceneRenderer::DisplayFrustum for GLES | ||||
#else | #else | ||||
glDepthMask(0); | glDepthMask(0); | ||||
glDisable(GL_CULL_FACE); | glDisable(GL_CULL_FACE); | ||||
glEnable(GL_BLEND); | |||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||||
g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2); | g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2); | ||||
glDisable(GL_BLEND); | |||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2); | g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2); | ||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
glEnable(GL_CULL_FACE); | glEnable(GL_CULL_FACE); | ||||
glDepthMask(1); | glDepthMask(1); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater()) | ||||
CCamera refractionCamera; | CCamera refractionCamera; | ||||
ComputeRefractionCamera(refractionCamera, waterScissor); | ComputeRefractionCamera(refractionCamera, waterScissor); | ||||
scene.EnumerateObjects(refractionCamera.GetFrustum(), this); | scene.EnumerateObjects(refractionCamera.GetFrustum(), this); | ||||
} | } | ||||
// Render the waves to the Fancy effects texture | // Render the waves to the Fancy effects texture | ||||
m->waterManager.RenderWaves(frustum); | m->waterManager.RenderWaves(deviceCommandContext, frustum); | ||||
} | } | ||||
} | } | ||||
m_CurrentCullGroup = -1; | m_CurrentCullGroup = -1; | ||||
ogl_WarnIfError(); | ogl_WarnIfError(); | ||||
RenderSubmissions(deviceCommandContext, waterScissor); | RenderSubmissions(deviceCommandContext, waterScissor); | ||||
▲ Show 20 Lines • Show All 50 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator