• Content count

  • Joined

  • Last visited

Community Reputation

171 Neutral

About gcard28

  • Rank
  1. Well as expected, it was a small error on my part that prevented this from working. Once I followed the advice of breaking everything down piece by piece I was able to discover what I did wrong.   Thanks again for everyone's help, I now have stable cascaded shadow maps working!
  2. One thing I have noticed in the shader is that when I multiply by the combined light view and orthographic projection matrix for a specific frustum, the generated point is NOT in the range -1.0f to 1.0f in both the x and y.   This seems to be the problem. Isn't the projection matrix supposed to get the coordinates in these ranges?   Has anyone else encountered this? Also if you do not think this is an issue won't it be an issue when the shadow map is sampled using these coordinates?   Thanks again for anyone's help
  3. I am working on figuring this out...... Right now I get a blank white screen..... So it won't be very helpful for me to post this..... :)
  4. I've been working furiously and so far stable cascaded shadow maps are mocking me..... I can't seem to get this working for the life of me.....   So I will run through my algorithm and perhaps some kind soul will take pity on me and show me the error of my ways......   [1] I calculate the split frustum values for FOUR cascades.        I use this equation: // get the currently active camera ICamera *pcCamera = getCurrentCamera (); vsAssert (pcCamera != NULL); if (m_fSplitNearZ < pcCamera->getNearZ ()) { m_fSplitNearZ = pcCamera->getNearZ (); } NUM_CASCADE_SPLITS = 4; for (vsInt32 iSplit = 1; iSplit < NUM_CASCADE_SPLITS; iSplit++) { vsFloat32 fStep = iSplit / (vsFloat32) NUM_CASCADE_SPLITS; vsFloat32 fLogSplit = m_fSplitNearZ * powf (m_fSplitFarZ / m_fSplitNearZ, fStep); vsFloat32 fLinearSplit = m_fSplitNearZ + (m_fSplitFarZ - m_fSplitNearZ) * fStep; // linearly interpolate between the linear and logarithmic split values m_fSplitPositions [iSplit] = fLogSplit * m_fLogSplitWeight + fLinearSplit * (1.0f - m_fLogSplitWeight); } // ensure the border split values are accurate m_fSplitPositions [0] = m_fSplitNearZ; m_fSplitPositions [NUM_CASCADE_SPLITS] = m_fSplitFarZ; So now I have my frustum splits.....   I use these splits to calculate the corners of the cascade frustum that is being considered. So if I am going to update the first cascade shadow map I use the first and second frustum split positions. ie. m_fSplitPositions [0] and m_fSplitPositions [1].   So now I have 8 view space corners for the split frustum in view space. I generate the bounding box of these points and get the center. Again this is in View space. I take the max AABB point, subtract from the centroid I calculated and get it's length. This is what I use as the radius of the sphere that encloses this split frustum.   I then multiply the View Space frustum center by the inverse view to get the center in world space. I do the above for all FOUR cascade frustums when I am done I have FOUR spheres in TOTAL. One for each split sub frustum. Since I have 4 cascades I have 4 spheres. CalculateCascadeBoundingSphere (void) { // find the minimum enclosing sphere for the split frustum, this is done in // local space to avoid precision variation between frames ICamera *pcCurrentCamera = getCurrentCamera (); vsAssert (pcCurrentCamera != NULL); vsFloat32 fTanHalfFOVY = pcCurrentCamera->getTanHalfFOVY (); vsFloat32 fTanHalfFOVX = fTanHalfFOVY * pcCurrentCamera->getAspectRatio (); vsFloat32 fNearX = fTanHalfFOVX * m_fCurrentNearSplit; vsFloat32 fNearY = fTanHalfFOVY * m_fCurrentNearSplit; vsFloat32 fNearZ = m_fCurrentNearSplit; vsFloat32 fFarX = fTanHalfFOVX * m_fCurrentFarSplit; vsFloat32 fFarY = fTanHalfFOVY * m_fCurrentFarSplit; vsFloat32 fFarZ = m_fCurrentFarSplit; // calculate the frustum AABB in view space CAABB cFrustumAABB; cFrustumAABB.m_cMin.setVector (FLT_MAX, FLT_MAX, FLT_MAX); cFrustumAABB.m_cMax.setVector (-FLT_MAX, -FLT_MAX, -FLT_MAX); cFrustumAABB.Add (CVector3 (fNearX, fNearY, fNearZ)); cFrustumAABB.Add (CVector3 (fNearX, -fNearY, fNearZ)); cFrustumAABB.Add (CVector3 (-fNearX, -fNearY, fNearZ)); cFrustumAABB.Add (CVector3 (-fNearX, fNearY, fNearZ)); cFrustumAABB.Add (CVector3 (fFarX, fFarY, fFarZ)); cFrustumAABB.Add (CVector3 (fFarX, -fFarY, fFarZ)); cFrustumAABB.Add (CVector3 (-fFarX, -fFarY, fFarZ)); cFrustumAABB.Add (CVector3 (-fFarX, fFarY, fFarZ)); CVector3 cCenter, cRadius; cCenter.Add (cFrustumAABB.m_cMin, cFrustumAABB.m_cMax); cCenter.MulScalar (0.5f); cRadius.Sub (cFrustumAABB.m_cMax, cCenter); vsFloat32 fRadius = cRadius.getLength (); } These spheres I use to generate FOUR light view and FOUR light view projection matrices. I do that as follows:   Remember I do this FOUR times, so at the end I have FOUR light view matrices and FOUR light projection matrices: CalculateCascadeViewMatrix (vsUInt32 iCascade) { vsAssert (m_pcDirectionalLightEditorObject != NULL); // calculate the cascade view matrix const CVector3 &rcLightDirection = m_pcDirectionalLightEditorObject->getDirection (); CVector3 cEye, cTarget; // target is center of view split frustum in world space cTarget.setVector (m_cCurrentCascadeBoundingSphere [iCascade].m_cCenter); // scale the light direction based on the shadow range CVector3 cScaledLightDirection (rcLightDirection); cScaledLightDirection.MulScalar (m_fShadowRange); // eye = target - (light_direction * shadow_range) cEye.Sub (cTarget, cScaledLightDirection); // generate the light view look at matrix LookAt (m_cViewMatrix [m_iCascade], cEye, cTarget); } LookAt (CMatrix4 &rcViewMatrix, const CVector3 &rcEye, const CVector3 &rcTarget) { CVector3 cZAxis; // we look down -z axis this is why vector is reversed cZAxis.Sub (rcEye, rcTarget); cZAxis.Normalize (); CVector3 cYAxis (CVector3::Y_AXIS); // check it's not coincident with direction if (CMath::FAbs (cYAxis.DotProduct (cZAxis)) >= 1.0f) { // use camera up cYAxis.setVector (CVector3::Z_AXIS); } // cross twice to rederive, only direction is unaltered CVector3 cXAxis; cXAxis.CrossProduct (cYAxis, cZAxis); cXAxis.Normalize (); cYAxis.CrossProduct (cZAxis, cXAxis); cYAxis.Normalize (); // setup the light view matrix (this places objects in light view space) rcViewMatrix.m [m00] = cXAxis.x; rcViewMatrix.m [m01] = cXAxis.y; rcViewMatrix.m [m02] = cXAxis.z; rcViewMatrix.m [m03] = -cXAxis.DotProduct (rcEye); rcViewMatrix.m [m10] = cYAxis.x; rcViewMatrix.m [m11] = cYAxis.y; rcViewMatrix.m [m12] = cYAxis.z; rcViewMatrix.m [m13] = -cYAxis.DotProduct (rcEye); rcViewMatrix.m [m20] = cZAxis.x; rcViewMatrix.m [m21] = cZAxis.y; rcViewMatrix.m [m22] = cZAxis.z; rcViewMatrix.m [m23] = -cZAxis.DotProduct (rcEye); rcViewMatrix.m [m30] = 0.0f; rcViewMatrix.m [m31] = 0.0f; rcViewMatrix.m [m32] = 0.0f; rcViewMatrix.m [m33] = 1.0f; } Ok now I generate FOUR orthographic projection matrices, using the radius values of the four frustum split bounding spheres I generated up above: CalculateCascadeProjectionMatrix (vsUInt32 iCascade) { vsFloat32 fWidth = m_cCascadeBoundingSphere [iCascade].m_fRadius * 2.0f; vsFloat32 fHeight = m_cCascadeBoundingSphere [iCascade].m_fRadius * 2.0f; // calculate the cascade orthographic projection matrix m_cProjectionMatrix [iCascade].m [m00] = 2.0f / fWidth; m_cProjectionMatrix [iCascade].m [m11] = 2.0f / fHeight; m_cProjectionMatrix [iCascade].m [m22] = -2.0f / (m_fProjectionFarZ - m_fProjectionNearZ); m_cProjectionMatrix [iCascade].m [m23] = -(m_fProjectionFarZ + m_fProjectionNearZ) / (m_fProjectionFarZ - m_fProjectionNearZ); m_cProjectionMatrix [iCascade].m [m33] = 1.0f; // engine specific projection matrix with render system depth range m_pcRenderSystem->ConvertProjectionMatrix (m_cProjectionMatrix [iCascade], m_cProjectionRSDepthMatrix [iCascade], true); } I also generate a rounding matrix to prevent the shadow map cascades from shimmering as the camera translates: CalculateCascadeRoundMatrix (vsUInt32 iCascade) { CVector3 cOriginShadow; CVector3 cOrigin (0.0f, 0.0f, 0.0f); // transform origin to light view projection space m_cLightViewProjectionMatrix [iCascade].Transform (cOriginShadow, cOrigin); vsFloat32 fShadowMapSize = getShadowMapSize (); // convert clip space to texture coordinates vsFloat32 fTexCoordX = cOriginShadow.x * fShadowMapSize * 0.5f; vsFloat32 fTexCoordY = cOriginShadow.y * fShadowMapSize * 0.5f; // round to the nearest whole texel vsFloat32 fTexCoordRoundedX = CMath::Round (fTexCoordX); vsFloat32 fTexCoordRoundedY = CMath::Round (fTexCoordY); /* the difference between the rounded and actual tex coordinate is the amount by which we need to translate the shadow matrix in order to cancel sub-texel movement */ vsFloat32 fDX = fTexCoordRoundedX - fTexCoordX; vsFloat32 fDY = fTexCoordRoundedY - fTexCoordY; // transform fDX, fDY back to homogenous light space fDX /= fShadowMapSize * 0.5f; fDY /= fShadowMapSize * 0.5f; // set the rounding matrix m_cRoundMatrix [iCascade].m [m03] = fDX; m_cRoundMatrix [iCascade].m [m13] = fDY; m_cRoundMatrix [iCascade].m [m23] = 0.0f; m_cRoundMatrix [iCascade].m [m33] = 1.0f; } So now I have CMatrix4x4 m_cLightViewMatrix [4],  CMatrix4x4 m_cLightProjectionMatrix [4] and m_cRoundMatrix [4];   I loop like so and generate the shadow matrix:   for (iCascade = 0; iCascade < 4; iCascade++) {        m_cShadowMatrix [iCascade] = m_cRoundMatrix [iCascade] * m_cLightProjectionMatrix [iCascade] * m_cLightViewMatrix [iCascade]; }   I use m_cShadowMatrix [4] to generate the shadow maps in my shadow atlas..... So In the shader I generate the vertices of the shadow caster into word space and then multiply like so:            m_cShadowMatrix * m_cWorldMatrix * vsInput.vPosition;   In the pixel shader I save out the z value.   Is my algortihm sound? Or perhaps I missed something in my understanding of the algorithm. I would appreciate any help anyone can give me as to where I could be going wrong. Also if anyone knows of any demos with source that I could run to test this algorithm I would be ever so greatful.   Many thanks to anyone who can help me!
  5. Ok so I have my engine up and running and I am able to blend in and blend out animations. However I cannot seem to get around the idea of how to get pain animations working with the current state of the engine. Currently the AI goes through some scripted behavior threads. Where the character periodically reloads his gun and then fires, then ducks and fires, stands up and fires, reloads etc. etc. Now my question is if the said character gets hit by a players bullet I want him to respond by playing a pain animation, but then still have him do whatever it was that he was doing in his scripted AI thread, ie. reloading, firing after the pain animation is done. Is there some way I could have this work automatically? Perhaps I should fade in a pain animation and when the pain animation is done playing, I gradually fade it out. This way whatever animations are still playing in the character will continue after the pain animation is done. Thanks for anyone's thoughts and opinions.
  6. Hi, I am having a devil of a time figuring out when a moving AABB collides with a triangle. I can't seem to figure this out. I think that this would be an extension of my ray triangle code but alas the way to relate a moving AABB to ray collision escapes me. Is there a kind soul that could point me in the right direction? either through relevant links (I was unable to find any) or pseudo code as to how one might go about this? Many thanks in advance to anyone who can help me. Thanks!
  7. Detecting Vsync...

    The reason is that a light gun is hooked to the monitor via a USB. And the device can only work and return valid data when vsync is active. So the screen needs to be flashed on a vsync
  8. Hello, I need to be able to detect when the card is in vertical sync. I am working under windows and using DirectX. I know that you can set that the swap effect is locked to vertical sync. But I need to actually detect when vertical sync actually happens. The reason for this is that I am developing an arcade game and I need to flash the screen white when a gun trigger is pressed. This needs to happen on a vertical sync. Thanks for anyones help.
  9. Hello I have a question in regards to projectiles. In several games you are able to fire a projectile and have it hit an enemy and stick to the enemy at the point of impact. Then as the enemy plays it's death animation the spike or projectile follows the animation at the location where it hit the mesh. Does anyone know how this is done? Or could point me to any information that might be helpful? Many thanks in advance for any help you anyone can give me. Thanks
  10. I have created a portal engine where artists place portals and sectors in Maya and then a plugin exports the level for use in my engine. Here is a problem I have encountered. When an artist places 2 sectors together, there is a very very slight overlap. However this will wreak havok in m engine when it comes time to determine what sector the player starts in. I fear that in some instances based on the player's position he can be in more than one sector because of this overlap. Does anyone have a good way of dealing with small overlap problems in sectors? I am having problems when it comes time to draw the scene and determining what sector the player is in as there is a chance for an ambiguity I think. Many thanks in advance.
  11. Hello, for my game I wish to model some canned ragdoll physics animations and then bake them out and then play them in my engine. Currently we are using Maya and this is not possible as ragdoll is not supported. We are thinking of using 3D studio max for this. Is it possible to use reactor to animate a mesh in max, and then export the skeleton frame by frame for the ragdoll animation for playback in our engine? Many thanks for anyone who can reply!
  12. ASM vs HLSL Shaders

    No problem, if you do take a performance hit it is more to do with your algorithm and or the way you are programming the shader in your code. I always check the generated assembler source to make sure the HLSL shader is doing what it should.
  13. ASM vs HLSL Shaders

    Well I have used both ASM and HLSL shaders and to be honest I can't see any performance difference. I use HLSL exclusively because it is so easy to develop for. Also you can have the shader compiler generate the assembly source of the HLSL shader for comparison with your own assembler routines.
  14. Hi yes, Thank you for everyones help. I wasn't aware you could resize the viewport to anything other than the full dimensions of the render target. I know there are better ways of doing shadows than projected textures, but this is the method I started with and it is not possible for me to start from scratch for shadows. But thanks for the suggestion of setting the viewport. Many thanks to everyone
  15. I have projected shadows running in my engine.... but they are dog slow..... Here is what I do, each item that is shadowed has it's own render target texture, so I switch from one render target to the next to draw the shadows for each character that is visible. This is KILLING and I mean KILLING my framerate. I was thinking that well have one render target texture that all the shadowed entities render to. Each entity renders to a section of this large render target. Now here comes my question. I am using DirectX9 and I have absolutely no idea how to do this. Is it even possible? Say I have a 512x512 texture and each shadowed entry uses 128x128 textures. That means I can have 16 entities stored in this one render texture.... The thing is how do I render into a subsection of this large texture? I would GREATLY appreciate any help anyone can give me. Perhaps some simple sample code or pointers to information or even if it is even possible. Many thanks to anyone kind enough to give some assistance