Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: 1 2 3 [4] 5
  Print  
Author Topic: Parallel Split Shadow Mapping  (Read 7889 times)
Mietze
Community Member
*
Posts: 235


« Reply #60 on: July 20, 2008, 05:19:36 AM »


CFrustum:
Code:
using System;
using System.Collections.Generic;
using System.Text;
using MTV3D65;

namespace eStudioz
{
    public class CFrustum
    {
        public TV_3DVECTOR[] m_vaPoints;
        public TVCamera m_pCamera;
        public CBoundingBox m_pBoundingBox;

        /// <summary>
        /// Initializes a new instance of the <see cref="CFrustum"/> class.
        /// </summary>
        /// <param name="pCamera">The p camera.</param>
        public CFrustum(TVCamera pCamera)
        {
            m_vaPoints = new TV_3DVECTOR[8];

            SetCamera(pCamera);
        }

        /// <summary>
        /// Sets the camera.
        /// </summary>
        /// <param name="pCamera">The p camera.</param>
        public void SetCamera(TVCamera pCamera)
        {
            TV_3DMATRIX mInvertedCameraProjectionMatrix = new TV_3DMATRIX();

            m_vaPoints[0] = new TV_3DVECTOR(-1, -1, 0);
            m_vaPoints[1] = new TV_3DVECTOR(1, -1, 0);
            m_vaPoints[2] = new TV_3DVECTOR(-1, 1, 0);
            m_vaPoints[3] = new TV_3DVECTOR(1, 1, 0);
            m_vaPoints[4] = new TV_3DVECTOR(-1, -1, 1);
            m_vaPoints[5] = new TV_3DVECTOR(1, -1, 1);
            m_vaPoints[6] = new TV_3DVECTOR(-1, 1, 1);
            m_vaPoints[7] = new TV_3DVECTOR(1, 1, 1);

            float fNull = 0.0f;

            m_pCamera = pCamera;

            TrueVision3D.MathLibrary.TVMatrixInverse(ref mInvertedCameraProjectionMatrix, ref fNull, m_pCamera.GetProjectionMatrix());

            for (int i = 0; i < 8; i++)
            {
                TrueVision3D.MathLibrary.TVVec3TransformCoord(ref m_vaPoints[i], m_vaPoints[i], mInvertedCameraProjectionMatrix);
                TrueVision3D.MathLibrary.TVVec3TransformCoord(ref m_vaPoints[i], m_vaPoints[i], m_pCamera.GetMatrix());
            }

            m_pBoundingBox = new CBoundingBox(m_vaPoints, 8);
        }

        /// <summary>
        /// Draws the specified n color.
        /// </summary>
        /// <param name="nColor">Color of the n.</param>
        public void Draw(int nColor)
        {
            // Near-/Farplane
            for (int i = 0; i < 2; i++)
            {
                TrueVision3D.Screen2DImmediate.Draw_Line3D(
                    m_vaPoints[0].x,
                    m_vaPoints[0].y,
                    m_vaPoints[0].z,
                    m_vaPoints[i + 1].x,
                    m_vaPoints[i + 1].y,
                    m_vaPoints[i + 1].z,
                    nColor);

                TrueVision3D.Screen2DImmediate.Draw_Line3D(
                    m_vaPoints[3].x,
                    m_vaPoints[3].y,
                    m_vaPoints[3].z,
                    m_vaPoints[i + 1].x,
                    m_vaPoints[i + 1].y,
                    m_vaPoints[i + 1].z,
                    nColor);

                TrueVision3D.Screen2DImmediate.Draw_Line3D(
                    m_vaPoints[4].x,
                    m_vaPoints[4].y,
                    m_vaPoints[4].z,
                    m_vaPoints[i + 5].x,
                    m_vaPoints[i + 5].y,
                    m_vaPoints[i + 5].z,
                    nColor);

                TrueVision3D.Screen2DImmediate.Draw_Line3D(
                    m_vaPoints[7].x,
                    m_vaPoints[7].y,
                    m_vaPoints[7].z,
                    m_vaPoints[i + 5].x,
                    m_vaPoints[i + 5].y,
                    m_vaPoints[i + 5].z,
                    nColor);
            }

            // Nearplane -> Farplane connections
            for (int i = 0; i < 4; i++)
                TrueVision3D.Screen2DImmediate.Draw_Line3D(
                    m_vaPoints[i].x,
                    m_vaPoints[i].y,
                    m_vaPoints[i].z,
                    m_vaPoints[i + 4].x,
                    m_vaPoints[i + 4].y,
                    m_vaPoints[i + 4].z,
                    nColor);
        }

        /// <summary>
        /// Draws the bounding box.
        /// </summary>
        /// <param name="nColor">Color of the n.</param>
        public void DrawBoundingBox(int nColor)
        {
            m_pBoundingBox.Draw(nColor);
        }
    }
}
Logged
Mietze
Community Member
*
Posts: 235


« Reply #61 on: July 20, 2008, 05:20:29 AM »

MathHelpers: (Its faster to do that on the "managed" side of your code)
Code:
using System;
using System.Collections.Generic;
using System.Text;
using MTV3D65;


namespace eStudioz
{
    public class MathHelpers
    {
        private static float fPIdiv180 = (float)Math.PI / 180.0f;

#region General Stuff
        /// <summary>
        ///
        /// </summary>
        /// <param name="fDegree"></param>
        /// <returns></returns>
        public static float DegreeToRadian(float fDegree)
        {
            return fPIdiv180 * fDegree;
        }

        /// <summary>
        /// Slide off the impacting surface - Aus Quake3 Source Code :)
        /// </summary>
        /// <param name="vVelocity"></param>
        /// <param name="vNormal"></param>
        /// <param name="fOverbounce"></param>
        public static void ClipVelocity(TV_3DVECTOR vNormal, ref TV_3DVECTOR vVelocity)
        {
            float fBackoff = MathHelpers.Vec3DotProduct(vVelocity, vNormal);
            vVelocity = vVelocity - vNormal * (fBackoff * 1.001f);
        }

        /// <summary>
        /// Quake2-Style Acceleration
        /// </summary>
        /// <param name="vWishDirection">Die Richtung, in die gelaufen werden soll</param>
        /// <param name="fAcceleration">Die Beschleunigung für diesen Frame</param>
        public static void AddAcceleration(TV_3DVECTOR vWishVelocity, ref TV_3DVECTOR vVelocity)
        {
            float fWishSpeed = MathHelpers.Vec3Length(vWishVelocity);

            // Y-Achse nicht mit einbeziehen, da sonst der Sprung mit beeinflusst wird.
            // Dies hätte zur Folge, dass man beim Beschleunigen nicht mehr so hoch springen könnte
            TV_3DVECTOR vCurrentVelocity = new TV_3DVECTOR(vVelocity.x, 0.0f, vVelocity.z);
            TV_3DVECTOR vPushDirection = MathHelpers.Vec3Normalize(vWishVelocity - vCurrentVelocity);
            float fPushLength = MathHelpers.Vec3Length(vPushDirection);

            if (fPushLength > 0.0f)
            {
                if (fWishSpeed > fPushLength)
                    fWishSpeed = fPushLength;

                vVelocity = MathHelpers.Vec3MultiplyAdd(vVelocity, vPushDirection, fWishSpeed);
            }
        }

        /// <summary>
        /// Returns the cotangent of the given value.
        /// </summary>
        /// <param name="x">The argument.</param>
        /// <returns>The cotangent.</returns>
        public static float Cot(float x)
        {
            return 1.0f / (float)Math.Tan(x);
        }
       
        /// <summary>
        /// "Normalisiert" einen Winkel zu [0, 359]
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public static float AngleNormalize360(float x)
        {
            if (x < 0.0f)
                x = (360.0f - x * -1.0f) % 360.0f;
            else
                x = x % 360.0f;

            return x;
        }
       
        /// <summary>
        /// Clamp'ed einen Wert zwischen Min und Max
        /// </summary>
        /// <param name="x"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns>true if clamped</returns>
        public static bool Clamp(ref float x, float min, float max)
        {
            if (x < min)
            {
                x = min;
                return true;
            }
            else if (x > max)
            {
                x = max;
                return true;
            }

            return false;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="x"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static bool Clamp(ref int x, int min, int max)
        {
            if (x < min)
            {
                x = min;
                return true;
            }
            else if (x > max)
            {
                x = max;
                return true;
            }

            return false;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static float Distance1D(float a, float b)
        {
            return (a > b) ? a - b : b - a;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static float Distance2D(TV_3DVECTOR a, TV_3DVECTOR b)
        {
            return (float)Math.Sqrt(Math.Pow(a.x - b.x, 2) + Math.Pow(a.z - b.z, 2));
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="x"></param>
        /// <param name="fDamping"></param>
        public static void DampToZero(ref float x, float fDamping)
        {
            if (x != 0.0f)
            {
                if (x > 0.0f)
                {
                    x -= fDamping;

                    if (x < 0.0f)
                        x = 0.0f;
                }
                else
                {
                    x += fDamping;

                    if (x > 0.0f)
                        x = 0.0f;
                }
            }
        }
#endregion

#region Vector Stuff
        /// <summary>
        /// Transformiert einen Vektor anhand einer Matrix
        /// </summary>
        /// <param name="m">Matrix</param>
        /// <param name="v">Vektor</param>
        /// <returns>Transformierter Vektor</returns>
        public static TV_3DVECTOR Vec3TransformCoord(TV_3DMATRIX m, TV_3DVECTOR v)
        {
            TV_3DVECTOR vNewVector = new TV_3DVECTOR();

            vNewVector.x = m.m11 * v.x + m.m21 * v.y + m.m31 * v.z + m.m41;
            vNewVector.y = m.m12 * v.x + m.m22 * v.y + m.m32 * v.z + m.m42;
            vNewVector.z = m.m13 * v.x + m.m23 * v.y + m.m33 * v.z + m.m43;

            return vNewVector;
        }

        /// <summary>
        /// Gibt das Kreuzprodukt zweier Vektoren zurück
        /// </summary>
        /// <param name="v1">Vektor 1</param>
        /// <param name="v2">Vektor 2</param>
        /// <returns>Kreuzprodukt</returns>
        public static TV_3DVECTOR Vec3CrossProduct(TV_3DVECTOR v1, TV_3DVECTOR v2)
        {
            TV_3DVECTOR vNewVector = new TV_3DVECTOR();

            vNewVector.x = v1.y * v2.z - v1.z * v2.y;
            vNewVector.y = v1.z * v2.x - v1.x * v2.z;
            vNewVector.z = v1.x * v2.y - v1.y * v2.x;

            return vNewVector;
        }

        /// <summary>
        /// Gibt das Punktprodukt zweier Vektoren zurück
        /// </summary>
        /// <param name="v1">Vektor 1</param>
        /// <param name="v2">Vektor 2</param>
        /// <returns>Punktprodukt</returns>
        public static float Vec3DotProduct(TV_3DVECTOR v1, TV_3DVECTOR v2)
        {
            return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
        }

        /// <summary>
        /// Gibt die Länge eines Vektors zurück
        /// </summary>
        /// <param name="v">Vektor</param>
        /// <returns>Länge</returns>
        public static float Vec3Length(TV_3DVECTOR v)
        {
            return (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
        }

        /// <summary>
        /// Normalisiert einen Vektor
        /// </summary>
        /// <param name="v">Der Vektor, der Normalisiert werden soll</param>
        /// <returns>Der Normalisierte Vektor</returns>
        public static TV_3DVECTOR Vec3Normalize(TV_3DVECTOR v)
        {
            TV_3DVECTOR vNewVector = new TV_3DVECTOR();
            float fLength = Vec3Length(v);

            if (fLength > 0.0f)
            {
                vNewVector.x = v.x / fLength;
                vNewVector.y = v.y / fLength;
                vNewVector.z = v.z / fLength;
            }

            return vNewVector;
        }

        /// <summary>
        /// out = v + b * s
        /// </summary>
        /// <param name="v"></param>
        /// <param name="b"></param>
        /// <param name="s"></param>
        public static TV_3DVECTOR Vec3MultiplyAdd(TV_3DVECTOR v, TV_3DVECTOR b, float s)
        {
            TV_3DVECTOR vOut = new TV_3DVECTOR();

            vOut.x = v.x + b.x * s;
            vOut.y = v.y + b.y * s;
            vOut.z = v.z + b.z * s;

            return vOut;
        }

        /// <summary>
        /// "Bereinigt" einen normalisierten Vektor um numerische Ungenauigkeiten
        /// </summary>
        /// <param name="vVector"></param>
        public static void CleanNormalizedVector(ref TV_3DVECTOR vVector)
        {
            float[] faComponents = new float[3];

            faComponents[0] = vVector.x;
            faComponents[1] = vVector.y;
            faComponents[2] = vVector.z;

            for (int i = 0; i < 3; i++)
            {
                if (faComponents[i] < 0.0f)
                {
                    if (faComponents[i] < -0.999f)
                        faComponents[i] = -1.0f;
                    else if (faComponents[i] > -0.001f)
                        faComponents[i] = 0.0f;
                }
                else
                {
                    if (faComponents[i] > 0.999f)
                        faComponents[i] = 1.0f;
                    else if (faComponents[i] < 0.001f)
                        faComponents[i] = 0.0f;
                }
            }

            vVector.x = faComponents[0];
            vVector.y = faComponents[1];
            vVector.z = faComponents[2];
        }

#endregion
#region Matrix Stuff
        /// <summary>
        /// Builds a left-handed orthographic projection matrix.
        /// http://msdn2.microsoft.com/en-us/library/bb205346(VS.85).aspx
        /// </summary>
        /// <param name="w">Width of the view volume.</param>
        /// <param name="h">Height of the view volume.</param>
        /// <param name="zn">Minimum z-value of the view volume which is referred to as z-near.</param>
        /// <param name="zf">Maximum z-value of the view volume which is referred to as z-far. </param>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixOrthoLH(float w, float h, float zn, float zf)
        {
            return new TV_3DMATRIX(2.0f / w,  0.0f,      0.0f,              0.0f,
                                   0.0f,      2.0f / h,  0.0f,              0.0f,
                                   0.0f,      0.0f,      1.0f / (zf - zn),  0.0f,
                                   0.0f,      0.0f,      -zn / (zf - zn),   1.0f);
        }

        /// <summary>
        /// Builds a left-handed, look-at matrix.
        /// http://msdn2.microsoft.com/en-us/library/bb205342.aspx
        /// </summary>
        /// <param name="vEye">defines the eye point. This value is used in translation.</param>
        /// <param name="vAt">defines the camera look-at target</param>
        /// <param name="vUp">structure that defines the current world's up, usually [0, 1, 0].</param>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixLookAtLH(TV_3DVECTOR vEye, TV_3DVECTOR vAt, TV_3DVECTOR vUp)
        {
            TV_3DVECTOR z = Vec3Normalize(vAt - vEye);
            TV_3DVECTOR x = Vec3Normalize(Vec3CrossProduct(vUp, z));
            TV_3DVECTOR y = Vec3CrossProduct(z, x);

            return new TV_3DMATRIX(x.x,  y.x,  z.x,  0.0f,
                                   x.y,  y.y,  z.y,  0.0f,
                                   x.z,  y.z,  z.z,  0.0f,
                                   -Vec3DotProduct(x, vEye),
                                   -Vec3DotProduct(y, vEye),
                                   -Vec3DotProduct(z, vEye), 1.0f);
        }

        /*
        [20:18] SylvainTV: float fAspect, fW, fH;
        [20:18] SylvainTV: if(cam->fAspectRatio > 0.0f)
        [20:18] SylvainTV: {
        [20:18] SylvainTV: fAspect = cam->fAspectRatio;
        [20:18] SylvainTV: fW = fZoom * fAspect;
        [20:18] SylvainTV: fH = fZoom;
        [20:18] SylvainTV: }
        [20:18] SylvainTV: else
        [20:18] SylvainTV: {
        [20:18] SylvainTV: fAspect = 1;
        [20:18] SylvainTV: fW = fZoom ;
        [20:18] SylvainTV: fH = fZoom * (float)cam->viewportheight / (float)cam->viewportwidth ;
        [20:18] SylvainTV: }
        [20:18] SylvainTV: D3DXMatrixOrthoLH(&cam->mProjMatrix, fW, fH, fNearPlane,  fFarPlane);
        [20:18] SylvainTV: cam->mOldProjection = cam->mProjMatrix;
        [20:18] SylvainTV: if(cam->inuse)
        [20:18] SylvainTV: {
        [20:18] SylvainTV: CameraManager_ApplyCamera(iCameraIndex);
        [20:18] SylvainTV: }
        */
        /// <summary>
        /// Builds a left-handed perspective projection matrix based on a field of view.
        /// http://msdn2.microsoft.com/en-us/library/bb205350(VS.85).aspx
        /// </summary>
        /// <param name="fovY">Field of view in the y direction, in radians.</param>
        /// <param name="aspect">Aspect ratio, defined as view space width divided by height.</param>
        /// <param name="zn">Z-value of the near view-plane.</param>
        /// <param name="zf">Z-value of the far view-plane.</param>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixPerspectiveFovLH(float fovY, float aspect, float zn, float zf)
        {
            float yScale = (float)Cot(fovY * 0.5f);
            float xScale = yScale / aspect;

            return new TV_3DMATRIX(xScale,   0.0f,        0.0f,            0.0f,
                                   0.0f,   yScale,        0.0f,            0.0f,
                                   0.0f,     0.0f,  zf/(zf-zn),            1.0f,
                                   0.0f,     0.0f,        -zn*zf/(zf-zn),  0.0f);
        }

        /// <summary>
        /// Returns a standard matrix identitiy.
        /// </summary>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixIdentity()
        {
            return new TV_3DMATRIX(1.0f, 0.0f, 0.0f, 0.0f,
                                   0.0f, 1.0f, 0.0f, 0.0f,
                                   0.0f, 0.0f, 1.0f, 0.0f,
                                   0.0f, 0.0f, 0.0f, 1.0f);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="mMatrix"></param>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixInverse(TV_3DMATRIX mMatrix)
        {
            float a = 0.0f;
            TrueVision3D.MathLibrary.TVMatrixInverse(ref mMatrix, ref a, mMatrix);

            return mMatrix;
        }


        /// <summary>
        /// Kombiniert zwei Matrixen via Multiplikation
        /// </summary>
        /// <param name="m1">Matrix 1</param>
        /// <param name="m2">Matrix 2</param>
        /// <returns>Kombinierte Matrix</returns>
        public static TV_3DMATRIX MatrixMultiply(TV_3DMATRIX m1, TV_3DMATRIX m2)
        {
            TV_3DMATRIX mMatrix = new TV_3DMATRIX();

            mMatrix.m11 = m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31 + m1.m14 * m2.m41;
            mMatrix.m12 = m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32 + m1.m14 * m2.m42;
            mMatrix.m13 = m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33 + m1.m14 * m2.m43;
            mMatrix.m14 = m1.m11 * m2.m14 + m1.m12 * m2.m24 + m1.m13 * m2.m34 + m1.m14 * m2.m44;

            mMatrix.m21 = m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31 + m1.m24 * m2.m41;
            mMatrix.m22 = m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32 + m1.m24 * m2.m42;
            mMatrix.m23 = m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33 + m1.m24 * m2.m43;
            mMatrix.m24 = m1.m21 * m2.m14 + m1.m22 * m2.m24 + m1.m23 * m2.m34 + m1.m24 * m2.m44;

            mMatrix.m31 = m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31 + m1.m34 * m2.m41;
            mMatrix.m32 = m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32 + m1.m34 * m2.m42;
            mMatrix.m33 = m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33 + m1.m34 * m2.m43;
            mMatrix.m34 = m1.m31 * m2.m14 + m1.m32 * m2.m24 + m1.m33 * m2.m34 + m1.m34 * m2.m44;

            mMatrix.m41 = m1.m41 * m2.m11 + m1.m42 * m2.m21 + m1.m43 * m2.m31 + m1.m44 * m2.m41;
            mMatrix.m42 = m1.m41 * m2.m12 + m1.m42 * m2.m22 + m1.m43 * m2.m32 + m1.m44 * m2.m42;
            mMatrix.m43 = m1.m41 * m2.m13 + m1.m42 * m2.m23 + m1.m43 * m2.m33 + m1.m44 * m2.m43;
            mMatrix.m44 = m1.m41 * m2.m14 + m1.m42 * m2.m24 + m1.m43 * m2.m34 + m1.m44 * m2.m44;

            return mMatrix;
        }

        /// <summary>
        /// Applies translation to a matrix.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="z">The z.</param>
        /// <returns></returns>
        public static TV_3DMATRIX MatrixTranslation(float x, float y, float z)
        {
            TV_3DMATRIX mMatrix = MatrixIdentity();

            mMatrix.m31 += x;
            mMatrix.m32 += y;
            mMatrix.m33 += z;

            return mMatrix;
        }
#endregion
    }
}
Logged
Mietze
Community Member
*
Posts: 235


« Reply #62 on: July 20, 2008, 05:20:53 AM »



mesh_depth.fx:
Code:
float4x4 g_mCameraWorldViewProj : WORLDVIEWPROJ;


void VS_DepthMap(
float4 vObjectSpacePosition : POSITION,
out float4 vScreenSpacePosition : POSITION,
out float fDepth : TEXCOORD0)
{
vScreenSpacePosition = mul(vObjectSpacePosition, g_mCameraWorldViewProj);
fDepth = vScreenSpacePosition.z;
}

float4 PS_DepthMap(float fDepth : TEXCOORD0): COLOR
{
return fDepth;
}

// This technique is used to render the final shadowed meshes
technique DepthMap
{
pass p0
{
//CullMode = CCW; // Backfaces -> Reduziert Surface Acne
VertexShader = compile vs_3_0 VS_DepthMap();
PixelShader = compile ps_3_0 PS_DepthMap();
}
}

mesh_shadow.fx
Code:
#define MAX_LIGHT_DEPTH 1.0f
#define ESM_COEFFICIENT -80.0f

float4x4 g_mCameraViewProj : VIEWPROJ;
float4x4 g_mWorld : WORLD;
float g_fCurrentSplit;
float3 g_vLightDirection;
float4x4 g_mShadowMap[4];
float4x4 g_mLightViewProj[4];
float4 g_fSplitDistances;
float g_fPCFScale;
   
const float4x3 g_mSplitTestColors = { {1.0f, 0.0f, 0.0f},
          {0.0f, 1.0f, 0.0f},
          {0.0f, 0.0f, 1.0f},
          {1.0f, 1.0f, 0.0f} };

///////////////////////////////////////////////////////////////////////////////
/// Textures & Samplers
///////////////////////////////////////////////////////////////////////////////

texture texAlbedo : TEXTURE0;
sampler2D sampAlbedo  =
sampler_state
{
Texture = (texAlbedo);
MinFilter = Anisotropic;
MagFilter = Anisotropic;
MipFilter = None;
};

   
texture texShadowMap;
sampler2D sampShadowMap  =
sampler_state
{
Texture = (texShadowMap);
MinFilter = None;
MagFilter = None;
MipFilter = None;
AddressU = Border;
AddressV = Border;
AddressW = Border;
BorderColor = 0x000000;
};

///////////////////////////////////////////////////////////////////////////////
/// Shadow Shader
///////////////////////////////////////////////////////////////////////////////

struct VS_SHADOWED_INPUT
{
float4 vObjectSpacePosition : POSITION;
float2 vTextureUV : TEXCOORD0;
float3 vNormal : NORMAL;
};

struct VS_SHADOWED_OUTPUT
{
float4 vScreenSpacePosition : POSITION;
float3 vNormal : TEXCOORD0;
float4 vDepthAndTextureUV : TEXCOORD1;
float4 fLightDepth : TEXCOORD2;
float2 vProjectedLightPosition[4] : TEXCOORD3;

};

float GetDiffuse(float3 vNormal, float3 vLightDirection) // Half-Lambert
{
    return (dot(vLightDirection, vNormal)) * 0.5f + 0.5f;
}

VS_SHADOWED_OUTPUT VS_Shadowed(VS_SHADOWED_INPUT IN)
{
VS_SHADOWED_OUTPUT OUT;

float4 vWorldSpacePosition = mul(IN.vObjectSpacePosition, g_mWorld);

OUT.vScreenSpacePosition = mul(vWorldSpacePosition, g_mCameraViewProj);
OUT.vNormal = IN.vNormal;
OUT.vDepthAndTextureUV.xy = IN.vTextureUV;
OUT.vDepthAndTextureUV.z = OUT.vScreenSpacePosition.z;
OUT.vDepthAndTextureUV.w = GetDiffuse(IN.vNormal, g_vLightDirection);

OUT.vProjectedLightPosition[0] = mul(vWorldSpacePosition, g_mShadowMap[0]).xy;
OUT.vProjectedLightPosition[1] = mul(vWorldSpacePosition, g_mShadowMap[1]).xy;
OUT.vProjectedLightPosition[2] = mul(vWorldSpacePosition, g_mShadowMap[2]).xy;
OUT.vProjectedLightPosition[3] = mul(vWorldSpacePosition, g_mShadowMap[3]).xy;

OUT.fLightDepth.x = mul(vWorldSpacePosition, g_mLightViewProj[0]).z - 0.005f;
OUT.fLightDepth.y = mul(vWorldSpacePosition, g_mLightViewProj[1]).z - 0.0075f;
OUT.fLightDepth.z = mul(vWorldSpacePosition, g_mLightViewProj[2]).z - 0.0125f;
OUT.fLightDepth.w = mul(vWorldSpacePosition, g_mLightViewProj[3]).z - 0.0125f;

return OUT;
}

int GetSplitByDepth(float fDepth)
{
half fSplitID = 0;

// Check from far2near, cause far is potential larger
if( fDepth >= g_fSplitDistances[3] )
fSplitID = 3;
else if( fDepth >= g_fSplitDistances[2] )
fSplitID = 2;
else if( fDepth >= g_fSplitDistances[1] )
fSplitID = 1;

return fSplitID;
}
/*
float2 poissonDisk[16] =
{
float2( -0.94201624, -0.39906216 ),
float2( 0.94558609, -0.76890725 ),
float2( -0.094184101, -0.92938870 ),
float2( 0.34495938, 0.29387760 ),
float2( -0.91588581, 0.45771432 ),
float2( -0.81544232, -0.87912464 ),
float2( -0.38277543, 0.27676845 ),
float2( 0.97484398, 0.75648379 ),
float2( 0.44323325, -0.97511554 ),
float2( 0.53742981, -0.47373420 ),
float2( -0.26496911, -0.41893023 ),
float2( 0.79197514, 0.19090188 ),
float2( -0.24188840, 0.99706507 ),
float2( -0.81409955, 0.91437590 ),
float2( 0.19984126, 0.78641367 ),
float2( 0.14383161, -0.14100790 )
};*/

// Fake one ;D
float2 poissonDisk[5] =
{
float2( -1, -1 ),
float2( -1, 1 ),
    float2( 0, 0),
    float2( 1, -1 ),
float2( 1, 1 )
};

float GetShadow(half fSplitIndex, float2 splitUV[4], float4 lightDepths)
{
float4 shadowMap;
    float shadow = 0.0f;

for( int i = 0; i < 5; i++ )
{
shadowMap = tex2D(sampShadowMap, splitUV[fSplitIndex].xy + poissonDisk[i] * g_fPCFScale);
        shadow += lightDepths[fSplitIndex] > shadowMap[fSplitIndex];
}

shadow /= 5.0f;

return 1.0f - (shadow * 0.2f);
}

float4 PS_Shadowed(VS_SHADOWED_OUTPUT IN) : COLOR
{
    half fSplitIndex = GetSplitByDepth(IN.vDepthAndTextureUV.z);

float3 normal = normalize(IN.vNormal);
float4 albedo = tex2D(sampAlbedo, IN.vDepthAndTextureUV.xy);
float diffuse = IN.vDepthAndTextureUV.w;
float shadow = GetShadow(fSplitIndex, IN.vProjectedLightPosition, IN.fLightDepth);

return float4(diffuse * albedo.rgb * shadow, albedo.a);
}

technique Shadowed
{
pass p0
{
VertexShader = compile vs_2_0 VS_Shadowed();
PixelShader = compile ps_2_0 PS_Shadowed();
}
}
Logged
Mietze
Community Member
*
Posts: 235


« Reply #63 on: July 20, 2008, 05:21:24 AM »

CParallelSplitShadowMapping:
Code:
using System;
using System.Collections.Generic;
using System.Text;
using MTV3D65;

namespace eStudioz
{
    public class CParallelSplitShadowMapping
    {
        public static CParallelSplitShadowMapping Instance = null;

        private int m_nShadowMapSize;
        private TVRenderSurface m_pShadowMapRenderSurface;
        private List<IEntity> m_paShadowCasters;
        private const int m_nSplitCount = 4;
        private float m_fSplitLambda;
        private float[] m_faSplitDistances;
        private TVViewport m_pSzeneViewport;
        private CBoundingBox m_pSceneBoundingBox;
        private double m_dNextRenderTime;
        private float m_fRenderInterval;
        private TVCamera m_pSceneCamera;
        private float m_fSceneCameraFarLastFrame;
        private float m_fSceneCameraNear;
        private float m_fSceneCameraFar;
        private float m_fSceneCameraMinFar;
        private float m_fSceneCameraMaxFar;
        private float m_fSceneCameraFieldOfView;
        private float m_fSceneCameraAspectRatio;
        private TV_3DVECTOR[] m_vaFrustumCorners;
        private TV_3DVECTOR m_vUpVector;
        private TV_3DMATRIX m_mShadowMapTextureMatrix;
        private TV_3DMATRIX[] m_maShadowMapTextureMatrices;
        private TV_3DMATRIX[] m_maLightViewProj;
        private TV_3DVECTOR m_vLightDirection;
        private TV_2DVECTOR m_vSceneViewportResolution;
        private bool[][] m_baSplitColors;

        // Use this property to set the lights direction
        // after you map has been loaded or whenever
        // the lights direction has changed
        public TV_3DVECTOR LightDirection
        {
            set
            {
                m_vLightDirection = value;
               
                // I inverse the lights direction vector to spare that step
                // within the fragment shaders later on
                CGlobalResources.Instance.Shaders.Mesh.SetEffectParamVector3("g_vLightDirection", -1.0f * m_vLightDirection);
                CGlobalResources.Instance.Shaders.Actor.SetEffectParamVector3("g_vLightDirection", -1.0f * m_vLightDirection);
            }
        }

        public CParallelSplitShadowMapping(TVCamera pSceneCamera, TV_2DVECTOR vSceneViewportResolution)
        {
            m_fSceneCameraFarLastFrame = 0.0f;
            m_fSplitLambda = 0.3f;
            m_nShadowMapSize = 1024;
            m_vUpVector = new TV_3DVECTOR(0, 1, 0);
            m_vSceneViewportResolution = vSceneViewportResolution;
            m_fSceneCameraAspectRatio = vSceneViewportResolution.x / vSceneViewportResolution.y;
            m_faSplitDistances = new float[m_nSplitCount + 1];
            m_pSceneCamera = pSceneCamera;
            m_vLightDirection = MathHelpers.Vec3Normalize(new TV_3DVECTOR(0.5f, -1.0f, -0.5f));
            m_pSceneBoundingBox = new CBoundingBox();
            m_paShadowCasters = new List<IEntity>();
            m_vaFrustumCorners = new TV_3DVECTOR[8];
            m_maLightViewProj = new TV_3DMATRIX[m_nSplitCount];
            m_maShadowMapTextureMatrices = new TV_3DMATRIX[m_nSplitCount];
            m_dNextRenderTime = 0.0;
            m_fRenderInterval = 1.0f / 200.0f;

            // Set up the color channels whe want to render the single
            // depth maps into
            m_baSplitColors = new bool[m_nSplitCount][];
            m_baSplitColors[0] = new bool[4] { true,  false, false, false };
            m_baSplitColors[1] = new bool[4] { false, true,  false, false };
            m_baSplitColors[2] = new bool[4] { false, false, true,  false };
            m_baSplitColors[3] = new bool[4] { false, false, false, true };

            // Compute the texture matrix for the depth maps to
            // sample within the correct UV zones. We need to use
            // "0.5f / m_nShadowMapSize", because D3DX samples at
            // the (imaginary) center of each texel
            float fOffset = 0.5f + (0.5f / (float)m_nShadowMapSize);

            m_mShadowMapTextureMatrix = new TV_3DMATRIX(
                0.5f,       0.0f, 0.0f, 0.0f,
                0.0f,      -0.5f, 0.0f, 0.0f,
                0.0f,       0.0f, 1.0f, 0.0f,
                fOffset, fOffset, 0.0f, 1.0f);

            // We need information about the viewport to compute
            // the cameras view frustum
            m_pSzeneViewport = TrueVision3D.Engine.GetViewport();

            // Create the depth map with a white background and ARGB16F
            // You may want to change that to a different format
            m_pShadowMapRenderSurface = TrueVision3D.Scene.CreateRenderSurface(m_nShadowMapSize, m_nShadowMapSize, true, CONST_TV_RENDERSURFACEFORMAT.TV_TEXTUREFORMAT_HDR_FLOAT16);
            m_pShadowMapRenderSurface.SetBackgroundColor(TrueVision3D.Globals.RGBA(1.0f, 1.0f, 1.0f, 1.0f));
            m_pShadowMapRenderSurface.StartRender(); // Render it once to clear the background
            m_pShadowMapRenderSurface.EndRender();

            // Set some weird parameters ;D
            CGlobalResources.Instance.Shaders.Mesh.SetEffectParamFloat("g_fPCFScale", 1.0f / 2000.0f);
            CGlobalResources.Instance.Shaders.Mesh.SetEffectParamVector3("g_vLightDirection", -1.0f * m_vLightDirection);
            CGlobalResources.Instance.Shaders.Mesh.SetEffectParamTexture("texShadowMap", m_pShadowMapRenderSurface.GetTexture());
            CGlobalResources.Instance.Shaders.Actor.SetEffectParamFloat("g_fPCFScale", 1.0f / 2000.0f);
            CGlobalResources.Instance.Shaders.Actor.SetEffectParamVector3("g_vLightDirection", -1.0f * m_vLightDirection);
            CGlobalResources.Instance.Shaders.Actor.SetEffectParamTexture("texShadowMap", m_pShadowMapRenderSurface.GetTexture());

            m_pSceneCamera.GetViewFrustum(ref m_fSceneCameraFieldOfView, ref m_fSceneCameraFar, ref m_fSceneCameraNear);
           
            // These are the limits of the cameras view frustum.
            // AdjustCameraPlanes() cares about these limits.
            // You may want to tune this a bit to avoid discarding the 1st split
            m_fSceneCameraMinFar = 60.0f;
            m_fSceneCameraMaxFar = 200.0f;
        }

 
        /// <summary>
        /// Adds a mesh as a shadow caster merges
        /// it into the worlds bounding box, if its static (bMergeWithSceneBoundingBox = true)
        /// </summary>
        /// <param name="pCaster"></param>
        /// <param name="bRebuildRenderList"></param>
        public void AddShadowCaster(IEntity pCaster, bool bMergeWithSceneBoundingBox)
        {
            TV_3DVECTOR vMinimum, vMaximum;

            if( bMergeWithSceneBoundingBox )
            {
                pCaster.GetShadowBoundingBox(out vMinimum, out vMaximum);

                m_pSceneBoundingBox.Merge(vMinimum);
                m_pSceneBoundingBox.Merge(vMaximum);
                m_pSceneBoundingBox.ConstructEverything();
            }
           
            m_paShadowCasters.Add(pCaster);
        }

        /// <summary>
        /// Removes the entity from the internal list to stop casting shadows
        /// </summary>
        /// <param name="pCaster"></param>
        public void RemoveShadowCaster(IEntity pCaster)
        {
            m_paShadowCasters.Remove(pCaster);
        }

        /// <summary>
        /// Calculates the split distances for each single split.
        /// This comes directly out of the demo, but you can also
        /// use procentual values for this
        /// </summary>
        private void CalculateSplitDistances()
        {
            float fIDM, fLog, fUniform;

            for (int i = 0; i < m_nSplitCount; i++)
            {
                fIDM = i / (float)m_nSplitCount;
                fLog = m_fSceneCameraNear * (float)Math.Pow((m_fSceneCameraFar / m_fSceneCameraNear), fIDM);
                fUniform = m_fSceneCameraNear + (m_fSceneCameraFar - m_fSceneCameraNear) * fIDM;
                m_faSplitDistances[i] = fLog * m_fSplitLambda + fUniform * (1.0f - m_fSplitLambda);
            }

            // Ensure, that the min and max values are exactly the same
            // as the view frustum
            m_faSplitDistances[0] = m_fSceneCameraNear;
            m_faSplitDistances[m_nSplitCount] = m_fSceneCameraFar;

            // Add the new values to the shader
            CGlobalResources.Instance.Shaders.Mesh.SetEffectParamFloatArray("g_fSplitDistances", m_faSplitDistances, m_nSplitCount);
            CGlobalResources.Instance.Shaders.Actor.SetEffectParamFloatArray("g_fSplitDistances", m_faSplitDistances, m_nSplitCount);
        }

        /// <summary>
        /// Calculates the frustum cornes / vertices / points / whatever
        /// of our scene camera for a single frustum split.
        /// </summary>
        /// <param name="fNear">Near plane of the split.</param>
        /// <param name="fFar">Far plane of the split</param>
        private void CalculateFrustumCorners(float fNear, float fFar)
        {
            float fScale, fNearPlaneHeight, fNearPlaneWidth, fFarPlaneHeight, fFarPlaneWidth;
            TV_3DVECTOR vCenter = new TV_3DVECTOR(), vFarPlaneCenter, vNearPlaneCenter;
            TV_3DVECTOR vSource, vTarget, vZ, vX, vY;

            // TVCamera.GetFrustumPoints() is not an option, since we
            // only compute the frustum corners for a single split,
            // not for the whole frustum. Changing the planes of the TVCamera
            // could work, but I haven't tested this.. since this is working fine :)
            vSource = m_pSceneCamera.GetPosition();
            vTarget = m_pSceneCamera.GetLookAt();
            vZ = MathHelpers.Vec3Normalize(vTarget - vSource);
            vX = MathHelpers.Vec3Normalize(MathHelpers.Vec3CrossProduct(m_vUpVector, vZ));
            vY = MathHelpers.Vec3CrossProduct(vZ, vX);

            fNearPlaneHeight = (float)Math.Tan(MathHelpers.DegreeToRadian(m_fSceneCameraFieldOfView) * 0.5f) * fNear;
            fNearPlaneWidth = fNearPlaneHeight * m_fSceneCameraAspectRatio;

            fFarPlaneHeight = (float)Math.Tan(MathHelpers.DegreeToRadian(m_fSceneCameraFieldOfView) * 0.5f) * fFar;
            fFarPlaneWidth = fFarPlaneHeight * m_fSceneCameraAspectRatio;

            vNearPlaneCenter = vSource + vZ * fNear;
            vFarPlaneCenter = vSource + vZ * fFar;

            m_vaFrustumCorners[0] = vNearPlaneCenter - vX * fNearPlaneWidth - vY * fNearPlaneHeight;
            m_vaFrustumCorners[1] = vNearPlaneCenter + vX * fNearPlaneWidth - vY * fNearPlaneHeight;
            m_vaFrustumCorners[2] = vNearPlaneCenter - vX * fNearPlaneWidth + vY * fNearPlaneHeight;
            m_vaFrustumCorners[3] = vNearPlaneCenter + vX * fNearPlaneWidth + vY * fNearPlaneHeight;
            m_vaFrustumCorners[4] = vFarPlaneCenter - vX * fFarPlaneWidth - vY * fFarPlaneHeight;
            m_vaFrustumCorners[5] = vFarPlaneCenter + vX * fFarPlaneWidth - vY * fFarPlaneHeight;
            m_vaFrustumCorners[6] = vFarPlaneCenter - vX * fFarPlaneWidth + vY * fFarPlaneHeight;
            m_vaFrustumCorners[7] = vFarPlaneCenter + vX * fFarPlaneWidth + vY * fFarPlaneHeight;

            // Increase the scale of the frustum a bit to avoid artefacts near the screen corners.
            // Start by calculating the center of our frustum points
            fScale = 1.1f;

            for (int i = 0; i < 8; i++)
                vCenter += m_vaFrustumCorners[i];

            vCenter /= 8.0f;

            // Finally scale it by adding offset from center
            for (int i = 0; i < 8; i++)
                m_vaFrustumCorners[i] += (m_vaFrustumCorners[i] - vCenter) * (fScale - 1.0f);
        }
Logged
Mietze
Community Member
*
Posts: 235


« Reply #64 on: July 20, 2008, 05:22:08 AM »

CParallelSplitShadowMapping, Part 2:
Code:

        /// <summary>
        ///
        /// </summary>
        /// <param name="mLightView"></param>
        /// <param name="mLightProj"></param>
        /// <param name="nSplit"></param>
        void EnclosePoints(out TV_3DMATRIX mLightView, out TV_3DMATRIX mLightProj, int nSplit)
        {
            float fDistance;
            float[] faNear = new float[3];
            float[] faFar = new float[3];
            float[] faDiff = new float[3]; // 0 = xaxis, 1 = yaxis, 2 = zaxis
            TV_3DVECTOR[] vaAxis = new TV_3DVECTOR[3]; // Orthonormal basis for the view matrix
            TV_3DVECTOR vCenterPosition = new TV_3DVECTOR();
            int i, k;

            // Reset boundaries
            for (i = 0; i < 3; i++)
            {
                faNear[i] = float.MaxValue;
                faFar[i] = float.MinValue;
            }

            // Construct orthonormal basis
            vaAxis[2] = m_vLightDirection;
            vaAxis[0] = MathHelpers.Vec3Normalize(MathHelpers.Vec3CrossProduct(m_vUpVector, vaAxis[2]));
            vaAxis[1] = MathHelpers.Vec3Normalize(MathHelpers.Vec3CrossProduct(vaAxis[2], vaAxis[0]));

            // Get the boundaries and compute the distances
            for (i = 0; i < 8; i++)
            {
                for (k = 0; k < 3; k++)
                {
                    fDistance = MathHelpers.Vec3DotProduct(vaAxis[k], m_vaFrustumCorners[i]);

                    if (fDistance < faNear[k])
                        faNear[k] = fDistance;

                    if (fDistance > faFar[k])
                        faFar[k] = fDistance;
                }
            }

            // Compute differences and get the center point of the new view frustum
            for (i = 0; i < 3; i++)
            {
                faDiff[i] = faFar[i] - faNear[i];
                vCenterPosition += vaAxis[i] * (faNear[i] + faFar[i]);
            }

            vCenterPosition *= 0.5f;

            // Finally compute the matrices
            // TODO: Compute the extra distance with the worlds bounding box to be sure that
            //       you have enclosed everything!
            float fExtraDistance = 20.0f;
            float ZNear = 5.0f;
            float fLightZFar = faDiff[2] + ZNear + fExtraDistance;
            TV_3DVECTOR vLightPosition = vCenterPosition - vaAxis[2] * (faDiff[2] * 0.5f + ZNear + fExtraDistance);         

            mLightView = MathHelpers.MatrixLookAtLH(vLightPosition, vCenterPosition, m_vUpVector);
            mLightProj = MathHelpers.MatrixOrthoLH(faDiff[0], faDiff[1], -ZNear, fLightZFar);

            // This would linearize the depth values. Its usually a good idea
            // and its required for some filtering purposes, but I don't use it :)
            //mLightProj.m33 /= fLightZFar;
            //mLightProj.m43 /= fLightZFar;
        }

        /// <summary>
        /// Re-compute the view frustum based on information
        /// </summary>
        private void AdjustCameraPlanes()
        {
            TV_3DMATRIX mCameraView = MathHelpers.MatrixLookAtLH(m_pSceneCamera.GetPosition(), m_pSceneCamera.GetLookAt(), m_vUpVector);

            // Find the most distant point of AABB
            float maxZ = 0.0f;
            float vertexZ;

            for (int i = 0; i < 8; i++)
            {
                // Transform z coordinate with view matrix
                vertexZ = m_pSceneBoundingBox.Vertices[i].x * mCameraView.m13
                        + m_pSceneBoundingBox.Vertices[i].y * mCameraView.m23
                        + m_pSceneBoundingBox.Vertices[i].z * mCameraView.m33
                        + mCameraView.m43;

                // Check if its largest
                if (vertexZ > maxZ)
                    maxZ = vertexZ;
            }

            // Use largest Z coordinate as new far plane
            m_fSceneCameraFar = maxZ + m_fSceneCameraNear;

            if (m_fSceneCameraFar < m_fSceneCameraMinFar)
                m_fSceneCameraFar = m_fSceneCameraMinFar;
            else if (m_fSceneCameraFar > m_fSceneCameraMaxFar)
                m_fSceneCameraFar = m_fSceneCameraMaxFar;

            // We need to recompute the split distances since the frustum has changed.
            // Only do this when the frustum size has changed - pheeew, what an uber optimization ;)
            if (m_fSceneCameraFar != m_fSceneCameraFarLastFrame)
            {
                CalculateSplitDistances();
                m_fSceneCameraFarLastFrame = m_fSceneCameraFar;
            }
        }

        /// <summary>
        /// Renders the depth maps for every split
        /// </summary>
        public void Update()
        {
            if (CEngine.Instance.Time >= m_dNextRenderTime)
            {
                TV_3DMATRIX mView, mProj;

                // Snap the cameras view frustum to the worlds bounding box.
                // If you're near the world boundings, it reduces the
                // space where no shadow caster can ever be
                AdjustCameraPlanes();

                // Render every split one by one
                for (int nSplit = 0; nSplit < m_nSplitCount; nSplit++)
                {
                    // Calculate the cameras frustum corners for the current split
                    // This "cuts" off the space of the frustum that isnt needed
                    CalculateFrustumCorners(m_faSplitDistances[nSplit], m_faSplitDistances[nSplit+1]);

                    // Calculate view and projection matrices for the light
                    // to enclose the whole split
                    EnclosePoints(out mView, out mProj, nSplit);

                    // Guess what this method does... ;)
                    RenderDepthMap(nSplit, mView, mProj);
                }

                // Set the proper
                CGlobalResources.Instance.Shaders.Mesh.SetEffectParamMatrixArray("g_mShadowMap", m_maShadowMapTextureMatrices, m_nSplitCount);
                CGlobalResources.Instance.Shaders.Mesh.SetEffectParamMatrixArray("g_mLightViewProj", m_maLightViewProj, m_nSplitCount);
                CGlobalResources.Instance.Shaders.Actor.SetEffectParamMatrixArray("g_mShadowMap", m_maShadowMapTextureMatrices, m_nSplitCount);
                CGlobalResources.Instance.Shaders.Actor.SetEffectParamMatrixArray("g_mLightViewProj", m_maLightViewProj, m_nSplitCount);

                // Re-enable the color writing to proceed "normal" rendering
                TrueVision3D.Scene.SetColorWriteEnable(true, true, true, true);

                // Rendering the shadows in realtime can be costly, so we
                // only render the depth maps in a certain render interval, which
                // is small enough to hide flickering
                m_dNextRenderTime = CEngine.Instance.Time + m_fRenderInterval;
            }
        }

        /// <summary>
        /// Rendert die Depthmap für einen bestimmten Split.
        /// </summary>
        /// <param name="nSplit">Die ID des Splits</param>
        /// <param name="mView">Die Viewmatrix des Lichts</param>
        /// <param name="mProjection">Die Projektionsmatrix des Lichts</param>
        private void RenderDepthMap(int nSplit, TV_3DMATRIX mView, TV_3DMATRIX mProj)
        {           
            // Compute that freaky matrices you will never understand, will you? :)
            m_maLightViewProj[nSplit] = mView * mProj;
            m_maShadowMapTextureMatrices[nSplit] = m_maLightViewProj[nSplit] * m_mShadowMapTextureMatrix;

            // Only inverse the view matrix for the TVCamera, since it needs
            // an inversed one
            mView = MathHelpers.MatrixInverse(mView);

            // Only enable the color writing for the channel we
            // want to render the split in
            TrueVision3D.Scene.SetColorWriteEnable(m_baSplitColors[nSplit][0],
                                                   m_baSplitColors[nSplit][1],
                                                   m_baSplitColors[nSplit][2],
                                                   m_baSplitColors[nSplit][3]);

            // Set the proper matrices we have computed before
            TVCamera pCamera = m_pShadowMapRenderSurface.GetCamera();
            pCamera.SetMatrix(mView);
            pCamera.SetCustomProjection(mProj);         

            // Start rendering the depth maps.
            // Only clear the render surfaces buffer when
            // we render the first split. In other words:
            // Keep the render surfaces content for one frame,
            // but four render passes
            m_pShadowMapRenderSurface.StartRender(nSplit > 0);

            // Render every shadow caster on the depth maps
            // You can increase the performance by using RenderMeshList() etc.
            // But since there are only a few entities in my current project that
            // casts a shadow, I was a bit lazy... :)
            foreach (IEntity pCaster in m_paShadowCasters)
                pCaster.RenderOnShadowMap(); // This method swaps the current shader to "depthmap"

            m_pShadowMapRenderSurface.EndRender();
        }

        /// <summary>
        /// This crappy function only renders the depth map to
        /// the left top of the screen. Useful for debugging and
        /// watching the colorful pictures in a book ;)
        /// </summary>
        public void RenderShadowMapDebug()
        {
            TrueVision3D.Screen2DImmediate.Action_Begin2D();
            TrueVision3D.Screen2DImmediate.Draw_Texture(m_pShadowMapRenderSurface.GetTexture(), 16, 16, 16 + 255, 16 + 255);
            TrueVision3D.Screen2DImmediate.Action_End2D();
        }
    }
}
Logged
Mietze
Community Member
*
Posts: 235


« Reply #65 on: July 20, 2008, 05:24:49 AM »

Eh.. the page just jumped over Smiley Here again what I wanted to tell ya:

Quote
So finally I had some time to grab the code and share it with you! Please let me know if you have done something cool with it Smiley I have translated most of the comments to English within the CParallelSplitShadowMapping-Class, but there are still German ones. I think this is enough to let you guess whats going on there... Wink

Note that some parts of the code arent optimized. If you have an idea how to optimize them, PLEEEEASE let me know Smiley

Again.. a small image of those shadows on a debugging shot of my current project:



Peace!
Logged
Raine
Customers
Community Member
*****
Posts: 1152


« Reply #66 on: July 20, 2008, 11:24:40 AM »

Thanks a lot for sharing this, I can't wait to poke Joe Basic to death until he'll include this in TVSM.

MathHelpers: (Its faster to do that on the "managed" side of your code)

I think Zak found out quite the opposite some time ago... you might want to try the good old TV functions again.
Logged

Zaknafein
Customers
Community Member
*****
Posts: 2625


WWW
« Reply #67 on: July 20, 2008, 11:35:34 AM »

There's probably a speedup in using them, but it's not nearly as substantial as I first thought.
When running from the IDE (with debugging, the filled green arrow) even in Release, all interop calls like ones to TV3D math functions are very slow. But out of IDE (or the empty green arrow in the IDE), they're almost as fast as managed calls.

Feel free to try for yourself...
Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
Mietze
Community Member
*
Posts: 235


« Reply #68 on: July 20, 2008, 11:56:28 AM »

If you take a closer look, there are functions like MatrixOrthoLH(), that are not available in TV3D... you can fake this with TVCamera, but that is a sucky way, isnt it? Smiley
Logged
Omnicrash
Community Member
*
Posts: 54


WWW
« Reply #69 on: July 21, 2008, 10:56:27 PM »

Nice! Thanks for the release! I could really learn a lot from this code, when I get something to work using it I'll post some screens here.

And since German is so close to Dutch, the untranslated comments don't bother me at all Smiley.

There are still a few 'loose ends' in the code, however, namely:
- IEntity
- CBoundingBox

Could you give a bit more info about these?
« Last Edit: July 21, 2008, 11:10:43 PM by Omnicrash » Logged

Mietze
Community Member
*
Posts: 235


« Reply #70 on: July 22, 2008, 03:20:16 AM »

This is actually very simple Smiley The CBoundingBox is just a.. ya .. a bounding box class Smiley The IEntity iterface is the base class for all of my game entities, like platforms, jetpacks, players and so on.

CBoundingBox:
Code:
using System;
using System.Collections.Generic;
using System.Text;
using MTV3D65;


namespace eStudioz
{
    public class CBoundingBox
    {
        // Baaaaad OOP, but for lazy ones...
        public TV_3DVECTOR m_vMinimum;
        public TV_3DVECTOR m_vMaximum;

        private TV_3DVECTOR[] m_vaVertices = new TV_3DVECTOR[8];
        public CLocatedVector[] m_vaEdges = new CLocatedVector[12];

        private bool m_bIsContructed;

        public TV_3DVECTOR[] Vertices
        {
            get { return m_vaVertic