Refactoring to enable multiple lights in forward rendering in progress

--HG--
extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40156
This commit is contained in:
kearwood
2012-11-15 22:05:25 +00:00
parent 50fc0a0533
commit 04bd2bbe16
27 changed files with 464 additions and 374 deletions

View File

@@ -13,7 +13,7 @@
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // 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 // 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 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
@@ -34,6 +34,7 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#import <assert.h> #import <assert.h>
#include <stack.h>
#import "KRVector2.h" #import "KRVector2.h"
#import "KRCamera.h" #import "KRCamera.h"
@@ -107,8 +108,7 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) {
volumetricLightAccumulationTexture = 0; volumetricLightAccumulationTexture = 0;
memset(shadowFramebuffer, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
memset(shadowDepthTexture, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
m_iFrame = 0; m_iFrame = 0;
@@ -121,8 +121,6 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) {
volumetric_environment_max_distance = 1000.0f; volumetric_environment_max_distance = 1000.0f;
volumetric_environment_quality = (50 - 5.0) / 495.0f; volumetric_environment_quality = (50 - 5.0) / 495.0f;
volumetric_environment_intensity = 1.0f; volumetric_environment_intensity = 1.0f;
invalidateShadowBuffers();
} }
KRCamera::~KRCamera() { KRCamera::~KRCamera() {
@@ -168,61 +166,6 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, float deltaTime)
if(firstDirectionalLight) { if(firstDirectionalLight) {
lightDirection = firstDirectionalLight->getWorldLightDirection(); lightDirection = firstDirectionalLight->getWorldLightDirection();
} }
allocateShadowBuffers(m_cShadowBuffers);
for(int iShadow=0; iShadow < m_cShadowBuffers; 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}};
KRVector3 shadowLook = -KRVector3::Normalize(lightDirection);
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(m_viewport.getCameraPosition() - shadowLook, m_viewport.getCameraPosition(), shadowUp);
KRMat4 matShadowProjection = KRMat4();
matShadowProjection.scale(0.001, 0.001, 0.001);
KRMat4 matBias;
matBias.bias();
matShadowProjection *= matBias;
// KRAABB frustrumWorldBounds = KRAABB(KRVector3(-1.0, -1.0, 0.0), KRVector3(1.0, 1.0, 1.0), m_viewport.getInverseProjectionMatrix() * m_viewport.getInverseViewMatrix());
// matShadowProjection.translate(KRVector3(0.0, 0.0, -frustrumWorldBounds.size().z));
// matShadowProjection.scale(2.0 / frustrumWorldBounds.size().x, 2.0 / frustrumWorldBounds.size().y, 2.0 / frustrumWorldBounds.size().z);
// matShadowView.translate(-m_viewport.getCameraPosition());
//matShadowProjection *= matBias;
m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
// KRMat4 newShadowMVP;
// if(shadowMaxDepths[m_cShadowBuffers - 1][iShadow] == 0.0) {
// KRBoundingVolume ext = KRBoundingVolume(-KRVector3::One(), KRVector3::One(), KRMat4()); // HACK - Temporary workaround to compile until this logic is updated to use information from the Octree
//
// newShadowMVP = ext.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
// } else {
// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]);
// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
// }
// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]);
// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
//
// m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), KRMat4(), newShadowMVP);
//
renderShadowBuffer(scene, iShadow);
}
renderFrame(scene, lightDirection, deltaTime); renderFrame(scene, lightDirection, deltaTime);
@@ -241,6 +184,10 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
std::set<KRAABB> newVisibleBounds; std::set<KRAABB> newVisibleBounds;
// GLuint shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
// KRViewport shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
// int cShadows = 0;
if(bEnableDeferredLighting) { if(bEnableDeferredLighting) {
// ----====---- Opaque Geometry, Deferred rendering Pass 1 ----====---- // ----====---- Opaque Geometry, Deferred rendering Pass 1 ----====----
@@ -265,7 +212,11 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
// Render the geometry // Render the geometry
scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds); scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds);
// ----====---- Generate Shadowmaps for Lights ----====----
scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds);
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
// ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====---- // ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====----
// Set render target // Set render target
@@ -291,7 +242,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
// Render the geometry // Render the geometry
scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS, newVisibleBounds); scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds);
// ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====----
// Set render target // Set render target
@@ -323,7 +274,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
// Render the geometry // Render the geometry
std::set<KRAABB> emptyBoundsSet; // At this point, we only render octree nodes that produced fragments during the 1st pass into the GBuffer std::set<KRAABB> emptyBoundsSet; // At this point, we only render octree nodes that produced fragments during the 1st pass into the GBuffer
scene.render(this, emptyBoundsSet, m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); scene.render(this, emptyBoundsSet, m_viewport, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds);
// Deactivate source buffer texture units // Deactivate source buffer texture units
m_pContext->getTextureManager()->selectTexture(6, NULL, 0); m_pContext->getTextureManager()->selectTexture(6, NULL, 0);
@@ -333,6 +284,10 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glActiveTexture(GL_TEXTURE7)); GLDEBUG(glActiveTexture(GL_TEXTURE7));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
} else { } else {
// ----====---- Generate Shadowmaps for Lights ----====----
scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds);
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
// ----====---- Opaque Geometry, Forward Rendering ----====---- // ----====---- Opaque Geometry, Forward Rendering ----====----
// Set render target // Set render target
@@ -361,7 +316,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
// Render the geometry // Render the geometry
scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds);
} }
// ----====---- Sky Box ----====---- // ----====---- Sky Box ----====----
@@ -386,8 +341,8 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
} }
if(m_pSkyBoxTexture) { if(m_pSkyBoxTexture) {
KRShader *pShader = getContext().getShaderManager()->getShader("sky_box", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_OPAQUE); KRShader *pShader = getContext().getShaderManager()->getShader("sky_box", this, std::stack<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_OPAQUE);
pShader->bind(m_viewport, m_shadowViewports, KRMat4(), lightDirection, NULL, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE); pShader->bind(m_viewport, KRMat4(), std::stack<KRLight *>(), KRNode::RENDER_PASS_FORWARD_OPAQUE);
getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 2048); getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 2048);
@@ -421,7 +376,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
// Render all transparent geometry // Render all transparent geometry
scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds); scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds);
// ----====---- Flares ----====---- // ----====---- Flares ----====----
@@ -445,11 +400,12 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Render all flares // Render all flares
scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds); scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds);
// ----====---- Volumetric Lighting ----====---- // ----====---- Volumetric Lighting ----====----
if(m_cShadowBuffers >= 1 && volumetric_environment_enable) { if(volumetric_environment_enable) {
KRViewport volumetricLightingViewport = KRViewport(KRVector2(volumetricBufferWidth, volumetricBufferHeight), m_viewport.getViewMatrix(), m_viewport.getProjectionMatrix());
if(volumetric_environment_downsample != 0) { if(volumetric_environment_downsample != 0) {
// Set render target // Set render target
@@ -463,6 +419,8 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
m_pContext->getTextureManager()->selectTexture(0, NULL, 0); m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y);
} else { } else {
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
@@ -470,28 +428,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
} }
std::string shader_name = volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; scene.render(this, m_viewport.getVisibleBounds(), volumetricLightingViewport, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, newVisibleBounds);
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
KRViewport volumetricLightingViewport = KRViewport(KRVector2(volumetricBufferWidth, volumetricBufferHeight), m_viewport.getViewMatrix(), m_viewport.getProjectionMatrix());
glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y);
if(pFogShader->bind(volumetricLightingViewport, m_shadowViewports, KRMat4(), lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) {
int slice_count = (int)(volumetric_environment_quality * 495.0) + 5;
float slice_near = -getPerspectiveNearZ();
float slice_far = -volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count;
KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]);
(KRVector3::One() * volumetric_environment_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]);
m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
}
if(volumetric_environment_downsample != 0) { if(volumetric_environment_downsample != 0) {
// Set render target // Set render target
@@ -521,7 +458,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
KRShader *pVisShader = m_pContext->getShaderManager()->getShader("visualize_overlay", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *pVisShader = getContext().getShaderManager()->getShader("visualize_overlay", this, std::stack<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
KRMat4 projectionMatrix = getProjectionMatrix(); KRMat4 projectionMatrix = getProjectionMatrix();
@@ -530,7 +467,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt
KRMat4 matModel = KRMat4(); KRMat4 matModel = KRMat4();
matModel.scale((*itr).size() / 2.0f); matModel.scale((*itr).size() / 2.0f);
matModel.translate((*itr).center()); matModel.translate((*itr).center());
if(pVisShader->bind(m_viewport, m_shadowViewports, matModel, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { if(pVisShader->bind(m_viewport, matModel, std::stack<KRLight *>(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14));
} }
} }
@@ -660,55 +597,10 @@ void KRCamera::createBuffers() {
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, volumetricLightAccumulationTexture, 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, volumetricLightAccumulationTexture, 0));
} }
} }
allocateShadowBuffers(m_cShadowBuffers);
}
void KRCamera::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++) {
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));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
}
}
} }
void KRCamera::destroyBuffers() void KRCamera::destroyBuffers()
{ {
allocateShadowBuffers(0);
if (compositeDepthTexture) { if (compositeDepthTexture) {
GLDEBUG(glDeleteTextures(1, &compositeDepthTexture)); GLDEBUG(glDeleteTextures(1, &compositeDepthTexture));
compositeDepthTexture = 0; compositeDepthTexture = 0;
@@ -745,70 +637,6 @@ void KRCamera::destroyBuffers()
} }
} }
void KRCamera::renderShadowBuffer(KRScene &scene, int iShadow)
{
glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y);
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
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", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
shadowShader->bind(m_shadowViewports[iShadow], m_shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_SHADOWMAP);
// // Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
// shadowmvpmatrix[iShadow].setUniform(shadowShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SHADOWMVP1]);
// // Calculate the bounding volume of the light map
// KRMat4 matInvShadow = shadowmvpmatrix[iShadow];
// matInvShadow.invert();
//
// KRVector3 vertices[8];
// vertices[0] = KRVector3(-1.0, -1.0, 0.0);
// vertices[1] = KRVector3(1.0, -1.0, 0.0);
// vertices[2] = KRVector3(1.0, 1.0, 0.0);
// vertices[3] = KRVector3(-1.0, 1.0, 0.0);
// vertices[4] = KRVector3(-1.0, -1.0, 1.0);
// vertices[5] = KRVector3(1.0, -1.0, 1.0);
// vertices[6] = KRVector3(1.0, 1.0, 1.0);
// vertices[7] = KRVector3(-1.0, 1.0, 1.0);
//
// for(int iVertex=0; iVertex < 8; iVertex++) {
// vertices[iVertex] = KRMat4::Dot(matInvShadow, vertices[iVertex]);
// }
//
// KRVector3 cameraPosition;
// KRVector3 lightDirection;
// KRBoundingVolume shadowVolume = KRBoundingVolume(vertices);
KRVector3 temp = KRVector3();
std::set<KRAABB> newVisibleBounds;
scene.render(this, m_shadowViewports[iShadow].getVisibleBounds(), m_pContext, m_shadowViewports[iShadow], m_shadowViewports, temp, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP, newVisibleBounds);
m_shadowViewports[iShadow].setVisibleBounds(newVisibleBounds);
GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y));
}
void KRCamera::renderPost() void KRCamera::renderPost()
{ {
// Disable alpha blending // Disable alpha blending
@@ -836,8 +664,8 @@ void KRCamera::renderPost()
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
KRShader *postShader = m_pContext->getShaderManager()->getShader("PostShader", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *postShader = m_pContext->getShaderManager()->getShader("PostShader", this, std::stack<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
postShader->bind(m_viewport, m_shadowViewports, KRMat4(), KRVector3(), shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); postShader->bind(m_viewport, KRMat4(), std::stack<KRLight *>(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getTextureManager()->selectTexture(0, NULL, 0); m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glActiveTexture(GL_TEXTURE0));
@@ -867,37 +695,37 @@ void KRCamera::renderPost()
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
if(bShowShadowBuffer) { // if(bShowShadowBuffer) {
KRShader *blitShader = m_pContext->getShaderManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); // KRShader *blitShader = m_pContext->getShaderManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
//
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { // for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
KRMat4 viewMatrix = KRMat4(); // KRMat4 viewMatrix = KRMat4();
viewMatrix.scale(0.20, 0.20, 0.20); // viewMatrix.scale(0.20, 0.20, 0.20);
viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); // viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0);
blitShader->bind(KRViewport(getViewportSize(), viewMatrix, KRMat4()), m_shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); // blitShader->bind(KRViewport(getViewportSize(), viewMatrix, KRMat4()), shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getTextureManager()->selectTexture(1, NULL, 0); // m_pContext->getTextureManager()->selectTexture(1, NULL, 0);
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false); // m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false);
GLDEBUG(glActiveTexture(GL_TEXTURE0)); // GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); // GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
#if GL_EXT_shadow_samplers //#if GL_EXT_shadow_samplers
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available // GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif //#endif
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); // GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
#if GL_EXT_shadow_samplers //#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_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif //#endif
} // }
//
m_pContext->getTextureManager()->selectTexture(0, NULL, 0); // m_pContext->getTextureManager()->selectTexture(0, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE0)); // GLDEBUG(glActiveTexture(GL_TEXTURE0));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); // GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
} // }
const char *szText = m_debug_text.c_str(); const char *szText = m_debug_text.c_str();
if(*szText) { if(*szText) {
KRShader *fontShader = m_pContext->getShaderManager()->getShader("debug_font", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *fontShader = m_pContext->getShaderManager()->getShader("debug_font", this, std::stack<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"), 2048); m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"), 2048);
@@ -942,12 +770,6 @@ void KRCamera::renderPost()
} }
void KRCamera::invalidateShadowBuffers() {
for(int i=0; i < m_cShadowBuffers; i++) {
shadowValid[i] = false;
}
}
void KRCamera::setSkyBox(const std::string &skyBoxName) { void KRCamera::setSkyBox(const std::string &skyBoxName) {
m_pSkyBoxTexture = NULL; m_pSkyBoxTexture = NULL;
m_skyBoxName = skyBoxName; m_skyBoxName = skyBoxName;
@@ -965,13 +787,11 @@ void KRCamera::setPerspectiveNear(float v)
{ {
if(perspective_nearz != v) { if(perspective_nearz != v) {
perspective_nearz = v; perspective_nearz = v;
invalidateShadowBuffers();
} }
} }
void KRCamera::setPerpsectiveFarZ(float v) void KRCamera::setPerpsectiveFarZ(float v)
{ {
if(perspective_farz != v) { if(perspective_farz != v) {
perspective_farz = v; perspective_farz = v;
invalidateShadowBuffers();
} }
} }

View File

@@ -43,10 +43,6 @@
#import "KRContext.h" #import "KRContext.h"
#import "KRViewport.h" #import "KRViewport.h"
#define KRENGINE_MAX_SHADOW_BUFFERS 3
#define KRENGINE_SHADOW_MAP_WIDTH 4096
#define KRENGINE_SHADOW_MAP_HEIGHT 4096
class KRInstance; class KRInstance;
class KRScene; class KRScene;
class KRViewport; class KRViewport;
@@ -130,9 +126,6 @@ public:
private: private:
KRVector3 m_position; KRVector3 m_position;
void renderShadowBuffer(KRScene &scene, int iShadow);
void invalidateShadowBuffers();
void allocateShadowBuffers(int cBuffers);
void createBuffers(); void createBuffers();
float perspective_nearz; float perspective_nearz;
@@ -145,12 +138,6 @@ private:
GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture; GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture;
GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS];
KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
void renderPost(); void renderPost();
void destroyBuffers(); void destroyBuffers();

View File

@@ -48,11 +48,68 @@ KRVector3 KRDirectionalLight::getLocalLightDirection() {
return KRVector3(0.0, 0.0, 1.0); return KRVector3(0.0, 0.0, 1.0);
} }
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
for(int iShadow=0; iShadow < 1; 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}};
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 matShadowProjection = KRMat4();
matShadowProjection.scale(0.001, 0.001, 0.001);
KRMat4 matBias;
matBias.bias();
matShadowProjection *= matBias;
// KRAABB frustrumWorldBounds = KRAABB(KRVector3(-1.0, -1.0, 0.0), KRVector3(1.0, 1.0, 1.0), m_viewport.getInverseProjectionMatrix() * m_viewport.getInverseViewMatrix());
// matShadowProjection.translate(KRVector3(0.0, 0.0, -frustrumWorldBounds.size().z));
// matShadowProjection.scale(2.0 / frustrumWorldBounds.size().x, 2.0 / frustrumWorldBounds.size().y, 2.0 / frustrumWorldBounds.size().z);
// matShadowView.translate(-m_viewport.getCameraPosition());
//matShadowProjection *= matBias;
m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
// KRMat4 newShadowMVP;
// if(shadowMaxDepths[m_cShadowBuffers - 1][iShadow] == 0.0) {
// KRBoundingVolume ext = KRBoundingVolume(-KRVector3::One(), KRVector3::One(), KRMat4()); // HACK - Temporary workaround to compile until this logic is updated to use information from the Octree
//
// newShadowMVP = ext.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
// } else {
// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]);
// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
// }
// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]);
// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch);
//
// m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), KRMat4(), newShadowMVP);
//
// renderShadowBuffer(scene, iShadow);
}
return 1;
}
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { void KRDirectionalLight::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRLight::render(pCamera, lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
// Lights are rendered on the second pass of the deferred renderer // Lights are rendered on the second pass of the deferred renderer
@@ -65,8 +122,8 @@ void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KR
light_direction_view_space = KRMat4::Dot(matModelViewInverseTranspose, light_direction_view_space); light_direction_view_space = KRMat4::Dot(matModelViewInverseTranspose, light_direction_view_space);
light_direction_view_space.normalize(); light_direction_view_space.normalize();
KRShader *pShader = pContext->getShaderManager()->getShader("light_directional", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, renderPass)) { if(pShader->bind(viewport, getModelMatrix(), lights, renderPass)) {
light_direction_view_space.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE]); light_direction_view_space.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE]);
m_color.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); m_color.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]);

View File

@@ -25,9 +25,13 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
#endif #endif
protected:
virtual int configureShadowBufferViewports(const KRViewport &viewport);
}; };

View File

@@ -75,12 +75,12 @@ void KRInstance::loadModel() {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { void KRInstance::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRNode::render(pCamera, lights, viewport, renderPass);
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && (renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT || this->hasTransparency()) && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && (renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT || this->hasTransparency()) && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
loadModel(); loadModel();
@@ -103,14 +103,14 @@ void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport
} }
if(m_pLightMap == NULL && m_lightMap.size()) { if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = pContext->getTextureManager()->getTexture(m_lightMap.c_str()); m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap.c_str());
} }
if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP) { if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, 2048); m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, 2048);
} }
pModel->render(pCamera, pContext, viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, m_receivesShadow ? cShadowBuffers : 0, m_pLightMap, renderPass); pModel->render(pCamera, lights, viewport, getModelMatrix(), m_pLightMap, renderPass);
} }
} }
} }

View File

@@ -58,7 +58,7 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
#endif #endif
bool hasTransparency(); bool hasTransparency();

View File

@@ -29,11 +29,17 @@ KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
m_flareTexture = ""; m_flareTexture = "";
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
m_flareSize = 0.0; m_flareSize = 0.0;
// Initialize shadow buffers
m_cShadowBuffers = 0;
memset(shadowFramebuffer, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
memset(shadowDepthTexture, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
memset(shadowValid, sizeof(bool) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
} }
KRLight::~KRLight() KRLight::~KRLight()
{ {
allocateShadowBuffers(0);
} }
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
@@ -118,14 +124,44 @@ float KRLight::getDecayStart() {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { void KRLight::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRNode::render(pCamera, lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
allocateShadowBuffers(configureShadowBufferViewports(viewport));
renderShadowBuffers(pCamera);
}
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
std::string shader_name = pCamera->volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
std::stack<KRLight *> this_light;
this_light.push(this);
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_light, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
if(pFogShader->bind(viewport, KRMat4(), std::stack<KRLight *>(), KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE)) {
int slice_count = (int)(pCamera->volumetric_environment_quality * 495.0) + 5;
float slice_near = -pCamera->getPerspectiveNearZ();
float slice_far = -pCamera->volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count;
KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]);
(KRVector3::One() * pCamera->volumetric_environment_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]);
m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
}
}
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_flareTexture.size() && m_flareSize > 0.0f) { if(m_flareTexture.size() && m_flareSize > 0.0f) {
if(!m_pFlareTexture && m_flareTexture.size()) { if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = pContext->getTextureManager()->getTexture(m_flareTexture.c_str()); m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture.c_str());
} }
if(m_pFlareTexture) { if(m_pFlareTexture) {
@@ -134,8 +170,8 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light flare on transparency pass // Render light flare on transparency pass
KRShader *pShader = pContext->getShaderManager()->getShader("flare", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, renderPass)) { if(pShader->bind(viewport, getModelMatrix(), lights, renderPass)) {
GLDEBUG(glUniform1f( GLDEBUG(glUniform1f(
pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE],
m_flareSize m_flareSize
@@ -150,4 +186,132 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v
} }
} }
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));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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
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()
{
memset(shadowValid, sizeof(bool) * KRENGINE_MAX_SHADOW_BUFFERS, 0);
}
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
{
return 0;
}
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);
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
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::stack<KRLight *>(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
shadowShader->bind(m_shadowViewports[iShadow], KRMat4(), std::stack<KRLight *>(), KRNode::RENDER_PASS_SHADOWMAP);
// // Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
// shadowmvpmatrix[iShadow].setUniform(shadowShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SHADOWMVP1]);
// // Calculate the bounding volume of the light map
// KRMat4 matInvShadow = shadowmvpmatrix[iShadow];
// matInvShadow.invert();
//
// KRVector3 vertices[8];
// vertices[0] = KRVector3(-1.0, -1.0, 0.0);
// vertices[1] = KRVector3(1.0, -1.0, 0.0);
// vertices[2] = KRVector3(1.0, 1.0, 0.0);
// vertices[3] = KRVector3(-1.0, 1.0, 0.0);
// vertices[4] = KRVector3(-1.0, -1.0, 1.0);
// vertices[5] = KRVector3(1.0, -1.0, 1.0);
// vertices[6] = KRVector3(1.0, 1.0, 1.0);
// vertices[7] = KRVector3(-1.0, 1.0, 1.0);
//
// for(int iVertex=0; iVertex < 8; iVertex++) {
// vertices[iVertex] = KRMat4::Dot(matInvShadow, vertices[iVertex]);
// }
//
// KRVector3 cameraPosition;
// KRVector3 lightDirection;
// KRBoundingVolume shadowVolume = KRBoundingVolume(vertices);
std::set<KRAABB> newVisibleBounds;
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, newVisibleBounds);
m_shadowViewports[iShadow].setVisibleBounds(newVisibleBounds);
}
}
#endif #endif

View File

@@ -15,6 +15,12 @@
static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f
// KRENGINE_MAX_SHADOW_BUFFERS must be at least 6 to allow omni-directional lights to render cube maps
#define KRENGINE_MAX_SHADOW_BUFFERS 6
#define KRENGINE_SHADOW_MAP_WIDTH 4096
#define KRENGINE_SHADOW_MAP_HEIGHT 4096
class KRLight : public KRNode { class KRLight : public KRNode {
public: public:
@@ -33,10 +39,11 @@ public:
void setFlareTexture(std::string flare_texture); void setFlareTexture(std::string flare_texture);
void setFlareSize(float flare_size); void setFlareSize(float flare_size);
void deleteBuffers();
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
#endif #endif
@@ -50,6 +57,19 @@ protected:
std::string m_flareTexture; std::string m_flareTexture;
KRTexture *m_pFlareTexture; KRTexture *m_pFlareTexture;
float m_flareSize; float m_flareSize;
// Shadow Maps
int m_cShadowBuffers;
GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS];
KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
void allocateShadowBuffers(int cBuffers);
void invalidateShadowBuffers();
virtual int configureShadowBufferViewports(const KRViewport &viewport);
void renderShadowBuffers(KRCamera *pCamera);
}; };
#endif #endif

View File

@@ -201,27 +201,27 @@ bool KRMaterial::isTransparent() {
} }
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass) { bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass) {
bool bSameMaterial = *prevBoundMaterial == this; bool bSameMaterial = *prevBoundMaterial == this;
bool bLightMap = pLightMap && pCamera->bEnableLightMap; bool bLightMap = pLightMap && pCamera->bEnableLightMap;
if(!m_pAmbientMap && m_ambientMap.size()) { if(!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = pContext->getTextureManager()->getTexture(m_ambientMap.c_str()); m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap.c_str());
} }
if(!m_pDiffuseMap && m_diffuseMap.size()) { if(!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = pContext->getTextureManager()->getTexture(m_diffuseMap.c_str()); m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap.c_str());
} }
if(!m_pNormalMap && m_normalMap.size()) { if(!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = pContext->getTextureManager()->getTexture(m_normalMap.c_str()); m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap.c_str());
} }
if(!m_pSpecularMap && m_specularMap.size()) { if(!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = pContext->getTextureManager()->getTexture(m_specularMap.c_str()); m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap.c_str());
} }
if(!m_pReflectionMap && m_reflectionMap.size()) { if(!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = pContext->getTextureManager()->getTexture(m_reflectionMap.c_str()); m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap.c_str());
} }
if(!m_pReflectionCube && m_reflectionCube.size()) { if(!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = pContext->getTextureManager()->getTextureCube(m_reflectionCube.c_str()); m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
} }
if(!bSameMaterial) { if(!bSameMaterial) {
@@ -238,11 +238,11 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, con
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE); bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
KRShader *pShader = pContext->getShaderManager()->getShader("ObjectShader", pCamera, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, cShadowBuffers, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_reflectionMapScale != default_scale && bReflectionMap, m_normalMapScale != default_scale && bNormalMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_reflectionMapOffset != default_offset && bReflectionMap, m_normalMapOffset != default_offset && bNormalMap, bAlphaTest, bAlphaBlend, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, lights, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_reflectionMapScale != default_scale && bReflectionMap, m_normalMapScale != default_scale && bNormalMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_reflectionMapOffset != default_offset && bReflectionMap, m_normalMapOffset != default_offset && bNormalMap, bAlphaTest, bAlphaBlend, renderPass);
bool bSameShader = strcmp(pShader->getKey(), szPrevShaderKey) == 0; bool bSameShader = strcmp(pShader->getKey(), szPrevShaderKey) == 0;
if(!bSameShader) { if(!bSameShader) {
if(!pShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass)) { if(!pShader->bind(viewport, matModel, lights, renderPass)) {
return false; return false;
} }

View File

@@ -89,7 +89,7 @@ public:
char *getName(); char *getName();
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
bool bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass); bool bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass);
#endif #endif

View File

@@ -111,17 +111,17 @@ void KRModel::loadPack(KRDataBlock *data) {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRModel::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass) { void KRModel::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass) {
//fprintf(stderr, "Rendering model: %s\n", m_name.c_str()); //fprintf(stderr, "Rendering model: %s\n", m_name.c_str());
if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
if(m_materials.size() == 0) { if(m_materials.size() == 0) {
vector<KRModel::Submesh *> submeshes = getSubmeshes(); vector<KRModel::Submesh *> submeshes = getSubmeshes();
for(std::vector<KRModel::Submesh *>::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) { for(std::vector<KRModel::Submesh *>::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) {
const char *szMaterialName = (*itr)->szMaterialName; const char *szMaterialName = (*itr)->szMaterialName;
KRMaterial *pMaterial = pContext->getMaterialManager()->getMaterial(szMaterialName); KRMaterial *pMaterial = getContext().getMaterialManager()->getMaterial(szMaterialName);
m_materials.push_back(pMaterial); m_materials.push_back(pMaterial);
if(pMaterial) { if(pMaterial) {
m_uniqueMaterials.insert(pMaterial); m_uniqueMaterials.insert(pMaterial);
@@ -164,7 +164,7 @@ void KRModel::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v
if(pMaterial != NULL && pMaterial == (*mat_itr)) { if(pMaterial != NULL && pMaterial == (*mat_itr)) {
if((!pMaterial->isTransparent() && renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { if((!pMaterial->isTransparent() && renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {
if(pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, pContext, pLightMap, renderPass)) { if(pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, lights, viewport, matModel, pLightMap, renderPass)) {
switch(pMaterial->getAlphaMode()) { switch(pMaterial->getAlphaMode()) {
case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials

View File

@@ -69,7 +69,7 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass); void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass);
#endif #endif

View File

@@ -168,7 +168,8 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRNode::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass) { void KRNode::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, RenderPass renderPass)
{
} }
#endif #endif

View File

@@ -13,6 +13,7 @@
#import "KRVector3.h" #import "KRVector3.h"
#import "KRViewport.h" #import "KRViewport.h"
#import "tinyxml2.h" #import "tinyxml2.h"
#import <stack.h>
class KRCamera; class KRCamera;
class KRShaderManager; class KRShaderManager;
@@ -34,6 +35,8 @@ public:
RENDER_PASS_DEFERRED_OPAQUE, RENDER_PASS_DEFERRED_OPAQUE,
RENDER_PASS_FORWARD_TRANSPARENT, RENDER_PASS_FORWARD_TRANSPARENT,
RENDER_PASS_ADDITIVE_PARTICLES, RENDER_PASS_ADDITIVE_PARTICLES,
RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE,
RENDER_PASS_GENERATE_SHADOWMAPS,
RENDER_PASS_SHADOWMAP RENDER_PASS_SHADOWMAP
}; };
@@ -68,7 +71,7 @@ public:
KRScene &getScene(); KRScene &getScene();
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, RenderPass renderPass);
#endif #endif

View File

@@ -23,7 +23,7 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) = 0; virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) = 0;
#endif #endif
protected: protected:

View File

@@ -52,10 +52,10 @@ void KRParticleSystemBrownian::physicsUpdate(float deltaTime)
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRParticleSystemBrownian::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { void KRParticleSystemBrownian::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRNode::render(pCamera, lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling
@@ -69,11 +69,11 @@ void KRParticleSystemBrownian::render(KRCamera *pCamera, KRContext *pContext, co
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 2048); m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 2048);
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
int particle_count = 10000; int particle_count = 10000;
if(pParticleShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { if(pParticleShader->bind(viewport, getModelMatrix(), lights, renderPass)) {
GLDEBUG(glUniform1f( GLDEBUG(glUniform1f(
pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE],
1.0f 1.0f

View File

@@ -26,7 +26,7 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
#endif #endif

View File

@@ -43,9 +43,10 @@ KRAABB KRPointLight::getBounds() {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { void KRPointLight::render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{
KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRLight::render(pCamera, lights, viewport, renderPass);
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->bShowDeferred; bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->bShowDeferred;
@@ -68,8 +69,8 @@ void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewpo
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->getPerspectiveNearZ()) * (influence_radius + pCamera->getPerspectiveNearZ()); bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->getPerspectiveNearZ()) * (influence_radius + pCamera->getPerspectiveNearZ());
KRShader *pShader = pContext->getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(pShader->bind(viewport, pShadowViewports, sphereModelMatrix, lightDirection, shadowDepthTextures, 0, renderPass)) { if(pShader->bind(viewport, sphereModelMatrix, lights, renderPass)) {

View File

@@ -24,7 +24,7 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); virtual void render(KRCamera *pCamera, std::stack<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
#endif #endif
private: private:

View File

@@ -42,12 +42,9 @@
#import "KRStockGeometry.h" #import "KRStockGeometry.h"
KRScene::KRScene(KRContext &context, std::string name) : KRResource(context, name) { KRScene::KRScene(KRContext &context, std::string name) : KRResource(context, name) {
m_pContext = &context;
m_pFirstDirectionalLight = NULL; m_pFirstDirectionalLight = NULL;
m_pRootNode = new KRNode(*this, "scene_root"); m_pRootNode = new KRNode(*this, "scene_root");
sun_yaw = 4.333; // TODO - Remove temporary testing code
sun_pitch = 0.55;
m_skyBoxName = ""; m_skyBoxName = "";
} }
KRScene::~KRScene() { KRScene::~KRScene() {
@@ -57,52 +54,29 @@ KRScene::~KRScene() {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void KRScene::render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set<KRAABB> &newVisibleBounds) { void KRScene::render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, std::set<KRAABB> &newVisibleBounds) {
std::stack<KRLight *> lights;
updateOctree(); updateOctree();
pCamera->setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph pCamera->setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph
if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) {
if(cShadowBuffers > 0) { std::set<KRNode *> outerNodes = std::set<KRNode *>(m_nodeTree.getOuterSceneNodes()); // HACK - Copying the std::set as it is potentially modified as KRNode's update their bounds during the iteration. This is very expensive and will be eliminated in the future.
m_pContext->getTextureManager()->selectTexture(3, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE3)); // Get lights from outer nodes (directional lights, which have no bounds)
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[0])); for(std::set<KRNode *>::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); KRNode *node = (*itr);
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); KRLight *light = dynamic_cast<KRLight *>(node);
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); if(light) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); lights.push(light);
}
if(cShadowBuffers > 1) {
m_pContext->getTextureManager()->selectTexture(4, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE4));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[1]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
if(cShadowBuffers > 2) {
m_pContext->getTextureManager()->selectTexture(5, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE5));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[2]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
} }
} }
KRVector3 forward_render_light_direction = lightDirection; // Render outer nodes
KRDirectionalLight *directional_light = getFirstDirectionalLight(); for(std::set<KRNode *>::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) {
if(directional_light) { KRNode *node = (*itr);
forward_render_light_direction = directional_light->getWorldLightDirection(); node->render(pCamera, lights, viewport, renderPass);
KRVector3 sun_color = directional_light->getColor() * (directional_light->getIntensity() / 100.0f);
pCamera->dSunR = sun_color.x;
pCamera->dSunG = sun_color.y;
pCamera->dSunB = sun_color.z;
} }
std::vector<KROctreeNode *> remainingOctrees; std::vector<KROctreeNode *> remainingOctrees;
@@ -118,10 +92,10 @@ void KRScene::render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, K
newRemainingOctrees.clear(); newRemainingOctrees.clear();
newRemainingOctreesTestResults.clear(); newRemainingOctreesTestResults.clear();
for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctrees.begin(); octree_itr != remainingOctrees.end(); octree_itr++) { for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctrees.begin(); octree_itr != remainingOctrees.end(); octree_itr++) {
render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); render(*octree_itr, visibleBounds, pCamera, lights, viewport, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false);
} }
for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctreesTestResults.begin(); octree_itr != remainingOctreesTestResults.end(); octree_itr++) { for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctreesTestResults.begin(); octree_itr != remainingOctreesTestResults.end(); octree_itr++) {
render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); render(*octree_itr, visibleBounds, pCamera, lights, viewport, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false);
} }
remainingOctrees = newRemainingOctrees; remainingOctrees = newRemainingOctrees;
remainingOctreesTestResults = newRemainingOctreesTestResults; remainingOctreesTestResults = newRemainingOctreesTestResults;
@@ -130,16 +104,11 @@ void KRScene::render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, K
newRemainingOctrees.clear(); newRemainingOctrees.clear();
newRemainingOctreesTestResults.clear(); newRemainingOctreesTestResults.clear();
for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctreesTestResultsOnly.begin(); octree_itr != remainingOctreesTestResultsOnly.end(); octree_itr++) { for(std::vector<KROctreeNode *>::iterator octree_itr = remainingOctreesTestResultsOnly.begin(); octree_itr != remainingOctreesTestResultsOnly.end(); octree_itr++) {
render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true); render(*octree_itr, visibleBounds, pCamera, lights, viewport, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true);
}
std::set<KRNode *> outerNodes = std::set<KRNode *>(m_nodeTree.getOuterSceneNodes()); // HACK - Copying the std::set as it is potentially modified as KRNode's update their bounds during the iteration. This is very expensive and will be eliminated in the future.
for(std::set<KRNode *>::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) {
(*itr)->render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass);
} }
} }
void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector<KROctreeNode *> &remainingOctrees, std::vector<KROctreeNode *> &remainingOctreesTestResults, std::vector<KROctreeNode *> &remainingOctreesTestResultsOnly, std::set<KRAABB> &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleBounds, KRCamera *pCamera, std::stack<KRLight *> lights, const KRViewport &viewport, KRNode::RenderPass renderPass, std::vector<KROctreeNode *> &remainingOctrees, std::vector<KROctreeNode *> &remainingOctreesTestResults, std::vector<KROctreeNode *> &remainingOctreesTestResultsOnly, std::set<KRAABB> &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly)
{ {
if(pOctreeNode) { if(pOctreeNode) {
@@ -215,16 +184,16 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleB
if(bNeedOcclusionTest) { if(bNeedOcclusionTest) {
pOctreeNode->beginOcclusionQuery(); pOctreeNode->beginOcclusionQuery();
KRShader *pVisShader = m_pContext->getShaderManager()->getShader("occlusion_test", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRShader *pVisShader = getContext().getShaderManager()->getShader("occlusion_test", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, true, false, false, false, false); getContext().getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, true, false, false, false, false);
KRMat4 matModel = KRMat4(); KRMat4 matModel = KRMat4();
matModel.scale(octreeBounds.size() / 2.0f); matModel.scale(octreeBounds.size() / 2.0f);
matModel.translate(octreeBounds.center()); matModel.translate(octreeBounds.center());
KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix(); KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix();
// Enable additive blending // Enable additive blending
if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
} }
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
@@ -239,7 +208,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleB
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
} }
if(pVisShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { if(pVisShader->bind(viewport, matModel, std::stack<KRLight *>(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14));
} }
@@ -254,12 +223,12 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleB
pOctreeNode->endOcclusionQuery(); pOctreeNode->endOcclusionQuery();
if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
} else if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT) { } else if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT) {
GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
} else { } else {
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); // RENDER_PASS_FORWARD_TRANSPARENT and RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE
} }
@@ -274,15 +243,33 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleB
if(bVisible) { if(bVisible) {
// Add lights that influence this octree level and its children to the stack
int light_count = 0;
for(std::set<KRNode *>::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { for(std::set<KRNode *>::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) {
//assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check KRNode *node = (*itr);
(*itr)->render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); KRLight *light = dynamic_cast<KRLight *>(node);
if(light) {
lights.push(light);
light_count++;
}
} }
const int *childOctreeOrder = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES ? viewport.getBackToFrontOrder() : viewport.getFrontToBackOrder(); // Render objects that are at this octree level
for(std::set<KRNode *>::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) {
//assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check
(*itr)->render(pCamera, lights, viewport, renderPass);
}
// Render child octrees
const int *childOctreeOrder = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES || renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE ? viewport.getBackToFrontOrder() : viewport.getFrontToBackOrder();
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, lights, viewport, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false);
}
// Remove lights added at this octree level from the stack
while(light_count--) {
lights.pop();
} }
} }
} }

View File

@@ -62,14 +62,12 @@ public:
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
void render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set<KRAABB> &newVisibleBounds); void render(KRCamera *pCamera, const std::set<KRAABB> &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, std::set<KRAABB> &newVisibleBounds);
void render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector<KROctreeNode *> &remainingOctrees, std::vector<KROctreeNode *> &remainingOctreesTestResults, std::vector<KROctreeNode *> &remainingOctreesTestResultsOnly, std::set<KRAABB> &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); void render(KROctreeNode *pOctreeNode, const std::set<KRAABB> &visibleBounds, KRCamera *pCamera, std::stack<KRLight *> lights, const KRViewport &viewport, KRNode::RenderPass renderPass, std::vector<KROctreeNode *> &remainingOctrees, std::vector<KROctreeNode *> &remainingOctreesTestResults, std::vector<KROctreeNode *> &remainingOctreesTestResultsOnly, std::set<KRAABB> &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly);
#endif #endif
float sun_pitch, sun_yaw;
void notify_sceneGraphCreate(KRNode *pNode); void notify_sceneGraphCreate(KRNode *pNode);
void notify_sceneGraphDelete(KRNode *pNode); void notify_sceneGraphDelete(KRNode *pNode);
@@ -78,7 +76,6 @@ public:
void physicsUpdate(float deltaTime); void physicsUpdate(float deltaTime);
private: private:
KRContext *m_pContext;
KRDirectionalLight *findFirstDirectionalLight(KRNode &node); KRDirectionalLight *findFirstDirectionalLight(KRNode &node);
KRNode *m_pRootNode; KRNode *m_pRootNode;

View File

@@ -32,7 +32,8 @@
#include "KRShader.h" #include "KRShader.h"
#import "assert.h" #import "assert.h"
KRShader::KRShader(char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) { KRShader::KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) : KRContextObject(context)
{
strcpy(m_szKey, szKey); strcpy(m_szKey, szKey);
m_iProgram = 0; m_iProgram = 0;
GLuint vertexShader = 0, fragShader = 0; GLuint vertexShader = 0, fragShader = 0;
@@ -205,11 +206,48 @@ KRShader::~KRShader() {
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
bool KRShader::bind(const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass) { bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const std::stack<KRLight *> &lights, const KRNode::RenderPass &renderPass) {
if(m_iProgram == 0) { if(m_iProgram == 0) {
return false; return false;
} }
GLDEBUG(glUseProgram(m_iProgram));
// FINDME - HACK - Temporary placeholder code
KRViewport *pShadowViewports = NULL;
KRVector3 lightDirection = KRVector3::Normalize(KRVector3(0.90, 0.70, 0.25));
GLuint *shadowDepthTextures = NULL;
int cShadowBuffers = 0;
GLDEBUG(glUseProgram(m_iProgram));
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) {
m_pContext->getTextureManager()->selectTexture(3, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE3));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[0]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1) {
m_pContext->getTextureManager()->selectTexture(4, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE4));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[1]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2) {
m_pContext->getTextureManager()->selectTexture(5, NULL, 0);
GLDEBUG(glActiveTexture(GL_TEXTURE5));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[2]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1 || m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) { if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1 || m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) {
KRMat4 inverseModelMatrix = matModel; KRMat4 inverseModelMatrix = matModel;

View File

@@ -32,6 +32,7 @@
#import <stdint.h> #import <stdint.h>
#import <vector> #import <vector>
#import <string> #import <string>
#import <stack>
#import "KREngine-common.h" #import "KREngine-common.h"
@@ -47,16 +48,16 @@ using std::vector;
#import "KRNode.h" #import "KRNode.h"
#import "KRViewport.h" #import "KRViewport.h"
class KRShader { class KRShader : public KRContextObject {
public: public:
KRShader(char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource); KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource);
~KRShader(); virtual ~KRShader();
GLuint getProgram(); GLuint getProgram();
char *getKey(); char *getKey();
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
bool bind(const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass); bool bind(const KRViewport &viewport, const KRMat4 &matModel, const std::stack<KRLight *> &lights, const KRNode::RenderPass &renderPass);
#endif #endif

View File

@@ -45,8 +45,11 @@ KRShaderManager::~KRShaderManager() {
} }
KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCamera *pCamera, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, int iShadowQuality, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass) { KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCamera *pCamera, const std::stack<KRLight *> &lights, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass) {
int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader
char szKey[256]; char szKey[256];
sprintf(szKey, "%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", 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, 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); sprintf(szKey, "%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", 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, 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);
@@ -130,7 +133,7 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCam
stream << "\n"; stream << "\n";
std::string options = stream.str(); std::string options = stream.str();
pShader = new KRShader(szKey, options, m_vertShaderSource[shader_name], m_fragShaderSource[shader_name]); pShader = new KRShader(getContext(), szKey, options, m_vertShaderSource[shader_name], m_fragShaderSource[shader_name]);
m_shaders[szKey] = pShader; m_shaders[szKey] = pShader;
} }

View File

@@ -59,7 +59,7 @@ public:
const std::string &getVertShaderSource(const std::string &name); const std::string &getVertShaderSource(const std::string &name);
KRShader *getShader(const std::string &shader_name, const KRCamera *pCamera, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, int iShadowQuality, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass); KRShader *getShader(const std::string &shader_name, const KRCamera *pCamera, const std::stack<KRLight *> &lights, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass);
long getShaderHandlesUsed(); long getShaderHandlesUsed();

View File

@@ -11,6 +11,7 @@
#include "KRVector2.h" #include "KRVector2.h"
#include "KRMat4.h" #include "KRMat4.h"
#include "KRViewport.h" #include "KRViewport.h"
#include "KRLight.h"
KRViewport::KRViewport() KRViewport::KRViewport()
@@ -163,3 +164,4 @@ void KRViewport::setVisibleBounds(const std::set<KRAABB> visibleBounds)
m_visibleBounds = visibleBounds; m_visibleBounds = visibleBounds;
} }

View File

@@ -13,6 +13,8 @@
#include "KRMat4.h" #include "KRMat4.h"
#include "KRAABB.h" #include "KRAABB.h"
class KRLight;
class KRViewport { class KRViewport {
public: public:
KRViewport(); KRViewport();
@@ -39,6 +41,9 @@ public:
const std::set<KRAABB> &getVisibleBounds(); const std::set<KRAABB> &getVisibleBounds();
void setVisibleBounds(const std::set<KRAABB> visibleBounds); void setVisibleBounds(const std::set<KRAABB> visibleBounds);
const std::set<KRLight *> &getVisibleLights();
void setVisibleLights(const std::set<KRLight *> visibleLights);
private: private:
KRVector2 m_size; KRVector2 m_size;
KRMat4 m_matView; KRMat4 m_matView;