2using UnityEngine.Rendering;
11 internal struct Cesium3DTileInfo
13 public bool usesAdditiveRefinement;
14 public float geometricError;
15 public Vector3 dimensions;
16 public bool isTranslucent;
20 [AddComponentMenu(
"")]
21 internal class CesiumPointCloudRenderer : MonoBehaviour
23 private Cesium3DTileset _tileset;
26 private MeshFilter _meshFilter;
27 private MeshRenderer _meshRenderer;
28 private GraphicsBuffer _meshVertexBuffer;
30 private int _pointCount = 0;
31 private Material _pointMaterial;
33 private Bounds _bounds;
35 private Vector4 _attenuationParameters;
36 private Vector4 _constantColor;
38 private Cesium3DTileInfo _tileInfo;
40 public Cesium3DTileInfo tileInfo
42 set => this._tileInfo = value;
47 this._tileset = this.gameObject.GetComponentInParent<Cesium3DTileset>();
49 this._meshFilter = this.gameObject.GetComponent<MeshFilter>();
50 this._mesh = this._meshFilter.sharedMesh;
51 this._meshRenderer = this.gameObject.GetComponent<MeshRenderer>();
53 this._pointCount = this._mesh.vertexCount;
54 this._pointMaterial = UnityEngine.Object.Instantiate(
55 Resources.Load<Material>(
"CesiumPointCloudShadingMaterial"));
57 GraphicsBuffer sourceBuffer = this._mesh.GetVertexBuffer(0);
59 bool usingDirect11 = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11;
62 this._meshVertexBuffer =
new GraphicsBuffer(
63 GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopyDestination,
66 Graphics.CopyBuffer(sourceBuffer, this._meshVertexBuffer);
67 sourceBuffer.Release();
70 this._mesh.vertexBufferTarget |= GraphicsBuffer.Target.Structured;
71 this._meshVertexBuffer = sourceBuffer;
74 if (this._mesh.HasVertexAttribute(VertexAttribute.Color))
76 this._pointMaterial.EnableKeyword(
"HAS_POINT_COLORS");
80 Material material = this._meshRenderer.sharedMaterial;
82 if (material.HasColor(
"_Color"))
84 this._constantColor = material.color;
86 else if (material.HasVector(
"_baseColorFactor"))
88 this._constantColor = material.GetVector(
"_baseColorFactor");
92 this._constantColor = Color.gray;
96 if (this._mesh.HasVertexAttribute(VertexAttribute.Normal))
98 this._pointMaterial.EnableKeyword(
"HAS_POINT_NORMALS");
101 if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced ||
102 XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview)
104 this._pointMaterial.EnableKeyword(
"INSTANCING_ON");
108 private float GetGeometricError(CesiumPointCloudShading pointCloudShading)
110 float geometricError = this._tileInfo.geometricError;
111 if (geometricError > 0.0f)
113 return geometricError;
116 if (pointCloudShading.baseResolution > 0.0f)
118 return pointCloudShading.baseResolution;
122 Vector3 dimensions = this._tileInfo.dimensions;
123 float volume = dimensions.x * dimensions.y * dimensions.z;
124 return Mathf.Pow(volume / this._pointCount, 1.0f / 3.0f);
127 private void UpdateAttenuationParameters()
129 float maximumPointSize =
130 this._tileInfo.usesAdditiveRefinement ?
132 this._tileset.maximumScreenSpaceError;
134 if (this._tileset.pointCloudShading.maximumAttenuation > 0.0f)
136 maximumPointSize = this._tileset.pointCloudShading.maximumAttenuation;
142 maximumPointSize *= Screen.dpi / 150;
145 CesiumPointCloudShading pointCloudShading = this._tileset.pointCloudShading;
147 float geometricError = this.GetGeometricError(pointCloudShading);
148 geometricError *= pointCloudShading.geometricErrorScale;
151 Camera camera = Camera.main;
152 float sseDenominator = 2.0f * Mathf.Tan(0.5f * Mathf.Deg2Rad * camera.fieldOfView);
153 float depthMultplier = camera.scaledPixelHeight / sseDenominator;
155 this._attenuationParameters =
156 new Vector4(maximumPointSize, geometricError, depthMultplier, 0);
159 private Vector3[] positionsScratch =
new Vector3[3];
161 private void UpdateBounds()
163 Matrix4x4 transformMatrix = this.gameObject.transform.localToWorldMatrix;
165 Bounds localBounds = this._mesh.bounds;
166 positionsScratch[0] = localBounds.center;
167 positionsScratch[1] = localBounds.min;
168 positionsScratch[2] = localBounds.max;
170 this._bounds = GeometryUtility.CalculateBounds(positionsScratch, transformMatrix);
173 private void DestroyResources()
175 if (this._meshVertexBuffer !=
null)
177 this._meshVertexBuffer.Release();
178 this._meshVertexBuffer =
null;
181 if (this._pointMaterial !=
null)
184 if (!EditorApplication.isPlaying) {
185 DestroyImmediate(this._pointMaterial);
189 Destroy(this._pointMaterial);
193 private void UpdateMaterial()
195 this._pointMaterial.SetBuffer(
"_inPoints", this._meshVertexBuffer);
196 this._pointMaterial.SetMatrix(
"_worldTransform", this.gameObject.transform.localToWorldMatrix);
197 this._pointMaterial.SetVector(
"_attenuationParameters", this._attenuationParameters);
198 this._pointMaterial.SetVector(
"_constantColor", this._constantColor);
200 if (this._tileInfo.isTranslucent ||
this._constantColor.w < 1.0f)
202 this._pointMaterial.SetOverrideTag(
"RenderType",
"Transparent");
203 this._pointMaterial.renderQueue = (int)RenderQueue.Transparent;
204 this._pointMaterial.SetInt(
"_SrcBlend", (
int)BlendMode.SrcAlpha);
205 this._pointMaterial.SetInt(
"_DstBlend", (
int)BlendMode.OneMinusSrcAlpha);
209 this._pointMaterial.SetInt(
"_SrcBlend", (
int)BlendMode.One);
210 this._pointMaterial.SetInt(
"_DstBlend", (
int)BlendMode.Zero);
214 private void DrawPointsWithAttenuation()
217 this.UpdateAttenuationParameters();
218 this.UpdateMaterial();
220 Graphics.DrawProcedural(
223 MeshTopology.Triangles,
224 this._pointCount * 6,
230 if (this._tileset.pointCloudShading.attenuation)
232 this.DrawPointsWithAttenuation();
233 this._meshRenderer.enabled =
false;
237 this._meshRenderer.enabled =
true;
243 this.DestroyResources();