#include "ShadowMappingShader.h"
#include <math.h>
namespace Graphics
{
ShadowMappingShader::ShadowMappingShader()
: mShadowSize(2048)
, mShadowPCFKernelSize(9)
{
}
ShadowMappingShader::~ShadowMappingShader()
{
glDeleteTextures( 1, &mShadowMap );
glDeleteFramebuffers( 1, &mFrameBuffer );
glDeleteRenderbuffers( 1, &mDepthRenderBuffer );
}
bool ShadowMappingShader::Initialize(const char* pVertexShaderPath, const char* pPixelShaderPath, const char* pVertexProjShaderPath)
{
bool lResult = Shader::Initialize(pVertexShaderPath, pPixelShaderPath, "-DENABLE_SHADOWS=1", "-DENABLE_SHADOWS=1");
if ( !lResult )
{
return false;
}
mShadowProjVertexShader = CreateShader(mVertexProfile, pVertexProjShaderPath,
NULL);
if ( !mShadowProjVertexShader )
{
ShowError( cgGetLastListing(mContext) );
return false;
}
mParamShadowProjMVP = cgGetNamedParameter( mShadowProjVertexShader, "ShadowMVP" );
mParamShadowMVP = cgGetNamedParameter( mVertexShader, "ShadowMVP" );
mParamShadowMap = cgGetNamedParameter( mPixelShader, "ShadowMap" );
mParamShadowCaster = cgGetNamedParameter( mPixelShader, "ShadowCaster" );
mParamShadowMapSize = cgGetNamedParameter( mPixelShader, "ShadowMapSize" );
mParamShadowPCFKernelSize = cgGetNamedParameter( mPixelShader, "ShadowPCFKernelSize" );
mParamShadowPCFKernelStep = cgGetNamedParameter( mPixelShader, "ShadowPCFKernelStep" );
glGenTextures( 1, &mShadowMap );
glBindTexture( GL_TEXTURE_2D, mShadowMap );
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32,
mShadowSize, mShadowSize,
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
float colour[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colour );
glGenFramebuffers( 1, &mFrameBuffer );
glBindFramebuffer( GL_FRAMEBUFFER_EXT, mFrameBuffer );
glFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, mShadowMap, 0 );
glDrawBuffer( GL_FALSE );
glReadBuffer( GL_FALSE );
GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER_EXT );
switch( status )
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
default:
ShowError("GL_FRAMEBUFFER_UNSUPPORTED_EXT");
return false;
break;
}
glBindFramebuffer( GL_FRAMEBUFFER_EXT, 0 );
return true;
}
void ShadowMappingShader::UploadParameters( FBRenderOptions* pRenderOptions, FBShaderModelInfo* pShaderModelInfo, FBArrayTemplate<FBLight*> *pAffectingLightList )
{
Shader::UploadParameters( pRenderOptions, pAffectingLightList);
cgGLSetTextureParameter( mParamShadowMap, mShadowMap );
cgGLEnableTextureParameter( mParamShadowMap );
FBMatrix modelMatrix;
pShaderModelInfo->GetFBModel()->GetMatrix(modelMatrix);
FBMatrix modelView;
FBMatrix mvp;
cgSetMatrixParameterdc( mParamShadowMVP, mvp);
cgSetParameter1i( mParamShadowCaster, mShadowCaster );
cgSetParameter1i( mParamShadowMapSize, mShadowSize );
cgSetParameter1i( mParamShadowPCFKernelSize, mShadowPCFKernelSize );
cgSetParameter1f( mParamShadowPCFKernelStep, 1.0f / mShadowSize );
}
void ShadowMappingShader::BeginShadowPass( FBRenderOptions* pRenderOptions, FBShaderModelInfo* pShaderModelInfo,
FBRenderingPass pPass )
{
mCurrentPass = pPass;
{
glBindFramebuffer( GL_FRAMEBUFFER_EXT, mFrameBuffer );
glPushAttrib( GL_VIEWPORT_BIT );
{
glClearDepth( 1.0 );
glClear( GL_DEPTH_BUFFER_BIT );
}
glViewport( 0, 0, mShadowSize, mShadowSize );
glPolygonOffset( 4, 10 );
glEnable(GL_POLYGON_OFFSET_FILL);
int lightCount = FBSystem::TheOne().Scene->Lights.GetCount();
for(
int i = 0;
i < lightCount; ++
i )
{
FBLight* light = FBSystem::TheOne().Scene->Lights[
i];
{
{
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
FBMatrix baseMat( base );
FBMatrix rotationMat;
FBMatrix transformationMat;
transformationMat(3,0) = ((
FBVector3d)light->Translation)[0];
transformationMat(3,1) = ((
FBVector3d)light->Translation)[1];
transformationMat(3,2) = ((
FBVector3d)light->Translation)[2];
transformationMat(3,3) = 1.0f;
float fov = 1.2f * light->OuterAngle / 2.0f;
float fFar = (double)light->Intensity * 2.0f;
float fNear = 1.0f;
float top = tan(fov*3.14159f/360.0f) * fNear;
float bottom = -top;
float left = bottom;
float right = top;
double perspectiveValues[16] =
{
(2.0*fNear)/(right-left), 0, 0, 0,
0, (2.0*fNear)/(top-bottom), 0, 0,
0, 0, -(fFar+fNear)/(fFar-fNear), -(2.0f*fFar*fNear)/(fFar-fNear),
0, 0, -1.0f, 0
};
mPerspectiveMatrix = FBMatrix( perspectiveValues );
break;
}
}
BindShadowPrograms();
UploadShadowParams( pRenderOptions, pShaderModelInfo );
}
{
BeginShading( pRenderOptions,
NULL );
}
}
void ShadowMappingShader::EndShadowPass()
{
{
UnbindShadowPrograms();
glDisable(GL_POLYGON_OFFSET_FILL);
glPopAttrib();
glBindFramebuffer( GL_FRAMEBUFFER_EXT, 0 );
}
{
EndShading();
}
}
void ShadowMappingShader::UploadShadowParams( FBRenderOptions* pRenderOptions, FBShaderModelInfo* pShaderModelInfo )
{
FBMatrix modelMatrix;
pShaderModelInfo->GetFBModel()->GetMatrix(modelMatrix);
FBMatrix modelView;
FBMatrix mvp;
cgSetMatrixParameterdc( mParamShadowProjMVP, mvp);
}
void ShadowMappingShader::BindShadowPrograms()
{
cgGLBindProgram(mShadowProjVertexShader);
cgGLBindProgram(0);
cgGLEnableProfile(mVertexProfile);
}
void ShadowMappingShader::UnbindShadowPrograms()
{
UnbindShaderPrograms();
}
void ShadowMappingShader::UnsetTextures()
{
Graphics::Shader::UnsetTextures();
cgGLDisableTextureParameter( mParamShadowMap );
}
}