commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
318
include/engine/gpu/gpu_render_queue_forward.cpp
Normal file
318
include/engine/gpu/gpu_render_queue_forward.cpp
Normal file
@ -0,0 +1,318 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "gpu/gpu_renderer.h"
|
||||
#include "gpu/gpu_shader_object.h"
|
||||
#include "gpu/gpu_geometry.h"
|
||||
#include "gpu/gpu_draw_context.h"
|
||||
#include "core/renderer_environment_interface.h"
|
||||
#include "core/geometry.h"
|
||||
#include "core/terrain.h"
|
||||
#include "core/camera.h"
|
||||
#include "core/light.h"
|
||||
#include "async/job.h"
|
||||
#include "alloc/ialloc.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::GPU;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Renderer::LightCullDisplayList(const Core::Light &light, const Stack <RenderPrimitive *> &in, Stack <RenderPrimitive *> &out)
|
||||
{
|
||||
for (uint n = 0; n < in.GetCount(); ++n)
|
||||
{
|
||||
RenderPrimitive *dl = in[n];
|
||||
|
||||
switch (light.model)
|
||||
{
|
||||
case Core::Light::Model_Point:
|
||||
if (light.range > 0)
|
||||
{
|
||||
MinMax &mm = dl->dlst->minmax;
|
||||
Vector4 dl_lpos = light.GetMatrix().GetRow(3) * dl->item->GetInverseMatrix();
|
||||
|
||||
if ( ((dl_lpos.x - light.range) < mm.mx.x) &&
|
||||
((dl_lpos.x + light.range) > mm.mn.x) &&
|
||||
((dl_lpos.y - light.range) < mm.mx.y) &&
|
||||
((dl_lpos.y + light.range) > mm.mn.y) &&
|
||||
((dl_lpos.z - light.range) < mm.mx.z) &&
|
||||
((dl_lpos.z + light.range) > mm.mn.z) )
|
||||
out.Push(dl);
|
||||
}
|
||||
else
|
||||
out.Push(dl);
|
||||
break;
|
||||
|
||||
case Core::Light::Model_Spot:
|
||||
if (light.frustum.ClassifyMinMax(dl->dlst->minmax, &dl->item->GetMatrix()) != Frustum::Outside)
|
||||
out.Push(dl);
|
||||
break;
|
||||
|
||||
case Core::Light::Model_Linear:
|
||||
default:
|
||||
out.Push(dl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Renderer::SetupForwardContext(const DrawContext::Context &ctx)
|
||||
{
|
||||
switch (ctx.draw)
|
||||
{
|
||||
case DrawContext::Base:
|
||||
switch (ctx.render)
|
||||
{
|
||||
case DrawContext::Opaque:
|
||||
EnableDepthTest(true);
|
||||
break;
|
||||
|
||||
case DrawContext::Alpha:
|
||||
EnableDepthWrite(false);
|
||||
EnableBlending(true);
|
||||
SetBlendFunc(BlendSrcAlpha, BlendOneMinusSrcAlpha);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DrawContext::Light:
|
||||
switch (ctx.render)
|
||||
{
|
||||
case DrawContext::Opaque:
|
||||
EnableBlending(true);
|
||||
SetBlendFunc(BlendSrcAlpha, BlendOne);
|
||||
break;
|
||||
|
||||
case DrawContext::Alpha:
|
||||
EnableDepthWrite(false);
|
||||
EnableBlending(true);
|
||||
SetBlendFunc(BlendSrcAlpha, BlendOne);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class GPU::PrepareLightJob : public ASync::Job
|
||||
{
|
||||
const Renderer &renderer;
|
||||
const Core::Light &light;
|
||||
|
||||
const Stack <RenderPrimitive *> ∈
|
||||
Stack <RenderPrimitive *> &out;
|
||||
|
||||
DrawContext::Render rc;
|
||||
|
||||
public:
|
||||
|
||||
NPLACEMENT_NEW(RendererJob)
|
||||
|
||||
bool use_shadow;
|
||||
|
||||
bool CullPrimitive(const Render::Material *m, const MinMax &mm, const Core::Item *item) const
|
||||
{
|
||||
if (m->renderword & Core::Material::Render_Unlit)
|
||||
return false; // exclude from lighting
|
||||
|
||||
switch (light.model)
|
||||
{
|
||||
case Core::Light::Model_Point:
|
||||
if (light.range > 0)
|
||||
{
|
||||
Vector4 dl_lpos = light.GetMatrix().GetRow(3) * item->GetInverseMatrix();
|
||||
|
||||
if ( ((dl_lpos.x - light.range) < mm.mx.x) &&
|
||||
((dl_lpos.y - light.range) < mm.mx.y) &&
|
||||
((dl_lpos.z - light.range) < mm.mx.z) &&
|
||||
((dl_lpos.x + light.range) > mm.mn.x) &&
|
||||
((dl_lpos.y + light.range) > mm.mn.y) &&
|
||||
((dl_lpos.z + light.range) > mm.mn.z) )
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
break;
|
||||
|
||||
case Core::Light::Model_Spot:
|
||||
if (light.frustum.ClassifyMinMax(mm, &item->GetMatrix()) != Frustum::Outside)
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
case Core::Light::Model_Linear:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Execute(uint)
|
||||
{
|
||||
for (uint n = 0; n < in.GetCount(); ++n)
|
||||
{
|
||||
RenderPrimitive *dl = in[n];
|
||||
|
||||
bool r = false;
|
||||
switch (dl->type)
|
||||
{
|
||||
case RenderPrimitive::TypeDisplayList:
|
||||
r = CullPrimitive(dl->dlst->material, dl->dlst->minmax, dl->item);
|
||||
break;
|
||||
case RenderPrimitive::TypeTerrainPatch:
|
||||
r = CullPrimitive(dl->patch->terrain->render_data->material, dl->patch->minmax, dl->item);
|
||||
break;
|
||||
|
||||
default:
|
||||
case RenderPrimitive::TypeEmitter:
|
||||
break;
|
||||
}
|
||||
if (r)
|
||||
out.Push(dl);
|
||||
}
|
||||
|
||||
// Prepare shadow map if required.
|
||||
if (out.GetCount() == 0)
|
||||
use_shadow = false;
|
||||
|
||||
else
|
||||
{
|
||||
use_shadow = renderer.gpu_config.enable_shadow && (light.shadow == Core::Light::Shadow_Map);
|
||||
if ((rc == DrawContext::Alpha) && (light.shadow_cast_all == false))
|
||||
use_shadow = false;
|
||||
|
||||
bool use_shadow_matrix = false;
|
||||
if ((light.model == Core::Light::Model_Spot) && !light.projection_texture.IsEmpty())
|
||||
use_shadow_matrix = true;
|
||||
|
||||
if (use_shadow || use_shadow_matrix)
|
||||
renderer.PrepareShadowMap(light, use_shadow);
|
||||
}
|
||||
}
|
||||
|
||||
PrepareLightJob(const Renderer &_renderer, const Core::Light &_light, const Stack <RenderPrimitive *> &_in, Stack <RenderPrimitive *> &_out, DrawContext::Render _rc) : Job("Light Draw Setup"), renderer(_renderer), light(_light), in(_in), out(_out), rc(_rc) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static MaterialShader::Variant DispatchLightShaderVariant(Core::Light::Model type, bool shadow, bool projection_map)
|
||||
{
|
||||
static MaterialShader::Variant table[2][2][Core::Light::Model_Last] =
|
||||
{
|
||||
{
|
||||
{ MaterialShader::Last, MaterialShader::FS_PointLight, MaterialShader::FS_LinearLight, MaterialShader::FS_SpotLight },
|
||||
{ MaterialShader::Last, MaterialShader::FS_PointLightShadowMapping, MaterialShader::FS_LinearLightShadowMapping, MaterialShader::FS_SpotLightShadowMapping }
|
||||
},
|
||||
{
|
||||
{ MaterialShader::Last, MaterialShader::FS_PointLight, MaterialShader::FS_LinearLight, MaterialShader::FS_SpotLightProjection },
|
||||
{ MaterialShader::Last, MaterialShader::FS_PointLightShadowMapping, MaterialShader::FS_LinearLightShadowMapping, MaterialShader::FS_SpotLightProjectionShadowMapping }
|
||||
}
|
||||
};
|
||||
return table[projection_map ? 1 : 0][shadow ? 1 : 0][type];
|
||||
}
|
||||
void Renderer::DrawForwardBaseConstant(DrawContext::Render rc, const Stack <RenderPrimitive *> &dl_list)
|
||||
{
|
||||
ScopedPerfEvent event(this, __FUNCTION__, Color::Blue);
|
||||
|
||||
DrawContext dc(rc, DrawContext::Base, MaterialShader::FS_Constant);
|
||||
SetupForwardContext(dc.ctx);
|
||||
DrawList(dl_list, dc);
|
||||
}
|
||||
void Renderer::DrawForwardLightContribution(DrawContext::Render rc, const List <Core::Light *> &light_list, const AutoStack <PrepareLightJob *> &setup_jobs, const Array <Stack <RenderPrimitive *> > &dl_list)
|
||||
{
|
||||
ScopedPerfEvent event(this, "Render light contribution", Color::Blue);
|
||||
|
||||
DrawContext dc(rc, DrawContext::Light, MaterialShader::FS_Constant);
|
||||
SetupForwardContext(dc.ctx);
|
||||
|
||||
EnableDepthWrite(false);
|
||||
SetDepthFunc(DepthLessEqual);
|
||||
|
||||
uint job_count = 0;
|
||||
ListForeachPtr(Core::Light *, l, light_list)
|
||||
{
|
||||
if (l->model == Core::Light::Model_None)
|
||||
continue;
|
||||
|
||||
// Wait for the light setup job to complete.
|
||||
Platform::Get().job_manager->JoinJob(setup_jobs[job_count]);
|
||||
|
||||
if (dl_list[job_count].GetCount())
|
||||
{
|
||||
bool use_shadow = setup_jobs[job_count]->use_shadow;
|
||||
|
||||
if (use_shadow)
|
||||
{
|
||||
PerfBeginEvent("Render shadow map", Color::Yellow);
|
||||
|
||||
EnableDepthWrite(true);
|
||||
RenderShadowMap(*l);
|
||||
EnableDepthWrite(false);
|
||||
|
||||
SetCurrentFBO(gpu_config.use_rtt ? render_fbo : NULL);
|
||||
SetupForwardContext(dc.ctx);
|
||||
|
||||
PerfEndEvent();
|
||||
}
|
||||
|
||||
// Add contribution.
|
||||
dc.ctx.variant = DispatchLightShaderVariant(l->model, use_shadow, asbool(l->projection_texture));
|
||||
dc.light = l;
|
||||
|
||||
DrawList(dl_list[job_count], dc);
|
||||
}
|
||||
|
||||
++stats.light_processed;
|
||||
++job_count;
|
||||
}
|
||||
}
|
||||
void Renderer::RenderListForward(Stack <RenderPrimitive *> &dl_list, DrawContext::Render rc)
|
||||
{
|
||||
ScopedPerfEvent event(this, __FUNCTION__, Color::Red);
|
||||
|
||||
if (dl_list.GetCount() == 0)
|
||||
return;
|
||||
|
||||
// Setup all lights.
|
||||
List <Core::Light *> frustum_light_list;
|
||||
environment_interface->GetLightsInFrustum(view_item->GetMatrix().GetRow(3), frustum, frustum_light_list);
|
||||
|
||||
Array <Stack <RenderPrimitive *> > light_dl_list(frustum_light_list.GetCount());
|
||||
AutoStack <PrepareLightJob *> light_setup_job(frustum_light_list.GetCount());
|
||||
|
||||
uint job_count = 0;
|
||||
ListForeachPtr(Core::Light *, l, frustum_light_list)
|
||||
{
|
||||
if (l->model == Core::Light::Model_None)
|
||||
continue;
|
||||
|
||||
if (PrepareLightJob *job = new PrepareLightJob(*this, *l, dl_list, light_dl_list[job_count++], rc))
|
||||
{
|
||||
light_setup_job.Push(job);
|
||||
Platform::Get().job_manager->EnqueueJob(job);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw all passes.
|
||||
DrawForwardBaseConstant(rc, dl_list);
|
||||
DrawForwardLightContribution(rc, frustum_light_list, light_setup_job, light_dl_list);
|
||||
|
||||
//
|
||||
CollectJobsPerf(light_setup_job, job_count, stats.bench_prepare_light);
|
||||
|
||||
// Restore default state.
|
||||
SetCullFunc(CullFront);
|
||||
|
||||
SetDepthFunc(DepthLess);
|
||||
EnableDepthWrite(true);
|
||||
|
||||
EnableBlending(false);
|
||||
SetBlendFunc(BlendSrcAlpha, BlendOneMinusSrcAlpha);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user