NearbyStarRenderer.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using System.IO;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace Funly.SkyStudio {
  6. public class NearbyStarRenderer : BaseStarDataRenderer {
  7. private const int kMaxStars = 2000;
  8. private const int kStarPointTextureWidth = 2048;
  9. private const float kStarPaddingRadiusMultipler = 2.1f;
  10. private RenderTexture CreateRenderTexture(string name, int renderTextureSize, RenderTextureFormat format) {
  11. RenderTexture rt = RenderTexture.GetTemporary(
  12. renderTextureSize,
  13. renderTextureSize,
  14. 0,
  15. format,
  16. RenderTextureReadWrite.Linear);
  17. rt.filterMode = FilterMode.Point;
  18. rt.wrapMode = TextureWrapMode.Clamp;
  19. rt.name = name;
  20. return rt;
  21. }
  22. private Material GetNearbyStarMaterial(Vector4 randomSeed, int starCount) {
  23. Material starPixelMat = new Material(new Material(Shader.Find("Hidden/Funly/Sky Studio/Computation/StarCalcNearby"))) {
  24. hideFlags = HideFlags.HideAndDontSave
  25. };
  26. starPixelMat.SetFloat("_StarDensity", density);
  27. starPixelMat.SetFloat("_NumStarPoints", starCount);
  28. starPixelMat.SetVector("_RandomSeed", randomSeed);
  29. starPixelMat.SetFloat("_TextureSize", kStarPointTextureWidth);
  30. return starPixelMat;
  31. }
  32. private void WriteDebugTexture(RenderTexture rt, string path) {
  33. Texture2D tex = ConvertToTexture2D(rt);
  34. File.WriteAllBytes(path, tex.EncodeToPNG());
  35. }
  36. private Texture2D GetStarListTexture(string starTexKey, out int validStarPixelCount) {
  37. // Generate a 1D texture that we'll sample to read back the points.
  38. Texture2D starPointTex = new Texture2D(kStarPointTextureWidth, 1, TextureFormat.RGBAFloat, false, true);
  39. starPointTex.filterMode = FilterMode.Point;
  40. int validStarCount = 0;
  41. float minDistance = maxRadius * kStarPaddingRadiusMultipler;
  42. List<Vector4> starPoints = new List<Vector4>();
  43. // Make sure star points are spaced so they don't overlap unless it's pixel sized stars.
  44. bool performPaddingCheck = maxRadius > .0015f;
  45. // Generate random points on a sphere for each star, and make sure they don't overlap.
  46. for (int i = 0; i < kMaxStars; i++) {
  47. Vector3 starPoint = Random.onUnitSphere;
  48. if (performPaddingCheck) {
  49. bool isToClose = false;
  50. for (int j = 0; j < starPoints.Count; j++) {
  51. float dist = Vector3.Distance(starPoint, starPoints[j]);
  52. if (dist < minDistance) {
  53. isToClose = true;
  54. break;
  55. }
  56. }
  57. if (isToClose) {
  58. continue;
  59. }
  60. }
  61. starPoints.Add(starPoint);
  62. starPointTex.SetPixel(validStarCount, 0, new Color(starPoint.x,
  63. starPoint.y,
  64. starPoint.z,
  65. 0.0f));
  66. validStarCount += 1;
  67. }
  68. starPointTex.Apply();
  69. validStarPixelCount = validStarCount;
  70. return starPointTex;
  71. }
  72. public override IEnumerator ComputeStarData() {
  73. SendProgress(0);
  74. RenderTexture nearbyStarRT = CreateRenderTexture("Nearby Star " + layerId,
  75. (int)imageSize,
  76. RenderTextureFormat.ARGB32);
  77. RenderTexture previousRenderTexture = RenderTexture.active;
  78. Random.State state = Random.state;
  79. Random.InitState(layerId.GetHashCode());
  80. Vector4 randomSeed = new Vector4(
  81. Random.Range(0.0f, 1.0f),
  82. Random.Range(0.0f, 1.0f),
  83. Random.Range(0.0f, 1.0f),
  84. Random.Range(0.0f, 1.0f));
  85. int generatedStarCount;
  86. Texture2D nearbyStarTex = GetStarListTexture(layerId, out generatedStarCount);
  87. int desiredStarCount = Mathf.FloorToInt(Mathf.Clamp01(density) * kMaxStars);
  88. int actualStarCount = System.Math.Min(desiredStarCount, generatedStarCount);
  89. // Generate the nearby star texture.
  90. RenderTexture.active = nearbyStarRT;
  91. Material nearbyStarMat = GetNearbyStarMaterial(randomSeed, actualStarCount);
  92. Graphics.Blit(nearbyStarTex, nearbyStarMat);
  93. Texture2D tex = ConvertToTexture2D(nearbyStarRT);
  94. RenderTexture.active = previousRenderTexture;
  95. nearbyStarRT.Release();
  96. Random.state = state;
  97. SendCompletion(tex, true);
  98. yield break;
  99. }
  100. private Texture2D ConvertToTexture2D(RenderTexture rt) {
  101. Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
  102. tex.name = layerId;
  103. tex.filterMode = FilterMode.Point;
  104. tex.wrapMode = TextureWrapMode.Clamp;
  105. tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0, false);
  106. tex.Apply(false);
  107. return tex;
  108. }
  109. }
  110. }