Expand Up
@@ -27,10 +27,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include " client/shader.h"
#include " client/client.h"
#include " client/clientmap.h"
#include " profiler.h"
ShadowRenderer::ShadowRenderer (IrrlichtDevice *device, Client *client) :
m_device(device), m_smgr(device->getSceneManager ()),
m_driver(device->getVideoDriver ()), m_client(client)
m_driver(device->getVideoDriver ()), m_client(client), m_current_frame( 0 )
{
m_shadows_enabled = true ;
Expand All
@@ -43,7 +44,7 @@ ShadowRenderer::ShadowRenderer(IrrlichtDevice *device, Client *client) :
m_shadow_map_texture_32bit = g_settings->getBool (" shadow_map_texture_32bit" );
m_shadow_map_colored = g_settings->getBool (" shadow_map_color" );
m_shadow_samples = g_settings->getS32 (" shadow_filters" );
m_update_delta = g_settings->getFloat ( " shadow_update_time " );
m_map_shadow_update_frames = g_settings->getS16 ( " shadow_update_frames " );
}
ShadowRenderer::~ShadowRenderer ()
Expand All
@@ -66,6 +67,9 @@ ShadowRenderer::~ShadowRenderer()
if (shadowMapClientMap)
m_driver->removeTexture (shadowMapClientMap);
if (shadowMapClientMapFuture)
m_driver->removeTexture (shadowMapClientMapFuture);
}
void ShadowRenderer::initialize ()
Expand Down
Expand Up
@@ -93,11 +97,6 @@ void ShadowRenderer::initialize()
}
float ShadowRenderer::getUpdateDelta () const
{
return m_update_delta;
}
size_t ShadowRenderer::addDirectionalLight ()
{
m_light_list.emplace_back (m_shadow_map_texture_size,
Expand Down
Expand Up
@@ -152,10 +151,9 @@ void ShadowRenderer::setClearColor(video::SColor ClearColor)
m_clear_color = ClearColor;
}
void ShadowRenderer::update (video::ITexture *outputTarget )
void ShadowRenderer::updateSMTextures ( )
{
if (!m_shadows_enabled || m_smgr->getActiveCamera () == nullptr ) {
m_smgr->drawAll ();
return ;
}
Expand All
@@ -174,6 +172,13 @@ void ShadowRenderer::update(video::ITexture *outputTarget)
true );
}
if (!shadowMapClientMapFuture && m_map_shadow_update_frames > 1 ) {
shadowMapClientMapFuture = getSMTexture (
std::string (" shadow_clientmap_bb_" ) + itos (m_shadow_map_texture_size),
m_shadow_map_colored ? m_texture_format_color : m_texture_format,
true );
}
if (m_shadow_map_colored && !shadowMapTextureColors) {
shadowMapTextureColors = getSMTexture (
std::string (" shadow_colored_" ) + itos (m_shadow_map_texture_size),
Expand Down
Expand Up
@@ -201,7 +206,22 @@ void ShadowRenderer::update(video::ITexture *outputTarget)
}
if (!m_shadow_node_array.empty () && !m_light_list.empty ()) {
// for every directional light:
bool reset_sm_texture = false ;
// detect if SM should be regenerated
for (DirectionalLight &light : m_light_list) {
if (light.should_update_map_shadow ) {
light.should_update_map_shadow = false ;
m_current_frame = 0 ;
reset_sm_texture = true ;
}
}
video::ITexture* shadowMapTargetTexture = shadowMapClientMapFuture;
if (shadowMapTargetTexture == nullptr )
shadowMapTargetTexture = shadowMapClientMap;
// Update SM incrementally:
for (DirectionalLight &light : m_light_list) {
// Static shader values.
m_shadow_depth_cb->MapRes = (f32)m_shadow_map_texture_size;
Expand All
@@ -212,22 +232,60 @@ void ShadowRenderer::update(video::ITexture *outputTarget)
// Depth texture is available in irrlicth maybe we
// should put some gl* fn here
if (light.should_update_map_shadow ) {
light.should_update_map_shadow = false ;
m_driver->setRenderTarget (shadowMapClientMap, true , true ,
if (m_current_frame < m_map_shadow_update_frames) {
m_driver->setRenderTarget (shadowMapTargetTexture, reset_sm_texture, true ,
video::SColor (255 , 255 , 255 , 255 ));
renderShadowMap (shadowMapClientMap, light);
if (m_shadow_map_colored) {
m_driver->setRenderTarget (shadowMapTextureColors,
true , false , video::SColor (255 , 255 , 255 , 255 ));
renderShadowMap (shadowMapTargetTexture, light);
// Render transparent part in one pass.
// This is also handled in ClientMap.
if (m_current_frame == m_map_shadow_update_frames - 1 ) {
if (m_shadow_map_colored) {
m_driver->setRenderTarget (shadowMapTextureColors,
true , false , video::SColor (255 , 255 , 255 , 255 ));
}
renderShadowMap (shadowMapTextureColors, light,
scene::ESNRP_TRANSPARENT);
}
renderShadowMap (shadowMapTextureColors, light,
scene::ESNRP_TRANSPARENT);
m_driver->setRenderTarget (0 , false , false );
}
reset_sm_texture = false ;
} // end for lights
// move to the next section
if (m_current_frame <= m_map_shadow_update_frames)
++m_current_frame;
// pass finished, swap textures and commit light changes
if (m_current_frame == m_map_shadow_update_frames) {
if (shadowMapClientMapFuture != nullptr )
std::swap (shadowMapClientMapFuture, shadowMapClientMap);
// Let all lights know that maps are updated
for (DirectionalLight &light : m_light_list)
light.commitFrustum ();
}
}
}
void ShadowRenderer::update (video::ITexture *outputTarget)
{
if (!m_shadows_enabled || m_smgr->getActiveCamera () == nullptr ) {
m_smgr->drawAll ();
return ;
}
updateSMTextures ();
if (!m_shadow_node_array.empty () && !m_light_list.empty ()) {
for (DirectionalLight &light : m_light_list) {
// Static shader values.
m_shadow_depth_cb->MapRes = (f32)m_shadow_map_texture_size;
m_shadow_depth_cb->MaxFar = (f32)m_shadow_map_max_distance * BS;
// render shadows for the n0n-map objects.
m_driver->setRenderTarget (shadowMapTextureDynamicObjects, true ,
true , video::SColor (255 , 255 , 255 , 255 ));
Expand Down
Expand Up
@@ -299,8 +357,8 @@ video::ITexture *ShadowRenderer::getSMTexture(const std::string &shadow_map_name
void ShadowRenderer::renderShadowMap (video::ITexture *target,
DirectionalLight &light, scene::E_SCENE_NODE_RENDER_PASS pass)
{
m_driver->setTransform (video::ETS_VIEW, light.getViewMatrix ());
m_driver->setTransform (video::ETS_PROJECTION, light.getProjectionMatrix ());
m_driver->setTransform (video::ETS_VIEW, light.getFutureViewMatrix ());
m_driver->setTransform (video::ETS_PROJECTION, light.getFutureProjectionMatrix ());
// Operate on the client map
for (const auto &shadow_node : m_shadow_node_array) {
Expand All
@@ -322,18 +380,21 @@ void ShadowRenderer::renderShadowMap(video::ITexture *target,
// material.PolygonOffsetDepthBias = 1.0f/4.0f;
// material.PolygonOffsetSlopeScale = -1.f;
if (m_shadow_map_colored && pass != scene::ESNRP_SOLID)
if (m_shadow_map_colored && pass != scene::ESNRP_SOLID) {
material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader_trans;
else
}
else {
material.MaterialType = (video::E_MATERIAL_TYPE) depth_shader;
material.BlendOperation = video::EBO_MIN;
}
// FIXME: I don't think this is needed here
map_node->OnAnimate (m_device->getTimer ()->getTime ());
m_driver->setTransform (video::ETS_WORLD,
map_node->getAbsoluteTransformation ());
map_node->renderMapShadows (m_driver, material, pass);
map_node->renderMapShadows (m_driver, material, pass, m_current_frame, m_map_shadow_update_frames );
break ;
}
}
Expand All
@@ -354,8 +415,10 @@ void ShadowRenderer::renderShadowObjects(
u32 n_node_materials = shadow_node.node ->getMaterialCount ();
std::vector<s32> BufferMaterialList;
std::vector<std::pair<bool , bool >> BufferMaterialCullingList;
std::vector<video::E_BLEND_OPERATION> BufferBlendOperationList;
BufferMaterialList.reserve (n_node_materials);
BufferMaterialCullingList.reserve (n_node_materials);
BufferBlendOperationList.reserve (n_node_materials);
// backup materialtype for each material
// (aka shader)
Expand All
@@ -365,12 +428,11 @@ void ShadowRenderer::renderShadowObjects(
BufferMaterialList.push_back (current_mat.MaterialType );
current_mat.MaterialType =
(video::E_MATERIAL_TYPE)depth_shader;
current_mat.setTexture (3 , shadowMapTextureFinal);
(video::E_MATERIAL_TYPE)depth_shader_entities;
BufferMaterialCullingList.emplace_back (
(bool )current_mat.BackfaceCulling , (bool )current_mat.FrontfaceCulling );
BufferBlendOperationList.push_back (current_mat.BlendOperation );
current_mat.BackfaceCulling = true ;
current_mat.FrontfaceCulling = false ;
Expand All
@@ -393,6 +455,7 @@ void ShadowRenderer::renderShadowObjects(
current_mat.BackfaceCulling = BufferMaterialCullingList[m].first ;
current_mat.FrontfaceCulling = BufferMaterialCullingList[m].second ;
current_mat.BlendOperation = BufferBlendOperationList[m];
}
} // end for caster shadow nodes
Expand Down
Expand Up
@@ -433,7 +496,7 @@ void ShadowRenderer::createShaders()
readShaderFile (depth_shader_vs).c_str (), " vertexMain" ,
video::EVST_VS_1_1,
readShaderFile (depth_shader_fs).c_str (), " pixelMain" ,
video::EPST_PS_1_2, m_shadow_depth_cb);
video::EPST_PS_1_2, m_shadow_depth_cb, video::EMT_ONETEXTURE_BLEND );
if (depth_shader == -1 ) {
// upsi, something went wrong loading shader.
Expand All
@@ -449,6 +512,41 @@ void ShadowRenderer::createShaders()
m_driver->getMaterialRenderer (depth_shader)->grab ();
}
// This creates a clone of depth_shader with base material set to EMT_SOLID,
// because entities won't render shadows with base material EMP_ONETEXTURE_BLEND
if (depth_shader_entities == -1 ) {
std::string depth_shader_vs = getShaderPath (" shadow_shaders" , " pass1_vertex.glsl" );
if (depth_shader_vs.empty ()) {
m_shadows_enabled = false ;
errorstream << " Error shadow mapping vs shader not found." << std::endl;
return ;
}
std::string depth_shader_fs = getShaderPath (" shadow_shaders" , " pass1_fragment.glsl" );
if (depth_shader_fs.empty ()) {
m_shadows_enabled = false ;
errorstream << " Error shadow mapping fs shader not found." << std::endl;
return ;
}
depth_shader_entities = gpu->addHighLevelShaderMaterial (
readShaderFile (depth_shader_vs).c_str (), " vertexMain" ,
video::EVST_VS_1_1,
readShaderFile (depth_shader_fs).c_str (), " pixelMain" ,
video::EPST_PS_1_2, m_shadow_depth_cb);
if (depth_shader_entities == -1 ) {
// upsi, something went wrong loading shader.
m_shadows_enabled = false ;
errorstream << " Error compiling shadow mapping shader (dynamic)." << std::endl;
return ;
}
// HACK, TODO: investigate this better
// Grab the material renderer once more so minetest doesn't crash
// on exit
m_driver->getMaterialRenderer (depth_shader_entities)->grab ();
}
if (mixcsm_shader == -1 ) {
std::string depth_shader_vs = getShaderPath (" shadow_shaders" , " pass2_vertex.glsl" );
if (depth_shader_vs.empty ()) {
Expand Down