2using UnityEngine.Rendering;
14 internal struct Cesium3DTileInfo
16 public bool usesAdditiveRefinement;
17 public float geometricError;
18 public Vector3 dimensions;
19 public bool isTranslucent;
23 [AddComponentMenu(
"")]
24 internal class CesiumPointCloudRenderer : MonoBehaviour
26 private Cesium3DTileset _tileset;
29 private MeshFilter _meshFilter;
30 private MeshRenderer _meshRenderer;
31 private GraphicsBuffer _meshVertexBuffer;
33 private int _pointCount = 0;
34 private Material _pointMaterial;
36 private Bounds _bounds;
38 private Vector4 _attenuationParameters;
39 private Vector4 _constantColor;
41 private Cesium3DTileInfo _tileInfo;
43 public Cesium3DTileInfo tileInfo
45 set => this._tileInfo = value;
50 this._tileset = this.gameObject.GetComponentInParent<Cesium3DTileset>();
52 this._meshFilter = this.gameObject.GetComponent<MeshFilter>();
53 this._mesh = this._meshFilter.sharedMesh;
54 this._meshRenderer = this.gameObject.GetComponent<MeshRenderer>();
56 this._pointCount = this._mesh.vertexCount;
57 this._pointMaterial = UnityEngine.Object.Instantiate(
58 Resources.Load<Material>(
"CesiumPointCloudShadingMaterial"));
60 GraphicsBuffer sourceBuffer = this._mesh.GetVertexBuffer(0);
62 bool usingDirect11 = SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11;
65 this._meshVertexBuffer =
new GraphicsBuffer(
66 GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.CopyDestination,
69 Graphics.CopyBuffer(sourceBuffer, this._meshVertexBuffer);
70 sourceBuffer.Release();
73 this._mesh.vertexBufferTarget |= GraphicsBuffer.Target.Structured;
74 this._meshVertexBuffer = sourceBuffer;
77 if (this._mesh.HasVertexAttribute(VertexAttribute.Color))
79 this._pointMaterial.EnableKeyword(
"HAS_POINT_COLORS");
83 Material material = this._meshRenderer.sharedMaterial;
85 if (material.HasColor(
"_Color"))
87 this._constantColor = material.color;
89 else if (material.HasVector(
"_baseColorFactor"))
91 this._constantColor = material.GetVector(
"_baseColorFactor");
95 this._constantColor = Color.gray;
99 if (this._mesh.HasVertexAttribute(VertexAttribute.Normal))
101 this._pointMaterial.EnableKeyword(
"HAS_POINT_NORMALS");
105 if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced ||
106 XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview)
108 this._pointMaterial.EnableKeyword(
"INSTANCING_ON");
113 private float GetGeometricError(CesiumPointCloudShading pointCloudShading)
115 float geometricError = this._tileInfo.geometricError;
116 if (geometricError > 0.0f)
118 return geometricError;
121 if (pointCloudShading.baseResolution > 0.0f)
123 return pointCloudShading.baseResolution;
127 Vector3 dimensions = this._tileInfo.dimensions;
128 float volume = dimensions.x * dimensions.y * dimensions.z;
129 return Mathf.Pow(volume / this._pointCount, 1.0f / 3.0f);
132 private void UpdateAttenuationParameters()
134 float maximumPointSize =
135 this._tileInfo.usesAdditiveRefinement ?
137 this._tileset.maximumScreenSpaceError;
139 CesiumPointCloudShading pointCloudShading = this._tileset.pointCloudShading;
141 if (pointCloudShading.maximumAttenuation > 0.0f)
143 maximumPointSize = this._tileset.pointCloudShading.maximumAttenuation;
149 maximumPointSize *= Screen.dpi / 150;
152 float geometricError = this.GetGeometricError(pointCloudShading);
153 geometricError *= pointCloudShading.geometricErrorScale;
156 Camera camera = Camera.main;
157 float sseDenominator = 2.0f * Mathf.Tan(0.5f * Mathf.Deg2Rad * camera.fieldOfView);
158 float depthMultplier = camera.scaledPixelHeight / sseDenominator;
160 this._attenuationParameters =
161 new Vector4(maximumPointSize, geometricError, depthMultplier, 0);
164 private Vector3[] positionsScratch =
new Vector3[3];
166 private void UpdateBounds()
168 Matrix4x4 transformMatrix = this.gameObject.transform.localToWorldMatrix;
170 Bounds localBounds = this._mesh.bounds;
171 positionsScratch[0] = localBounds.center;
172 positionsScratch[1] = localBounds.min;
173 positionsScratch[2] = localBounds.max;
175 this._bounds = GeometryUtility.CalculateBounds(positionsScratch, transformMatrix);
178 private void DestroyResources()
180 if (this._meshVertexBuffer !=
null)
182 this._meshVertexBuffer.Release();
183 this._meshVertexBuffer =
null;
186 if (this._pointMaterial !=
null)
189 if (!EditorApplication.isPlaying) {
190 DestroyImmediate(this._pointMaterial);
194 Destroy(this._pointMaterial);
198 private void UpdateMaterial()
200 this._pointMaterial.SetBuffer(
"_inPoints", this._meshVertexBuffer);
201 this._pointMaterial.SetMatrix(
"_worldTransform", this.gameObject.transform.localToWorldMatrix);
202 this._pointMaterial.SetVector(
"_attenuationParameters", this._attenuationParameters);
203 this._pointMaterial.SetVector(
"_constantColor", this._constantColor);
205 if (this._tileInfo.isTranslucent ||
this._constantColor.w < 1.0f)
207 this._pointMaterial.SetOverrideTag(
"RenderType",
"Transparent");
208 this._pointMaterial.renderQueue = (int)RenderQueue.Transparent;
209 this._pointMaterial.SetInt(
"_SrcBlend", (
int)BlendMode.SrcAlpha);
210 this._pointMaterial.SetInt(
"_DstBlend", (
int)BlendMode.OneMinusSrcAlpha);
214 this._pointMaterial.SetInt(
"_SrcBlend", (
int)BlendMode.One);
215 this._pointMaterial.SetInt(
"_DstBlend", (
int)BlendMode.Zero);
219 private void DrawPointsWithAttenuation()
222 this.UpdateAttenuationParameters();
223 this.UpdateMaterial();
225 Graphics.DrawProcedural(
228 MeshTopology.Triangles,
229 this._pointCount * 6,
235 CesiumPointCloudShading pointCloudShading = this._tileset.pointCloudShading;
236 if (pointCloudShading !=
null && pointCloudShading.attenuation)
238 this.DrawPointsWithAttenuation();
239 this._meshRenderer.enabled =
false;
243 this._meshRenderer.enabled =
true;
249 this.DestroyResources();