Ejemplo n.º 1
0
 internal void ClearStencil(ScriptableRenderContext context, Material nonSharedStencilMaterial, StencilTestOptions stencilTestOptions)
 {
     if (m_stencilTestState != StencilTestState.None)
     {
         if ((stencilTestOptions & StencilTestOptions.ClearStencil) == StencilTestOptions.ClearStencil)
         {
             CommandBuffer commandBuffer = CommandBufferPool.Get();
             if (m_stencilTestState == StencilTestState.BackfaceOnly)
             {
                 if ((stencilTestOptions & StencilTestOptions.PreventOverwriting) == 0)
                 {
                     commandBuffer.DrawMesh(GetFrustumMesh(), transform.localToWorldMatrix, nonSharedStencilMaterial, 0, 1);
                 }
                 else
                 {
                     ClearFullscreenStencil(commandBuffer);
                     StencilMaskAllocator.Init(StencilMaskAllocator.availableBits);                             // reset stencil allocator
                 }
             }
             else
             {
                 commandBuffer.DrawMesh(GetFrustumMesh(), transform.localToWorldMatrix, nonSharedStencilMaterial, 0, 3);
             }
             context.ExecuteCommandBuffer(commandBuffer);
             CommandBufferPool.Release(commandBuffer);
         }
         else
         {
             // allocate new stencil bit for the next projector
             StencilMaskAllocator.AllocateSingleBit();
         }
         m_stencilTestState = StencilTestState.None;
     }
 }
Ejemplo n.º 2
0
        private void Draw(DrawState state, Vector2 scale, byte clipDepth)
        {
            Element parent = this.parent;


            Matrix         matrix;
            GraphicsDevice device = null;

            if (parent == null)
            {
                if (state.DrawTarget.MultiSampleType != MultiSampleType.None)
                {
                    device = state.BeginGetGraphicsDevice(StateFlag.None);
                    device.RenderState.MultiSampleAntiAlias = false;
                }

                this.clipTestActive = false;

                DeviceRenderState rstate = new DeviceRenderState();
                rstate.DepthColourCull.DepthWriteEnabled = false;
                rstate.DepthColourCull.DepthTestEnabled  = false;

                state.PushRenderState(ref rstate);

                if (camera == null)
                {
                    camera = state.UserValues[cameraID] as Xen.Camera.Camera2D;
                    if (camera == null)
                    {
                        camera = new Xen.Camera.Camera2D(true);
                        state.UserValues[cameraID] = camera;
                    }
                }

                state.PushCamera(camera);
            }
            else
            {
                this.clipTestActive = parent.clipTestActive | parent.ClipsChildren;
            }

            StencilTestState stencilState = new StencilTestState();

            if (clipTestActive)
            {
                stencilState.Enabled              = true;
                stencilState.ReferenceValue       = clipDepth;
                stencilState.StencilFunction      = CompareFunction.Equal;
                stencilState.StencilPassOperation = StencilOperation.Keep;
            }

            bool clearStencil = false;

            if (this.ClipsChildren)
            {
                clearStencil = clipDepth == 255;
                clipDepth--;

                if (!clipTestActive)
                {
                    //check there actually is a stencil buffer
#if DEBUG
                    DepthFormat format = state.DrawTarget.SurfaceDepthFormat ?? DepthFormat.Unknown;

                    if (format != DepthFormat.Depth24Stencil8)
                    {
                        throw new InvalidOperationException("ElementRect.ClipChildren requires the DrawTarget has a valid Depth Buffer with an 8bit Stencil Buffer");
                    }
#endif

                    stencilState.Enabled              = true;
                    stencilState.ReferenceValue       = clipDepth;
                    stencilState.StencilPassOperation = StencilOperation.Replace;
                }
                else
                {
                    stencilState.StencilPassOperation = StencilOperation.Decrement;
                }
            }

            if ((scale.X != 0 && scale.Y != 0))
            {
                Vector2 size = ElementSize;
                GetDisplayMatrix(out matrix, scale, ref size);

                state.PushWorldMatrixMultiply(ref matrix);

                BindShader(state, false);

                state.RenderState.AlphaBlend  = blend;
                state.RenderState.StencilTest = stencilState;


                if (!UseSize)
                {
                    size = new Vector2(1, 1);
                }
                else
                if (IsNormalised)
                {
                    size *= scale;
                }

                PreDraw(size);

                DrawElement(state);

                List <Element> children = Children;
                if (children != null)
                {
                    foreach (Element child in children)
                    {
                        if (((IDraw)child).CullTest(state))
                        {
                            child.Draw(state, size, clipDepth);
                        }
                    }
                }

                if (clearStencil)
                {
                    BindShader(state, true);
                    stencilState                      = new StencilTestState();
                    stencilState.Enabled              = true;
                    stencilState.StencilFunction      = CompareFunction.Never;
                    stencilState.StencilFailOperation = StencilOperation.Zero;
                    state.RenderState.StencilTest     = stencilState;

                    DrawElement(state);
                }

                state.PopWorldMatrix();
            }


            if (parent == null)
            {
                state.PopRenderState();
                state.PopCamera();
            }

            if (device != null)
            {
                device.RenderState.MultiSampleAntiAlias = true;
                state.EndGetGraphicsDevice();
            }
        }
Ejemplo n.º 3
0
        internal void WriteFrustumStencil(ScriptableRenderContext context, Camera camera, Material nonSharedStencilMaterial)
        {
            int stencilMask = StencilMaskAllocator.GetCurrentBit();

            if (stencilMask == 0)
            {
                m_stencilTestState = StencilTestState.None;
                Debug.LogError("Couldn't use stencil test. No stencil bits available. Please change Stencil Mask value in Projector Renderer Feature.");
                return;
            }

            // check if the frustum intersect with camera near plane.
            Vector3 cameraLocalPos = transform.InverseTransformPoint(camera.transform.position);
            Vector3 nearClipRect   = camera.nearClipPlane * 2.0f * Mathf.Tan(Mathf.Deg2Rad * camera.fieldOfView) * new Vector3(camera.aspect, 1.0f, 0.0f);

            nearClipRect.z = camera.nearClipPlane;
            Matrix4x4 localToCamera = camera.worldToCameraMatrix * transform.localToWorldMatrix;
            bool      clipped       = true;

            for (int i = 0; i < 6; ++i)
            {
                int     face         = i >> 1;
                int     n            = i & 1;
                int     axis1        = (face + 1 + n) % 3;
                int     axis2        = (face + 2 - n) % 3;
                int     vtx1         = n * (1 << face);
                int     vtx2         = vtx1 + (1 << axis1);
                int     vtx3         = vtx1 + (1 << axis2);
                Plane   frustumPlane = new Plane(GetProjectorFrustumVertex(vtx1), GetProjectorFrustumVertex(vtx2), GetProjectorFrustumVertex(vtx3));
                Vector3 offset       = Vector3.Scale(nearClipRect, localToCamera.MultiplyVector(frustumPlane.normal));
                if (Mathf.Abs(offset.x) + Mathf.Abs(offset.y) + Mathf.Max(0, offset.z) < frustumPlane.GetDistanceToPoint(cameraLocalPos))
                {
                    clipped = false;
                    break;
                }
            }
            CommandBuffer commandBuffer = CommandBufferPool.Get();

            if (StencilMaskAllocator.loopFlag)
            {
                StencilMaskAllocator.ClearLoopFlag();
                ClearFullscreenStencil(commandBuffer);
            }
            nonSharedStencilMaterial.SetFloat(s_shaderPropIdStencilRef, stencilMask);
            nonSharedStencilMaterial.SetFloat(s_shaderPropIdStencilMask, stencilMask);
            Mesh frustumMesh = GetFrustumMesh();

            if (clipped)
            {
                m_stencilTestState = StencilTestState.BackfaceOnly;
                commandBuffer.DrawMesh(frustumMesh, transform.localToWorldMatrix, nonSharedStencilMaterial, 0, 2);
            }
            else
            {
                m_stencilTestState = StencilTestState.BothSide;
                commandBuffer.DrawMesh(frustumMesh, transform.localToWorldMatrix, nonSharedStencilMaterial, 0, 0);
                commandBuffer.DrawMesh(frustumMesh, transform.localToWorldMatrix, nonSharedStencilMaterial, 0, 1);
            }
            context.ExecuteCommandBuffer(commandBuffer);
            CommandBufferPool.Release(commandBuffer);
        }