Advertisement
Zgragselus

Untitled

Aug 17th, 2023
998
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 18.92 KB | None | 0 0
  1. using RayTracer;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Unity.Collections;
  5. using UnityEngine;
  6. using UnityEngine.Profiling;
  7.  
  8. public class RaytraceGeneration : MonoBehaviour
  9. {
  10.     Generator generator;
  11.  
  12.     public int currentElement = 0;
  13.     public int updateElement = 0;
  14.     public int totalElements = 0;
  15.  
  16.     public int resolution = 8;
  17.  
  18.     public int rtSteps = 256;
  19.     public int rtUpdate = 4096;
  20.  
  21.     public int bvhDebug = 0;
  22.  
  23.     RayTracer.Triangle[] triangles;
  24.     RayTracer.BVH accel;
  25.  
  26.     bool prevBaking = false;
  27.  
  28.     ComputeBuffer trianglesBuffer;
  29.     ComputeBuffer bvhNodesBuffer;
  30.     ComputeBuffer bvhTrianglesBuffer;
  31.  
  32.     [SerializeField]
  33.     ComputeShader rayTracer;
  34.  
  35.     void CalculateGPU()
  36.     {
  37.         rayTracer.SetBuffer(0, "_Triangles", trianglesBuffer);
  38.         rayTracer.SetBuffer(0, "_BVHNodes", bvhNodesBuffer);
  39.         rayTracer.SetBuffer(0, "_BVHIndices", bvhTrianglesBuffer);
  40.         rayTracer.SetTexture(0, "_LightMap", generator.LightMap);
  41.         rayTracer.SetTexture(0, "_RayOrigin", generator.PositionTexture);
  42.         rayTracer.SetTexture(0, "_RayDirection", generator.NormalsTexture);
  43.         rayTracer.SetInt("_Resolution", generator.settings.Resolution);
  44.         rayTracer.SetFloat("_Time", Time.time);
  45.  
  46.         int workgroup = 8;
  47.         int groups = Mathf.CeilToInt(generator.settings.Resolution / workgroup);
  48.  
  49.         rayTracer.Dispatch(0, groups, groups, 1);
  50.     }
  51.  
  52.     // Start is called before the first frame update
  53.     void Start()
  54.     {
  55.         generator = Object.FindObjectOfType<Generator>();
  56.     }
  57.  
  58.     // Update is called once per frame
  59.     void Update()
  60.     {
  61.         if (generator.IsBaking)
  62.         {
  63.             if (prevBaking == false)
  64.             {
  65.                 totalElements = generator.settings.Resolution * generator.settings.Resolution;
  66.                 Prepare();
  67.             }
  68.  
  69.             //Calculate(rtSteps);
  70.             CalculateGPU();
  71.         }
  72.  
  73.         prevBaking = generator.IsBaking;
  74.     }
  75.  
  76.     public class StackElement
  77.     {
  78.         public Transform transform;
  79.         public Matrix4x4 worldMatrix;
  80.  
  81.         public StackElement(Transform transform, Matrix4x4 worldMatrix)
  82.         {
  83.             this.transform = transform;
  84.             this.worldMatrix = worldMatrix;
  85.         }
  86.     }
  87.  
  88.     void Prepare()
  89.     {
  90.         Profiler.BeginSample("LightMap - Prepare LightMap Objects Transform");
  91.  
  92.         // Get all lightmap objects and add them into DFS stack
  93.         LightMap[] lightMaps = Object.FindObjectsOfType<LightMap>();
  94.         Stack<StackElement> transforms = new Stack<StackElement>();
  95.         for (int i = 0; i < lightMaps.Length; i++)
  96.         {
  97.             transforms.Push(new StackElement(lightMaps[i].transform, lightMaps[i].transform.localToWorldMatrix));
  98.         }
  99.  
  100.         Profiler.EndSample();
  101.  
  102.         Profiler.BeginSample("LightMap - Count Triangles");
  103.  
  104.         // Loop through stack and count number of triangles
  105.         int trianglesCount = 0;
  106.         while (transforms.Count > 0)
  107.         {
  108.             // Pop Transform
  109.             StackElement se = transforms.Pop();
  110.             Transform t = se.transform;
  111.             Matrix4x4 curr = se.worldMatrix * t.localToWorldMatrix;
  112.  
  113.             // Enqueue all children for search
  114.             for (int i = 0; i < t.childCount; i++)
  115.             {
  116.                 transforms.Push(new StackElement(t.GetChild(i), curr));
  117.             }
  118.  
  119.             // If transform has game object, game object has mesh filter and mesh filter contains mesh - process that mesh into triangle list
  120.             if (t.gameObject != null)
  121.             {
  122.                 MeshFilter mf = t.GetComponent<MeshFilter>();
  123.  
  124.                 if (mf != null)
  125.                 {
  126.                     if (mf.sharedMesh != null)
  127.                     {
  128.                         Vector3[] vertices = mf.sharedMesh.vertices;
  129.  
  130.                         for (int j = 0; j < mf.sharedMesh.subMeshCount; j++)
  131.                         {
  132.                             int[] indices = mf.sharedMesh.GetTriangles(j);
  133.  
  134.                             trianglesCount += indices.Length / 3;
  135.                         }
  136.                     }
  137.                 }
  138.             }
  139.         }
  140.  
  141.         Profiler.EndSample();
  142.  
  143.         Profiler.BeginSample("LightMap - Restart Stack");
  144.  
  145.         // Clean tri list
  146.         triangles = new RayTracer.Triangle[trianglesCount];
  147.  
  148.         // Restart stack
  149.         for (int i = 0; i < lightMaps.Length; i++)
  150.         {
  151.             transforms.Push(new StackElement(lightMaps[i].transform, lightMaps[i].transform.localToWorldMatrix));
  152.         }
  153.  
  154.         Profiler.EndSample();
  155.  
  156.         Profiler.BeginSample("LightMap - Add Triangles");
  157.  
  158.         // Add triangles
  159.         int counter = 0;
  160.         while (transforms.Count > 0)
  161.         {
  162.             // Pop Transform
  163.             StackElement se = transforms.Pop();
  164.             Transform t = se.transform;
  165.             Matrix4x4 curr = se.worldMatrix * t.localToWorldMatrix;
  166.  
  167.             // Enqueue all children for search
  168.             for (int i = 0; i < t.childCount; i++)
  169.             {
  170.                 transforms.Push(new StackElement(t.GetChild(i), curr));
  171.             }
  172.  
  173.             // If transform has game object, game object has mesh filter and mesh filter contains mesh - process that mesh into triangle list
  174.             if (t.gameObject != null)
  175.             {
  176.                 MeshFilter mf = t.GetComponent<MeshFilter>();
  177.  
  178.                 if (mf != null)
  179.                 {
  180.                     if (mf.sharedMesh != null)
  181.                     {
  182.                         Vector3[] vertices = mf.sharedMesh.vertices;
  183.  
  184.                         for (int j = 0; j < mf.sharedMesh.subMeshCount; j++)
  185.                         {
  186.                             int[] indices = mf.sharedMesh.GetTriangles(j);
  187.  
  188.                             for (int k = 0; k < indices.Length; k += 3)
  189.                             {
  190.                                 int a = indices[k + 0];
  191.                                 int b = indices[k + 1];
  192.                                 int c = indices[k + 2];
  193.  
  194.                                 Vector3 va = curr * new Vector4(vertices[a].x, vertices[a].y, vertices[a].z, 1.0f);
  195.                                 Vector3 vb = curr * new Vector4(vertices[b].x, vertices[b].y, vertices[b].z, 1.0f);
  196.                                 Vector3 vc = curr * new Vector4(vertices[c].x, vertices[c].y, vertices[c].z, 1.0f);
  197.  
  198.                                 triangles[counter] = new RayTracer.Triangle(va, vb, vc);
  199.  
  200.                                 counter++;
  201.                             }
  202.                         }
  203.                     }
  204.                 }
  205.             }
  206.         }
  207.  
  208.         if (trianglesBuffer != null)
  209.         {
  210.             trianglesBuffer.Release();
  211.             trianglesBuffer = null;
  212.         }
  213.  
  214.         trianglesBuffer = new ComputeBuffer(counter, 36, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
  215.         trianglesBuffer.SetData(triangles);
  216.  
  217.         Profiler.EndSample();
  218.  
  219.         // Build BVH
  220.         accel = new RayTracer.BVH(triangles);
  221.  
  222.         if (bvhNodesBuffer != null)
  223.         {
  224.             bvhNodesBuffer.Release();
  225.             bvhNodesBuffer = null;
  226.         }
  227.  
  228.         bvhNodesBuffer = new ComputeBuffer(accel.GetNodes().Count, 64, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
  229.         bvhNodesBuffer.SetData(accel.GetNodes().ToArray());
  230.  
  231.         if (bvhTrianglesBuffer != null)
  232.         {
  233.             bvhTrianglesBuffer.Release();
  234.             bvhTrianglesBuffer = null;
  235.         }
  236.  
  237.         bvhTrianglesBuffer = new ComputeBuffer(accel.GetPrimitiveIndexes().Count, 4, ComputeBufferType.Structured, ComputeBufferMode.Immutable);
  238.         bvhTrianglesBuffer.SetData(accel.GetPrimitiveIndexes().ToArray());
  239.     }
  240.  
  241.     private void OnDisable()
  242.     {
  243.         if (trianglesBuffer != null)
  244.         {
  245.             trianglesBuffer.Release();
  246.             trianglesBuffer = null;
  247.         }
  248.     }
  249.  
  250.     void Calculate(int steps)
  251.     {
  252.         Profiler.BeginSample("Raytrace - Loop Samples");
  253.  
  254.         NativeArray<float> positions = generator.PositionTexture.GetRawTextureData<float>();
  255.         NativeArray<float> normals = generator.NormalsTexture.GetRawTextureData<float>();
  256.  
  257.         for (int i = 0; i < steps; i++)
  258.         {
  259.             Profiler.BeginSample("Raytrace - Gather Position/Normals");
  260.  
  261.             Vector3 pos = new Vector3(positions[(currentElement + i) * 4 + 0], positions[(currentElement + i) * 4 + 1], positions[(currentElement + i) * 4 + 2]);
  262.             Vector3 dir = new Vector3(normals[(currentElement + i) * 4 + 0], normals[(currentElement + i) * 4 + 1], normals[(currentElement + i) * 4 + 2]);
  263.  
  264.             if (Vector3.Dot(pos, pos) == 0.0f && Vector3.Dot(dir, dir) == 0.0f)
  265.             {
  266.                 Profiler.EndSample();
  267.  
  268.                 continue;
  269.             }
  270.  
  271.             Profiler.EndSample();
  272.  
  273.             Profiler.BeginSample("Raytrace - Trace Ray");
  274.  
  275.             RayTracer.Ray r = new RayTracer.Ray(pos + dir * 0.01f, new Vector3(0.0f, 1.0f, 0.0f));
  276.  
  277.             /*float closestDistance = float.MaxValue;
  278.             float closestU = 0.0f;
  279.             float closestV = 0.0f;
  280.             int closestIndex;
  281.             bool closestHit = false;
  282.  
  283.             for (int j = 0; j < triangles.Count; j++)
  284.             {
  285.                 RayTracer.IntersectResult result;
  286.                 result.baryU = 0.0f;
  287.                 result.baryV = 0.0f;
  288.                 result.distance = 0.0f;
  289.                 bool hit = RayTracer.Intersect.RayTriangle(r, triangles[j], ref result);
  290.  
  291.                 if (hit == true)
  292.                 {
  293.                     if (result.distance > 0.0f && result.distance < closestDistance)
  294.                     {
  295.                         closestDistance = result.distance;
  296.                         closestU = result.baryU;
  297.                         closestV = result.baryV;
  298.                         closestHit = true;
  299.                         closestIndex = j;
  300.                     }
  301.                 }
  302.             }
  303.  
  304.             float resultRed = 1.0f;
  305.             float resultGreen = 1.0f;
  306.             float resultBlue = 1.0f;
  307.  
  308.             if (closestHit)
  309.             {
  310.                 resultRed = resultGreen = resultBlue = 0.0f;
  311.             }*/
  312.  
  313.             RayTracer.IntersectResult result = new RayTracer.IntersectResult();
  314.  
  315.             int index = accel.IntersectRay(r, ref result);
  316.  
  317.             Profiler.EndSample();
  318.  
  319.             Profiler.BeginSample("Raytrace - Write Pixel");
  320.  
  321.             float resultRed = 1.0f;
  322.             float resultGreen = 1.0f;
  323.             float resultBlue = 1.0f;
  324.  
  325.             if (index >= 0)
  326.             {
  327.                 resultRed = resultGreen = resultBlue = 0.0f;
  328.             }
  329.  
  330.             /*generator.LightMap.SetPixel((currentElement + i) % generator.settings.Resolution,
  331.                 (currentElement + i) / generator.settings.Resolution,
  332.                 new Color(resultRed, resultGreen, resultBlue));*/
  333.  
  334.             Profiler.EndSample();
  335.         }
  336.  
  337.         currentElement += steps;
  338.         updateElement += steps;
  339.         if (currentElement >= totalElements)
  340.         {
  341.             currentElement = 0;
  342.             updateElement = 0;
  343.             //generator.LightMap.Apply();
  344.         }
  345.  
  346.         if (updateElement > rtUpdate)
  347.         {
  348.             updateElement -= rtUpdate;
  349.             //generator.LightMap.Apply();
  350.         }
  351.  
  352.         Profiler.EndSample();
  353.     }
  354.  
  355.     private void OnDrawGizmosSelected()
  356.     {
  357.         if (Application.isPlaying == true && generator != null && generator.IsBaking)
  358.         {
  359.             /*NativeArray<float> positions = generator.PositionTexture.GetRawTextureData<float>();
  360.             NativeArray<float> normals = generator.NormalsTexture.GetRawTextureData<float>();
  361.  
  362.             Vector3 pos = new Vector3(positions[currentElement * 4 + 0], positions[currentElement * 4 + 1], positions[currentElement * 4 + 2]);
  363.             Vector3 dir = new Vector3(normals[currentElement * 4 + 0], normals[currentElement * 4 + 1], normals[currentElement * 4 + 2]);
  364.  
  365.             RayTracer.Ray r = new RayTracer.Ray(pos + dir * 0.01f, new Vector3(0.0f, 1.0f, 0.0f));
  366.  
  367.             float closestDistance = float.MaxValue;
  368.             float closestU = 0.0f;
  369.             float closestV = 0.0f;
  370.             bool closestHit = false;
  371.  
  372.             Color prev = Gizmos.color;
  373.  
  374.             for (int j = 0; j < triangles.Count; j++)
  375.             {
  376.                 RayTracer.IntersectResult result = new RayTracer.IntersectResult();
  377.                 bool hit = RayTracer.Intersect.RayTriangle(r, triangles[j], ref result);
  378.  
  379.                 if (hit == true)
  380.                 {
  381.                     if (result.distance > 0.0f && result.distance < closestDistance)
  382.                     {
  383.                         closestDistance = result.distance;
  384.                         closestU = result.baryU;
  385.                         closestV = result.baryV;
  386.                         closestHit = true;
  387.                     }
  388.                 }
  389.  
  390.                 Gizmos.color = Color.white;
  391.                 Gizmos.DrawLine(triangles[j].a, triangles[j].b);
  392.                 Gizmos.DrawLine(triangles[j].b, triangles[j].c);
  393.                 Gizmos.DrawLine(triangles[j].c, triangles[j].a);
  394.             }
  395.  
  396.             Gizmos.color = Color.green;
  397.             Gizmos.DrawLine(r.origin + new Vector3(1.0f, 0.0f, 0.0f), r.origin - new Vector3(1.0f, 0.0f, 0.0f));
  398.             Gizmos.DrawLine(r.origin + new Vector3(0.0f, 1.0f, 0.0f), r.origin - new Vector3(0.0f, 1.0f, 0.0f));
  399.             Gizmos.DrawLine(r.origin + new Vector3(0.0f, 0.0f, 1.0f), r.origin - new Vector3(0.0f, 0.0f, 1.0f));
  400.  
  401.             if (closestHit)
  402.             {
  403.                 Gizmos.color = Color.red;
  404.                 Gizmos.DrawLine(r.origin, r.origin + r.direction * closestDistance);
  405.             }
  406.             else
  407.             {
  408.                 Gizmos.color = Color.blue;
  409.                 Gizmos.DrawLine(r.origin, r.origin + r.direction * 100.0f);
  410.             }*/
  411.  
  412.             NativeArray<float> positions = generator.PositionTexture.GetRawTextureData<float>();
  413.             NativeArray<float> normals = generator.NormalsTexture.GetRawTextureData<float>();
  414.  
  415.             Vector3 pos = new Vector3(positions[currentElement * 4 + 0], positions[currentElement * 4 + 1], positions[currentElement * 4 + 2]);
  416.             Vector3 dir = new Vector3(normals[currentElement * 4 + 0], normals[currentElement * 4 + 1], normals[currentElement * 4 + 2]);
  417.  
  418.             RayTracer.Ray r = new RayTracer.Ray(pos + dir * 0.01f, new Vector3(0.0f, 1.0f, 0.0f));
  419.  
  420.             RayTracer.IntersectResult result = new RayTracer.IntersectResult();
  421.  
  422.             int index = accel.IntersectRay(r, ref result);
  423.  
  424.             Color prev = Gizmos.color;
  425.  
  426.             Gizmos.color = Color.green;
  427.             Gizmos.DrawLine(r.origin + new Vector3(1.0f, 0.0f, 0.0f), r.origin - new Vector3(1.0f, 0.0f, 0.0f));
  428.             Gizmos.DrawLine(r.origin + new Vector3(0.0f, 1.0f, 0.0f), r.origin - new Vector3(0.0f, 1.0f, 0.0f));
  429.             Gizmos.DrawLine(r.origin + new Vector3(0.0f, 0.0f, 1.0f), r.origin - new Vector3(0.0f, 0.0f, 1.0f));
  430.  
  431.             if (index >= 0)
  432.             {
  433.                 Gizmos.color = Color.red;
  434.                 Gizmos.DrawLine(r.origin, r.origin + r.direction * result.distance);
  435.             }
  436.             else
  437.             {
  438.                 Gizmos.color = Color.blue;
  439.                 Gizmos.DrawLine(r.origin, r.origin + r.direction * 100.0f);
  440.             }
  441.  
  442.             RayTracer.BVH.BuildNode node = accel.GetHelperBuildNode(bvhDebug);
  443.             if (node != null)
  444.             {
  445.                 if (node.primitiveCount == 0)
  446.                 {
  447.                     Gizmos.color = Color.yellow;
  448.                 }
  449.                 else
  450.                 {
  451.                     for (int i = 0; i < node.primitiveCount; i++)
  452.                     {
  453.                         int baseindex = node.primitiveOffset + i;
  454.                         int triIndex = accel.GetIndices()[baseindex];
  455.  
  456.                         Gizmos.color = Color.white;
  457.                         Gizmos.DrawLine(triangles[triIndex].a, triangles[triIndex].b);
  458.                         Gizmos.DrawLine(triangles[triIndex].b, triangles[triIndex].c);
  459.                         Gizmos.DrawLine(triangles[triIndex].c, triangles[triIndex].a);
  460.                     }
  461.  
  462.                     Gizmos.color = Color.red;
  463.                 }
  464.  
  465.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.min.z),
  466.                     new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.min.z));
  467.  
  468.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.min.z),
  469.                     new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.min.z));
  470.  
  471.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.min.z),
  472.                     new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.min.z));
  473.  
  474.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.min.z),
  475.                     new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.min.z));
  476.  
  477.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.max.z),
  478.                     new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.max.z));
  479.  
  480.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.max.z),
  481.                     new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.max.z));
  482.  
  483.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.max.z),
  484.                     new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.max.z));
  485.  
  486.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.max.z),
  487.                     new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.max.z));
  488.  
  489.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.min.z),
  490.                     new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.min.z));
  491.  
  492.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.min.z),
  493.                     new Vector3(node.bounds.min.x, node.bounds.min.y, node.bounds.max.z));
  494.  
  495.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.min.z),
  496.                     new Vector3(node.bounds.max.x, node.bounds.min.y, node.bounds.max.z));
  497.  
  498.                 Gizmos.DrawLine(new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.min.z),
  499.                     new Vector3(node.bounds.max.x, node.bounds.max.y, node.bounds.max.z));
  500.  
  501.                 Gizmos.DrawLine(new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.min.z),
  502.                     new Vector3(node.bounds.min.x, node.bounds.max.y, node.bounds.max.z));
  503.             }
  504.  
  505.             Gizmos.color = prev;
  506.         }
  507.     }
  508. }
  509.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement