Beispiel #1
0
        void finalGatherSingleThreaded(gatherWorkerData wd)
        {
            {
                float[]   AOVals      = TerrainGlobals.getEditor().getAmbientOcclusionValues();
                Vector3[] normals     = TerrainGlobals.getEditor().getNormals();
                int       numXVerts   = TerrainGlobals.getTerrain().getNumXVerts();
                int       numZVerts   = TerrainGlobals.getTerrain().getNumZVerts();
                Matrix    worldToProj = wd.workdToProj;

                for (int x = 0; x < numXVerts; x++)
                {
                    for (int z = 0; z < numZVerts; z++)
                    {
                        int index = z + x * numXVerts;

                        //only cast rays towards the light..
                        Vector3 nrm = -normals[index];
                        if (BMathLib.Dot(ref nrm, ref wd.rayDir) < 0)
                        {
                            continue;
                        }


                        Vector3 pos  = TerrainGlobals.getTerrain().getPos(x, z);
                        Vector4 vPos = new Vector4(pos.X, pos.Y, pos.Z, 1);
                        Vector4 rPos = BMathLib.vec4Transform(ref vPos, ref worldToProj);
                        rPos = rPos * (1.0f / rPos.W);
                        float depth = rPos.Z;// +0.07f;//CLM this matches the shader...

                        if (rPos.X < -1 || rPos.X >= 1 || rPos.Y < -1 || rPos.Y >= 1)
                        {
                            continue;
                        }

                        //grab our location in the depthGrid (screen space)
                        float xPos = BMathLib.Clamp(0.5f * rPos.Y + 0.5f, 0, 1);
                        float yPos = BMathLib.Clamp(0.5f * rPos.X + 0.5f, 0, 1);


                        int xGridLoc = (int)((wd.imgWidth - 1) * (1 - xPos));
                        int yGridLoc = (int)((wd.imgHeight - 1) * (yPos));

                        if (!wd.fragList[xGridLoc, yGridLoc].anyValueSmaller(depth))
                        {
                            AOVals[index] += wd.rcpNumSamples;
                            Debug.Assert(AOVals[index] <= 1);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        void finalGatherWorker(object workerObjectDat)
        {
            gatherWorkerData workerDat = workerObjectDat as gatherWorkerData;
            int    numXVerts           = TerrainGlobals.getTerrain().getNumXVerts();
            Matrix worldToProj         = workerDat.workdToProj;

            for (int x = workerDat.minXVert; x < workerDat.maxXVert; x++)
            {
                for (int z = workerDat.minZVert; z < workerDat.maxZVert; z++)
                {
                    //only cast rays towards the light..
                    Vector3 nrm = -TerrainGlobals.getTerrain().getNormal(x, z);
                    if (BMathLib.Dot(ref nrm, ref workerDat.rayDir) < 0)
                    {
                        continue;
                    }


                    Vector3 pos  = TerrainGlobals.getTerrain().getPos(x, z);
                    Vector4 vPos = new Vector4(pos.X, pos.Y, pos.Z, 1);
                    Vector4 rPos = BMathLib.vec4Transform(ref vPos, ref worldToProj);
                    rPos = rPos * (1.0f / rPos.W);
                    float depth = rPos.Z;

                    if (rPos.X < -1 || rPos.X >= 1 || rPos.Y < -1 || rPos.Y >= 1)
                    {
                        continue;
                    }

                    //grab our location in the depthGrid (screen space)
                    float xPos     = BMathLib.Clamp(0.5f * rPos.Y + 0.5f, 0, 1);
                    float yPos     = BMathLib.Clamp(0.5f * rPos.X + 0.5f, 0, 1);
                    int   xGridLoc = (int)((workerDat.imgWidth - 1) * (1 - xPos));
                    int   yGridLoc = (int)((workerDat.imgHeight - 1) * (yPos));

                    if (workerDat.fragList[xGridLoc, yGridLoc] != null && !workerDat.fragList[xGridLoc, yGridLoc].anyValueSmaller(depth))
                    {
                        int index = z + x * numXVerts;
                        Interlocked.Increment(ref AmbientOcclusion.AOIncrements[index]);
                    }
                }
            }
            Interlocked.Increment(ref AmbientOcclusion.IncrementCount);

            workerDat.destroy();
            workerDat       = null;
            workerObjectDat = null;
        }
Beispiel #3
0
        public void calcualteAO(eAOQuality quality, bool renderWorldObjects, ref float totalTime, ref float peelTime, ref float gatherTime,
                                int startSampleIndex, int endSampleIndex)
        {
            totalTime  = 0;
            peelTime   = 0;
            gatherTime = 0;

            DateTime n = DateTime.Now;


            //should we multithread?
            if (CoreGlobals.mProcessorInfo.NumLogicalProcessors > 1)
            {
                mUsingMultithreading            = true;
                AmbientOcclusion.IncrementCount = 0;
                AOIncrements = new int[TerrainGlobals.getTerrain().getNumXVerts() * TerrainGlobals.getTerrain().getNumZVerts()];
            }
            else
            {
                mUsingMultithreading = false;
            }



            int width  = 512;
            int height = 512;

            int numXSegments = 1;
            int numYSegments = 1;

            //special settings for Final mode
            if (quality == eAOQuality.cAO_Final)
            {
                numXSegments = 4; //what should these values really be?
                numYSegments = 4; // they should scale, so that huge terrain gets more segments..

                //   width = 1024;
                //  height = 1024;

                // mUsingMultithreading = false;
            }

            //clear any handles available so we can use them as we see fit!
            TerrainGlobals.getTerrain().getQuadNodeRoot().clearVisibleDatHandle();
            TerrainGlobals.getVisual().destroyAllHandles();
            TerrainGlobals.getVisual().setHandleGenMode(true);

            blackoutAO(); //so we can gather light data

            Vector3      mWorldMin   = Vector3.Empty;
            Vector3      mWorldMax   = Vector3.Empty;
            BBoundingBox worldBounds = new BBoundingBox();

            calculateWorldBounds(ref mWorldMin, ref mWorldMax, ref worldBounds, renderWorldObjects);


            mPeeler.init(width, height);

            Vector3 rayDir = -BMathLib.unitY;

            rayDir.Normalize();
            Matrix worldToView = Matrix.Identity;
            Matrix viewToProj  = Matrix.Identity;

            int numDesiredSamples = (int)Math.Sqrt((int)quality);

            int            startIndex = 0;
            int            endIndex   = numDesiredSamples;
            List <Vector3> rayDirs    = null;

            if (startSampleIndex != -1)
            {
                rayDirs    = giveStratifiedOnHemiSphere(0, numDesiredSamples, false);
                startIndex = startSampleIndex;
                endIndex   = Math.Min(endSampleIndex, rayDirs.Count);
            }
            else
            {
                rayDirs    = giveStratifiedOnHemiSphere(0, numDesiredSamples, true);
                startIndex = 0;
                endIndex   = rayDirs.Count;
            }

            float rcpNumSamples = 1.0f / (float)(rayDirs.Count);


            int numSamples = endIndex - startIndex;
            //begin our peel & gather process...
            bool ownBeginScene = !BRenderDevice.isInSceneRender();

            if (ownBeginScene)
            {
                BRenderDevice.getDevice().BeginScene();
            }
            for (int dc = startIndex; dc < endIndex; dc++)
            {
                //choose one
                rayDir = -rayDirs[dc];

                computeWorldToView(ref rayDir, ref mWorldMin, ref mWorldMax, out worldToView);
                for (int x = 0; x < numXSegments; x++)
                {
                    for (int y = 0; y < numYSegments; y++)
                    {
                        //calculate our lightspace projection matrix
                        computeViewToProj(ref rayDir, worldBounds, worldToView, out viewToProj,
                                          numXSegments, numYSegments, x, y);


                        //use worker threads..
                        gatherWorkerData wd = new gatherWorkerData(0, 0, TerrainGlobals.getTerrain().getNumXVerts(), TerrainGlobals.getTerrain().getNumZVerts(),
                                                                   width, height,
                                                                   rayDir,
                                                                   worldToView * viewToProj,
                                                                   rcpNumSamples);
                        mPeeler.mDepthArray = null;
                        mPeeler.mDepthArray = wd.fragList;



                        //create our depth layers
                        DateTime dpn = DateTime.Now;
                        mPeeler.depthPeel(ref rayDir, ref worldToView, ref viewToProj, renderWorldObjects);
                        TimeSpan dpts = DateTime.Now - dpn;
                        peelTime += (float)dpts.TotalMinutes;



                        //do final gathering (AO SPECIFIC)
                        if (mUsingMultithreading)
                        {
                            finalGatherMultiThreaded(wd);
                        }
                        else
                        {
                            DateTime fgn = DateTime.Now;
                            finalGatherSingleThreaded(wd);
                            TimeSpan fgts = DateTime.Now - fgn;
                            gatherTime += (float)fgts.TotalMinutes;
                        }
                        wd = null;
                        mPeeler.mDepthArray = null;
                    }
                }
            }



            if (ownBeginScene)
            {
                BRenderDevice.getDevice().EndScene();
            }
            mPeeler.destroy();
            TerrainGlobals.getVisual().setHandleGenMode(false);



            //if we're using multithreading, wait for all our worker threads to finish.
            if (mUsingMultithreading)
            {
                while (AmbientOcclusion.IncrementCount <= numSamples - 1)
                {
                    Thread.Sleep(1);
                }

                float[] AOVals = TerrainGlobals.getEditor().getAmbientOcclusionValues();
                for (int i = 0; i < AOIncrements.Length; i++)
                {
                    AOVals[i] = AOIncrements[i] * rcpNumSamples;
                }
            }



            TimeSpan ts = DateTime.Now - n;

            totalTime = (float)ts.TotalMinutes;
        }
Beispiel #4
0
 void finalGatherMultiThreaded(gatherWorkerData wd)
 {
     ThreadPool.QueueUserWorkItem(new WaitCallback(finalGatherWorker), wd);
     wd = null;
 }