2012-04-05 23:09:41 +00:00
//
// KRLight.cpp
// KREngine
//
// Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
2013-01-11 03:21:19 +00:00
# include "KREngine-common.h"
# include "KRLight.h"
2012-06-15 00:05:56 +00:00
2013-01-11 03:21:19 +00:00
# include "KRNode.h"
# include "KRMat4.h"
# include "KRVector3.h"
# include "KRCamera.h"
# include "KRContext.h"
2012-06-15 00:05:56 +00:00
2013-01-11 03:21:19 +00:00
# include "KRShaderManager.h"
# include "KRShader.h"
# include "KRStockGeometry.h"
2013-04-25 16:21:28 -07:00
# include "KRDirectionalLight.h"
# include "KRSpotLight.h"
# include "KRPointLight.h"
2012-04-05 23:09:41 +00:00
2012-06-15 00:05:56 +00:00
2012-08-29 21:43:11 +00:00
KRLight : : KRLight ( KRScene & scene , std : : string name ) : KRNode ( scene , name )
2012-04-05 23:09:41 +00:00
{
2012-04-12 00:43:53 +00:00
m_intensity = 1.0f ;
2012-11-23 01:02:22 +00:00
m_dust_particle_intensity = 1.0f ;
m_color = KRVector3 : : One ( ) ;
2012-06-15 00:05:56 +00:00
m_flareTexture = " " ;
m_pFlareTexture = NULL ;
m_flareSize = 0.0 ;
2013-01-17 19:27:17 -08:00
m_flareOcclusionSize = 0.05 ;
2012-11-16 02:58:23 +00:00
m_casts_shadow = true ;
m_light_shafts = true ;
2012-11-23 01:02:22 +00:00
m_dust_particle_density = 0.1f ;
m_dust_particle_size = 1.0f ;
2013-01-17 19:27:17 -08:00
m_occlusionQuery = 0 ;
2012-11-15 22:05:25 +00:00
// Initialize shadow buffers
m_cShadowBuffers = 0 ;
2012-11-16 02:58:23 +00:00
for ( int iBuffer = 0 ; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS ; iBuffer + + ) {
shadowFramebuffer [ iBuffer ] = 0 ;
shadowDepthTexture [ iBuffer ] = 0 ;
shadowValid [ iBuffer ] = false ;
}
2012-04-05 23:09:41 +00:00
}
KRLight : : ~ KRLight ( )
{
2013-01-17 19:27:17 -08:00
if ( m_occlusionQuery ) {
GLDEBUG ( glDeleteQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
m_occlusionQuery = 0 ;
}
2012-11-15 22:05:25 +00:00
allocateShadowBuffers ( 0 ) ;
2012-04-05 23:09:41 +00:00
}
2012-04-12 00:43:53 +00:00
tinyxml2 : : XMLElement * KRLight : : saveXML ( tinyxml2 : : XMLNode * parent )
2012-04-05 23:09:41 +00:00
{
2012-04-12 00:43:53 +00:00
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 ) ;
2012-06-15 00:05:56 +00:00
e - > SetAttribute ( " flare_size " , m_flareSize ) ;
2013-01-17 19:27:17 -08:00
e - > SetAttribute ( " flare_occlusion_size " , m_flareOcclusionSize ) ;
2012-06-15 00:05:56 +00:00
e - > SetAttribute ( " flare_texture " , m_flareTexture . c_str ( ) ) ;
2012-11-16 02:58:23 +00:00
e - > SetAttribute ( " casts_shadow " , m_casts_shadow ? " true " : " false " ) ;
e - > SetAttribute ( " light_shafts " , m_light_shafts ? " true " : " false " ) ;
2012-11-23 01:02:22 +00:00
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 ) ;
2012-04-12 00:43:53 +00:00
return e ;
}
2012-04-12 01:27:30 +00:00
void KRLight : : loadXML ( tinyxml2 : : XMLElement * e ) {
KRNode : : loadXML ( e ) ;
2012-11-23 01:02:22 +00:00
float x = 1.0f , y = 1.0f , z = 1.0f ;
2012-06-15 00:05:56 +00:00
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 ;
}
2012-04-12 01:27:30 +00:00
m_color = KRVector3 ( x , y , z ) ;
2012-06-15 00:05:56 +00:00
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 ;
}
2013-01-17 19:27:17 -08:00
if ( e - > QueryFloatAttribute ( " flare_occlusion_size " , & m_flareOcclusionSize ) ! = tinyxml2 : : XML_SUCCESS ) {
m_flareOcclusionSize = 0.05 ;
}
2012-11-16 02:58:23 +00:00
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 ;
}
2012-11-23 01:02:22 +00:00
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 ;
}
2012-06-15 00:05:56 +00:00
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 ;
2012-04-12 01:27:30 +00:00
}
2013-03-14 14:29:12 -07:00
void KRLight : : setFlareOcclusionSize ( float occlusion_size ) {
m_flareOcclusionSize = occlusion_size ;
2013-01-17 19:27:17 -08:00
}
2012-04-12 00:43:53 +00:00
void KRLight : : setIntensity ( float intensity ) {
m_intensity = intensity ;
}
float KRLight : : getIntensity ( ) {
return m_intensity ;
}
const KRVector3 & KRLight : : getColor ( ) {
return m_color ;
}
void KRLight : : setColor ( const KRVector3 & color ) {
m_color = color ;
}
void KRLight : : setDecayStart ( float decayStart ) {
m_decayStart = decayStart ;
}
float KRLight : : getDecayStart ( ) {
return m_decayStart ;
}
2012-06-15 00:05:56 +00:00
2013-04-25 16:21:28 -07:00
void KRLight : : render ( KRCamera * pCamera , std : : vector < KRPointLight * > & point_lights , std : : vector < KRDirectionalLight * > & directional_lights , std : : vector < KRSpotLight * > & spot_lights , const KRViewport & viewport , KRNode : : RenderPass renderPass ) {
2012-11-15 22:05:25 +00:00
2013-04-25 16:21:28 -07:00
KRNode : : render ( pCamera , point_lights , directional_lights , spot_lights , viewport , renderPass ) ;
2012-11-15 22:05:25 +00:00
2012-12-20 22:08:41 +00: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 ) ) ) {
2012-11-15 22:05:25 +00:00
allocateShadowBuffers ( configureShadowBufferViewports ( viewport ) ) ;
renderShadowBuffers ( pCamera ) ;
}
2012-12-20 22:08:41 +00:00
if ( renderPass = = KRNode : : RENDER_PASS_ADDITIVE_PARTICLES & & pCamera - > settings . dust_particle_enable ) {
2012-11-23 01:02:22 +00:00
// 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 ) {
2013-04-24 12:48:55 -07:00
if ( viewport . visible ( getBounds ( ) ) | | true ) { // FINDME, HACK need to remove "|| true"?
2012-11-23 01:02:22 +00:00
float particle_range = 600.0f ;
int particle_count = m_dust_particle_density * pow ( particle_range , 3 ) ;
2013-01-09 22:37:23 +00:00
if ( particle_count > KRMeshManager : : KRENGINE_MAX_RANDOM_PARTICLES ) particle_count = KRMeshManager : : KRENGINE_MAX_RANDOM_PARTICLES ;
2012-11-23 01:02:22 +00:00
// Enable z-buffer test
GLDEBUG ( glEnable ( GL_DEPTH_TEST ) ) ;
GLDEBUG ( glDepthRangef ( 0.0 , 1.0 ) ) ;
KRMat4 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 ( ) ) ;
2013-04-25 16:21:28 -07:00
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 ) ;
}
2012-11-23 01:02:22 +00:00
2013-04-25 16:21:28 -07:00
KRShader * pParticleShader = m_pContext - > getShaderManager ( ) - > getShader ( " 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 ) ;
2012-11-23 01:02:22 +00:00
2013-04-25 16:21:28 -07:00
if ( getContext ( ) . getShaderManager ( ) - > selectShader ( * pCamera , pParticleShader , viewport , particleModelMatrix , this_point_light , this_directional_light , this_spot_light , 0 , renderPass ) ) {
2012-11-23 01:02:22 +00:00
2012-12-20 22:08:41 +00:00
( m_color * pCamera - > settings . dust_particle_intensity * m_dust_particle_intensity * m_intensity ) . setUniform ( pParticleShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_LIGHT_COLOR ] ) ;
2012-11-23 01:02:22 +00:00
KRMat4 : : DotWDiv ( KRMat4 : : Invert ( particleModelMatrix ) , KRVector3 : : Zero ( ) ) . setUniform ( pParticleShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_PARTICLE_ORIGIN ] ) ;
2013-04-24 15:51:57 -07:00
if ( pParticleShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_FLARE_SIZE ] ! = - 1 ) {
GLDEBUG ( glUniform1f ( pParticleShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_FLARE_SIZE ] , m_dust_particle_size ) ) ;
}
2012-11-23 01:02:22 +00:00
2013-03-21 13:21:04 -07:00
m_pContext - > getModelManager ( ) - > bindVBO ( ( void * ) m_pContext - > getModelManager ( ) - > getRandomParticles ( ) , KRMeshManager : : KRENGINE_MAX_RANDOM_PARTICLES * 3 * sizeof ( KRMeshManager : : RandomParticleVertexData ) , NULL , 0 , true , false , false , true , false , false , false , true ) ;
2012-11-23 01:02:22 +00:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLES , 0 , particle_count * 3 ) ) ;
}
}
}
}
2012-12-20 22:08:41 +00:00
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 " ;
2012-11-15 22:05:25 +00:00
2013-04-25 16:21:28 -07:00
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 ) ;
}
2012-11-15 22:05:25 +00:00
2013-04-25 16:21:28 -07:00
KRShader * pFogShader = m_pContext - > getShaderManager ( ) - > getShader ( 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 ) ;
2012-11-15 22:05:25 +00:00
2013-04-25 16:21:28 -07:00
if ( getContext ( ) . getShaderManager ( ) - > selectShader ( * pCamera , pFogShader , viewport , KRMat4 ( ) , this_point_light , this_directional_light , this_spot_light , 0 , KRNode : : RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE ) ) {
2012-12-20 22:08:41 +00:00
int slice_count = ( int ) ( pCamera - > settings . volumetric_environment_quality * 495.0 ) + 5 ;
2012-11-15 22:05:25 +00:00
2012-12-20 22:08:41 +00:00
float slice_near = - pCamera - > settings . getPerspectiveNearZ ( ) ;
float slice_far = - pCamera - > settings . volumetric_environment_max_distance ;
2012-11-15 22:05:25 +00:00
float slice_spacing = ( slice_far - slice_near ) / slice_count ;
KRVector2 ( slice_near , slice_spacing ) . setUniform ( pFogShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_SLICE_DEPTH_SCALE ] ) ;
2012-12-20 22:08:41 +00:00
( m_color * pCamera - > settings . volumetric_environment_intensity * m_intensity * - slice_spacing / 1000.0f ) . setUniform ( pFogShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_LIGHT_COLOR ] ) ;
2012-11-15 22:05:25 +00:00
2013-03-21 13:21:04 -07:00
m_pContext - > getModelManager ( ) - > bindVBO ( ( void * ) m_pContext - > getModelManager ( ) - > getVolumetricLightingVertexes ( ) , KRMeshManager : : KRENGINE_MAX_VOLUMETRIC_PLANES * 6 * sizeof ( KRMeshManager : : VolumetricLightingVertexData ) , NULL , 0 , true , false , false , false , false , false , false , true ) ;
2012-11-15 22:05:25 +00:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLES , 0 , slice_count * 6 ) ) ;
}
2012-06-15 00:05:56 +00:00
2012-11-15 22:05:25 +00:00
}
2012-06-15 00:05:56 +00:00
2013-01-17 19:27:17 -08:00
if ( renderPass = = KRNode : : RENDER_PASS_PARTICLE_OCCLUSION ) {
2012-06-15 00:05:56 +00:00
if ( m_flareTexture . size ( ) & & m_flareSize > 0.0f ) {
2013-01-17 19:27:17 -08:00
KRMat4 occlusion_test_sphere_matrix = KRMat4 ( ) ;
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 ( ) ;
2012-06-15 00:05:56 +00:00
}
2013-01-17 19:27:17 -08:00
2013-04-25 16:21:28 -07:00
if ( getContext ( ) . getShaderManager ( ) - > selectShader ( " 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 ) ) {
2013-01-17 19:27:17 -08:00
GLDEBUG ( glGenQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
2013-02-06 11:59:24 -08:00
# if TARGET_OS_IPHONE
2013-01-17 19:27:17 -08:00
GLDEBUG ( glBeginQueryEXT ( GL_ANY_SAMPLES_PASSED_EXT , m_occlusionQuery ) ) ;
2013-02-06 11:59:24 -08:00
# else
GLDEBUG ( glBeginQuery ( GL_SAMPLES_PASSED , m_occlusionQuery ) ) ;
# endif
2013-01-17 19:27:17 -08:00
std : : vector < KRMesh * > sphereModels = getContext ( ) . getModelManager ( ) - > getModel ( " __sphere " ) ;
if ( sphereModels . size ( ) ) {
for ( int i = 0 ; i < sphereModels [ 0 ] - > getSubmeshCount ( ) ; i + + ) {
2013-03-21 19:58:35 -07:00
sphereModels [ 0 ] - > renderSubmesh ( i , renderPass , getName ( ) , " occlusion_test " ) ;
2013-01-17 19:27:17 -08:00
}
}
2013-02-06 11:59:24 -08:00
# if TARGET_OS_IPHONE
2013-01-17 19:27:17 -08:00
GLDEBUG ( glEndQueryEXT ( GL_ANY_SAMPLES_PASSED_EXT ) ) ;
2013-02-06 11:59:24 -08:00
# else
GLDEBUG ( glEndQuery ( GL_SAMPLES_PASSED ) ) ;
# endif
2013-01-17 19:27:17 -08:00
}
}
}
if ( renderPass = = KRNode : : RENDER_PASS_ADDITIVE_PARTICLES ) {
if ( m_flareTexture . size ( ) & & m_flareSize > 0.0f ) {
2012-06-15 00:05:56 +00:00
2013-01-17 19:27:17 -08:00
if ( m_occlusionQuery ) {
2013-04-12 01:07:41 -07:00
/*
2013-04-11 14:04:56 -07:00
GLuint hasBeenTested = 0 ;
while ( ! hasBeenTested ) {
GLDEBUG ( glGetQueryObjectuivEXT ( m_occlusionQuery , GL_QUERY_RESULT_AVAILABLE_EXT , & hasBeenTested ) ) ; // FINDME, HACK!! This needs to be replaced with asynchonous logic
}
2013-04-12 01:07:41 -07:00
*/
2013-01-17 19:27:17 -08:00
GLuint params = 0 ;
GLDEBUG ( glGetQueryObjectuivEXT ( m_occlusionQuery , GL_QUERY_RESULT_EXT , & params ) ) ;
GLDEBUG ( glDeleteQueriesEXT ( 1 , & m_occlusionQuery ) ) ;
2012-11-02 20:50:45 +00:00
2013-01-17 19:27:17 -08:00
if ( params ) {
if ( ! m_pFlareTexture & & m_flareTexture . size ( ) ) {
2013-04-24 12:48:55 -07:00
m_pFlareTexture = getContext ( ) . getTextureManager ( ) - > getTexture ( m_flareTexture ) ;
2013-01-17 19:27:17 -08:00
}
if ( m_pFlareTexture ) {
// Disable z-buffer test
GLDEBUG ( glDisable ( GL_DEPTH_TEST ) ) ;
GLDEBUG ( glDepthRangef ( 0.0 , 1.0 ) ) ;
// Render light flare on transparency pass
2013-04-25 16:21:28 -07:00
KRShader * pShader = getContext ( ) . getShaderManager ( ) - > getShader ( " 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 ) ;
if ( getContext ( ) . getShaderManager ( ) - > selectShader ( * pCamera , pShader , viewport , getModelMatrix ( ) , point_lights , directional_lights , spot_lights , 0 , renderPass ) ) {
2013-04-24 15:51:57 -07:00
if ( pShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_FLARE_SIZE ] ! = - 1 ) {
GLDEBUG ( glUniform1f (
pShader - > m_uniforms [ KRShader : : KRENGINE_UNIFORM_FLARE_SIZE ] ,
m_flareSize
) ) ;
}
2013-01-17 19:27:17 -08:00
m_pContext - > getTextureManager ( ) - > selectTexture ( 0 , m_pFlareTexture ) ;
2013-03-21 13:21:04 -07:00
m_pContext - > getModelManager ( ) - > bindVBO ( ( void * ) KRENGINE_VBO_2D_SQUARE , KRENGINE_VBO_2D_SQUARE_SIZE , NULL , 0 , true , false , false , true , false , false , false , true ) ;
2013-01-17 19:27:17 -08:00
GLDEBUG ( glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ) ;
}
}
2012-09-20 09:32:20 +00:00
}
2012-06-15 00:05:56 +00:00
}
}
}
}
2012-11-15 22:05:25 +00:00
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 + + ) {
KRVector2 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 ) ) ;
2013-04-24 15:51:57 -07:00
m_pContext - > getTextureManager ( ) - > _setWrapModeS ( shadowDepthTexture [ iShadow ] , GL_CLAMP_TO_EDGE ) ;
m_pContext - > getTextureManager ( ) - > _setWrapModeT ( shadowDepthTexture [ iShadow ] , GL_CLAMP_TO_EDGE ) ;
2012-11-15 22:05:25 +00:00
# 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
GLDEBUG ( glTexImage2D ( GL_TEXTURE_2D , 0 , GL_DEPTH_COMPONENT , viewportSize . x , viewportSize . y , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , NULL ) ) ;
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 ( )
{
2012-11-22 09:02:25 +00:00
for ( int iShadow = 0 ; iShadow < m_cShadowBuffers ; iShadow + + ) {
shadowValid [ iShadow ] = false ;
}
2012-11-15 22:05:25 +00:00
}
int KRLight : : configureShadowBufferViewports ( const KRViewport & viewport )
{
return 0 ;
}
void KRLight : : renderShadowBuffers ( KRCamera * pCamera )
2012-11-24 00:25:44 +00:00
{
2012-11-15 22:05:25 +00:00
for ( int iShadow = 0 ; iShadow < m_cShadowBuffers ; iShadow + + ) {
2012-11-22 09:02:25 +00:00
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 ) ) ;
GLDEBUG ( glViewport ( 0 , 0 , m_shadowViewports [ iShadow ] . getSize ( ) . x , m_shadowViewports [ iShadow ] . getSize ( ) . y ) ) ;
GLDEBUG ( glClearDepthf ( 0.0f ) ) ;
GLDEBUG ( glClear ( GL_DEPTH_BUFFER_BIT ) ) ;
GLDEBUG ( glViewport ( 1 , 1 , m_shadowViewports [ iShadow ] . getSize ( ) . x - 2 , m_shadowViewports [ iShadow ] . getSize ( ) . y - 2 ) ) ;
2012-11-15 22:05:25 +00:00
2012-11-22 09:02:25 +00:00
GLDEBUG ( glClearDepthf ( 1.0f ) ) ;
2012-12-28 06:25:57 +00:00
2012-11-22 09:02:25 +00:00
GLDEBUG ( glClear ( GL_DEPTH_BUFFER_BIT ) ) ;
GLDEBUG ( glDisable ( GL_DITHER ) ) ;
2013-04-17 13:39:37 -07:00
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG ( glDisable ( GL_CULL_FACE ) ) ;
2012-11-22 09:02:25 +00:00
// 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
2013-04-25 16:21:28 -07:00
KRShader * shadowShader = m_pContext - > getShaderManager ( ) - > getShader ( " 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 ) ;
2012-11-22 09:02:25 +00:00
2013-04-25 16:21:28 -07:00
getContext ( ) . getShaderManager ( ) - > selectShader ( * pCamera , shadowShader , m_shadowViewports [ iShadow ] , KRMat4 ( ) , std : : vector < KRPointLight * > ( ) , std : : vector < KRDirectionalLight * > ( ) , std : : vector < KRSpotLight * > ( ) , 0 , KRNode : : RENDER_PASS_SHADOWMAP ) ;
2012-11-22 09:02:25 +00:00
getScene ( ) . render ( pCamera , m_shadowViewports [ iShadow ] . getVisibleBounds ( ) , m_shadowViewports [ iShadow ] , KRNode : : RENDER_PASS_SHADOWMAP , true ) ;
2013-04-17 13:39:37 -07:00
GLDEBUG ( glEnable ( GL_CULL_FACE ) ) ;
2012-11-22 09:02:25 +00:00
}
2012-11-15 22:05:25 +00:00
}
}
2012-11-24 00:25:44 +00:00
2012-11-16 02:58:23 +00:00
int KRLight : : getShadowBufferCount ( )
{
2012-11-22 09:02:25 +00:00
int cBuffers = 0 ;
for ( int iBuffer = 0 ; iBuffer < m_cShadowBuffers ; iBuffer + + ) {
if ( shadowValid [ iBuffer ] ) {
cBuffers + + ;
} else {
break ;
}
}
return cBuffers ;
2012-11-16 02:58:23 +00:00
}
GLuint * KRLight : : getShadowTextures ( )
{
return shadowDepthTexture ;
}
KRViewport * KRLight : : getShadowViewports ( )
{
return m_shadowViewports ;
}