Exemplo n.º 1
0
 public static void R_FreeInteractionCullInfo(SrfCullInfo cullInfo)
 {
     if (cullInfo.facing != null)
     {
         R_StaticFree(cullInfo.facing); cullInfo.facing = null;
     }
     if (cullInfo.cullBits != null)
     {
         if (cullInfo.cullBits != IInteraction.LIGHT_CULL_ALL_FRONT)
         {
             R_StaticFree(cullInfo.cullBits);
         }
         cullInfo.cullBits = null;
     }
 }
Exemplo n.º 2
0
        // are dangling edges that are outside the light frustum still making planes?
        public static SrfTriangles R_CreateVertexProgramTurboShadowVolume(RenderEntityLocal ent, SrfTriangles tri, RenderLightLocal light, SrfCullInfo cullInfo)
        {
            int          i, j;
            SrfTriangles newTri;
            SilEdge      sil;

            GlIndex[] indexes;
            byte[]    facing;

            R_CalcInteractionFacing(ent, tri, light, cullInfo);

            if (r_useShadowProjectedCull.Bool)
            {
                R_CalcInteractionCullBits(ent, tri, light, cullInfo);
            }

            var numFaces          = tri.numIndexes / 3;
            var numShadowingFaces = 0;

            facing = cullInfo.facing;

            // if all the triangles are inside the light frustum
            if (cullInfo.cullBits == LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.Bool)
            {
                // count the number of shadowing faces
                for (i = 0; i < numFaces; i++)
                {
                    numShadowingFaces += facing[i];
                }
                numShadowingFaces = numFaces - numShadowingFaces;
            }
            else
            {
                // make all triangles that are outside the light frustum "facing", so they won't cast shadows
                indexes = tri.indexes;
                byte *modifyFacing = cullInfo.facing;
                byte *cullBits     = cullInfo.cullBits;

                for (j = i = 0; i < tri.numIndexes; i += 3, j++)
                {
                    if (modifyFacing[j] == 0)
                    {
                        var i1 = indexes[i + 0];
                        var i2 = indexes[i + 1];
                        var i3 = indexes[i + 2];

                        if ((cullBits[i1] & cullBits[i2] & cullBits[i3]) != 0)
                        {
                            modifyFacing[j] = 1;
                        }
                        else
                        {
                            numShadowingFaces++;
                        }
                    }
                }
            }

            // no faces are inside the light frustum and still facing the right way
            if (numShadowingFaces == 0)
            {
                return(null);
            }

            // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface
            newTri = R_AllocStaticTriSurf();

            newTri.numVerts = tri.numVerts * 2;

            // alloc the max possible size
#if USE_TRI_DATA_ALLOCATOR
            R_AllocStaticTriSurfIndexes(newTri, (numShadowingFaces + tri.numSilEdges) * 6);
            GlIndex tempIndexes   = newTri.indexes;
            GlIndex shadowIndexes = newTri.indexes;
#else
            GlIndex tempIndexes   = new GlIndex[tri.numSilEdges * 6];
            GlIndex shadowIndexes = tempIndexes;
#endif

            // create new triangles along sil planes
            for (sil = tri.silEdges, i = tri.numSilEdges; i > 0; i--, sil++)
            {
                int f1 = facing[sil.p1], f2 = facing[sil.p2];

                if ((f1 ^ f2) == 0)
                {
                    continue;
                }

                int v1 = sil.v1 << 1, v2 = sil.v2 << 1;

                // set the two triangle winding orders based on facing without using a poorly-predictable branch

                shadowIndexes[0] = v1;
                shadowIndexes[1] = v2 ^ f1;
                shadowIndexes[2] = v2 ^ f2;
                shadowIndexes[3] = v1 ^ f2;
                shadowIndexes[4] = v1 ^ f1;
                shadowIndexes[5] = v2 ^ 1;

                shadowIndexes += 6;
            }

            int numShadowIndexes = shadowIndexes - tempIndexes;

            // we aren't bothering to separate front and back caps on these
            newTri.numIndexes             = newTri.numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6;
            newTri.numShadowIndexesNoCaps = numShadowIndexes;
            newTri.shadowCapPlaneBits     = SHADOW_CAP_INFINITE;

#if USE_TRI_DATA_ALLOCATOR
            // decrease the size of the memory block to only store the used indexes
            R_ResizeStaticTriSurfIndexes(newTri, newTri.numIndexes);
#else
            // allocate memory for the indexes
            R_AllocStaticTriSurfIndexes(newTri, newTri.numIndexes);
            // copy the indexes we created for the sil planes
            Simd.Memcpy(newTri.indexes, tempIndexes, numShadowIndexes * sizeof(tempIndexes[0]));
#endif

            // these have no effect, because they extend to infinity
            newTri.bounds.Clear();

            // put some faces on the model and some on the distant projection
            indexes       = tri.indexes;
            shadowIndexes = newTri.indexes + numShadowIndexes;

            for (i = 0, j = 0; i < tri.numIndexes; i += 3, j++)
            {
                if (facing[j] != 0)
                {
                    continue;
                }

                var i0 = indexes[i + 0] << 1; shadowIndexes[2] = i0; shadowIndexes[3] = i0 ^ 1;
                var i1 = indexes[i + 1] << 1; shadowIndexes[1] = i1; shadowIndexes[4] = i1 ^ 1;
                var i2 = indexes[i + 2] << 1; shadowIndexes[0] = i2; shadowIndexes[5] = i2 ^ 1;
                shadowIndexes += 6;
            }

            return(newTri);
        }
Exemplo n.º 3
0
        // We want to cull a little on the sloppy side, because the pre-clipping of geometry to the lights in dmap will give many cases that are right
        // at the border we throw things out on the border, because if any one vertex is clearly inside, the entire triangle will be accepted.
        static void R_CalcInteractionCullBits(IRenderEntity ent, SrfTriangles tri, IRenderLight light, ref SrfCullInfo cullInfo)
        {
            int i, frontBits;

            if (cullInfo.cullBits != null)
            {
                return;
            }

            frontBits = 0;

            // cull the triangle surface bounding box
            for (i = 0; i < 6; i++)
            {
                R_GlobalPlaneToLocal(ent.modelMatrix, -light.frustum[i], out cullInfo.localClipPlanes[i]);

                // get front bits for the whole surface
                if (tri.bounds.PlaneDistance(cullInfo.localClipPlanes[i]) >= IInteraction.LIGHT_CLIP_EPSILON)
                {
                    frontBits |= 1 << i;
                }
            }

            // if the surface is completely inside the light frustum
            if (frontBits == ((1 << 6) - 1))
            {
                cullInfo.cullBits = IInteraction.LIGHT_CULL_ALL_FRONT; return;
            }

            cullInfo.cullBits = (byte *)R_StaticAlloc(tri.numVerts * sizeof(byte));
            Simd.Memset(cullInfo.cullBits, 0, tri.numVerts * sizeof(byte));

            var planeSide = stackalloc float[tri.numVerts + floatX.ALLOC16]; planeSide = (float *)_alloca16(planeSide);

            for (i = 0; i < 6; i++)
            {
                // if completely infront of this clipping plane
                if ((frontBits & (1 << i)) != 0)
                {
                    continue;
                    fixed(DrawVert *vertsD = tri.verts) Simd.Dotpd(planeSide, cullInfo.localClipPlanes[i], vertsD, tri.numVerts);

                    Simd.CmpLTb(cullInfo.cullBits, (byte)i, planeSide, IInteraction.LIGHT_CLIP_EPSILON, tri.numVerts);
            }
        }
Exemplo n.º 4
0
        // Determines which triangles of the surface are facing towards the light origin.
        // The facing array should be allocated with one extra index than the number of surface triangles, which will be used to handle dangling edge silhouettes.
        static void R_CalcInteractionFacing(IRenderEntity ent, SrfTriangles tri, IRenderLight light, ref SrfCullInfo cullInfo)
        {
            if (cullInfo.facing != null)
            {
                return;
            }

            Vector3 localLightOrigin;

            R_GlobalPointToLocal(ent.modelMatrix, light.globalLightOrigin, out localLightOrigin);

            var numFaces = tri.numIndexes / 3;

            if (tri.facePlanes == null || !tri.facePlanesCalculated)
            {
                R_DeriveFacePlanes(tri);
            }

            cullInfo.facing = (byte *)R_StaticAlloc((numFaces + 1) * sizeof(byte));

            // calculate back face culling
            var planeSide = stackalloc float[numFaces + floatX.ALLOC16]; planeSide = (float *)_alloca16(planeSide);

            // exact geometric cull against face
            fixed(Plane *facePlanesP = tri.facePlanes) Simd.Dotcp(planeSide, localLightOrigin, facePlanesP, numFaces);

            Simd.CmpGE(cullInfo.facing, planeSide, 0f, numFaces);

            cullInfo.facing[numFaces] = 1;  // for dangling edges to reference
        }