2019-01-11 00:48:33 -08:00
//
// KRLight.cpp
2021-08-16 16:35:36 -07:00
// Kraken Engine
2019-01-11 00:48:33 -08:00
//
2022-04-03 21:56:23 -07:00
// Copyright 2022 Kearwood Gilbert. All rights reserved.
2021-08-16 16:35:36 -07:00
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
2019-01-11 00:48:33 -08:00
//
# include "KREngine-common.h"
# include "KRLight.h"
# include "KRNode.h"
# include "KRCamera.h"
# include "KRContext.h"
2019-12-01 15:49:49 -08:00
# include "KRPipelineManager.h"
# include "KRPipeline.h"
2019-01-11 00:48:33 -08:00
# include "KRDirectionalLight.h"
# include "KRSpotLight.h"
# include "KRPointLight.h"
2020-06-21 22:42:10 -07:00
/* static */
void KRLight : : InitNodeInfo ( KrNodeInfo * nodeInfo )
{
KRNode : : InitNodeInfo ( nodeInfo ) ;
nodeInfo - > light . casts_shadow = true ;
nodeInfo - > light . color = Vector3 : : One ( ) ;
nodeInfo - > light . decay_start = 0.0f ;
nodeInfo - > light . dust_particle_density = 0.1f ;
nodeInfo - > light . dust_particle_intensity = 1.0f ;
nodeInfo - > light . dust_particle_size = 1.0f ;
nodeInfo - > light . flare_occlusion_size = 0.05f ;
nodeInfo - > light . flare_size = 0.0f ;
nodeInfo - > light . flare_texture = - 1 ;
nodeInfo - > light . intensity = 1.0f ;
nodeInfo - > light . light_shafts = true ;
}
2019-01-11 00:48:33 -08:00
KRLight : : KRLight ( KRScene & scene , std : : string name ) : KRNode ( scene , name )
{
m_intensity = 1.0f ;
m_dust_particle_intensity = 1.0f ;
m_color = Vector3 : : One ( ) ;
m_flareTexture = " " ;
m_pFlareTexture = NULL ;
m_flareSize = 0.0f ;
m_flareOcclusionSize = 0.05f ;
m_casts_shadow = true ;
m_light_shafts = true ;
m_dust_particle_density = 0.1f ;
m_dust_particle_size = 1.0f ;
2020-06-21 22:42:10 -07:00
m_dust_particle_intensity = 1.0f ;
2019-01-11 00:48:33 -08:00
m_occlusionQuery = 0 ;
2020-06-21 22:42:10 -07:00
m_decayStart = 0 ;
2019-01-11 00:48:33 -08:00
// Initialize shadow buffers
m_cShadowBuffers = 0 ;
for ( int iBuffer = 0 ; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS ; iBuffer + + ) {
shadowFramebuffer [ iBuffer ] = 0 ;
shadowDepthTexture [ iBuffer ] = 0 ;
shadowValid [ iBuffer ] = false ;
}
}
KRLight : : ~ KRLight ( )
{
if ( m_occlusionQuery ) {
GLDEBUG ( glDeleteQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
m_occlusionQuery = 0 ;
}
allocateShadowBuffers ( 0 ) ;
}
tinyxml2 : : XMLElement * KRLight : : saveXML ( tinyxml2 : : XMLNode * parent )
{
tinyxml2 : : XMLElement * e = KRNode : : saveXML ( parent ) ;
e - > SetAttribute ( " intensity " , m_intensity ) ;
e - > SetAttribute ( " color_r " , m_color . x ) ;
e - > SetAttribute ( " color_g " , m_color . y ) ;
e - > SetAttribute ( " color_b " , m_color . z ) ;
e - > SetAttribute ( " decay_start " , m_decayStart ) ;
e - > SetAttribute ( " flare_size " , m_flareSize ) ;
e - > SetAttribute ( " flare_occlusion_size " , m_flareOcclusionSize ) ;
e - > SetAttribute ( " flare_texture " , m_flareTexture . c_str ( ) ) ;
e - > SetAttribute ( " casts_shadow " , m_casts_shadow ? " true " : " false " ) ;
e - > SetAttribute ( " light_shafts " , m_light_shafts ? " true " : " false " ) ;
e - > SetAttribute ( " dust_particle_density " , m_dust_particle_density ) ;
e - > SetAttribute ( " dust_particle_size " , m_dust_particle_size ) ;
e - > SetAttribute ( " dust_particle_intensity " , m_dust_particle_intensity ) ;
return e ;
}
void KRLight : : loadXML ( tinyxml2 : : XMLElement * e ) {
KRNode : : loadXML ( e ) ;
float x = 1.0f , y = 1.0f , z = 1.0f ;
if ( e - > QueryFloatAttribute ( " color_r " , & x ) ! = tinyxml2 : : XML_SUCCESS ) {
x = 1.0 ;
}
if ( e - > QueryFloatAttribute ( " color_g " , & y ) ! = tinyxml2 : : XML_SUCCESS ) {
y = 1.0 ;
}
if ( e - > QueryFloatAttribute ( " color_b " , & z ) ! = tinyxml2 : : XML_SUCCESS ) {
z = 1.0 ;
}
m_color = Vector3 : : Create ( x , y , z ) ;
if ( e - > QueryFloatAttribute ( " intensity " , & m_intensity ) ! = tinyxml2 : : XML_SUCCESS ) {
m_intensity = 100.0 ;
}
if ( e - > QueryFloatAttribute ( " decay_start " , & m_decayStart ) ! = tinyxml2 : : XML_SUCCESS ) {
m_decayStart = 0.0 ;
}
if ( e - > QueryFloatAttribute ( " flare_size " , & m_flareSize ) ! = tinyxml2 : : XML_SUCCESS ) {
m_flareSize = 0.0 ;
}
if ( e - > QueryFloatAttribute ( " flare_occlusion_size " , & m_flareOcclusionSize ) ! = tinyxml2 : : XML_SUCCESS ) {
m_flareOcclusionSize = 0.05f ;
}
if ( e - > QueryBoolAttribute ( " casts_shadow " , & m_casts_shadow ) ! = tinyxml2 : : XML_SUCCESS ) {
m_casts_shadow = true ;
}
if ( e - > QueryBoolAttribute ( " light_shafts " , & m_light_shafts ) ! = tinyxml2 : : XML_SUCCESS ) {
m_light_shafts = true ;
}
m_dust_particle_density = 0.1f ;
if ( e - > QueryFloatAttribute ( " dust_particle_density " , & m_dust_particle_density ) ! = tinyxml2 : : XML_SUCCESS ) {
m_dust_particle_density = 0.1f ;
}
m_dust_particle_size = 1.0f ;
if ( e - > QueryFloatAttribute ( " dust_particle_size " , & m_dust_particle_size ) ! = tinyxml2 : : XML_SUCCESS ) {
m_dust_particle_size = 1.0f ;
}
m_dust_particle_intensity = 1.0f ;
if ( e - > QueryFloatAttribute ( " dust_particle_intensity " , & m_dust_particle_intensity ) ! = tinyxml2 : : XML_SUCCESS ) {
m_dust_particle_intensity = 1.0f ;
}
const char * szFlareTexture = e - > Attribute ( " flare_texture " ) ;
if ( szFlareTexture ) {
m_flareTexture = szFlareTexture ;
} else {
m_flareTexture = " " ;
}
m_pFlareTexture = NULL ;
}
void KRLight : : setFlareTexture ( std : : string flare_texture ) {
m_flareTexture = flare_texture ;
m_pFlareTexture = NULL ;
}
void KRLight : : setFlareSize ( float flare_size ) {
m_flareSize = flare_size ;
}
void KRLight : : setFlareOcclusionSize ( float occlusion_size ) {
m_flareOcclusionSize = occlusion_size ;
}
void KRLight : : setIntensity ( float intensity ) {
m_intensity = intensity ;
}
float KRLight : : getIntensity ( ) {
return m_intensity ;
}
const Vector3 & KRLight : : getColor ( ) {
return m_color ;
}
void KRLight : : setColor ( const Vector3 & color ) {
m_color = color ;
}
void KRLight : : setDecayStart ( float decayStart ) {
m_decayStart = decayStart ;
}
float KRLight : : getDecayStart ( ) {
return m_decayStart ;
}
2022-02-28 01:41:04 -08:00
void KRLight : : render ( VkCommandBuffer & commandBuffer , KRCamera * pCamera , std : : vector < KRPointLight * > & point_lights , std : : vector < KRDirectionalLight * > & directional_lights , std : : vector < KRSpotLight * > & spot_lights , const KRViewport & viewport , KRNode : : RenderPass renderPass ) {
2019-01-11 00:48:33 -08:00
if ( m_lod_visible < = LOD_VISIBILITY_PRESTREAM ) return ;
2022-02-28 01:41:04 -08:00
KRNode : : render ( commandBuffer , pCamera , point_lights , directional_lights , spot_lights , viewport , renderPass ) ;
2019-01-11 00:48:33 -08:00
if ( renderPass = = KRNode : : RENDER_PASS_GENERATE_SHADOWMAPS & & ( pCamera - > settings . volumetric_environment_enable | | pCamera - > settings . dust_particle_enable | | ( pCamera - > settings . m_cShadowBuffers > 0 & & m_casts_shadow ) ) ) {
allocateShadowBuffers ( configureShadowBufferViewports ( viewport ) ) ;
2022-02-28 01:41:04 -08:00
renderShadowBuffers ( commandBuffer , pCamera ) ;
2019-01-11 00:48:33 -08:00
}
if ( renderPass = = KRNode : : RENDER_PASS_ADDITIVE_PARTICLES & & pCamera - > settings . dust_particle_enable ) {
// Render brownian particles for dust floating in air
if ( m_cShadowBuffers > = 1 & & shadowValid [ 0 ] & & m_dust_particle_density > 0.0f & & m_dust_particle_size > 0.0f & & m_dust_particle_intensity > 0.0f ) {
if ( viewport . visible ( getBounds ( ) ) | | true ) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f ;
2019-01-14 21:07:32 -08:00
int particle_count = ( int ) ( m_dust_particle_density * pow ( particle_range , 3 ) ) ;
2019-01-11 00:48:33 -08:00
if ( particle_count > KRMeshManager : : KRENGINE_MAX_RANDOM_PARTICLES ) particle_count = KRMeshManager : : KRENGINE_MAX_RANDOM_PARTICLES ;
// Enable z-buffer test
GLDEBUG ( glEnable ( GL_DEPTH_TEST ) ) ;
GLDEBUG ( glDepthRangef ( 0.0 , 1.0 ) ) ;
Matrix4 particleModelMatrix ;
particleModelMatrix . scale ( particle_range ) ; // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
particleModelMatrix . translate ( viewport . getCameraPosition ( ) ) ;
std : : vector < KRDirectionalLight * > this_directional_light ;
std : : vector < KRSpotLight * > this_spot_light ;
std : : vector < KRPointLight * > this_point_light ;
KRDirectionalLight * directional_light = dynamic_cast < KRDirectionalLight * > ( this ) ;
KRSpotLight * spot_light = dynamic_cast < KRSpotLight * > ( this ) ;
KRPointLight * point_light = dynamic_cast < KRPointLight * > ( this ) ;
if ( directional_light ) {
this_directional_light . push_back ( directional_light ) ;
}
if ( spot_light ) {
this_spot_light . push_back ( spot_light ) ;
}
if ( point_light ) {
this_point_light . push_back ( point_light ) ;
}
2019-12-01 15:49:49 -08:00
KRPipeline * pParticleShader = m_pContext - > getPipelineManager ( ) - > getPipeline ( " dust_particle " , pCamera , this_point_light , this_directional_light , this_spot_light , 0 , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , renderPass ) ;
2019-01-11 00:48:33 -08:00
2019-12-01 15:49:49 -08:00
if ( getContext ( ) . getPipelineManager ( ) - > selectPipeline ( * pCamera , pParticleShader , viewport , particleModelMatrix , this_point_light , this_directional_light , this_spot_light , 0 , renderPass , Vector3 : : Zero ( ) , 0.0f , Vector4 : : Zero ( ) ) ) {
2019-01-11 00:48:33 -08:00
2019-12-01 15:49:49 -08:00
pParticleShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_LIGHT_COLOR , m_color * pCamera - > settings . dust_particle_intensity * m_dust_particle_intensity * m_intensity ) ;
pParticleShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_PARTICLE_ORIGIN , Matrix4 : : DotWDiv ( Matrix4 : : Invert ( particleModelMatrix ) , Vector3 : : Zero ( ) ) ) ;
pParticleShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_FLARE_SIZE , m_dust_particle_size ) ;
2019-01-11 00:48:33 -08:00
KRDataBlock particle_index_data ;
2022-02-28 20:14:22 -08:00
m_pContext - > getMeshManager ( ) - > bindVBO ( commandBuffer , m_pContext - > getMeshManager ( ) - > getRandomParticles ( ) , particle_index_data , ( 1 < < KRMesh : : KRENGINE_ATTRIB_VERTEX ) | ( 1 < < KRMesh : : KRENGINE_ATTRIB_TEXUVA ) , true , 1.0f
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
, " Light Particles "
# endif
) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLES , 0 , particle_count * 3 ) ) ;
}
}
}
}
if ( renderPass = = KRNode : : RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE & & pCamera - > settings . volumetric_environment_enable & & m_light_shafts ) {
std : : string shader_name = pCamera - > settings . volumetric_environment_downsample ! = 0 ? " volumetric_fog_downsampled " : " volumetric_fog " ;
std : : vector < KRDirectionalLight * > this_directional_light ;
std : : vector < KRSpotLight * > this_spot_light ;
std : : vector < KRPointLight * > this_point_light ;
KRDirectionalLight * directional_light = dynamic_cast < KRDirectionalLight * > ( this ) ;
KRSpotLight * spot_light = dynamic_cast < KRSpotLight * > ( this ) ;
KRPointLight * point_light = dynamic_cast < KRPointLight * > ( this ) ;
if ( directional_light ) {
this_directional_light . push_back ( directional_light ) ;
}
if ( spot_light ) {
this_spot_light . push_back ( spot_light ) ;
}
if ( point_light ) {
this_point_light . push_back ( point_light ) ;
}
2019-12-01 15:49:49 -08:00
KRPipeline * pFogShader = m_pContext - > getPipelineManager ( ) - > getPipeline ( shader_name , pCamera , this_point_light , this_directional_light , this_spot_light , 0 , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , KRNode : : RENDER_PASS_ADDITIVE_PARTICLES ) ;
2019-01-11 00:48:33 -08:00
2019-12-01 15:49:49 -08:00
if ( getContext ( ) . getPipelineManager ( ) - > selectPipeline ( * pCamera , pFogShader , viewport , Matrix4 ( ) , this_point_light , this_directional_light , this_spot_light , 0 , KRNode : : RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE , Vector3 : : Zero ( ) , 0.0f , Vector4 : : Zero ( ) ) ) {
2019-01-11 00:48:33 -08:00
int slice_count = ( int ) ( pCamera - > settings . volumetric_environment_quality * 495.0 ) + 5 ;
float slice_near = - pCamera - > settings . getPerspectiveNearZ ( ) ;
float slice_far = - pCamera - > settings . volumetric_environment_max_distance ;
float slice_spacing = ( slice_far - slice_near ) / slice_count ;
2019-12-01 15:49:49 -08:00
pFogShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_SLICE_DEPTH_SCALE , Vector2 : : Create ( slice_near , slice_spacing ) ) ;
pFogShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_LIGHT_COLOR , ( m_color * pCamera - > settings . volumetric_environment_intensity * m_intensity * - slice_spacing / 1000.0f ) ) ;
2019-01-11 00:48:33 -08:00
KRDataBlock index_data ;
2022-02-28 20:14:22 -08:00
m_pContext - > getMeshManager ( ) - > bindVBO ( commandBuffer , m_pContext - > getMeshManager ( ) - > getVolumetricLightingVertexes ( ) , index_data , ( 1 < < KRMesh : : KRENGINE_ATTRIB_VERTEX ) , true , 1.0f
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
, " Participating Media "
# endif
) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLES , 0 , slice_count * 6 ) ) ;
}
}
if ( renderPass = = KRNode : : RENDER_PASS_PARTICLE_OCCLUSION ) {
if ( m_flareTexture . size ( ) & & m_flareSize > 0.0f ) {
Matrix4 occlusion_test_sphere_matrix = Matrix4 ( ) ;
occlusion_test_sphere_matrix . scale ( m_localScale * m_flareOcclusionSize ) ;
occlusion_test_sphere_matrix . translate ( m_localTranslation ) ;
if ( m_parentNode ) {
occlusion_test_sphere_matrix * = m_parentNode - > getModelMatrix ( ) ;
}
2019-12-01 15:49:49 -08:00
if ( getContext ( ) . getPipelineManager ( ) - > selectPipeline ( " occlusion_test " , * pCamera , point_lights , directional_lights , spot_lights , 0 , viewport , occlusion_test_sphere_matrix , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , renderPass , Vector3 : : Zero ( ) , 0.0f , Vector4 : : Zero ( ) ) ) {
2019-01-11 00:48:33 -08:00
GLDEBUG ( glGenQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
# if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG ( glBeginQueryEXT ( GL_ANY_SAMPLES_PASSED_EXT , m_occlusionQuery ) ) ;
# else
GLDEBUG ( glBeginQuery ( GL_SAMPLES_PASSED , m_occlusionQuery ) ) ;
# endif
std : : vector < KRMesh * > sphereModels = getContext ( ) . getMeshManager ( ) - > getModel ( " __sphere " ) ;
if ( sphereModels . size ( ) ) {
for ( int i = 0 ; i < sphereModels [ 0 ] - > getSubmeshCount ( ) ; i + + ) {
2022-02-28 20:14:22 -08:00
sphereModels [ 0 ] - > renderSubmesh ( commandBuffer , i , renderPass , getName ( ) , " occlusion_test " , 1.0f ) ;
2019-01-11 00:48:33 -08:00
}
}
# if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG ( glEndQueryEXT ( GL_ANY_SAMPLES_PASSED_EXT ) ) ;
# else
GLDEBUG ( glEndQuery ( GL_SAMPLES_PASSED ) ) ;
# endif
}
}
}
if ( renderPass = = KRNode : : RENDER_PASS_ADDITIVE_PARTICLES ) {
if ( m_flareTexture . size ( ) & & m_flareSize > 0.0f ) {
if ( m_occlusionQuery ) {
GLuint params = 0 ;
GLDEBUG ( glGetQueryObjectuivEXT ( m_occlusionQuery , GL_QUERY_RESULT_EXT , & params ) ) ;
GLDEBUG ( glDeleteQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
if ( params ) {
if ( ! m_pFlareTexture & & m_flareTexture . size ( ) ) {
m_pFlareTexture = getContext ( ) . getTextureManager ( ) - > getTexture ( m_flareTexture ) ;
}
if ( m_pFlareTexture ) {
// Disable z-buffer test
GLDEBUG ( glDisable ( GL_DEPTH_TEST ) ) ;
GLDEBUG ( glDepthRangef ( 0.0 , 1.0 ) ) ;
// Render light flare on transparency pass
2019-12-01 15:49:49 -08:00
KRPipeline * pShader = getContext ( ) . getPipelineManager ( ) - > getPipeline ( " flare " , pCamera , point_lights , directional_lights , spot_lights , 0 , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , renderPass ) ;
2019-01-11 00:48:33 -08:00
2019-12-01 15:49:49 -08:00
if ( getContext ( ) . getPipelineManager ( ) - > selectPipeline ( * pCamera , pShader , viewport , getModelMatrix ( ) , point_lights , directional_lights , spot_lights , 0 , renderPass , Vector3 : : Zero ( ) , 0.0f , Vector4 : : Zero ( ) ) ) {
pShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_MATERIAL_ALPHA , 1.0f ) ;
pShader - > setUniform ( KRPipeline : : KRENGINE_UNIFORM_FLARE_SIZE , m_flareSize ) ;
2019-01-11 00:48:33 -08:00
m_pContext - > getTextureManager ( ) - > selectTexture ( 0 , m_pFlareTexture , 0.0f , KRTexture : : TEXTURE_USAGE_LIGHT_FLARE ) ;
2022-02-28 20:14:22 -08:00
m_pContext - > getMeshManager ( ) - > bindVBO ( commandBuffer , & getContext ( ) . getMeshManager ( ) - > KRENGINE_VBO_DATA_2D_SQUARE_VERTICES , 1.0f ) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ) ;
}
}
}
}
}
}
}
void KRLight : : allocateShadowBuffers ( int cBuffers ) {
// First deallocate buffers no longer needed
for ( int iShadow = cBuffers ; iShadow < KRENGINE_MAX_SHADOW_BUFFERS ; iShadow + + ) {
if ( shadowDepthTexture [ iShadow ] ) {
GLDEBUG ( glDeleteTextures ( 1 , shadowDepthTexture + iShadow ) ) ;
shadowDepthTexture [ iShadow ] = 0 ;
}
if ( shadowFramebuffer [ iShadow ] ) {
GLDEBUG ( glDeleteFramebuffers ( 1 , shadowFramebuffer + iShadow ) ) ;
shadowFramebuffer [ iShadow ] = 0 ;
}
}
// Allocate newly required buffers
for ( int iShadow = 0 ; iShadow < cBuffers ; iShadow + + ) {
Vector2 viewportSize = m_shadowViewports [ iShadow ] . getSize ( ) ;
if ( ! shadowDepthTexture [ iShadow ] ) {
shadowValid [ iShadow ] = false ;
GLDEBUG ( glGenFramebuffers ( 1 , shadowFramebuffer + iShadow ) ) ;
GLDEBUG ( glGenTextures ( 1 , shadowDepthTexture + iShadow ) ) ;
// ===== Create offscreen shadow framebuffer object =====
GLDEBUG ( glBindFramebuffer ( GL_FRAMEBUFFER , shadowFramebuffer [ iShadow ] ) ) ;
// ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG ( glBindTexture ( GL_TEXTURE_2D , shadowDepthTexture [ iShadow ] ) ) ;
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ) ;
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ) ;
m_pContext - > getTextureManager ( ) - > _setWrapModeS ( shadowDepthTexture [ iShadow ] , GL_CLAMP_TO_EDGE ) ;
m_pContext - > getTextureManager ( ) - > _setWrapModeT ( shadowDepthTexture [ iShadow ] , GL_CLAMP_TO_EDGE ) ;
# if GL_EXT_shadow_samplers
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_COMPARE_MODE_EXT , GL_COMPARE_REF_TO_TEXTURE_EXT ) ) ; // TODO - Detect GL_EXT_shadow_samplers and only activate if available
GLDEBUG ( glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_COMPARE_FUNC_EXT , GL_LEQUAL ) ) ; // TODO - Detect GL_EXT_shadow_samplers and only activate if available
# endif
2019-01-14 22:20:04 -08:00
GLDEBUG ( glTexImage2D ( GL_TEXTURE_2D , 0 , GL_DEPTH_COMPONENT , ( GLsizei ) viewportSize . x , ( GLsizei ) viewportSize . y , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , NULL ) ) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_TEXTURE_2D , shadowDepthTexture [ iShadow ] , 0 ) ) ;
}
}
m_cShadowBuffers = cBuffers ;
}
void KRLight : : deleteBuffers ( )
{
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
allocateShadowBuffers ( 0 ) ;
}
void KRLight : : invalidateShadowBuffers ( )
{
for ( int iShadow = 0 ; iShadow < m_cShadowBuffers ; iShadow + + ) {
shadowValid [ iShadow ] = false ;
}
}
int KRLight : : configureShadowBufferViewports ( const KRViewport & viewport )
{
return 0 ;
}
2022-02-28 01:41:04 -08:00
void KRLight : : renderShadowBuffers ( VkCommandBuffer & commandBuffer , KRCamera * pCamera )
2019-01-11 00:48:33 -08:00
{
for ( int iShadow = 0 ; iShadow < m_cShadowBuffers ; iShadow + + ) {
if ( ! shadowValid [ iShadow ] ) {
shadowValid [ iShadow ] = true ;
GLDEBUG ( glBindFramebuffer ( GL_FRAMEBUFFER , shadowFramebuffer [ iShadow ] ) ) ;
GLDEBUG ( glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_TEXTURE_2D , shadowDepthTexture [ iShadow ] , 0 ) ) ;
2019-01-14 21:07:32 -08:00
GLDEBUG ( glViewport ( 0 , 0 , ( GLsizei ) m_shadowViewports [ iShadow ] . getSize ( ) . x , ( GLsizei ) m_shadowViewports [ iShadow ] . getSize ( ) . y ) ) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glClearDepthf ( 0.0f ) ) ;
GLDEBUG ( glClear ( GL_DEPTH_BUFFER_BIT ) ) ;
2019-01-14 21:07:32 -08:00
GLDEBUG ( glViewport ( 1 , 1 , ( GLsizei ) m_shadowViewports [ iShadow ] . getSize ( ) . x - 2 , ( GLsizei ) m_shadowViewports [ iShadow ] . getSize ( ) . y - 2 ) ) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glClearDepthf ( 1.0f ) ) ;
GLDEBUG ( glClear ( GL_DEPTH_BUFFER_BIT ) ) ;
GLDEBUG ( glDisable ( GL_DITHER ) ) ;
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG ( glDisable ( GL_CULL_FACE ) ) ;
// Enable z-buffer test
GLDEBUG ( glEnable ( GL_DEPTH_TEST ) ) ;
GLDEBUG ( glDepthFunc ( GL_LESS ) ) ;
GLDEBUG ( glDepthRangef ( 0.0 , 1.0 ) ) ;
// Disable alpha blending as we are using alpha channel for packed depth info
GLDEBUG ( glDisable ( GL_BLEND ) ) ;
// Use shader program
2019-12-01 15:49:49 -08:00
KRPipeline * shadowShader = m_pContext - > getPipelineManager ( ) - > getPipeline ( " ShadowShader " , pCamera , std : : vector < KRPointLight * > ( ) , std : : vector < KRDirectionalLight * > ( ) , std : : vector < KRSpotLight * > ( ) , 0 , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , false , KRNode : : RENDER_PASS_FORWARD_TRANSPARENT ) ;
2019-01-11 00:48:33 -08:00
2019-12-01 15:49:49 -08:00
getContext ( ) . getPipelineManager ( ) - > selectPipeline ( * pCamera , shadowShader , m_shadowViewports [ iShadow ] , Matrix4 ( ) , std : : vector < KRPointLight * > ( ) , std : : vector < KRDirectionalLight * > ( ) , std : : vector < KRSpotLight * > ( ) , 0 , KRNode : : RENDER_PASS_SHADOWMAP , Vector3 : : Zero ( ) , 0.0f , Vector4 : : Zero ( ) ) ;
2019-01-11 00:48:33 -08:00
2022-02-28 01:41:04 -08:00
getScene ( ) . render ( commandBuffer , pCamera , m_shadowViewports [ iShadow ] . getVisibleBounds ( ) , m_shadowViewports [ iShadow ] , KRNode : : RENDER_PASS_SHADOWMAP , true ) ;
2019-01-11 00:48:33 -08:00
GLDEBUG ( glEnable ( GL_CULL_FACE ) ) ;
}
}
}
int KRLight : : getShadowBufferCount ( )
{
int cBuffers = 0 ;
for ( int iBuffer = 0 ; iBuffer < m_cShadowBuffers ; iBuffer + + ) {
if ( shadowValid [ iBuffer ] ) {
cBuffers + + ;
} else {
break ;
}
}
return cBuffers ;
}
GLuint * KRLight : : getShadowTextures ( )
{
return shadowDepthTexture ;
}
KRViewport * KRLight : : getShadowViewports ( )
{
return m_shadowViewports ;
}