From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- KaplaDemo/samples/sampleViewer3/ShadowMap.cpp | 383 ++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 KaplaDemo/samples/sampleViewer3/ShadowMap.cpp (limited to 'KaplaDemo/samples/sampleViewer3/ShadowMap.cpp') diff --git a/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp b/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp new file mode 100644 index 00000000..cf9caea3 --- /dev/null +++ b/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp @@ -0,0 +1,383 @@ +//---------------------------------------------------------------------------------- +// File: ShadowMapping.cpp +// Original Author: Rouslan Dimitrov +// Modified by: Nuttapong Chentanez and Matthias Müller-Fischer +// Email: sdkfeedback@nvidia.com +// +// Copyright (c) 2007 NVIDIA Corporation. All rights reserved. +// +// TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED +// *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS +// OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS +// BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES +// WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, +// BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) +// ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS +// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +// +//---------------------------------------------------------------------------------- + +#include "ShadowMap.h" +#include + +//---------------------------------------------------------------------------------- +struct ShadowMap::Vec4 { + Vec4() {} + Vec4(const PxVec3 &v, float vw = 1.0f) { x = v.x; y = v.y; z = v.z; w = vw; } + float x,y,z,w; +}; + +//---------------------------------------------------------------------------------- +struct ShadowMap::Matrix44 { + Vec4 operator*(const Vec4& v) const { + Vec4 res; + res.x = elems[0] * v.x + elems[4] * v.y + elems[8] * v.z + elems[12] * v.w; + res.y = elems[1] * v.x + elems[5] * v.y + elems[9] * v.z + elems[13] * v.w; + res.z = elems[2] * v.x + elems[6] * v.y + elems[10] * v.z + elems[14] * v.w; + res.w = elems[3] * v.x + elems[7] * v.y + elems[11] * v.z + elems[15] * v.w; + return res; + } + float &element(int i, int j) { return elems[i + 4*j]; } + void zero() { for (int i = 0; i < 16; i++) elems[i] = 0.0f; } + void id() { zero(); elems[0] = 1.0f; elems[5] = 1.0f; elems[10] = 1.0f; elems[15] = 1.0f; } + + float elems[16]; +}; + +//---------------------------------------------------------------------------------- +ShadowMap::ShadowMap( int w, int h, float fovi, int matOffseti, int resolution) +{ + shadowOff = 1.0f; + shadowOff2 = 2048.0f; + fov = fovi; + cur_num_splits = 1; + //cur_num_splits = 3; + + width = w; + height = h; + depth_size = resolution; + split_weight = 0.75; + matOffset = matOffseti; + + minZAdd = 0; + maxZAdd = 30.0f; + + init(); +} + +//---------------------------------------------------------------------------------- +void ShadowMap::updateFrustumPoints(Frustum &f, const PxVec3 ¢er, const PxVec3 &view_dir) +{ + PxVec3 up(0.0, 1.0, 0.0); + PxVec3 right = view_dir.cross(up); + + PxVec3 fc = center + view_dir*f.fard; + PxVec3 nc = center + view_dir*f.neard; + + right.normalize(); + up = right.cross(view_dir); + up.normalize(); + + // these heights and widths are half the heights and widths of + // the near and far plane rectangles + float near_height = tanf(f.fov/2.0f) * f.neard; + float near_width = near_height * f.ratio; + float far_height = tanf(f.fov/2.0f) * f.fard; + float far_width = far_height * f.ratio; + + f.point[0] = nc - up*near_height - right*near_width; + f.point[1] = nc + up*near_height - right*near_width; + f.point[2] = nc + up*near_height + right*near_width; + f.point[3] = nc - up*near_height + right*near_width; + + f.point[4] = fc - up*far_height - right*far_width; + f.point[5] = fc + up*far_height - right*far_width; + f.point[6] = fc + up*far_height + right*far_width; + f.point[7] = fc - up*far_height + right*far_width; +} + +//---------------------------------------------------------------------------------- +// updateSplitDist computes the near and far distances for every frustum slice +// in camera eye space - that is, at what distance does a slice start and end +void ShadowMap::updateSplitDist(Frustum f[MAX_SPLITS], float nd, float fd) +{ + float lambda = split_weight; + float ratio = fd/nd; + f[0].neard = nd; + + for(int i=1; i maxZ) maxZ = transf.z; + if(transf.z < minZ) minZ = transf.z; + } + + minZ += minZAdd; + maxZ += maxZAdd; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + // set the projection matrix with the new z-bounds + // note the inversion because the light looks at the neg. z axis + // gluPerspective(LIGHT_FOV, 1.0, maxZ, minZ); // for point lights + glOrtho(-1.0, 1.0, -1.0, 1.0, -maxZ, -minZ); + glGetFloatv(GL_PROJECTION_MATRIX, shad_proj); + glPushMatrix(); + glMultMatrixf(nv_mvp.elems); + glGetFloatv(GL_PROJECTION_MATRIX, nv_mvp.elems); + glPopMatrix(); + + // find the extends of the frustum slice as projected in light's homogeneous coordinates + for(int i=0; i<8; i++) + { + transf = nv_mvp * Vec4(f.point[i]); + + transf.x /= transf.w; + transf.y /= transf.w; + + if(transf.x > maxX) maxX = transf.x; + if(transf.x < minX) minX = transf.x; + if(transf.y > maxY) maxY = transf.y; + if(transf.y < minY) minY = transf.y; + } + + float scaleX = 2.0f/(maxX - minX); + float scaleY = 2.0f/(maxY - minY); + float offsetX = -0.5f*(maxX + minX)*scaleX; + float offsetY = -0.5f*(maxY + minY)*scaleY; + + // apply a crop matrix to modify the projection matrix we got from glOrtho. + nv_mvp.id(); + nv_mvp.element(0,0) = scaleX; + nv_mvp.element(1,1) = scaleY; + nv_mvp.element(0,3) = offsetX; + nv_mvp.element(1,3) = offsetY; + glLoadMatrixf(nv_mvp.elems); + glMultMatrixf(shad_proj); + + glMatrixMode(GL_MODELVIEW); + + return minZ; +} + +//---------------------------------------------------------------------------------- +// here all shadow map textures and their corresponding matrices are created +void ShadowMap::makeShadowMap(const PxVec3 &cameraPos, const PxVec3 &cameraDir, const PxVec3 &lightDir, float znear, float zfar, + void (*renderShadowCasters)()) +{ + float shad_modelview[16]; + glDisable(GL_TEXTURE_2D); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + gluLookAt( + cameraPos.x, cameraPos.y, cameraPos.z, + cameraPos.x-lightDir.x, cameraPos.y-lightDir.y, cameraPos.z-lightDir.z, + -1.0, 0.0, 0.0); + + glGetFloatv(GL_MODELVIEW_MATRIX, shad_modelview); + + // redirect rendering to the depth texture + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fb); + // store the screen viewport + glPushAttrib(GL_VIEWPORT_BIT); + // and render only to the shadowmap + glViewport(0, 0, depth_size, depth_size); + // offset the geometry slightly to prevent z-fighting + // note that this introduces some light-leakage artifacts + glPolygonOffset(shadowOff, shadowOff2); +// cout<<"shadowOff = "<