internal RenderStateBlock GetDefaultRenderStateBlock(bool stencilTest, StencilTestOptions stencilTestOptions) { RenderStateBlock renderStateBlock = new RenderStateBlock(); if (stencilTest && m_stencilTestState != StencilTestState.None) { int stencilMask = StencilMaskAllocator.GetCurrentBit(); renderStateBlock.mask = RenderStateMask.Stencil; renderStateBlock.stencilReference = stencilMask; if (m_stencilTestState == StencilTestState.BothSide) { if ((stencilTestOptions & StencilTestOptions.PreventOverwriting) == 0) { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, 0, CompareFunction.Equal, StencilOp.Keep, StencilOp.Keep, StencilOp.Keep); } else { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, (byte)stencilMask, CompareFunction.Equal, StencilOp.Zero, StencilOp.Keep, StencilOp.Keep); } } else { if ((stencilTestOptions & StencilTestOptions.PreventOverwriting) == 0) { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, 0, CompareFunction.NotEqual, StencilOp.Keep, StencilOp.Keep, StencilOp.Keep); } else { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, (byte)stencilMask, CompareFunction.NotEqual, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep); } } } return(renderStateBlock); }
protected void GetDefaultDrawSettings(ref RenderingData renderingData, Material material, out DrawingSettings drawingSettings, out FilteringSettings filteringSettings, out RenderStateBlock renderStateBlock) { base.GetDefaultDrawSettings(renderingData.cameraData.camera, material, out drawingSettings, out filteringSettings); drawingSettings.enableDynamicBatching = renderingData.supportsDynamicBatching; drawingSettings.perObjectData = perObjectData; renderStateBlock = new RenderStateBlock(); if (useStencilTest && m_stencilTestState != StencilTestState.None) { int stencilMask = StencilMaskAllocator.GetCurrentBit(); renderStateBlock.mask = RenderStateMask.Stencil; renderStateBlock.stencilReference = stencilMask; if (m_stencilTestState == StencilTestState.BothSide) { if ((m_stencilTestOptions & StencilTestOptions.PreventOverwriting) == 0) { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, 0, CompareFunction.Equal, StencilOp.Keep, StencilOp.Keep, StencilOp.Keep); } else { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, (byte)stencilMask, CompareFunction.Equal, StencilOp.Zero, StencilOp.Keep, StencilOp.Keep); } } else { if ((m_stencilTestOptions & StencilTestOptions.PreventOverwriting) == 0) { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, 0, CompareFunction.NotEqual, StencilOp.Keep, StencilOp.Keep, StencilOp.Keep); } else { renderStateBlock.stencilState = new StencilState(true, (byte)stencilMask, (byte)stencilMask, CompareFunction.NotEqual, StencilOp.Replace, StencilOp.Keep, StencilOp.Keep); } } } }
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); }