Exemplo n.º 1
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_device == null)
            {
                return;
            }

            m_CB_Main.m._sourceIndex  = (uint)integerTrackbarControlShowQuerySourceIndex.Value;
            m_CB_Main.m._renderFlags  = 0U;
            m_CB_Main.m._renderFlags |= radioButtonShowBarycentrics.Checked ? 0x1U : 0U;
            m_CB_Main.m._renderFlags |= radioButtonShowResultsBarycentric.Checked ? 0x2U : 0U;
            m_CB_Main.m._renderFlags |= radioButtonShowResultsSum.Checked ? 0x4U : 0U;
            m_CB_Main.m._renderFlags |= checkBoxShowLog.Checked ? 0x10U : 0U;
            m_CB_Main.m._barycentricDistanceTolerance = floatTrackbarControlResultsTolerance.Value;
            m_CB_Main.m._barycentricBias      = floatTrackbarControlBarycentricBias.Value;
            m_CB_Main.m._diffusionCoefficient = floatTrackbarControlDiffusionConstant.Value;
            m_CB_Main.UpdateData();


            //////////////////////////////////////////////////////////////////////////
            // Simulate heat wave
            if (checkBoxRun.Checked && m_queryNodes.Length > 0 && m_compute_HeatDiffusion.Use())
            {
                m_SB_HeatSource.SetInput(0);
                m_SB_HeatTarget.SetOutput(0);

                m_SB_Nodes.SetInput(1);
                m_SB_LinkTargets.SetInput(2);

                m_SB_SourceIndices.SetInput(3);

                // Simulate heat propagation
                m_compute_HeatDiffusion.Dispatch((m_nodesCount + 63) >> 6, (uint)m_queryNodes.Length, 1);

                // Splat heat sources
                m_compute_SplatHeatSources.Use();
                m_compute_SplatHeatSources.Dispatch(((uint)m_queryNodes.Length + 63) >> 6, 1, 1);

                // Swap source & target
                StructuredBuffer <float> temp = m_SB_HeatTarget;
                m_SB_HeatTarget = m_SB_HeatSource;
                m_SB_HeatSource = temp;

                m_barycentricsDirty = true;
                m_sumDirty          = true;
            }


            //////////////////////////////////////////////////////////////////////////
            // Render
            m_device.Clear(float4.Zero);
            m_device.ClearDepthStencil(m_device.DefaultDepthStencil, 1.0f, 0, true, false);

            m_SB_Nodes.SetInput(0);
            m_SB_LinkTargets.SetInput(1);
            m_SB_LinkSources.SetInput(2);

            m_SB_HeatSource.SetInput(3);
            if (radioButtonShowTemperature.Checked)
            {
                m_tex_FalseColors0.Set(5);
            }
            else if (radioButtonShowBarycentrics.Checked)
            {
                GetBarycentricsBuffer().SetInput(4);
                m_tex_FalseColors1.Set(5);
            }
            else if (radioButtonShowResultsBarycentric.Checked)
            {
                GetBarycentricsBuffer().SetInput(4);
            }
            else if (radioButtonShowResultsSum.Checked)
            {
                GetSumBuffer().SetInput(4);
                m_tex_FalseColors0.Set(5);
            }

            if (m_shader_RenderGraphLink.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);
                m_device.SetRenderTarget(m_device.DefaultTarget, m_device.DefaultDepthStencil);

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderGraphLink, m_totalLinksCount);
            }

            if (m_shader_RenderGraphNode.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.NOCHANGE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.NOCHANGE);
                m_device.SetRenderTarget(m_device.DefaultTarget, null);

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderGraphNode, m_nodesCount);
            }


            //////////////////////////////////////////////////////////////////////////
            // Draw some text
            if (m_displayText != null && m_displayText.Length > 0 && m_shader_RenderText.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);
                m_device.SetRenderTarget(m_device.DefaultTarget, null);

                m_tex_FontAtlas.SetPS(0);
                m_tex_FontRectangle.SetVS(1);

                // Fill text letters
                int totalWidth  = 0;
                int totalHeight = (int)m_tex_FontAtlas.Height;
                for (int i = 0; i < m_displayText.Length; i++)
                {
                    int       letterIndex = m_char2Index[(int)m_displayText[i]];
                    Rectangle rect        = m_fontRectangles[letterIndex];
                    m_SB_Text.m[i].m_letterIndex = (uint)letterIndex;
                    m_SB_Text.m[i].m_offset      = totalWidth;
                    m_SB_Text.m[i].m_ratio       = rect.Width;
                    totalWidth += rect.Width;
                }
                // Normalize
                float norm = 1.0f / totalWidth;
                for (int i = 0; i < m_displayText.Length; i++)
                {
                    m_SB_Text.m[i].m_offset *= norm;
                    m_SB_Text.m[i].m_ratio  *= norm;
                }
                m_SB_Text.Write();
                m_SB_Text.SetInput(2);

                // Setup text rectangle
                const float textHeight_pixels = 20.0f;                          // What we want the text size to be on screen
                float       textWidth_pixels  = totalWidth * textHeight_pixels / totalHeight;

                float2 textSize_proj = new float2(2.0f * textWidth_pixels / panelOutput.Width, 2.0f * textHeight_pixels / panelOutput.Height);

                float2 selectedNodePosition_proj = new float2(2.0f * (m_selectedNodePosition.x - m_CB_Main.m._cameraCenter.x) / m_CB_Main.m._cameraSize.x,
                                                              -2.0f * (m_selectedNodePosition.y - m_CB_Main.m._cameraCenter.y) / m_CB_Main.m._cameraSize.y);
                m_CB_Text.m._position.Set(selectedNodePosition_proj.x - 0.5f * textSize_proj.x, selectedNodePosition_proj.y + 1.0f * textSize_proj.y);                          // Horizontal centering on node position, vertical offset so it's above
                m_CB_Text.m._right.Set(textSize_proj.x, 0.0f);
                m_CB_Text.m._up.Set(0.0f, textSize_proj.y);
                m_CB_Text.UpdateData();

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderText, (uint)m_displayText.Length);
            }

            m_device.Present(false);
        }
Exemplo n.º 2
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_device == null)
            {
                return;
            }

            m_CB_Simulation.m._deltaTime       = floatTrackbarControlDeltaTime.Value;
            m_CB_Simulation.m._springConstant  = floatTrackbarControlSpringConstant.Value;
            m_CB_Simulation.m._dampingConstant = floatTrackbarControlDampingConstant.Value;
            m_CB_Simulation.m._restDistance    = floatTrackbarControlRestDistance.Value;
            m_CB_Simulation.m._K.Set(floatTrackbarControlK0.Value, floatTrackbarControlK1.Value, floatTrackbarControlK2.Value, floatTrackbarControlK3.Value);
            m_CB_Simulation.UpdateData();


//          Point	clientPos = panelOutput.PointToClient( Control.MousePosition );
//          m_CB_Main.m.mousePosition.Set( GRAPH_SIZE * (float) clientPos.X / panelOutput.Width, GRAPH_SIZE * (float) clientPos.Y / panelOutput.Height );
//          m_CB_Main.m.mouseButtons = (uint) ((((Control.MouseButtons & MouseButtons.Left) != 0) ? 1 : 0)
// //											| (((Control.MouseButtons & MouseButtons.Middle) != 0) ? 2 : 0)
//                                          | (m_plotSource ? 2 : 0)
//                                          | (((Control.MouseButtons & MouseButtons.Right) != 0) ? 4 : 0)
//                                          | (Control.ModifierKeys == Keys.Shift ? 8 : 0));
//          m_CB_Main.m.diffusionCoefficient = floatTrackbarControlDiffusionCoefficient.Value;
//          m_CB_Main.m.flags = (uint) (
//                                    (checkBoxShowSearch.Checked ? 1 : 0)
//
//                                    // 2 bits to select 4 display modes
//                                  | (radioButtonShowNormalizedSpace.Checked ? 2 : 0)
//                                  | (radioButtonShowResultsSpace.Checked ? 4 : 0)
//
//                                  | (checkBoxShowLog.Checked ? 8 : 0)
//                              );
//          m_CB_Main.m.sourceIndex = (uint) integerTrackbarControlSimulationSourceIndex.Value;
//          m_CB_Main.m.sourcesCount = (uint) m_simulationHotSpots.Count;
//          m_CB_Main.m.resultsConfinementDistance = floatTrackbarControlResultsSpaceConfinement.Value;

            //////////////////////////////////////////////////////////////////////////
            // Perform simulation
            if (checkBoxRun.Checked && m_shader_ComputeForces.Use())
            {
                // Compute forces
                m_SB_Nodes.SetInput(1);
                m_SB_Links.SetInput(2);

                m_SB_NodeSims[0].SetInput(0);                           // Input positions & velocities
                m_SB_NodeSims[1].SetOutput(0);                          // Output positions & velocities

                m_SB_Forces.SetOutput(1);                               // Simulation forces

                uint groupsCount = (m_nodesCount + 255) >> 8;
                m_shader_ComputeForces.Dispatch(groupsCount, 1, 1);

                // Apply forces
                m_shader_Simulate.Use();
                m_shader_Simulate.Dispatch(groupsCount, 1, 1);

                m_SB_NodeSims[0].RemoveFromLastAssignedSlots();
                m_SB_NodeSims[1].RemoveFromLastAssignedSlotUAV();
                m_SB_Forces.RemoveFromLastAssignedSlotUAV();

                // Swap simulation buffers
                StructuredBuffer <SB_NodeSim> temp = m_SB_NodeSims[0];
                m_SB_NodeSims[0] = m_SB_NodeSims[1];
                m_SB_NodeSims[1] = temp;
            }


            //////////////////////////////////////////////////////////////////////////
            // Render
#if RENDER_GRAPH_PROPER
            if (m_shader_RenderGraphLink.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);
                m_device.SetRenderTarget(m_device.DefaultTarget, m_device.DefaultDepthStencil);

                m_device.Clear(float4.Zero);
                m_device.ClearDepthStencil(m_device.DefaultDepthStencil, 1.0f, 0, true, false);

                m_SB_NodeSims[0].SetInput(0);
                m_SB_Nodes.SetInput(1);
                m_SB_Links.SetInput(2);
                m_SB_LinkSources.SetInput(3);

                m_tex_FalseColors.SetPS(4);

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderGraphLink, m_totalLinksCount);
            }

            if (m_shader_RenderGraphNode.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.NOCHANGE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.NOCHANGE);
                m_device.SetRenderTarget(m_device.DefaultTarget, null);

                m_SB_NodeSims[0].SetInput(0);
                m_SB_Nodes.SetInput(1);
                m_SB_Links.SetInput(2);
                m_SB_LinkSources.SetInput(3);

                m_tex_FalseColors.SetPS(4);

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderGraphNode, m_nodesCount);
            }
#else
            m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);

            if (m_shader_RenderGraph.Use())
            {
                m_device.SetRenderTarget(m_device.DefaultTarget, null);

                m_SB_NodeSims[0].SetInput(0);
                m_SB_Nodes.SetInput(1);

                m_tex_FalseColors.SetPS(4);

                m_device.RenderFullscreenQuad(m_shader_RenderGraph);
            }
#endif

            //////////////////////////////////////////////////////////////////////////
            // Draw some text
            if (m_displayText != null && m_displayText.Length > 0 && m_shader_RenderText.Use())
            {
                m_device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);
                m_device.SetRenderTarget(m_device.DefaultTarget, null);

                m_tex_FontAtlas.SetPS(0);
                m_tex_FontRectangle.SetVS(1);

                // Fill text letters
                int totalWidth  = 0;
                int totalHeight = (int)m_tex_FontAtlas.Height;
                for (int i = 0; i < m_displayText.Length; i++)
                {
                    int       letterIndex = m_char2Index[(int)m_displayText[i]];
                    Rectangle rect        = m_fontRectangles[letterIndex];
                    m_SB_Text.m[i].m_letterIndex = (uint)letterIndex;
                    m_SB_Text.m[i].m_offset      = totalWidth;
                    m_SB_Text.m[i].m_ratio       = rect.Width;
                    totalWidth += rect.Width;
                }
                // Normalize
                float norm = 1.0f / totalWidth;
                for (int i = 0; i < m_displayText.Length; i++)
                {
                    m_SB_Text.m[i].m_offset *= norm;
                    m_SB_Text.m[i].m_ratio  *= norm;
                }
                m_SB_Text.Write();
                m_SB_Text.SetInput(2);

                // Setup text rectangle
                const float textHeight_pixels = 20.0f;                          // What we want the text size to be on screen
                float       textWidth_pixels  = totalWidth * textHeight_pixels / totalHeight;

                float2 textSize_proj = new float2(2.0f * textWidth_pixels / panelOutput.Width, 2.0f * textHeight_pixels / panelOutput.Height);

                float2 selectedNodePosition_proj = new float2(2.0f * (m_selectedNodePosition.x - m_CB_Main.m._cameraCenter.x) / m_CB_Main.m._cameraSize.x,
                                                              -2.0f * (m_selectedNodePosition.y - m_CB_Main.m._cameraCenter.y) / m_CB_Main.m._cameraSize.y);
                m_CB_Text.m._position.Set(selectedNodePosition_proj.x - 0.5f * textSize_proj.x, selectedNodePosition_proj.y + 1.0f * textSize_proj.y);                          // Horizontal centering on node position, vertical offset so it's above
                m_CB_Text.m._right.Set(textSize_proj.x, 0.0f);
                m_CB_Text.m._up.Set(0.0f, textSize_proj.y);
                m_CB_Text.UpdateData();

                m_device.ScreenQuad.RenderInstanced(m_shader_RenderText, (uint)m_displayText.Length);
            }

            //////////////////////////////////////////////////////////////////////////
            // Auto-center camera
            if (checkBoxAutoCenter.Checked)
            {
                m_SB_NodeSims[0].Read();

                float2 minPos = new float2(float.MaxValue, float.MaxValue);
                float2 maxPos = new float2(-float.MaxValue, -float.MaxValue);
                for (int i = 0; i < m_nodesCount; i++)
                {
                    float2 P = m_SB_NodeSims[0].m[i].m_position;
                    if (float.IsNaN(P.x) || float.IsNaN(P.y))
                    {
                        continue;
                    }

                    minPos.Min(P);
                    maxPos.Max(P);
                }

                if (minPos.x > maxPos.x || minPos.y > maxPos.y)
                {
                    minPos.Set(-10, -10);
                    maxPos.Set(10, 10);
                }

                float2 size = maxPos - minPos;
                if (size.x * panelOutput.Height > size.y * panelOutput.Width)
                {
                    // Fit horizontally
                    size.y = size.x * panelOutput.Height / panelOutput.Width;
                }
                else
                {
                    // Fit vertically
                    size.x = size.y * panelOutput.Width / panelOutput.Height;
                }

                m_CB_Main.m._cameraSize   = 1.05f * size;
                m_CB_Main.m._cameraCenter = 0.5f * (minPos + maxPos);

                m_CB_Main.UpdateData();
            }

            m_device.Present(false);
        }
Exemplo n.º 3
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_Device == null)
            {
                return;
            }

            DateTime currentTime = DateTime.Now;
            double   time        = (float)(currentTime - m_StartTime).TotalSeconds;
            double   deltaTime   = (float)(currentTime - m_LastTime).TotalSeconds;

            m_LastTime = currentTime;


            /////////////////////////////////////////////////////////////////////////////////////
            // Build 4D Camera vectors
            const float CAMERA_FOV_4D   = 60.0f;
            const float CAMERA_FAR_CLIP = 8.0f;

            if (checkBoxAuto.Checked)
            {
                const float RADIUS = 1.0f;
                double      alpha  = 0.5 * time * Math.PI;
                double      beta   = 0.3 * time * Math.PI;
                double      gamma  = 0.7 * time * Math.PI;

                m_CameraPosition4D = new float4(RADIUS * (float)(Math.Cos(alpha) * Math.Cos(gamma)), RADIUS * (float)(Math.Cos(beta) * Math.Sin(alpha)), RADIUS * (float)(Math.Cos(beta) * Math.Sin(gamma)), RADIUS * (float)Math.Sin(alpha));
            }
            else
            {
                m_CameraPosition4D = new float4(floatTrackbarControlX.Value, floatTrackbarControlY.Value, floatTrackbarControlZ.Value, floatTrackbarControlW.Value);
            }

            float4 At = (m_CameraTarget4D - m_CameraPosition4D).Normalized;

            m_CB_Camera4D.m._CameraPos        = m_CameraPosition4D;
            m_CB_Camera4D.m._CameraTanHalfFOV = (float)Math.Tan(0.5f * Math.PI / 180.0 * CAMERA_FOV_4D);
            m_CB_Camera4D.m._CameraW          = At;
            m_CB_Camera4D.m._CameraX          = Cross4D(m_CameraUp4D, m_CameraOver4D, At).Normalized;
            m_CB_Camera4D.m._CameraY          = Cross4D(m_CameraOver4D, At, m_CB_Camera4D.m._CameraX).Normalized;
            m_CB_Camera4D.m._CameraZ          = Cross4D(At, m_CB_Camera4D.m._CameraX, m_CB_Camera4D.m._CameraY);

            m_CB_Camera4D.m._CameraX /= CAMERA_FAR_CLIP;
            m_CB_Camera4D.m._CameraY /= CAMERA_FAR_CLIP;
            m_CB_Camera4D.m._CameraZ /= CAMERA_FAR_CLIP;

            m_CB_Camera4D.UpdateData();


            /////////////////////////////////////////////////////////////////////////////////////
            // Simulate
            if (m_CS_Simulator.Use())
            {
                m_SB_Points4D[0].RemoveFromLastAssignedSlots();

                m_SB_Points4D[0].SetInput(0);
                m_SB_Velocities4D.SetInput(1);
                m_SB_Points4D[1].SetOutput(0);

                float timeStep = floatTrackbarControlTimeStep.Value * (float)(deltaTime / 0.01);                        // Compensate for variations in delta time based on the default 10ms timer delay

                m_CB_Simulation.m._Flags    = 0;
                m_CB_Simulation.m._TimeStep = checkBoxSimulate.Checked ? timeStep : 0.0f;
                m_CB_Simulation.UpdateData();

                int groupsCount = POINTS_COUNT >> 8;
                m_CS_Simulator.Dispatch(groupsCount, 1, 1);

                StructuredBuffer <float4> Temp = m_SB_Points4D[0];
                m_SB_Points4D[0] = m_SB_Points4D[1];
                m_SB_Points4D[1] = Temp;
            }


            /////////////////////////////////////////////////////////////////////////////////////
            // Transform points from 4D to 2D using compute shader
            if (m_CS_Project4D.Use())
            {
                m_SB_Points2D.RemoveFromLastAssignedSlots();

                m_SB_Points4D[0].SetInput(0);
                m_SB_Points2D.SetOutput(0);

                int groupsCount = POINTS_COUNT >> 8;
                m_CS_Project4D.Dispatch(groupsCount, 1, 1);
            }


            /////////////////////////////////////////////////////////////////////////////////////
            // Render points
            m_Device.Clear(m_Device.DefaultTarget, float4.Zero);
            m_Device.ClearDepthStencil(m_Device.DefaultDepthStencil, 1.0f, 0, true, false);

            if (m_PS_Display.Use())
            {
                m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);
                m_Device.SetRenderTarget(m_Device.DefaultTarget, m_Device.DefaultDepthStencil);

                m_SB_Points2D.SetInput(0);

                m_PrimQuad.RenderInstanced(m_PS_Display, POINTS_COUNT);
            }

            // Show!
            m_Device.Present(false);
        }
Exemplo n.º 4
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_Device == null)
            {
                return;
            }

            int W = panelOutput.Width;
            int H = panelOutput.Height;

            // Timer
            float lastGameTime = m_CurrentGameTime;

            m_CurrentGameTime = GetGameTime();

            if (m_CurrentGameTime - m_StartFPSTime > 1.0f)
            {
                m_AverageFrameTime = (m_CurrentGameTime - m_StartFPSTime) / Math.Max(1, m_SumFrames);
                m_SumFrames        = 0;
                m_StartFPSTime     = m_CurrentGameTime;
            }
            m_SumFrames++;

            m_CB_Global.m._ScreenSize.Set(W, H, 1.0f / W, 1.0f / H);
            m_CB_Global.m._Time = m_CurrentGameTime;
            m_CB_Global.UpdateData();

            Camera_CameraTransformChanged(m_Camera, EventArgs.Empty);

            m_Device.ClearDepthStencil(m_Device.DefaultDepthStencil, 1.0f, 0, true, false);

            m_Tex_Noise.Set(8);
            m_Tex_Noise4D.Set(9);


            float sigma_t = floatTrackbarControlExtinction.Value;
            float sigma_s = floatTrackbarControlExtinction.Value * floatTrackbarControlAlbedo.Value;
            float phase_g = floatTrackbarControlPhaseAnisotropy.Value;


            //////////////////////////////////////////////////////////////////////////
            // Build Deforming Height Map
            if (m_Shader_UpdateHeightMap.Use())
            {
                m_Tex_HeightMap.RemoveFromLastAssignedSlots();
                m_Tex_HeightMap.SetCSUAV(0);

                m_Shader_UpdateHeightMap.Dispatch(HEIGHTMAP_SIZE >> 4, HEIGHTMAP_SIZE >> 4, 1);

                m_Tex_HeightMap.RemoveFromLastAssignedSlotUAV();
                m_Tex_HeightMap.Set(11);
            }

            //////////////////////////////////////////////////////////////////////////
            // Render volume density
            if (m_shader_GenerateDensity.Use())
            {
                int GroupsCount = VOLUME_SIZE >> 3;

                m_CB_GenerateDensity.m._wsOffset.Set(0.5f * m_CurrentGameTime, 0, 0);
                m_CB_GenerateDensity.UpdateData();

                m_Tex_VolumeDensity.RemoveFromLastAssignedSlots();
                m_Tex_VolumeDensity.SetCSUAV(0);

                m_shader_GenerateDensity.Dispatch(GroupsCount, GroupsCount, GroupsCount);

                m_Tex_VolumeDensity.RemoveFromLastAssignedSlotUAV();
            }

            //////////////////////////////////////////////////////////////////////////
            // Splat photons
            {
                int GroupsCount = PHOTONS_COUNT >> 8;                           // 256 threads per group

                m_Tex_AccumPhoton3D.RemoveFromLastAssignedSlots();
                m_Tex_AccumPhoton3D.SetCSUAV(2);

                // Clear
                if (m_Shader_ClearAccumulator.Use())
                {
                    m_Shader_ClearAccumulator.Dispatch(VOLUME_SIZE >> 2, VOLUME_SIZE >> 2, VOLUME_SIZE >> 2);
                }

                // Init
                if (m_Shader_InitPhotons.Use())
                {
                    m_SB_PhotonInfos.RemoveFromLastAssignedSlots();
                    m_SB_Photons[0].RemoveFromLastAssignedSlots();

                    m_SB_PhotonInfos.SetOutput(0);
//					m_SB_Photons[0].SetOutput( 1 );
                    m_Shader_InitPhotons.Dispatch(GroupsCount, 1, 1);
                }

                // Trace
                if (m_Shader_TracePhotons.Use())
                {
                    m_CB_TracePhotons.m._Sigma_t = sigma_t;
                    m_CB_TracePhotons.UpdateData();

                    m_SB_PhotonInfos.SetInput(0);
                    m_SB_Photons[0].SetInput(1);
                    m_Tex_VolumeDensity.Set(10);

                    m_Shader_TracePhotons.Dispatch(GroupsCount, 1, 1);
                }

                m_Tex_AccumPhoton3D.RemoveFromLastAssignedSlotUAV();
            }

            //////////////////////////////////////////////////////////////////////////
            // Render room
            if (m_Shader_RenderRoom.Use())
            {
                m_Device.SetRenderStates(RASTERIZER_STATE.CULL_FRONT, DEPTHSTENCIL_STATE.READ_WRITE_DEPTH_LESS, BLEND_STATE.DISABLED);
                m_Device.SetRenderTarget(m_Tex_TempBackBuffer, m_Device.DefaultDepthStencil);

                m_CB_RenderRoom.UpdateData();

                m_Prim_Cube.Render(m_Shader_RenderRoom);
            }

            //////////////////////////////////////////////////////////////////////////
            // Render sphere
            if (m_Shader_RenderSphere.Use())
            {
                m_Device.SetRenderStates(RASTERIZER_STATE.CULL_BACK, DEPTHSTENCIL_STATE.NOCHANGE, BLEND_STATE.NOCHANGE);
//				m_Device.SetRenderTarget( m_Tex_TempBackBuffer, m_Device.DefaultDepthStencil );

                m_CB_RenderSphere.UpdateData();

                m_Prim_Sphere.Render(m_Shader_RenderSphere);
            }

            //////////////////////////////////////////////////////////////////////////
            // Ray-March volume
            if (m_Shader_RayMarcher.Use())
            {
                m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);
                m_Device.SetRenderTargets(W, H, new IView[] { m_Tex_Scattering.GetView(0, 1, 0, 1), m_Tex_Scattering.GetView(0, 1, 1, 1) }, null);

                m_Tex_AccumPhoton3D.Set(1);

                m_CB_RayMarch.m._Sigma_t = sigma_t;
                m_CB_RayMarch.m._Sigma_s = sigma_s;
                m_CB_RayMarch.m._Phase_g = phase_g;
                m_CB_RayMarch.UpdateData();

                m_Prim_Quad.Render(m_Shader_RayMarcher);
            }

            //////////////////////////////////////////////////////////////////////////
            // Post-process
            if (m_Shader_PostProcess.Use())
            {
                m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);
                m_Device.SetRenderTarget(m_Device.DefaultTarget, null);

                m_CB_PostProcess.UpdateData();

                m_Tex_TempBackBuffer.SetPS(0);
                m_Tex_Scattering.SetPS(1);

                m_Prim_Quad.Render(m_Shader_PostProcess);

                m_Tex_Scattering.RemoveFromLastAssignedSlots();
            }

            // Show!
            m_Device.Present(false);

            // Update window text
            Text = "GloubiBoule - Avg. Frame Time " + (1000.0f * m_AverageFrameTime).ToString("G5") + " ms (" + (1.0f / m_AverageFrameTime).ToString("G5") + " FPS)";
        }
Exemplo n.º 5
0
        void Application_Idle(object sender, EventArgs e)
        {
            if (m_Device == null || m_closing)
            {
                return;
            }
            if (m_Tex_CubeMap == null)
            {
                return;
            }

            m_CB_Main.m._Resolution = new float3(panelOutput.Width, panelOutput.Height, 0);
            DateTime Now       = DateTime.Now;
            float    DeltaTime = (float)(Now - m_lastTime).TotalSeconds;

            m_lastTime = Now;
            m_CB_Main.m._GlobalTime = (float)(Now - m_startTime).TotalSeconds;
            m_CB_Main.UpdateData();

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.DISABLED);

            //////////////////////////////////////////////////////////////////////////
            // 1] Render to the HDR buffer
            if (m_Shader_RenderHDR.Use())
            {
                m_Device.SetRenderTarget(m_Tex_HDR, null);
                if (m_Tex_CubeMap != null)
                {
                    m_Tex_CubeMap.SetPS(0);
                }
                m_Device.RenderFullscreenQuad(m_Shader_RenderHDR);
            }

            //////////////////////////////////////////////////////////////////////////
            // 2] Compute auto-exposure
            if (m_Shader_ComputeTallHistogram.Use())
            {
                // Build a 128xH "tall histogram"
                m_Device.RemoveRenderTargets();
                m_Tex_HDR.SetCS(0);
                m_Tex_TallHistogram.SetCSUAV(0);
                m_Shader_ComputeTallHistogram.Dispatch(1, m_Tex_TallHistogram.Height, 1);
            }
            if (m_Shader_FinalizeHistogram.Use())
            {
                // Build the 128x1 standard histogram
                m_Tex_Histogram.SetCSUAV(0);
                m_Tex_TallHistogram.SetCS(0);
                m_Shader_FinalizeHistogram.Dispatch(128, 1, 1);
            }
            if (m_Shader_ComputeAutoExposure.Use())
            {
                // Compute auto-exposure from histogram and last value
                m_Buffer_AutoExposureSource.SetInput(0);
                m_Buffer_AutoExposureTarget.SetOutput(0);
                m_Tex_Histogram.SetCS(1);

                float EV = floatTrackbarControlExposure.Value;

                m_CB_AutoExposure.m._delta_time = Math.Max(0.01f, Math.Min(1.0f, DeltaTime));
                if (checkBoxEnable.Checked && checkBoxAutoExposureUseWhiteLevel.Checked)
                {
                    m_CB_AutoExposure.m._white_level = tabControlToneMappingTypes.SelectedIndex == 0 ? floatTrackbarControlIG_WhitePoint.Value : floatTrackbarControlWhitePoint.Value;
                }
                else
                {
                    m_CB_AutoExposure.m._white_level = 1.0f;
                }

                m_CB_AutoExposure.m._clip_shadows    = 0.0f;                                                                     // (0.0) Shadow cropping in histogram (first buckets will be ignored, leading to brighter image)
                m_CB_AutoExposure.m._clip_highlights = 1.0f;                                                                     // (1.0) Highlights cropping in histogram (last buckets will be ignored, leading to darker image)
                m_CB_AutoExposure.m._EV                   = EV;                                                                  // (0.0) Your typical EV setting
                m_CB_AutoExposure.m._fstop_bias           = 0.0f;                                                                // (0.0) F-stop number bias to override automatic computation (NOTE: This will NOT change exposure, only the F number)
                m_CB_AutoExposure.m._reference_camera_fps = 30.0f;                                                               // (30.0) Default camera at 30 FPS
                m_CB_AutoExposure.m._adapt_min_luminance  = m_advancedParmsForm.floatTrackbarControlMinLuminance.Value;          // (0.03) Prevents the auto-exposure to adapt to luminances lower than this
                m_CB_AutoExposure.m._adapt_max_luminance  = m_advancedParmsForm.floatTrackbarControlMaxLuminance.Value;          // (2000.0) Prevents the auto-exposure to adapt to luminances higher than this
                m_CB_AutoExposure.m._adapt_speed_up       = m_advancedParmsForm.floatTrackbarControlAdaptationSpeedBright.Value; // (0.99) Adaptation speed from low to high luminances
                m_CB_AutoExposure.m._adapt_speed_down     = m_advancedParmsForm.floatTrackbarControlAdaptationSpeedDark.Value;   // (0.99) Adaptation speed from high to low luminances
                m_CB_AutoExposure.UpdateData();

                m_Shader_ComputeAutoExposure.Dispatch(1, 1, 1);

                // Swap source & target for next frame
                StructuredBuffer <autoExposure_t> temp = m_Buffer_AutoExposureSource;
                m_Buffer_AutoExposureSource = m_Buffer_AutoExposureTarget;
                m_Buffer_AutoExposureTarget = temp;
            }

            //////////////////////////////////////////////////////////////////////////
            // 3] Apply tone mapping
            if (m_Shader_ToneMapping.Use())
            {
                m_Device.SetRenderTarget(m_Device.DefaultTarget, null);

                float mouseU         = 1.0f;
                float mouseV         = 0.0f;
                Point clientMousePos = panelOutput.PointToClient(Control.MousePosition);
                if (clientMousePos.X >= 0 && clientMousePos.X < panelOutput.Width &&
                    clientMousePos.Y >= 0 && clientMousePos.Y < panelOutput.Height)
                {
                    mouseU = (float)clientMousePos.X / panelOutput.Width;
                    mouseV = (float)clientMousePos.Y / panelOutput.Height;
                }

                m_CB_ToneMapping.m._Exposure = 1.0f;                //(float) Math.Pow( 2, floatTrackbarControlExposure.Value );
                m_CB_ToneMapping.m._Flags    = (checkBoxEnable.Checked ? 1U : 0U)
                                               | (checkBoxDebugLuminanceLevel.Checked ? 2U : 0U)
                                               | (checkBoxShowHistogram.Checked ? 4U : 0U)
                                               | (tabControlToneMappingTypes.SelectedIndex == 0 ? 0U : 8U)
                                               | (checkBoxLuminanceOnly.Checked ? 16U : 0U);
                if (tabControlToneMappingTypes.SelectedIndex == 0)
                {
                    m_CB_ToneMapping.m._WhitePoint = floatTrackbarControlIG_WhitePoint.Value;
                    m_CB_ToneMapping.m._A          = floatTrackbarControlIG_BlackPoint.Value;
                    m_CB_ToneMapping.m._B          = Math.Min(m_CB_ToneMapping.m._WhitePoint - 1e-3f, floatTrackbarControlIG_JunctionPoint.Value);
                    m_CB_ToneMapping.m._C          = ComputeToeStrength();           // floatTrackbarControlIG_ToeStrength.Value;
                    m_CB_ToneMapping.m._D          = ComputeShoulderStrength();      // floatTrackbarControlIG_ShoulderStrength.Value;

                    // Compute junction factor
                    float b = m_CB_ToneMapping.m._A;
                    float w = m_CB_ToneMapping.m._WhitePoint;
                    float t = m_CB_ToneMapping.m._C;
                    float s = m_CB_ToneMapping.m._D;
                    float c = m_CB_ToneMapping.m._B;
                    m_CB_ToneMapping.m._E = (1.0f - t) * (c - b) / ((1.0f - s) * (w - c) + (1.0f - t) * (c - b));
                }
                else
                {
                    // Hable Filmic
                    m_CB_ToneMapping.m._WhitePoint = floatTrackbarControlWhitePoint.Value;
                    m_CB_ToneMapping.m._A          = floatTrackbarControlA.Value;
                    m_CB_ToneMapping.m._B          = floatTrackbarControlB.Value;
                    m_CB_ToneMapping.m._C          = floatTrackbarControlC.Value;
                    m_CB_ToneMapping.m._D          = floatTrackbarControlD.Value;
                    m_CB_ToneMapping.m._E          = floatTrackbarControlE.Value;
                    m_CB_ToneMapping.m._F          = floatTrackbarControlF.Value;
                }
                m_CB_ToneMapping.m._DebugLuminanceLevel = floatTrackbarControlDebugLuminanceLevel.Value;
                m_CB_ToneMapping.m._MouseU = mouseU;
                m_CB_ToneMapping.m._MouseV = mouseV;
                m_CB_ToneMapping.UpdateData();

                m_Buffer_AutoExposureSource.SetInput(0);
                m_Tex_Histogram.SetPS(1);
                m_Tex_HDR.SetPS(2);
                m_Tex_TallHistogram.SetPS(3);

                m_Device.RenderFullscreenQuad(m_Shader_ToneMapping);

                m_Tex_TallHistogram.RemoveFromLastAssignedSlots();
                m_Tex_Histogram.RemoveFromLastAssignedSlots();
                m_Tex_HDR.RemoveFromLastAssignedSlots();
            }

            // Show!
            m_Device.Present(false);
        }
Exemplo n.º 6
0
        private void buttonShootPhotons_Click(object sender, EventArgs e)
        {
            //////////////////////////////////////////////////////////////////////////
            // 1] Build initial photon positions and directions
            float3 SunDirection = new float3(0, 1, 0).Normalized;

            uint InitialDirection = PackPhotonDirection(-SunDirection);
            uint InitialColor     = EncodeRGBE(new float3(1.0f, 1.0f, 1.0f));

            int   PhotonsPerSize     = (int)Math.Floor(Math.Sqrt(PHOTONS_COUNT));
            float PhotonCoverageSize = CLOUDSCAPE_SIZE / PhotonsPerSize;

            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                int Z = PhotonIndex / PhotonsPerSize;
                int X = PhotonIndex - Z * PhotonsPerSize;

                float x = ((X + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;
                float z = ((Z + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;

                m_SB_Photons.m[PhotonIndex].Position.Set(x, z);
                m_SB_Photons.m[PhotonIndex].Direction = InitialDirection;
                m_SB_Photons.m[PhotonIndex].RGBE      = InitialColor;

#if DEBUG_INFOS
                m_SB_Photons.m[PhotonIndex].Infos.Set(0, 0, 0, 0);                      // Will store scattering events counter, marched length, steps count, etc.
#endif
            }
            m_SB_Photons.Write();


            //////////////////////////////////////////////////////////////////////////
            // 2] Initialize layers & textures

            // 2.1) Fill source bucket with all photons
            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                m_SB_PhotonLayerIndices.m[PhotonIndex] = 0U;                    // Starting from top layer, direction is down
            }
            m_SB_PhotonLayerIndices.Write();

            // 2.2) Clear photon splatting texture
            m_Device.Clear(m_Tex_PhotonLayers_Flux, new float4(0, 0, 0, 0));
            m_Device.Clear(m_Tex_PhotonLayers_Direction, new float4(0, 0, 0, 0));


            //////////////////////////////////////////////////////////////////////////
            // 3] Prepare buffers & states

            m_CloudScapeSize.Set(CLOUDSCAPE_SIZE, floatTrackbarControlCloudscapeThickness.Value, CLOUDSCAPE_SIZE);

            // 3.1) Prepare density field
            m_Tex_DensityField.SetCS(2);

            // 3.2) Constant buffer for photon shooting
            m_CB_PhotonShooterInput.m.LayersCount     = LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.MaxScattering   = 30;
            m_CB_PhotonShooterInput.m.LayerThickness  = m_CloudScapeSize.y / LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.SigmaScattering = floatTrackbarControlSigmaScattering.Value;              // 0.04523893421169302263386206471922f;	// re=6µm Gamma=2 N0=4e8   Sigma_t = N0 * PI * re²
            m_CB_PhotonShooterInput.m.CloudScapeSize  = m_CloudScapeSize;

            // 3.3) Prepare photon splatting buffer & states
            m_CB_SplatPhoton.m.CloudScapeSize = m_CloudScapeSize;
            m_CB_SplatPhoton.m.SplatSize      = 1.0f * (2.0f / m_Tex_PhotonLayers_Flux.Width);
            m_CB_SplatPhoton.m.SplatIntensity = 1.0f;                                                                // 1000.0f / PHOTONS_COUNT;

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.ADDITIVE); // Splatting is additive
            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();


            //////////////////////////////////////////////////////////////////////////
            // 4] Splat initial photons to the top layer
            m_PS_PhotonSplatter.Use();

            m_SB_Photons.SetInput(0);                           // RO version for splatting
            m_SB_PhotonLayerIndices.SetInput(1);                // RO version for splatting

            m_CB_SplatPhoton.m.LayerIndex = 0U;
            m_CB_SplatPhoton.UpdateData();

            m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                      new View3D[] {
                m_Tex_PhotonLayers_Flux.GetView(0, 0, 0, 1),
                m_Tex_PhotonLayers_Direction.GetView(0, 0, 0, 1)
            }, null);
            m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);


            //////////////////////////////////////////////////////////////////////////
            // 5] Render loop
            int BatchesCount = PHOTONS_COUNT / PHOTON_BATCH_SIZE;

            m_SB_ProcessedPhotonsCounter.SetOutput(2);

            for (int BounceIndex = 0; BounceIndex < BOUNCES_COUNT; BounceIndex++)
            {
                // 5.1] Process every layers from top to bottom
                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = 0; LayerIndex < LAYERS_COUNT; LayerIndex++)
                {
                    // 5.1.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex+1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex;

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

#if DEBUG_INFOS
//DEBUG Read back photons buffer
                    m_SB_Photons.Read();
// m_SB_PhotonLayerIndices.Read();
// Verify photons have the same energy and were indeed transported to the next layer unaffected (this test is only valid if the density field is filled with 0s)
// for ( int PhotonIndex=0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++ )
// {
//  if ( m_SB_Photons.m[PhotonIndex].RGBE != 0x80FFFFFF )
//      throw new Exception( "Intensity changed!" );
//  if ( m_SB_PhotonLayerIndices.m[PhotonIndex] != LayerIndex+1 )
//      throw new Exception( "Unexpected layer index!" );
// }
//DEBUG
#endif

                    // 5.1.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                   // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                        // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex + 1);
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex + 1, 1),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex + 1, 1)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
                // ================================================================================
                // 5.2] Process every layers from bottom to top
                BounceIndex++;
                if (BounceIndex >= BOUNCES_COUNT)
                {
                    break;
                }

                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = LAYERS_COUNT; LayerIndex > 0; LayerIndex--)
                {
                    // 5.2.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex-1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex | 0x80000000U;                      // <= MSB indicates photons are going up

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

                    // 5.2.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                             // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                                  // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex - 1) | 0x80000000U; // <= MSB indicates photons are going up
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex - 1, 0),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex - 1, 0)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
            }

            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();

            Render();
        }
Exemplo n.º 7
0
        private void buttonShootPhotons_Click(object sender, EventArgs e)
        {
            //////////////////////////////////////////////////////////////////////////
            // 1] Shoot the photons and store the result into the structured buffer
            m_CS_PhotonShooter.Use();

            m_SB_Random.SetInput(0);
            m_SB_PhaseQuantile.SetInput(1);
            m_SB_PhotonOut.SetOutput(0);

            m_CB_PhotonShooterInput.m.MaxScattering    = 100;
            m_CB_PhotonShooterInput.m.InitialPosition  = new float2(floatTrackbarControlPositionX.Value, floatTrackbarControlPositionZ.Value);                                                                 // Center of the cube side
            m_CB_PhotonShooterInput.m.InitialIncidence = new float2(floatTrackbarControlOrientationPhi.Value * (float)Math.PI / 180.0f, floatTrackbarControlOrientationTheta.Value * (float)Math.PI / 180.0f); // Vertical incidence
            m_CB_PhotonShooterInput.m.CubeSize         = floatTrackbarControlCubeSize.Value;                                                                                                                   // Try a 100m thick cube
//			m_CB_PhotonShooterInput.m.SigmaScattering = 0.5f;
            m_CB_PhotonShooterInput.m.SigmaScattering = 0.04523893421169302263386206471922f;                                                                                                                   // re=6µm Gamma=2 N0=4e8   Sigma_t = N0 * PI * re²
            m_CB_PhotonShooterInput.m.FullSurface     = (uint)(checkBoxFullSurface.Checked ? 1 : 0);
            //	mean free path = 22.1048m

            int BatchesCount = PHOTONS_COUNT / PHOTON_BATCH_SIZE;

            for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
            {
                m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                m_CB_PhotonShooterInput.UpdateData();

                m_CS_PhotonShooter.Dispatch(1, 1, 1);

                m_Device.Present(true);
                progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex) / BatchesCount;
                Application.DoEvents();
            }

            m_SB_PhotonOut.RemoveFromLastAssignedSlots();

            //////////////////////////////////////////////////////////////////////////
            // Splat photons
            m_Tex_Photons.RemoveFromLastAssignedSlots();
            m_Device.Clear(m_Tex_Photons, new float4(0, 0, 0, 0));

            m_SB_PhotonOut.SetInput(0);

            // Splat data
            m_CB_SplatPhoton.m.SplatSize = 2.0f * (2.0f / m_Tex_Photons.Width);
            m_CB_SplatPhoton.UpdateData();

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.ALPHA_BLEND);

            View2D[] Views = new View2D[] {
                m_Tex_Photons.GetView(0, 0, 6 * 0, 6),
                m_Tex_Photons.GetView(0, 0, 6 * 1, 6),
                m_Tex_Photons.GetView(0, 0, 6 * 2, 6),
            };
            m_Device.SetRenderTargets(m_Tex_Photons.Width, m_Tex_Photons.Height, Views, null);

            m_PS_PhotonSplatter.Use();
            m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);

            // Splat additive intensity
            m_CB_SplatPhoton.m.SplatSize      = 8.0f * (2.0f / m_Tex_Photons.Width);
            m_CB_SplatPhoton.m.SplatIntensity = 1000.0f / PHOTONS_COUNT;
            m_CB_SplatPhoton.UpdateData();

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.ADDITIVE);

            Views = new View2D[] { m_Tex_Photons.GetView(0, 0, 6 * 3, 6) };
            m_Device.SetRenderTargets(m_Tex_Photons.Width, m_Tex_Photons.Height, Views, null);

            m_PS_PhotonSplatter_Intensity.Use();
            m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter_Intensity, PHOTONS_COUNT);

            m_Tex_Photons.RemoveFromLastAssignedSlots();

            Render();
        }