private void BuildPhaseQuantileBuffer(System.IO.FileInfo _PhaseQuantileFileName) { const int QUANTILES_COUNT = 65536; Reg(m_SB_PhaseQuantile = new StructuredBuffer <float>(m_Device, 2 * QUANTILES_COUNT, true)); using (System.IO.FileStream S = _PhaseQuantileFileName.OpenRead()) using (System.IO.BinaryReader R = new System.IO.BinaryReader(S)) { for (int i = 0; i < m_SB_PhaseQuantile.m.Length; i++) { m_SB_PhaseQuantile.m[i] = R.ReadSingle(); } } m_SB_PhaseQuantile.Write(); }
private void timer1_Tick(object sender, EventArgs e) { if (!m_bHasRendered) { return; } m_bHasRendered = false; // Perform simulation int NeighborsCount = m_NeighborPositions.Length; // Compute pressure forces float F = 0.01f * floatTrackbarControlForce.Value; float3[] Forces = new float3[NeighborsCount]; for (int i = 0; i < NeighborsCount - 1; i++) { float3 D0 = m_NeighborPositions[i].Normalized; for (int j = i + 1; j < NeighborsCount; j++) { float3 D1 = m_NeighborPositions[j].Normalized; float3 Dir = (D1 - D0).Normalized; float Dot = D0.Dot(D1) - 1.0f; // in [0,-2] float Force = F * (float)Math.Exp(Dot); Forces[i] = Forces[i] - Force * Dir; // Pushes 0 away from 1 Forces[j] = Forces[j] + Force * Dir; // Pushes 1 away from 0 } } // Apply force for (int i = 0; i < NeighborsCount; i++) { float3 NewPosition = (m_NeighborPositions[i] + Forces[i]).Normalized; m_NeighborPositions[i] = NewPosition; m_SB_Neighbors.m[i].m_Position = NewPosition; } // Update m_SB_Neighbors.Write(); if (checkBoxRenderCell.Checked) { buttonBuildCell_Click(this, EventArgs.Empty); Application.DoEvents(); } }
private void integerTrackbarControlNeighborsCount_ValueChanged(IntegerTrackbarControl _Sender, int _FormerValue) { int NeighborsCount = integerTrackbarControlNeighborsCount.Value; if (m_SB_Neighbors != null) { m_SB_Neighbors.Dispose(); } m_SB_Neighbors = new StructuredBuffer <SB_Neighbor>(m_Device, NeighborsCount, true); WMath.Vector[] Directions = null; if (radioButtonHammersley.Checked) { double[,] Samples = m_Hammersley.BuildSequence(NeighborsCount, 2); Directions = m_Hammersley.MapSequenceToSphere(Samples); } else { Random TempRNG = new Random(); Directions = new WMath.Vector[NeighborsCount]; for (int i = 0; i < NeighborsCount; i++) { Directions[i] = new WMath.Vector(2.0f * (float)TempRNG.NextDouble() - 1.0f, 2.0f * (float)TempRNG.NextDouble() - 1.0f, 2.0f * (float)TempRNG.NextDouble() - 1.0f); Directions[i].Normalize(); } } Random RNG = new Random(1); m_NeighborPositions = new float3[NeighborsCount]; m_NeighborColors = new float3[NeighborsCount]; for (int NeighborIndex = 0; NeighborIndex < NeighborsCount; NeighborIndex++) { float Radius = 2.0f; // Make that random! m_NeighborPositions[NeighborIndex] = Radius * new float3(Directions[NeighborIndex].x, Directions[NeighborIndex].y, Directions[NeighborIndex].z); float R = (float)RNG.NextDouble(); float G = (float)RNG.NextDouble(); float B = (float)RNG.NextDouble(); m_NeighborColors[NeighborIndex] = new float3(R, G, B); m_SB_Neighbors.m[NeighborIndex].m_Position = m_NeighborPositions[NeighborIndex]; m_SB_Neighbors.m[NeighborIndex].m_Color = m_NeighborColors[NeighborIndex]; } m_SB_Neighbors.Write(); // Upload }
StructuredBuffer <float> GetSumBuffer() { if (!m_sumDirty || m_queryNodes.Length < 2) { return(m_SB_HeatSum); } // Read back simulation & accumulate into each node m_SB_HeatSource.Read(); // Build a matrix of mutual heat values for each simulation at the position of each source int sourcesCount = m_queryNodes.Length; float maxHeat = 0.0f; for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++) { float sumHeat = 0.0f; for (int sourceIndex = 0; sourceIndex < sourcesCount; sourceIndex++) { sumHeat += m_SB_HeatSource.m[m_nodesCount * sourceIndex + nodeIndex]; } m_SB_HeatSum.m[nodeIndex] = sumHeat; maxHeat = Mathf.Max(maxHeat, sumHeat); } // Normalize for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++) { m_SB_HeatSum.m[nodeIndex] = m_SB_HeatSum.m[nodeIndex] / maxHeat; } // Write results m_SB_HeatSum.Write(); m_sumDirty = false; return(m_SB_HeatSum); }
private void checkBoxShowChildren_CheckedChanged(object sender, EventArgs e) { if (checkBoxShowChildren.Checked) { foreach (ProtoParser.Neuron N in Selection) { foreach (ProtoParser.Neuron child in N.Children) { m_SB_Nodes.m[(int)m_neuron2ID[child]].m_flags |= 0x4U; } } } else { foreach (ProtoParser.Neuron N in Selection) { foreach (ProtoParser.Neuron child in N.Children) { m_SB_Nodes.m[(int)m_neuron2ID[child]].m_flags &= ~0x4U; } } } m_SB_Nodes.Write(); }
void LoadProbePixels(FileInfo _FileName) { if (m_Tex_CubeMap != null) { m_Tex_CubeMap.Dispose(); m_Tex_CubeMap = null; } if (m_SB_Samples != null) { m_SB_Samples.Dispose(); m_SB_Samples = null; } if (m_SB_EmissiveSurfaces != null) { m_SB_EmissiveSurfaces.Dispose(); m_SB_EmissiveSurfaces = null; } using (FileStream S = _FileName.OpenRead()) using (BinaryReader R = new BinaryReader(S)) { ////////////////////////////////////////////////////////////////// // Read pixels Pixel[][,] CubeMapFaces = new Pixel[6][, ]; int CubeMapSize = R.ReadInt32(); for (int CubeMapFaceIndex = 0; CubeMapFaceIndex < 6; CubeMapFaceIndex++) { Pixel[,] Face = new Pixel[CubeMapSize, CubeMapSize]; CubeMapFaces[CubeMapFaceIndex] = Face; for (int Y = 0; Y < CubeMapSize; Y++) { for (int X = 0; X < CubeMapSize; X++) { Face[X, Y].ParentSampleIndex = R.ReadUInt32(); Face[X, Y].UsedForSampling = R.ReadBoolean(); Face[X, Y].Position.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].Normal.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].Albedo.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].F0.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].StaticLitColor.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].SmoothedStaticLitColor.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); Face[X, Y].FaceIndex = R.ReadUInt32(); Face[X, Y].EmissiveMatID = R.ReadUInt32(); Face[X, Y].NeighborProbeID = R.ReadUInt32(); Face[X, Y].NeighborProbeDistance = R.ReadSingle(); Face[X, Y].VoronoiProbeID = R.ReadUInt32(); Face[X, Y].Importance = R.ReadDouble(); Face[X, Y].Distance = R.ReadSingle(); Face[X, Y].SmoothedDistance = R.ReadSingle(); Face[X, Y].Infinity = R.ReadByte() != 0; Face[X, Y].SmoothedInfinity = R.ReadSingle(); } } } List <PixelsBuffer> Content = new List <PixelsBuffer>(); float4 Value = new float4(); for (int CubeIndex = 0; CubeIndex < 8; CubeIndex++) { for (int CubeMapFaceIndex = 0; CubeMapFaceIndex < 6; CubeMapFaceIndex++) { PixelsBuffer Buff = new PixelsBuffer(CubeMapSize * CubeMapSize * 16); Content.Add(Buff); using (BinaryWriter W = Buff.OpenStreamWrite()) { for (int Y = 0; Y < CubeMapSize; Y++) { for (int X = 0; X < CubeMapSize; X++) { Pixel P = CubeMapFaces[CubeMapFaceIndex][X, Y]; switch (CubeIndex) { case 0: Value.Set(P.Position, P.Distance); break; case 1: Value.Set(P.Normal, P.SmoothedDistance); break; case 2: Value.Set(P.Albedo, P.SmoothedInfinity); break; case 3: Value.Set(P.StaticLitColor, (float)P.ParentSampleIndex); break; case 4: Value.Set(P.SmoothedStaticLitColor, (float)P.Importance); break; case 5: Value.Set(P.UsedForSampling ? 1 : 0, P.Infinity ? 1 : 0, (float)P.FaceIndex, (float)P.VoronoiProbeID); break; case 6: Value.Set(P.F0, (float)P.NeighborProbeID); break; case 7: Value.Set(P.NeighborProbeDistance, 0, 0, 0); break; } W.Write(Value.x); W.Write(Value.y); W.Write(Value.z); W.Write(Value.w); } } } } } m_Tex_CubeMap = new Texture2D(m_Device, CubeMapSize, CubeMapSize, -6 * 8, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, Content.ToArray()); ////////////////////////////////////////////////////////////////// // Read samples int SamplesCount = (int)R.ReadUInt32(); m_SB_Samples = new StructuredBuffer <SB_Sample>(m_Device, SamplesCount, true); for (int SampleIndex = 0; SampleIndex < SamplesCount; SampleIndex++) { m_SB_Samples.m[SampleIndex].ID = (uint)SampleIndex; m_SB_Samples.m[SampleIndex].Position.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); m_SB_Samples.m[SampleIndex].Normal.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); m_SB_Samples.m[SampleIndex].Albedo.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); m_SB_Samples.m[SampleIndex].F0.Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle()); m_SB_Samples.m[SampleIndex].PixelsCount = R.ReadUInt32(); m_SB_Samples.m[SampleIndex].SHFactor = R.ReadSingle(); m_SB_Samples.m[SampleIndex].SH0.Set((float)R.ReadDouble(), (float)R.ReadDouble(), (float)R.ReadDouble()); m_SB_Samples.m[SampleIndex].SH1.Set((float)R.ReadDouble(), (float)R.ReadDouble(), (float)R.ReadDouble()); m_SB_Samples.m[SampleIndex].SH2.Set((float)R.ReadDouble(), (float)R.ReadDouble(), (float)R.ReadDouble()); } m_SB_Samples.Write(); } }
StructuredBuffer <float> GetBarycentricsBuffer() { if (!m_barycentricsDirty || m_queryNodes.Length < 2) { return(m_SB_HeatBarycentrics); } // Read back simulation & transform into computable log heat m_SB_HeatSource.Read(); for (int nodeIndex = 0; nodeIndex < m_SB_HeatSource.m.Length; nodeIndex++) { m_SB_HeatSource.m[nodeIndex] = ComputeLogHeat(m_SB_HeatSource.m[nodeIndex]); } // Build a matrix of mutual heat values for each simulation at the position of each source int sourcesCount = m_queryNodes.Length; Matrix mutualHeat = new Matrix(sourcesCount); for (int source0 = 0; source0 < sourcesCount; source0++) { int sourceHeatOffset0 = (int)m_nodesCount * source0; for (int source1 = 0; source1 < sourcesCount; source1++) { int sourceNodeIndex = (int)m_neuron2ID[m_queryNodes[source1]]; float heat = m_SB_HeatSource.m[sourceHeatOffset0 + sourceNodeIndex]; // Here we read the temperature of source 1 in the simulation space of source 0 mutualHeat[source1, source0] = heat; } } // Invert so we get the matrix that will help us compute barycentric coordinates Matrix barycentric = mutualHeat.Invert(); //Matrix test = mutualHeat * barycentric; // Apply transform to the fields double[] sourceHeatVector = new double[sourcesCount]; double[] barycentricsVector = new double[sourcesCount]; for (int nodeIndex = 0; nodeIndex < (int)m_nodesCount; nodeIndex++) { // Build source vector for (int sourceIndex = 0; sourceIndex < sourcesCount; sourceIndex++) { sourceHeatVector[sourceIndex] = m_SB_HeatSource.m[(int)m_nodesCount * sourceIndex + nodeIndex]; } // Transform into barycentrics Matrix.Mul(sourceHeatVector, barycentric, barycentricsVector); // Write back for (int sourceIndex = 0; sourceIndex < sourcesCount; sourceIndex++) { m_SB_HeatBarycentrics.m[(int)m_nodesCount * sourceIndex + nodeIndex] = (float)barycentricsVector[sourceIndex]; } } // Write results m_SB_HeatBarycentrics.Write(); m_barycentricsDirty = false; return(m_SB_HeatBarycentrics); }
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); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { m_device.Init(panelOutput.Handle, false, true); } catch (Exception _e) { m_device = null; MessageBox.Show("Failed to initialize DX device!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } ////////////////////////////////////////////////////////////////////////// m_CB_Main = new ConstantBuffer <CB_Main>(m_device, 0); m_CB_Text = new ConstantBuffer <CB_Text>(m_device, 2); m_compute_HeatDiffusion = new ComputeShader(m_device, new FileInfo("./Shaders/HeatDiffusion.hlsl"), "CS"); m_compute_SplatHeatSources = new ComputeShader(m_device, new FileInfo("./Shaders/HeatDiffusion.hlsl"), "CS2"); m_shader_RenderGraphNode = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); m_shader_RenderGraphLink = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS2", null, "PS2"); m_shader_RenderText = new Shader(m_device, new FileInfo("./Shaders/RenderText.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); ////////////////////////////////////////////////////////////////////////// // Load the graph we need to run m_graph = new ProtoParser.Graph(); // Load graph using (FileStream S = new FileInfo("./Graphs/Birds.graph").OpenRead()) using (BinaryReader R = new BinaryReader(S)) m_graph.Read(R); // Load graph node positions (simulated and saved by the TestGraphViz project) float2[] graphNodePositions = null; using (FileStream S = new FileInfo("./Graphs/Birds.graphpos").OpenRead()) using (BinaryReader R = new BinaryReader(S)) { float2 BBoxMin = new float2(R.ReadSingle(), R.ReadSingle()); float2 BBoxMax = new float2(R.ReadSingle(), R.ReadSingle()); m_CB_Main.m._cameraCenter = 0.5f * (BBoxMin + BBoxMax); m_CB_Main.m._cameraSize = BBoxMax - BBoxMin; int nodesCount = R.ReadInt32(); if (nodesCount != m_graph.NeuronsCount) { throw new Exception("Graph nodes count mismatch!"); } graphNodePositions = new float2[nodesCount]; for (int i = 0; i < nodesCount; i++) { graphNodePositions[i].Set(R.ReadSingle(), R.ReadSingle()); } } ProtoParser.Neuron[] neurons = m_graph.Neurons; m_nodesCount = (uint)neurons.Length; // Build node info m_SB_Nodes = new StructuredBuffer <SB_NodeInfo>(m_device, m_nodesCount, true); m_neuron2ID = new Dictionary <ProtoParser.Neuron, uint>(neurons.Length); for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++) { ProtoParser.Neuron N = neurons[neuronIndex]; m_neuron2ID[N] = (uint)neuronIndex; uint linksCount = (uint)(N.ParentsCount + N.ChildrenCount + N.FeaturesCount); m_SB_Nodes.m[neuronIndex].m_position = graphNodePositions[neuronIndex]; m_SB_Nodes.m[neuronIndex].m_linkOffset = m_totalLinksCount; m_SB_Nodes.m[neuronIndex].m_linksCount = linksCount; m_SB_Nodes.m[neuronIndex].m_flags = 0U; m_totalLinksCount += linksCount; } m_SB_Nodes.Write(); // Build node links m_SB_LinkTargets = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true); m_SB_LinkSources = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true); m_totalLinksCount = 0; for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++) { ProtoParser.Neuron N = neurons[neuronIndex]; foreach (ProtoParser.Neuron O in N.Parents) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O]; } foreach (ProtoParser.Neuron O in N.Children) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O]; } foreach (ProtoParser.Neuron O in N.Features) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_LinkTargets.m[m_totalLinksCount++] = m_neuron2ID[O]; } } m_SB_LinkTargets.Write(); m_SB_LinkSources.Write(); // Build heat buffers uint elementsCount = m_nodesCount * MAX_QUERY_SOURCES; m_SB_SourceIndices = new StructuredBuffer <uint>(m_device, MAX_QUERY_SOURCES, true); m_SB_HeatSource = new StructuredBuffer <float>(m_device, elementsCount, true); m_SB_HeatTarget = new StructuredBuffer <float>(m_device, elementsCount, true); m_SB_HeatBarycentrics = new StructuredBuffer <float>(m_device, elementsCount, true); m_SB_HeatSum = new StructuredBuffer <float>(m_device, m_nodesCount, true); // Setup initial CB m_CB_Main.m._nodesCount = m_nodesCount; m_CB_Main.m._sourcesCount = 0; m_CB_Main.m._resX = (uint)panelOutput.Width; m_CB_Main.m._resY = (uint)panelOutput.Height; m_CB_Main.m._diffusionCoefficient = 1.0f; m_CB_Main.m._hoveredNodeIndex = ~0U; m_CB_Main.m._renderFlags = 0U; m_CB_Main.UpdateData(); // Load false colors m_tex_FalseColors0 = LoadFalseColors(new FileInfo("../../Images/Gradients/Magma.png")); m_tex_FalseColors1 = LoadFalseColors(new FileInfo("../../Images/Gradients/Viridis.png")); // Prepare font atlas m_SB_Text = new StructuredBuffer <SB_Letter>(m_device, 1024U, true); BuildFont(); Application.Idle += Application_Idle; }
private void buttonInit_Click(object sender, EventArgs e) { int initType = radioButton1.Checked ? 1 : radioButton2.Checked ? 2 : radioButton3.Checked ? 3 : radioButton4.Checked ? 4 : radioButton5.Checked ? 5 : 0; Random RNG = new Random(1); float3 temp3 = new float3(); float4 temp = new float4(); // Initialize positions StructuredBuffer <float4> buffer = m_SB_Points4D[0]; switch (initType) { case 1: // Big Bang temp = new float4(0, 0, 0, 1); for (int i = 0; i < POINTS_COUNT; i++) { buffer.m[i] = temp; } break; case 2: // X translation for (int i = 0; i < POINTS_COUNT; i++) { temp3.x = (float)(2.0 * RNG.NextDouble() - 1.0); temp3.y = (float)(2.0 * RNG.NextDouble() - 1.0); temp3.z = (float)(2.0 * RNG.NextDouble() - 1.0); // temp3 = temp3.Normalized; temp.x = -100.0f; temp.y = temp3.x; temp.z = temp3.y; temp.w = temp3.z; temp = temp.Normalized; // Makes the point lie on a hypersphere of radius 1 buffer.m[i] = temp; } break; case 5: // W translation for (int i = 0; i < POINTS_COUNT; i++) { temp3.x = (float)(2.0 * RNG.NextDouble() - 1.0); temp3.y = (float)(2.0 * RNG.NextDouble() - 1.0); temp3.z = (float)(2.0 * RNG.NextDouble() - 1.0); // temp3 = temp3.Normalized; temp.x = temp3.x; temp.y = temp3.y; temp.z = temp3.z; temp.w = -100.0f; temp = temp.Normalized; // Makes the point lie on a hypersphere of radius 1 buffer.m[i] = temp; } break; default: // Total random for (int i = 0; i < POINTS_COUNT; i++) { temp.x = (float)(2.0 * RNG.NextDouble() - 1.0); temp.y = (float)(2.0 * RNG.NextDouble() - 1.0); temp.z = (float)(2.0 * RNG.NextDouble() - 1.0); temp.w = (float)(2.0 * RNG.NextDouble() - 1.0); temp = temp.Normalized; // Makes the point lie on a hypersphere of radius 1 buffer.m[i] = temp; } break; } buffer.Write(); // Upload // Initialize velocities switch (initType) { case 0: temp = float4.Zero; for (int i = 0; i < POINTS_COUNT; i++) { m_SB_Velocities4D.m[i] = temp; } break; case 1: for (int i = 0; i < POINTS_COUNT; i++) { temp.x = (float)(2.0 * RNG.NextDouble() - 1.0); temp.y = (float)(2.0 * RNG.NextDouble() - 1.0); temp.z = (float)(2.0 * RNG.NextDouble() - 1.0); temp.w = (float)(2.0 * RNG.NextDouble() - 1.0); temp = temp.Normalized; // Makes the point lie on a hypersphere of radius 1 m_SB_Velocities4D.m[i] = temp; } break; case 2: temp = float4.UnitX; for (int i = 0; i < POINTS_COUNT; i++) { m_SB_Velocities4D.m[i] = temp; } break; case 3: temp = float4.UnitY; for (int i = 0; i < POINTS_COUNT; i++) { m_SB_Velocities4D.m[i] = temp; } break; case 4: temp = float4.UnitZ; for (int i = 0; i < POINTS_COUNT; i++) { m_SB_Velocities4D.m[i] = temp; } break; case 5: temp = float4.UnitW; for (int i = 0; i < POINTS_COUNT; i++) { m_SB_Velocities4D.m[i] = temp; } break; } m_SB_Velocities4D.Write(); // Upload }
protected override void OnLoad( EventArgs e ) { base.OnLoad( e ); try { m_Device.Init( panelOutput.Handle, false, true ); } catch ( Exception _e ) { m_Device = null; MessageBox( "Failed to initialize DX device!\n\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error ); return; } m_CB_Main = new ConstantBuffer<CB_Main>( m_Device, 0 ); m_CB_Camera = new ConstantBuffer<CB_Camera>( m_Device, 1 ); m_CB_AutoExposure = new ConstantBuffer<CB_AutoExposure>( m_Device, 10 ); m_CB_ToneMapping = new ConstantBuffer<CB_ToneMapping>( m_Device, 10 ); try { #if DEBUG m_Shader_RenderHDR = new Shader( m_Device, new ShaderFile( new System.IO.FileInfo( "Shaders/RenderCubeMap.hlsl" ) ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); m_Shader_ComputeTallHistogram = new ComputeShader( m_Device, new ShaderFile( new System.IO.FileInfo( "Shaders/AutoExposure/ComputeTallHistogram.hlsl" ) ), "CS", null ); m_Shader_FinalizeHistogram = new ComputeShader( m_Device, new ShaderFile( new System.IO.FileInfo( "Shaders/AutoExposure/FinalizeHistogram.hlsl" ) ), "CS", null ); m_Shader_ComputeAutoExposure = new ComputeShader( m_Device, new ShaderFile( new System.IO.FileInfo( "Shaders/AutoExposure/ComputeAutoExposure.hlsl" ) ), "CS", null ); m_Shader_ToneMapping = new Shader( m_Device, new ShaderFile( new System.IO.FileInfo( "Shaders/ToneMapping.hlsl" ) ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); #else m_Shader_RenderHDR = Shader.CreateFromBinaryBlob( m_Device, new System.IO.FileInfo( "Shaders/RenderCubeMap.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS" ); m_Shader_ComputeTallHistogram = ComputeShader.CreateFromBinaryBlob( m_Device, new System.IO.FileInfo( "Shaders/AutoExposure/ComputeTallHistogram.hlsl" ), "CS" ); m_Shader_FinalizeHistogram = ComputeShader.CreateFromBinaryBlob( m_Device, new System.IO.FileInfo( "Shaders/AutoExposure/FinalizeHistogram.hlsl" ), "CS" ); m_Shader_ComputeAutoExposure = ComputeShader.CreateFromBinaryBlob( m_Device, new System.IO.FileInfo( "Shaders/AutoExposure/ComputeAutoExposure.hlsl" ), "CS" ); m_Shader_ToneMapping = Shader.CreateFromBinaryBlob( m_Device, new System.IO.FileInfo( "Shaders/ToneMapping.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS" ); #endif } catch ( Exception _e ) { MessageBox( "Shader failed to compile!\n\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error ); m_Shader_RenderHDR = null; m_Shader_ComputeTallHistogram = null; m_Shader_FinalizeHistogram = null; m_Shader_ComputeAutoExposure = null; m_Shader_ToneMapping = null; } // Create the HDR buffer m_Tex_HDR = new Texture2D( m_Device, panelOutput.Width, panelOutput.Height, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, null ); // Create the histogram & auto-exposure buffers int tallHistogramHeight = (panelOutput.Height + 3) >> 2; m_Tex_TallHistogram = new Texture2D( m_Device, 128, tallHistogramHeight, 1, 1, PIXEL_FORMAT.R32_UINT, false, true, null ); m_Tex_Histogram = new Texture2D( m_Device, 128, 1, 1, 1, PIXEL_FORMAT.R32_UINT, false, true, null ); m_Buffer_AutoExposureSource = new StructuredBuffer<autoExposure_t>( m_Device, 1, true ); m_Buffer_AutoExposureSource.m[0].EngineLuminanceFactor = 1.0f; m_Buffer_AutoExposureSource.m[0].TargetLuminance = 1.0f; m_Buffer_AutoExposureSource.m[0].MinLuminanceLDR = 0.0f; m_Buffer_AutoExposureSource.m[0].MaxLuminanceLDR = 1.0f; m_Buffer_AutoExposureSource.m[0].MiddleGreyLuminanceLDR = 1.0f; m_Buffer_AutoExposureSource.m[0].EV = 0.0f; m_Buffer_AutoExposureSource.m[0].Fstop = 0.0f; m_Buffer_AutoExposureSource.m[0].PeakHistogramValue = 0; m_Buffer_AutoExposureSource.Write(); m_Buffer_AutoExposureTarget = new StructuredBuffer<autoExposure_t>( m_Device, 1, true ); // Load cube map try { m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( "garage4_hd.dds" ) ); // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\hdrcube6.dds" ) ); // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_28_cube_BC6H_UF16.bimage" ) ); // Tunnel // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_89_cube_BC6H_UF16.bimage" ) ); // Large sky // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_115_cube_BC6H_UF16.bimage" ) ); // Indoor // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_123_cube_BC6H_UF16.bimage" ) ); // Under the arch // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_189_cube_BC6H_UF16.bimage" ) ); // Indoor viewing out (vista) // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_246_cube_BC6H_UF16.bimage" ) ); // Nice! Statue's feet // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_248_cube_BC6H_UF16.bimage" ) ); // Nice! In a corner with lot of sky } catch ( Exception ) { } // Setup camera m_Camera.CreatePerspectiveCamera( (float) (90.0 * Math.PI / 180.0), (float) panelOutput.Width / panelOutput.Height, 0.01f, 100.0f ); m_Manipulator.Attach( panelOutput, m_Camera ); m_Manipulator.InitializeCamera( new float3( 0, 0, 1 ), new float3( 0, 0, 0 ), float3.UnitY ); }
void LoadProbePixels( FileInfo _FileName ) { if ( m_Tex_CubeMap != null ) { m_Tex_CubeMap.Dispose(); m_Tex_CubeMap = null; } if ( m_SB_Samples != null ) { m_SB_Samples.Dispose(); m_SB_Samples = null; } if ( m_SB_EmissiveSurfaces != null ) { m_SB_EmissiveSurfaces.Dispose(); m_SB_EmissiveSurfaces = null; } using ( FileStream S = _FileName.OpenRead() ) using ( BinaryReader R = new BinaryReader( S ) ) { ////////////////////////////////////////////////////////////////// // Read pixels Pixel[][,] CubeMapFaces = new Pixel[6][,]; int CubeMapSize = R.ReadInt32(); for ( int CubeMapFaceIndex=0; CubeMapFaceIndex < 6; CubeMapFaceIndex++ ) { Pixel[,] Face = new Pixel[CubeMapSize,CubeMapSize]; CubeMapFaces[CubeMapFaceIndex] = Face; for ( int Y=0; Y < CubeMapSize; Y++ ) for ( int X=0; X < CubeMapSize; X++ ) { Face[X,Y].ParentSampleIndex = R.ReadUInt32(); Face[X,Y].UsedForSampling = R.ReadBoolean(); Face[X,Y].Position.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].Normal.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].Albedo.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].F0.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].StaticLitColor.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].SmoothedStaticLitColor.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].FaceIndex = R.ReadUInt32(); Face[X,Y].EmissiveMatID = R.ReadUInt32(); Face[X,Y].NeighborProbeID = R.ReadUInt32(); Face[X,Y].NeighborProbeDistance = R.ReadSingle(); Face[X,Y].VoronoiProbeID = R.ReadUInt32(); Face[X,Y].Importance = R.ReadDouble(); Face[X,Y].Distance = R.ReadSingle(); Face[X,Y].SmoothedDistance = R.ReadSingle(); Face[X,Y].Infinity = R.ReadByte() != 0; Face[X,Y].SmoothedInfinity = R.ReadSingle(); } } List<PixelsBuffer> Content = new List<PixelsBuffer>(); float4 Value = new float4(); for ( int CubeIndex=0; CubeIndex < 8; CubeIndex++ ) { for ( int CubeMapFaceIndex=0; CubeMapFaceIndex < 6; CubeMapFaceIndex++ ) { PixelsBuffer Buff = new PixelsBuffer( CubeMapSize*CubeMapSize * 16 ); Content.Add( Buff ); using ( BinaryWriter W = Buff.OpenStreamWrite() ) { for ( int Y=0; Y < CubeMapSize; Y++ ) for ( int X=0; X < CubeMapSize; X++ ) { Pixel P = CubeMapFaces[CubeMapFaceIndex][X,Y]; switch ( CubeIndex ) { case 0: Value.Set( P.Position, P.Distance ); break; case 1: Value.Set( P.Normal, P.SmoothedDistance ); break; case 2: Value.Set( P.Albedo, P.SmoothedInfinity ); break; case 3: Value.Set( P.StaticLitColor, (float) P.ParentSampleIndex ); break; case 4: Value.Set( P.SmoothedStaticLitColor, (float) P.Importance ); break; case 5: Value.Set( P.UsedForSampling ? 1 : 0, P.Infinity ? 1 : 0, (float) P.FaceIndex, (float) P.VoronoiProbeID ); break; case 6: Value.Set( P.F0, (float) P.NeighborProbeID ); break; case 7: Value.Set( P.NeighborProbeDistance, 0, 0, 0 ); break; } W.Write( Value.x ); W.Write( Value.y ); W.Write( Value.z ); W.Write( Value.w ); } } } } m_Tex_CubeMap = new Texture2D( m_Device, CubeMapSize, CubeMapSize, -6*8, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, Content.ToArray() ); ////////////////////////////////////////////////////////////////// // Read samples int SamplesCount = (int) R.ReadUInt32(); m_SB_Samples = new StructuredBuffer<SB_Sample>( m_Device, SamplesCount, true ); for ( int SampleIndex=0; SampleIndex < SamplesCount; SampleIndex++ ) { m_SB_Samples.m[SampleIndex].ID = (uint) SampleIndex; m_SB_Samples.m[SampleIndex].Position.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].Normal.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].Albedo.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].F0.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].PixelsCount = R.ReadUInt32(); m_SB_Samples.m[SampleIndex].SHFactor = R.ReadSingle(); m_SB_Samples.m[SampleIndex].SH0.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); m_SB_Samples.m[SampleIndex].SH1.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); m_SB_Samples.m[SampleIndex].SH2.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); } m_SB_Samples.Write(); } }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { m_device.Init(panelOutput.Handle, false, true); } catch (Exception _e) { m_device = null; MessageBox.Show("Failed to initialize DX device!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } try { ////////////////////////////////////////////////////////////////////////// // Load the graph we need to simulate m_graph = new ProtoParser.Graph(); // FileInfo file = new FileInfo( "../../../AI/Projects/Semantic Memory/Tests/Birds Database/Tools/ProtoParser/Concepts.graph" ); FileInfo file = new FileInfo("../../../AI/Projects/Semantic Memory/Tests/Birds Database/Tools/ProtoParser/TestGraph.graph"); if (!file.Exists) { file = new FileInfo("./Graphs/TestGraph.graph"); } using (FileStream S = file.OpenRead()) using (BinaryReader R = new BinaryReader(S)) m_graph.Read(R); ProtoParser.Neuron[] neurons = m_graph.Neurons; m_nodesCount = (uint)neurons.Length; /* * m_nodesCount = 2; * neurons = new ProtoParser.Neuron[2]; * neurons[0] = new ProtoParser.Neuron(); * neurons[1] = new ProtoParser.Neuron(); * neurons[0].LinkChild( neurons[1] ); * //*/ ////////////////////////////////////////////////////////////////////////// m_CB_Main = new ConstantBuffer <CB_Main>(m_device, 0); m_CB_Simulation = new ConstantBuffer <CB_Simulation>(m_device, 1); m_CB_Text = new ConstantBuffer <CB_Text>(m_device, 2); m_shader_ComputeForces = new ComputeShader(m_device, new FileInfo("./Shaders/SimulateGraph.hlsl"), "CS"); m_shader_Simulate = new ComputeShader(m_device, new FileInfo("./Shaders/SimulateGraph.hlsl"), "CS2"); #if RENDER_GRAPH_PROPER m_shader_RenderGraphNode = new Shader(m_device, new FileInfo("./Shaders/RenderGraph2.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); m_shader_RenderGraphLink = new Shader(m_device, new FileInfo("./Shaders/RenderGraph2.hlsl"), VERTEX_FORMAT.Pt4, "VS2", null, "PS2"); #else m_shader_RenderGraph = new Shader(m_device, new FileInfo("./Shaders/RenderGraph.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); #endif m_shader_RenderText = new Shader(m_device, new FileInfo("./Shaders/RenderText.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); // Build node info m_SB_Nodes = new StructuredBuffer <SB_NodeInfo>(m_device, m_nodesCount, true); m_neuron2ID = new Dictionary <ProtoParser.Neuron, uint>(neurons.Length); float maxMass = 0.0f; for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++) { ProtoParser.Neuron N = neurons[neuronIndex]; m_neuron2ID[N] = (uint)neuronIndex; uint linksCount = (uint)(N.ParentsCount + N.ChildrenCount + N.FeaturesCount); // m_SB_Nodes.m[neuronIndex].m_mass = (1 + 10.0f * linksCount) / (0.1f + N.Distance2Root); // Works with S=1e4 D=-1e3 // m_SB_Nodes.m[neuronIndex].m_mass = (1 + 1.0f * linksCount) / (0.01f + 0.0f * N.Distance2Root); // Works with S=1e4 D=-1e3 // m_SB_Nodes.m[neuronIndex].m_mass = (1 + 0.1f * linksCount) / (0.1f + N.Distance2Root); // Works with S=10 D=-10 m_SB_Nodes.m[neuronIndex].m_mass = 100.0f * (1 + 1.0f * linksCount); // Works with S=1e4 D=-1e3 m_SB_Nodes.m[neuronIndex].m_linkOffset = m_totalLinksCount; m_SB_Nodes.m[neuronIndex].m_linksCount = linksCount; m_SB_Nodes.m[neuronIndex].m_flags = 0U; maxMass = Mathf.Max(maxMass, m_SB_Nodes.m[neuronIndex].m_mass); m_totalLinksCount += linksCount; } m_SB_Nodes.m[0].m_mass = 1e4f; m_SB_Nodes.Write(); // Build node links m_SB_Links = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true); m_SB_LinkSources = new StructuredBuffer <uint>(m_device, m_totalLinksCount, true); m_totalLinksCount = 0; for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++) { ProtoParser.Neuron N = neurons[neuronIndex]; foreach (ProtoParser.Neuron O in N.Parents) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_Links.m[m_totalLinksCount++] = m_neuron2ID[O]; } foreach (ProtoParser.Neuron O in N.Children) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_Links.m[m_totalLinksCount++] = m_neuron2ID[O]; } foreach (ProtoParser.Neuron O in N.Features) { m_SB_LinkSources.m[m_totalLinksCount] = (uint)neuronIndex; m_SB_Links.m[m_totalLinksCount++] = m_neuron2ID[O]; } } m_SB_Links.Write(); m_SB_LinkSources.Write(); // Setup initial CB m_CB_Main.m._nodesCount = m_nodesCount; m_CB_Main.m._resX = (uint)panelOutput.Width; m_CB_Main.m._resY = (uint)panelOutput.Height; m_CB_Main.m._maxMass = maxMass; m_CB_Main.m._cameraCenter = float2.Zero; m_CB_Main.m._cameraSize.Set(10.0f, 10.0f); m_CB_Main.m._hoveredNodeIndex = ~0U; m_CB_Main.UpdateData(); // Initialize sim buffers m_SB_Forces = new StructuredBuffer <float2>(m_device, m_nodesCount * m_nodesCount, false); m_SB_NodeSims[0] = new StructuredBuffer <SB_NodeSim>(m_device, m_nodesCount, true); m_SB_NodeSims[1] = new StructuredBuffer <SB_NodeSim>(m_device, m_nodesCount, true); buttonReset_Click(null, EventArgs.Empty); // m_shader_HeatDiffusion = new Shader( m_device, new FileInfo( "./Shaders/HeatDiffusion.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); // m_tex_Search = new Texture2D( m_device, (uint) GRAPH_SIZE, (uint) GRAPH_SIZE, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, null ); // m_tex_Search_Staging = new Texture2D( m_device, (uint) GRAPH_SIZE, (uint) GRAPH_SIZE, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, true, false, null ); // Load false colors // using ( ImageUtility.ImageFile sourceImage = new ImageUtility.ImageFile( new FileInfo( "../../Images/Gradients/Viridis.png" ), ImageUtility.ImageFile.FILE_FORMAT.PNG ) ) { using (ImageUtility.ImageFile sourceImage = new ImageUtility.ImageFile(new FileInfo("../../Images/Gradients/Magma.png"), ImageUtility.ImageFile.FILE_FORMAT.PNG)) { ImageUtility.ImageFile convertedImage = new ImageUtility.ImageFile(); convertedImage.ConvertFrom(sourceImage, ImageUtility.PIXEL_FORMAT.BGRA8); using (ImageUtility.ImagesMatrix image = new ImageUtility.ImagesMatrix(convertedImage, ImageUtility.ImagesMatrix.IMAGE_TYPE.sRGB)) m_tex_FalseColors = new Texture2D(m_device, image, ImageUtility.COMPONENT_FORMAT.UNORM_sRGB); } // Prepare font atlas m_SB_Text = new StructuredBuffer <SB_Letter>(m_device, 1024U, true); BuildFont(); Application.Idle += Application_Idle; } catch (Exception _e) { m_device = null; MessageBox.Show("Failed to initialize shaders!\n\n" + _e.Message, "Heat Wave Test", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } }
/// <summary> /// Generates blue noise distribution by randomly swapping pixels in the texture to reach lowest possible score and minimize a specific energy function /// </summary> /// <param name="_randomSeed"></param> /// <param name="_maxIterations">The maximum amount of iterations before exiting with the last best solution</param> /// <param name="_standardDeviationImage">Standard deviation for image space. If not sure, use 2.1</param> /// <param name="_standardDeviationValue">Standard deviation for value space. If not sure, use 1.0</param> /// <param name="_neighborsOnlyMutations">True to only authorize mutations of neighbor pixels, false to randomly mutate any pixel</param> /// <param name="_notifyProgressEveryNIterations">Will read back the GPU texture to the CPU and notify of progress every N iterations</param> /// <param name="_progress"></param> public void Generate(uint _randomSeed, uint _maxIterations, float _standardDeviationImage, float _standardDeviationValue, bool _neighborsOnlyMutations, uint _notifyProgressEveryNIterations, ProgressDelegate _progress) { m_CB_Main.m._texturePOT = (uint)m_texturePOT; m_CB_Main.m._textureSize = m_textureSize; m_CB_Main.m._textureMask = m_textureSizeMask; m_CB_Main.m._kernelFactorSpatial = -1.0f / (_standardDeviationImage * _standardDeviationImage); m_CB_Main.m._kernelFactorValue = -1.0f / (_standardDeviationValue * _standardDeviationValue); m_CB_Main.UpdateData(); ////////////////////////////////////////////////////////////////////////// // Generate initial white noise { SimpleRNG.SetSeed(_randomSeed, 362436069U); switch (m_vectorDimension) { case 1: { // Build ordered initial values float[,] initialValues = new float[m_textureSize, m_textureSize]; for (uint Y = 0; Y < m_textureSize; Y++) { for (uint X = 0; X < m_textureSize; X++) { initialValues[X, Y] = (float)(m_textureSize * Y + X) / m_textureTotalSize; } } // Displace them randomly for (uint i = 0; i < m_textureTotalSize; i++) { uint startX = GetUniformInt(m_textureSize); uint startY = GetUniformInt(m_textureSize); uint endX = GetUniformInt(m_textureSize); uint endY = GetUniformInt(m_textureSize); float temp = initialValues[startX, startY]; initialValues[startX, startY] = initialValues[endX, endY]; initialValues[endX, endY] = temp; } m_texNoiseCPU.WritePixels(0, 0, (uint _X, uint _Y, System.IO.BinaryWriter _W) => { _W.Write(initialValues[_X, _Y]); }); break; } case 2: { // Build ordered initial values float2[,] initialValues = new float2[m_textureSize, m_textureSize]; for (uint Y = 0; Y < m_textureSize; Y++) { for (uint X = 0; X < m_textureSize; X++) { initialValues[X, Y].Set((float)(m_textureSize * Y + X) / m_textureTotalSize, (float)(m_textureSize * Y + X) / m_textureTotalSize); } } // Displace them randomly for (uint i = 0; i < m_textureTotalSize; i++) { uint startX = GetUniformInt(m_textureSize); uint startY = GetUniformInt(m_textureSize); uint endX = GetUniformInt(m_textureSize); uint endY = GetUniformInt(m_textureSize); float temp = initialValues[startX, startY].x; initialValues[startX, startY].x = initialValues[endX, endY].x; initialValues[endX, endY].x = temp; startX = GetUniformInt(m_textureSize); startY = GetUniformInt(m_textureSize); endX = GetUniformInt(m_textureSize); endY = GetUniformInt(m_textureSize); temp = initialValues[startX, startY].y; initialValues[startX, startY].y = initialValues[endX, endY].y; initialValues[endX, endY].y = temp; } m_texNoiseCPU.WritePixels(0, 0, (uint _X, uint _Y, System.IO.BinaryWriter _W) => { _W.Write(initialValues[_X, _Y].x); _W.Write(initialValues[_X, _Y].y); }); break; } } m_texNoise0.CopyFrom(m_texNoiseCPU); } ////////////////////////////////////////////////////////////////////////// // Perform iterations float bestScore = ComputeScore(m_texNoise0); float score = bestScore; uint iterationIndex = 0; uint mutationsRate = MAX_MUTATIONS_RATE; int iterationsCountWithoutImprovement = 0; #if !CAILLOU float maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.1f * m_textureTotalSize; // Arbitrary: 10% of the texture size #else float maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.01f * m_textureTotalSize; // Arbitrary: 1% of the texture size #endif // float maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.002f * m_textureTotalSize; // Arbitrary: 0.2% of the texture size float averageIterationsCountWithoutImprovement = 0.0f; float alpha = 0.001f; uint[] neighborOffsetX = new uint[8] { 0, 1, 2, 2, 2, 1, 0, 0 }; uint[] neighborOffsetY = new uint[8] { 0, 0, 0, 1, 2, 2, 2, 1 }; List <float> statistics = new List <float>(); //ReadBackScoreTexture( m_texNoiseScore2, textureCPU ); while (iterationIndex < _maxIterations) { ////////////////////////////////////////////////////////////////////////// // Copy if (m_CS_Copy.Use()) { m_texNoise0.SetCS(0); m_texNoise1.SetCSUAV(0); uint groupsCount = m_textureSize >> 4; m_CS_Copy.Dispatch(groupsCount, groupsCount, 1); } ////////////////////////////////////////////////////////////////////////// // Mutate current solution by swapping up to N pixels randomly if (m_CS_Mutate.Use()) { // Fill up mutations buffer if (_neighborsOnlyMutations) { // Swap neighbor pixels only for (int mutationIndex = 0; mutationIndex < mutationsRate; mutationIndex++) { uint sourceIndex = GetUniformInt(m_textureTotalSize); uint X, Y; ComputeXYFromSingleIndex(sourceIndex, out X, out Y); // Randomly pick one of the 8 neighbors uint neighborIndex = SimpleRNG.GetUint() & 0x7; uint Xn = (X + m_textureSizeMask + neighborOffsetX[neighborIndex]) & m_textureSizeMask; uint Yn = (Y + m_textureSizeMask + neighborOffsetY[neighborIndex]) & m_textureSizeMask; m_SB_Mutations.m[mutationIndex]._pixelSourceX = X; m_SB_Mutations.m[mutationIndex]._pixelSourceY = Y; m_SB_Mutations.m[mutationIndex]._pixelTargetX = Xn; m_SB_Mutations.m[mutationIndex]._pixelTargetY = Yn; if (m_vectorDimension > 1) { m_SB_Mutations.m[mutationIndex]._pixelTargetY |= SimpleRNG.GetUniform() > 0.5 ? 0x80000000U : 0x40000000U; } } } else { // Swap pixels randomly for (int mutationIndex = 0; mutationIndex < mutationsRate; mutationIndex++) { uint sourceIndex = GetUniformInt(m_textureTotalSize); uint targetIndex = GetUniformInt(m_textureTotalSize); ComputeXYFromSingleIndex(sourceIndex, out m_SB_Mutations.m[mutationIndex]._pixelSourceX, out m_SB_Mutations.m[mutationIndex]._pixelSourceY); ComputeXYFromSingleIndex(targetIndex, out m_SB_Mutations.m[mutationIndex]._pixelTargetX, out m_SB_Mutations.m[mutationIndex]._pixelTargetY); if (m_vectorDimension > 1) { m_SB_Mutations.m[mutationIndex]._pixelTargetY |= SimpleRNG.GetUniform() > 0.5 ? 0x80000000U : 0x40000000U; } } } m_SB_Mutations.Write(mutationsRate); m_SB_Mutations.SetInput(1); m_CS_Mutate.Dispatch(mutationsRate, 1, 1); m_texNoise0.RemoveFromLastAssignedSlots(); m_texNoise1.RemoveFromLastAssignedSlotUAV(); } ////////////////////////////////////////////////////////////////////////// // Compute new score float previousScore = score; score = ComputeScore(m_texNoise1); if (score < bestScore) { // New best score! Swap textures so we accept the new state... bestScore = score; Texture2D temp = m_texNoise0; m_texNoise0 = m_texNoise1; m_texNoise1 = temp; iterationsCountWithoutImprovement = 0; } else { iterationsCountWithoutImprovement++; } averageIterationsCountWithoutImprovement *= 1.0f - alpha; averageIterationsCountWithoutImprovement += alpha * iterationsCountWithoutImprovement; if (averageIterationsCountWithoutImprovement > maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount) { averageIterationsCountWithoutImprovement = 0.0f; // Start over... mutationsRate >>= 1; // Halve mutations count if (mutationsRate == 0) { break; // Clearly we've reached a steady state here... } } //statistics.Add( averageIterationsCountWithoutImprovement ); ////////////////////////////////////////////////////////////////////////// // Notify iterationIndex++; if (_progress == null || (iterationIndex % _notifyProgressEveryNIterations) != 1) { continue; } // _progress( iterationIndex, mutationsCount, bestScore, ReadBackScoreTexture( m_texNoiseScore ), statistics ); // Notify! switch (m_vectorDimension) { case 1: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture1D(m_texNoise0), statistics); break; // Notify! case 2: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture2D(m_texNoise0), statistics); break; // Notify! } } // One final call with our best final result switch (m_vectorDimension) { case 1: ReadBackTexture1D(m_texNoise0); break; case 2: ReadBackTexture2D(m_texNoise0); break; } if (_progress != null) { // _progress( iterationIndex, mutationsCount, bestScore, ReadBackScoreTexture( m_texNoiseScore ), statistics ); // Notify! switch (m_vectorDimension) { case 1: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture1D(m_texNoise0), statistics); break; // Notify! case 2: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture2D(m_texNoise0), statistics); break; // Notify! } } }
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(); }
private void BuildRandomBuffer() { Reg( m_SB_Random = new StructuredBuffer<float4>( m_Device, RANDOM_TABLE_SIZE, true ) ); for ( int i=0; i < RANDOM_TABLE_SIZE; i++ ) // m_SB_Random.m[i] = new float4( (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform() ); m_SB_Random.m[i] = new float4( (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), -(float) Math.Log( 1e-3 + (1.0-1e-3) * SimpleRNG.GetUniform() ) ); m_SB_Random.Write(); }
private void BuildPhaseQuantileBuffer( System.IO.FileInfo _PhaseQuantileFileName ) { const int QUANTILES_COUNT = 65536; Reg( m_SB_PhaseQuantile = new StructuredBuffer<float>( m_Device, 2*QUANTILES_COUNT, true ) ); using ( System.IO.FileStream S = _PhaseQuantileFileName.OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) { for ( int i=0; i < m_SB_PhaseQuantile.m.Length; i++ ) m_SB_PhaseQuantile.m[i] = R.ReadSingle(); } m_SB_PhaseQuantile.Write(); }
private void integerTrackbarControlNeighborsCount_ValueChanged( IntegerTrackbarControl _Sender, int _FormerValue ) { int NeighborsCount = integerTrackbarControlNeighborsCount.Value; if ( m_SB_Neighbors != null ) m_SB_Neighbors.Dispose(); m_SB_Neighbors = new StructuredBuffer< SB_Neighbor >( m_Device, NeighborsCount, true ); WMath.Vector[] Directions = null; if ( radioButtonHammersley.Checked ) { double[,] Samples = m_Hammersley.BuildSequence( NeighborsCount, 2 ); Directions = m_Hammersley.MapSequenceToSphere( Samples ); } else { Random TempRNG = new Random(); Directions = new WMath.Vector[NeighborsCount]; for ( int i=0; i < NeighborsCount; i++ ) { Directions[i] = new WMath.Vector( 2.0f * (float) TempRNG.NextDouble() - 1.0f, 2.0f * (float) TempRNG.NextDouble() - 1.0f, 2.0f * (float) TempRNG.NextDouble() - 1.0f ); Directions[i].Normalize(); } } Random RNG = new Random( 1 ); m_NeighborPositions = new float3[NeighborsCount]; m_NeighborColors = new float3[NeighborsCount]; for ( int NeighborIndex=0; NeighborIndex < NeighborsCount; NeighborIndex++ ) { float Radius = 2.0f; // Make that random! m_NeighborPositions[NeighborIndex] = Radius * new float3( Directions[NeighborIndex].x, Directions[NeighborIndex].y, Directions[NeighborIndex].z ); float R = (float) RNG.NextDouble(); float G = (float) RNG.NextDouble(); float B = (float) RNG.NextDouble(); m_NeighborColors[NeighborIndex] = new float3( R, G, B ); m_SB_Neighbors.m[NeighborIndex].m_Position = m_NeighborPositions[NeighborIndex]; m_SB_Neighbors.m[NeighborIndex].m_Color = m_NeighborColors[NeighborIndex]; } m_SB_Neighbors.Write(); // Upload }
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); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); try { m_Device.Init(panelOutput.Handle, false, true); } catch (Exception _e) { m_Device = null; MessageBox("Failed to initialize DX device!\n\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } m_CB_Main = new ConstantBuffer <CB_Main>(m_Device, 0); m_CB_Camera = new ConstantBuffer <CB_Camera>(m_Device, 1); m_CB_AutoExposure = new ConstantBuffer <CB_AutoExposure>(m_Device, 10); m_CB_ToneMapping = new ConstantBuffer <CB_ToneMapping>(m_Device, 10); try { #if DEBUG m_Shader_RenderHDR = new Shader(m_Device, new ShaderFile(new System.IO.FileInfo("Shaders/RenderCubeMap.hlsl")), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); m_Shader_ComputeTallHistogram = new ComputeShader(m_Device, new ShaderFile(new System.IO.FileInfo("Shaders/AutoExposure/ComputeTallHistogram.hlsl")), "CS", null); m_Shader_FinalizeHistogram = new ComputeShader(m_Device, new ShaderFile(new System.IO.FileInfo("Shaders/AutoExposure/FinalizeHistogram.hlsl")), "CS", null); m_Shader_ComputeAutoExposure = new ComputeShader(m_Device, new ShaderFile(new System.IO.FileInfo("Shaders/AutoExposure/ComputeAutoExposure.hlsl")), "CS", null); m_Shader_ToneMapping = new Shader(m_Device, new ShaderFile(new System.IO.FileInfo("Shaders/ToneMapping.hlsl")), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); #else m_Shader_RenderHDR = Shader.CreateFromBinaryBlob(m_Device, new System.IO.FileInfo("Shaders/RenderCubeMap.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); m_Shader_ComputeTallHistogram = ComputeShader.CreateFromBinaryBlob(m_Device, new System.IO.FileInfo("Shaders/AutoExposure/ComputeTallHistogram.hlsl"), "CS"); m_Shader_FinalizeHistogram = ComputeShader.CreateFromBinaryBlob(m_Device, new System.IO.FileInfo("Shaders/AutoExposure/FinalizeHistogram.hlsl"), "CS"); m_Shader_ComputeAutoExposure = ComputeShader.CreateFromBinaryBlob(m_Device, new System.IO.FileInfo("Shaders/AutoExposure/ComputeAutoExposure.hlsl"), "CS"); m_Shader_ToneMapping = Shader.CreateFromBinaryBlob(m_Device, new System.IO.FileInfo("Shaders/ToneMapping.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS"); #endif } catch (Exception _e) { MessageBox("Shader failed to compile!\n\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); m_Shader_RenderHDR = null; m_Shader_ComputeTallHistogram = null; m_Shader_FinalizeHistogram = null; m_Shader_ComputeAutoExposure = null; m_Shader_ToneMapping = null; } // Create the HDR buffer m_Tex_HDR = new Texture2D(m_Device, panelOutput.Width, panelOutput.Height, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, null); // Create the histogram & auto-exposure buffers int tallHistogramHeight = (panelOutput.Height + 3) >> 2; m_Tex_TallHistogram = new Texture2D(m_Device, 128, tallHistogramHeight, 1, 1, PIXEL_FORMAT.R32_UINT, false, true, null); m_Tex_Histogram = new Texture2D(m_Device, 128, 1, 1, 1, PIXEL_FORMAT.R32_UINT, false, true, null); m_Buffer_AutoExposureSource = new StructuredBuffer <autoExposure_t>(m_Device, 1, true); m_Buffer_AutoExposureSource.m[0].EngineLuminanceFactor = 1.0f; m_Buffer_AutoExposureSource.m[0].TargetLuminance = 1.0f; m_Buffer_AutoExposureSource.m[0].MinLuminanceLDR = 0.0f; m_Buffer_AutoExposureSource.m[0].MaxLuminanceLDR = 1.0f; m_Buffer_AutoExposureSource.m[0].MiddleGreyLuminanceLDR = 1.0f; m_Buffer_AutoExposureSource.m[0].EV = 0.0f; m_Buffer_AutoExposureSource.m[0].Fstop = 0.0f; m_Buffer_AutoExposureSource.m[0].PeakHistogramValue = 0; m_Buffer_AutoExposureSource.Write(); m_Buffer_AutoExposureTarget = new StructuredBuffer <autoExposure_t>(m_Device, 1, true); // Load cube map try { m_Tex_CubeMap = LoadCubeMap(new System.IO.FileInfo("garage4_hd.dds")); // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\hdrcube6.dds" ) ); // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_28_cube_BC6H_UF16.bimage" ) ); // Tunnel // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_89_cube_BC6H_UF16.bimage" ) ); // Large sky // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_115_cube_BC6H_UF16.bimage" ) ); // Indoor // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_123_cube_BC6H_UF16.bimage" ) ); // Under the arch // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_189_cube_BC6H_UF16.bimage" ) ); // Indoor viewing out (vista) // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_246_cube_BC6H_UF16.bimage" ) ); // Nice! Statue's feet // m_Tex_CubeMap = LoadCubeMap( new System.IO.FileInfo( @"..\..\..\Arkane\CubeMaps\dust_return\pr_obe_248_cube_BC6H_UF16.bimage" ) ); // Nice! In a corner with lot of sky } catch (Exception) { } // Setup camera m_Camera.CreatePerspectiveCamera((float)(90.0 * Math.PI / 180.0), (float)panelOutput.Width / panelOutput.Height, 0.01f, 100.0f); m_Manipulator.Attach(panelOutput, m_Camera); m_Manipulator.InitializeCamera(new float3(0, 0, 1), new float3(0, 0, 0), float3.UnitY); }
private void timer1_Tick(object sender, EventArgs e) { if (!m_bHasRendered) { return; } m_bHasRendered = false; // Perform simulation int neighborsCount = m_neighborPositions.Length; bool hemi = checkBoxHemisphere.Checked; float solidAngle = (float)(2.0 * Math.PI / neighborsCount); // Hemisphere mode only covers 2PI float cosHalfAngle = 1.0f - solidAngle / (float)Math.PI; float halfAngle = (float)Math.Acos(cosHalfAngle); // Not used, just to check // Compute pressure forces float F = 0.01f * floatTrackbarControlForce.Value; float3[] forces = new float3[neighborsCount]; for (int i = 0; i < neighborsCount - 1; i++) { float3 D0 = m_neighborPositions[i]; for (int j = i + 1; j < neighborsCount; j++) { float3 D1 = m_neighborPositions[j]; float3 Dir = (D1 - D0).Normalized; float Dot = D0.Dot(D1) - 1.0f; // in [0,-2] float Force = F * (float)Math.Exp(Dot); forces[i] = forces[i] - Force * Dir; // Pushes 0 away from 1 forces[j] = forces[j] + Force * Dir; // Pushes 1 away from 0 } if (hemi) { // forces[i] += Math.Max( 0.0f, cosHalfAngle / Math.Max( 1e-1f, D0.z ) - 1.0f ) * float3.UnitZ; forces[i] += forces[i].Length * F * Math.Max(0.0f, 1.0f - D0.y / cosHalfAngle) * float3.UnitY; } } if (hemi) { forces[neighborsCount - 1] += forces[neighborsCount - 1].Length * F * Math.Max(0.0f, 1.0f - forces[neighborsCount - 1].y / cosHalfAngle) * float3.UnitY; } if (checkBoxForceOneSample.Checked) { // Force first sample up m_neighborPositions[0] = float3.UnitY; forces[0] = float3.Zero; } // Apply force for (int i = 0; i < neighborsCount; i++) { float3 newPosition = (m_neighborPositions[i] + forces[i]).Normalized; m_neighborPositions[i] = newPosition; m_SB_Neighbors.m[i].m_Position = newPosition; } // Update m_SB_Neighbors.Write(); if (checkBoxRenderCell.Checked) { buttonBuildCell_Click(this, EventArgs.Empty); Application.DoEvents(); } }
private void GenerateRays( int _raysCount, StructuredBuffer<float3> _target ) { _raysCount = Math.Min( MAX_THREADS, _raysCount ); // Half-Life 2 basis float3[] HL2Basis = new float3[] { new float3( (float) Math.Sqrt( 2.0 / 3.0 ), 0.0f, (float) Math.Sqrt( 1.0 / 3.0 ) ), new float3( -(float) Math.Sqrt( 1.0 / 6.0 ), (float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ), new float3( -(float) Math.Sqrt( 1.0 / 6.0 ), -(float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ) }; float centerTheta = (float) Math.Acos( HL2Basis[0].z ); float[] centerPhi = new float[] { (float) Math.Atan2( HL2Basis[0].y, HL2Basis[0].x ), (float) Math.Atan2( HL2Basis[1].y, HL2Basis[1].x ), (float) Math.Atan2( HL2Basis[2].y, HL2Basis[2].x ), }; for ( int rayIndex=0; rayIndex < _raysCount; rayIndex++ ) { double phi = (Math.PI / 3.0) * (2.0 * SimpleRNG.GetUniform() - 1.0); // Stratified version double theta = (Math.Acos( Math.Sqrt( (rayIndex + SimpleRNG.GetUniform()) / _raysCount ) )); // // Don't give a shit version (a.k.a. melonhead version) // // double Theta = Math.Acos( Math.Sqrt(WMath.SimpleRNG.GetUniform() ) ); // double Theta = 0.5 * Math.PI * WMath.SimpleRNG.GetUniform(); theta = Math.Min( 0.499f * Math.PI, theta ); double cosTheta = Math.Cos( theta ); double sinTheta = Math.Sin( theta ); double lengthFactor = 1.0 / sinTheta; // The ray is scaled so we ensure we always walk at least a texel in the texture cosTheta *= lengthFactor; sinTheta *= lengthFactor; // Yeah, yields 1... :) _target.m[0*MAX_THREADS+rayIndex].Set( (float) (Math.Cos( centerPhi[0] + phi ) * sinTheta), (float) (Math.Sin( centerPhi[0] + phi ) * sinTheta), (float) cosTheta ); _target.m[1*MAX_THREADS+rayIndex].Set( (float) (Math.Cos( centerPhi[1] + phi ) * sinTheta), (float) (Math.Sin( centerPhi[1] + phi ) * sinTheta), (float) cosTheta ); _target.m[2*MAX_THREADS+rayIndex].Set( (float) (Math.Cos( centerPhi[2] + phi ) * sinTheta), (float) (Math.Sin( centerPhi[2] + phi ) * sinTheta), (float) cosTheta ); } _target.Write(); }