Implemented automatic tuning of shadow space frustum used for illuminating volumetric effects and particle systems.
--HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40163
This commit is contained in:
@@ -73,6 +73,20 @@ KRVector3 KRAABB::size() const
|
||||
return max - min;
|
||||
}
|
||||
|
||||
void KRAABB::scale(const KRVector3 &s)
|
||||
{
|
||||
KRVector3 prev_center = center();
|
||||
KRVector3 prev_size = size();
|
||||
KRVector3 new_scale = KRVector3(prev_size.x * s.x, prev_size.y * s.y, prev_size.z * s.z) * 0.5f;
|
||||
min = prev_center - new_scale;
|
||||
max = prev_center + new_scale;
|
||||
}
|
||||
|
||||
void KRAABB::scale(float s)
|
||||
{
|
||||
scale(KRVector3(s));
|
||||
}
|
||||
|
||||
bool KRAABB::operator >(const KRAABB& b) const
|
||||
{
|
||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
||||
|
||||
@@ -22,6 +22,9 @@ public:
|
||||
KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix);
|
||||
~KRAABB();
|
||||
|
||||
void scale(const KRVector3 &s);
|
||||
void scale(float s);
|
||||
|
||||
KRVector3 center() const;
|
||||
KRVector3 size() const;
|
||||
bool intersects(const KRAABB& b) const;
|
||||
|
||||
@@ -119,13 +119,13 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) {
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 1000.0f;
|
||||
volumetric_environment_quality = (50 - 5.0) / 495.0f;
|
||||
volumetric_environment_intensity = 1.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 500.0f;
|
||||
fog_far = 1000.0f;
|
||||
fog_density = 0.01f;
|
||||
fog_color = KRVector3(0.5, 0.5, 0.5);
|
||||
fog_far = 5000.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = KRVector3(0.45, 0.45, 0.5);
|
||||
fog_type = 0;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) {
|
||||
|
||||
|
||||
// Render the geometry
|
||||
scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, false);
|
||||
scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_LIGHTS, false);
|
||||
|
||||
// ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====----
|
||||
// Set render target
|
||||
@@ -288,13 +288,12 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) {
|
||||
} else {
|
||||
// ----====---- Generate Shadowmaps for Lights ----====----
|
||||
scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, true);
|
||||
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
|
||||
|
||||
// ----====---- Opaque Geometry, Forward Rendering ----====----
|
||||
|
||||
// Set render target
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
|
||||
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
|
||||
|
||||
// Disable alpha blending
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
@@ -421,7 +420,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) {
|
||||
GLDEBUG(glActiveTexture(GL_TEXTURE0));
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
|
||||
|
||||
glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y);
|
||||
GLDEBUG(glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y));
|
||||
} else {
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
@@ -436,7 +435,7 @@ void KRCamera::renderFrame(KRScene &scene, float deltaTime) {
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
|
||||
|
||||
glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y);
|
||||
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,27 +50,48 @@ KRVector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
|
||||
|
||||
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
|
||||
|
||||
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
|
||||
int cShadows = 1;
|
||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||
GLfloat shadowMinDepths[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.05, 0.3}};
|
||||
GLfloat shadowMaxDepths[3][3] = {{0.0, 0.0, 1.0},{0.1, 0.0, 0.0},{0.1, 0.3, 1.0}};
|
||||
|
||||
float min_depth = 0.0f;
|
||||
float max_depth = 1.0f;
|
||||
|
||||
KRAABB worldSpacefrustrumSliceBounds = KRAABB(KRVector3(-1.0f, -max_depth, -1.0f), KRVector3(1.0f, -min_depth, 1.0f), KRMat4::Invert(viewport.getViewProjectionMatrix()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
KRVector3 shadowLook = -KRVector3::Normalize(getWorldLightDirection());
|
||||
|
||||
KRVector3 shadowUp(0.0, 1.0, 0.0);
|
||||
if(KRVector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = KRVector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
||||
|
||||
KRMat4 matShadowView = KRMat4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
|
||||
// KRMat4 matShadowView = KRMat4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// KRMat4 matShadowProjection = KRMat4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
KRMat4 matShadowView = KRMat4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
KRMat4 matShadowProjection = KRMat4();
|
||||
matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
KRAABB shadowSpaceFrustrumSliceBounds = KRAABB(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, KRMat4::Invert(matShadowProjection));
|
||||
KRAABB shadowSpaceSceneBounds = KRAABB(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, KRMat4::Invert(matShadowProjection));
|
||||
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
|
||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||
|
||||
KRMat4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||
KRViewport newShadowViewport = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||
KRAABB prevShadowBounds = KRAABB(-KRVector3::One(), KRVector3::One(), KRMat4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
||||
KRAABB minimumShadowBounds = KRAABB(-KRVector3::One(), KRVector3::One(), KRMat4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow]) {
|
||||
m_shadowViewports[iShadow] = newShadowViewport;
|
||||
shadowValid[iShadow] = false;
|
||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -578,8 +578,8 @@ float const PI = 3.141592653589793f;
|
||||
1.0f, 10.0f, 2.0f, 1.0f, 1.0f, 1.0f, 5.0f, 1.0f,
|
||||
0.5f, 1.0f, 2.0f, 2.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f, 1000.0f, 10000.0f,
|
||||
1.0f, 5.0f, 10000.0f, 1.0f, 10.0f,
|
||||
3.0f, 10000.0f, 10000.0f, 0.10f, 1.0f, 1.0f, 1.0f
|
||||
1.0f, 5.0f, 10000.0f, 1.0f, 5.0f,
|
||||
3.0f, 10000.0f, 10000.0f, 0.01f, 1.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
return maxValues[i];
|
||||
|
||||
@@ -256,7 +256,9 @@ void KRLight::deleteBuffers()
|
||||
|
||||
void KRLight::invalidateShadowBuffers()
|
||||
{
|
||||
memset(shadowValid, sizeof(bool) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
shadowValid[iShadow] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
@@ -267,41 +269,45 @@ int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y);
|
||||
if(!shadowValid[iShadow]) {
|
||||
shadowValid[iShadow] = true;
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||
|
||||
GLDEBUG(glClearDepthf(0.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y);
|
||||
|
||||
GLDEBUG(glClearDepthf(1.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2);
|
||||
|
||||
GLDEBUG(glDisable(GL_DITHER));
|
||||
|
||||
GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||
GLDEBUG(glEnable(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
|
||||
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
|
||||
|
||||
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], KRMat4(), std::vector<KRLight *>(), KRNode::RENDER_PASS_SHADOWMAP);
|
||||
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
|
||||
|
||||
|
||||
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
// 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
|
||||
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
|
||||
|
||||
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], KRMat4(), std::vector<KRLight *>(), KRNode::RENDER_PASS_SHADOWMAP);
|
||||
|
||||
|
||||
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +315,15 @@ void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
|
||||
int KRLight::getShadowBufferCount()
|
||||
{
|
||||
return m_cShadowBuffers;
|
||||
int cBuffers=0;
|
||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||
if(shadowValid[iBuffer]) {
|
||||
cBuffers++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cBuffers;
|
||||
}
|
||||
|
||||
GLuint *KRLight::getShadowTextures()
|
||||
|
||||
@@ -424,6 +424,15 @@ void KRScene::addDefaultLights()
|
||||
{
|
||||
KRDirectionalLight *light1 = new KRDirectionalLight(*this, "default_light1");
|
||||
|
||||
light1->setLocalRotation((KRQuaternion(KRVector3(0.0, M_PI * 0.25, 0.0)) * KRQuaternion(KRVector3(0.0, 0.0, -M_PI * 0.25))).euler());
|
||||
light1->setLocalRotation((KRQuaternion(KRVector3(0.0, M_PI * 0.10, 0.0)) * KRQuaternion(KRVector3(0.0, 0.0, -M_PI * 0.15))).euler());
|
||||
m_pRootNode->addChild(light1);
|
||||
}
|
||||
|
||||
KRAABB KRScene::getRootOctreeBounds()
|
||||
{
|
||||
if(m_nodeTree.getRootNode()) {
|
||||
return m_nodeTree.getRootNode()->getBounds();
|
||||
} else {
|
||||
return KRAABB(-KRVector3::One(), KRVector3::One());
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,8 @@ public:
|
||||
void physicsUpdate(float deltaTime);
|
||||
void addDefaultLights();
|
||||
|
||||
KRAABB getRootOctreeBounds();
|
||||
|
||||
private:
|
||||
KRLight *findFirstLight(KRNode &node);
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ bool KRShader::bind(KRCamera &camera, const KRViewport &viewport, const KRMat4 &
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
}
|
||||
|
||||
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1) {
|
||||
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1 && camera.m_cShadowBuffers > 1) {
|
||||
m_pContext->getTextureManager()->selectTexture(4, NULL);
|
||||
GLDEBUG(glActiveTexture(GL_TEXTURE4));
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, directional_light->getShadowTextures()[1]));
|
||||
@@ -268,7 +268,7 @@ bool KRShader::bind(KRCamera &camera, const KRViewport &viewport, const KRMat4 &
|
||||
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
}
|
||||
|
||||
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2) {
|
||||
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2 && camera.m_cShadowBuffers > 2) {
|
||||
m_pContext->getTextureManager()->selectTexture(5, NULL);
|
||||
GLDEBUG(glActiveTexture(GL_TEXTURE5));
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, directional_light->getShadowTextures()[2]));
|
||||
|
||||
@@ -73,6 +73,9 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, KRCamera *p
|
||||
}
|
||||
}
|
||||
|
||||
if(iShadowQuality > pCamera->m_cShadowBuffers) {
|
||||
iShadowQuality = pCamera->m_cShadowBuffers;
|
||||
}
|
||||
|
||||
char szKey[256];
|
||||
sprintf(szKey, "%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f", light_directional_count, light_point_count, light_spot_count, pCamera->fog_type, pCamera->bEnablePerPixel,bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->bDebugPSSM, iShadowQuality, pCamera->bEnableAmbient, pCamera->bEnableDiffuse, pCamera->bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->volumetric_environment_enable && pCamera->volumetric_environment_downsample != 0, renderPass, shader_name.c_str(),pCamera->dof_quality,pCamera->bEnableFlash,pCamera->bEnableVignette,pCamera->dof_depth,pCamera->dof_falloff,pCamera->flash_depth,pCamera->flash_falloff,pCamera->flash_intensity,pCamera->vignette_radius,pCamera->vignette_falloff);
|
||||
|
||||
Reference in New Issue
Block a user