154 lines
4.4 KiB
C#
154 lines
4.4 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Serialization;
|
|
|
|
[RequireComponent(typeof(MeshRenderer)), RequireComponent(typeof(MeshFilter))]
|
|
public class GrassChunk : MonoBehaviour {
|
|
|
|
[SerializeField] private Material materialLOD0;
|
|
public Material MaterialLOD0 {
|
|
get { return materialLOD0; }
|
|
set {
|
|
materialLOD0 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private Mesh meshLOD0;
|
|
public Mesh MeshLOD0 {
|
|
get { return meshLOD0; }
|
|
set {
|
|
meshLOD0 = value;
|
|
UpdateLODAssets();
|
|
UpdateLOD(); // a new mesh may change the AABB which may affect the LOD
|
|
}
|
|
}
|
|
|
|
[SerializeField] private bool enableShadowsLOD0;
|
|
public bool EnableShadowsLOD0 {
|
|
get { return enableShadowsLOD0; }
|
|
set {
|
|
enableShadowsLOD0 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private Material materialLOD1;
|
|
public Material MaterialLOD1 {
|
|
get { return materialLOD1; }
|
|
set {
|
|
materialLOD1 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private Mesh meshLOD1;
|
|
public Mesh MeshLOD1 {
|
|
get { return meshLOD1; }
|
|
set {
|
|
meshLOD1 = value;
|
|
UpdateLODAssets();
|
|
UpdateLOD(); // a new mesh may change the AABB which may affect the LOD
|
|
}
|
|
}
|
|
|
|
[SerializeField] private bool enableShadowsLOD1;
|
|
public bool EnableShadowsLOD1 {
|
|
get { return enableShadowsLOD1; }
|
|
set {
|
|
enableShadowsLOD1 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private Material materialLOD2;
|
|
public Material MaterialLOD2 {
|
|
get { return materialLOD2; }
|
|
set {
|
|
materialLOD2 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
[SerializeField] private Mesh meshLOD2;
|
|
public Mesh MeshLOD2 {
|
|
get { return meshLOD2; }
|
|
set {
|
|
meshLOD2 = value;
|
|
UpdateLODAssets();
|
|
UpdateLOD(); // a new mesh may change the AABB which may affect the LOD
|
|
}
|
|
}
|
|
|
|
[SerializeField] private bool enableShadowsLOD2;
|
|
public bool EnableShadowsLOD2 {
|
|
get { return enableShadowsLOD2; }
|
|
set {
|
|
enableShadowsLOD2 = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
private int lod = -1; // set to -1 so LOD.set does not exit early when initially called with 0
|
|
public int LOD {
|
|
get { return lod; }
|
|
set {
|
|
if (lod == value) return;
|
|
|
|
lod = value;
|
|
UpdateLODAssets();
|
|
}
|
|
}
|
|
|
|
private void Update() {
|
|
UpdateLOD();
|
|
}
|
|
|
|
public void UpdateLOD() {
|
|
var meshRenderer = GetComponent<MeshRenderer>();
|
|
if (Camera.main) {
|
|
// using meshRenderer.bounds may cause a loop where LOD switches constantly
|
|
var sqrCamDist = meshRenderer.bounds.SqrDistance(Camera.main.transform.position);
|
|
if (sqrCamDist > 20f * 20f) {
|
|
LOD = 2;
|
|
}
|
|
else if (sqrCamDist > 5f * 5f) {
|
|
LOD = 1;
|
|
}
|
|
else {
|
|
LOD = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateLODAssets() {
|
|
var meshRenderer = GetComponent<MeshRenderer>();
|
|
var meshFilter = GetComponent<MeshFilter>();
|
|
switch (lod) {
|
|
case 0:
|
|
meshRenderer.sharedMaterial = materialLOD0;
|
|
meshRenderer.shadowCastingMode = EnableShadowsLOD0 ? ShadowCastingMode.On : ShadowCastingMode.Off;
|
|
meshFilter.sharedMesh = meshLOD0;
|
|
break;
|
|
case 1:
|
|
meshRenderer.sharedMaterial = materialLOD1;
|
|
meshRenderer.shadowCastingMode = EnableShadowsLOD1 ? ShadowCastingMode.On : ShadowCastingMode.Off;
|
|
meshFilter.sharedMesh = meshLOD1;
|
|
break;
|
|
case 2:
|
|
meshRenderer.sharedMaterial = materialLOD2;
|
|
meshRenderer.shadowCastingMode = EnableShadowsLOD2 ? ShadowCastingMode.On : ShadowCastingMode.Off;
|
|
meshFilter.sharedMesh = meshLOD2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmos() {
|
|
Gizmos.color = new Color(1f, 0.7f, 0f, 0.5f);
|
|
var meshRenderer = GetComponent<MeshRenderer>();
|
|
var bounds = meshRenderer.bounds;
|
|
Gizmos.DrawWireCube(bounds.center, bounds.size);
|
|
}
|
|
}
|