Beispiel #1
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_device == null)
            {
                return;
            }

            // Setup global data
            m_CB_Main.m.iResolution = new float2(panelOutput.Width, panelOutput.Height);
            m_CB_Main.m.tanHalfFOV  = Mathf.Tan(0.5f * Mathf.ToRad(FOV_DEGREES));
            m_CB_Main.m.iGlobalTime = GetGameTime() - m_startTime;
            m_CB_Main.UpdateData();

            // Setup light data
            float3 wsLightPosition = new float3(floatTrackbarControlLightPosX.Value, floatTrackbarControlLightPosY.Value, floatTrackbarControlLightPosZ.Value);
            float3 at = (m_wsLightTargetPosition - wsLightPosition).Normalized;

            if (radioButtonNegativeFreeTarget.Checked)
            {
                at = -at;
            }
            else if (radioButtonHorizontalTarget.Checked)
            {
                at.y = 0;
                at.Normalize();
            }

            float  roll = Mathf.ToRad(floatTrackbarControlLightRoll.Value);
            float3 left, up;

            at.OrthogonalBasis(out left, out up);

            float3 axisX = Mathf.Cos(roll) * left + Mathf.Sin(roll) * up;
            float3 axisY = -Mathf.Sin(roll) * left + Mathf.Cos(roll) * up;

            float radiusX = floatTrackbarControlLightScaleX.Value;
            float radiusY = floatTrackbarControlLightScaleY.Value;

            m_CB_Light.m._luminance = floatTrackbarControlLuminance.Value;
            m_CB_Light.m._wsLight2World.r0.Set(axisX, radiusX);
            m_CB_Light.m._wsLight2World.r1.Set(axisY, radiusY);
            m_CB_Light.m._wsLight2World.r2.Set(at, Mathf.PI * radiusX * radiusY);               // Disk area in W
            m_CB_Light.m._wsLight2World.r3.Set(wsLightPosition, 1);
            m_CB_Light.UpdateData();

            // Upload FGD & LTC tables
            m_tex_MSBRDF_E.SetPS(2);
            m_tex_MSBRDF_Eavg.SetPS(3);
            m_tex_LTC.SetPS(4);
            m_tex_MS_LTC.SetPS(5);

            // =========== Render scene ===========
            m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);

            if (!checkBoxShowDiff.Checked)
            {
                m_device.SetRenderTarget(m_device.DefaultTarget, m_device.DefaultDepthStencil);
                m_device.Clear(m_device.DefaultTarget, float4.Zero);
                m_device.ClearDepthStencil(m_device.DefaultDepthStencil, 1.0f, 0, true, false);

                if (checkBoxShowReference.Checked)
                {
                    // Use expensive reference
                    if (m_shader_RenderScene_Reference.Use())
                    {
                        m_device.RenderFullscreenQuad(m_shader_RenderScene_Reference);
                    }
                }
                else
                {
                    if (m_shader_RenderScene.Use())
                    {
                        m_device.RenderFullscreenQuad(m_shader_RenderScene);
                    }
                }
            }
            else
            {
                // Render reference in RT0
                m_device.SetRenderTarget(m_RT_temp0, m_device.DefaultDepthStencil);
                m_device.ClearDepthStencil(m_device.DefaultDepthStencil, 1.0f, 0, true, false);
                if (m_shader_RenderScene_Reference.Use())
                {
                    m_device.RenderFullscreenQuad(m_shader_RenderScene_Reference);
                }

                // Render LTC in RT1
                m_device.SetRenderTarget(m_RT_temp1, m_device.DefaultDepthStencil);
                m_device.ClearDepthStencil(m_device.DefaultDepthStencil, 1.0f, 0, true, false);
                if (m_shader_RenderScene.Use())
                {
                    m_device.RenderFullscreenQuad(m_shader_RenderScene);
                }

                // Render difference
                m_device.SetRenderStates(RASTERIZER_STATE.NOCHANGE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);
                m_device.SetRenderTarget(m_device.DefaultTarget, null);
                if (m_shader_RenderDiff.Use())
                {
                    m_RT_temp0.SetPS(0);
                    m_RT_temp1.SetPS(1);
                    m_tex_FalseColors.SetPS(2);

                    m_device.RenderFullscreenQuad(m_shader_RenderDiff);
                }
            }

            // =========== Render Light Disk ===========
            m_device.SetRenderTarget(m_device.DefaultTarget, m_device.DefaultDepthStencil);
            if (!checkBoxDebugMatrix.Checked)
            {
                m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);

                if (m_shader_RenderLight.Use())
                {
                    m_prim_disk.Render(m_shader_RenderLight);
                }
            }
            else
            {
                if (m_shader_RenderTestQuad.Use())
                {
                    m_CB_TestQuad.m._wsLight2World.r0.Set(radiusX * axisX, 0);
                    m_CB_TestQuad.m._wsLight2World.r1.Set(radiusY * axisY, 0);
                    m_CB_TestQuad.m._wsLight2World.r2.Set(at, 0);
                    m_CB_TestQuad.m._wsLight2World.r3.Set(wsLightPosition, 1);

                    // Upload the full matrix, although we only really need the 4 non trivial coefficients at indices m11, m13, m31 and m33...
                    int roughnessIndex = (int)Mathf.Floor(63.99f * Mathf.Sqrt(floatTrackbarControlRoughness.Value));
                    int thetaIndex     = (int)Mathf.Floor(63.99f * Mathf.Sqrt(1.0f - Mathf.Cos(Mathf.ToRad(floatTrackbarControlViewAngle.Value))));
                    int matrixIndex    = roughnessIndex + 64 * thetaIndex;

                    double[,]       LTC = radioButtonGGX.Checked ? LTCAreaLight.s_LtcMatrixData_GGX : LTCAreaLight.s_LtcMatrixData_OrenNayar;

                    // NOTE: The LTC inverse matrices stored in the tables are transposed: columns are stored first
                    // So in order to use them in the shaders, we need to compute P * M^-1^T instead of the paper's formulation M^-1 * P
                    //
                    m_CB_TestQuad.m._invM_transposed_r0.Set((float)LTC[matrixIndex, 0], (float)LTC[matrixIndex, 1], (float)LTC[matrixIndex, 2], 0);
                    m_CB_TestQuad.m._invM_transposed_r1.Set((float)LTC[matrixIndex, 3], (float)LTC[matrixIndex, 4], (float)LTC[matrixIndex, 5], 0);
                    m_CB_TestQuad.m._invM_transposed_r2.Set((float)LTC[matrixIndex, 6], (float)LTC[matrixIndex, 7], (float)LTC[matrixIndex, 8], 0);

                    m_CB_TestQuad.UpdateData();

                    m_device.RenderFullscreenQuad(m_shader_RenderTestQuad);
                }
            }

            // Show!
            m_device.Present(false);
        }