예제 #1
0
        public void calcualteAO(eAOQuality quality, bool renderWorldObjects)
        {
            float totalTime  = 0;
            float peelTime   = 0;
            float gatherTime = 0;

            calcualteAO(quality, renderWorldObjects, ref totalTime, ref peelTime, ref gatherTime);
        }
예제 #2
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;
        }