This commit is contained in:
2025-09-17 18:56:28 +08:00
commit 54c72710a5
5244 changed files with 5717609 additions and 0 deletions

View File

@@ -0,0 +1,180 @@
using UnityEngine;
namespace DestroyIt
{
[ExecuteInEditMode]
[AddComponentMenu ("Image Effects/Color Adjustments/Color Correction (Curves, Saturation)")]
public class ColorCorrectionCurves : PostEffectsBase
{
public enum ColorCorrectionMode
{
Simple = 0,
Advanced = 1
}
public AnimationCurve redChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public AnimationCurve greenChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public AnimationCurve blueChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public bool useDepthCorrection = false;
public AnimationCurve zCurve = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public AnimationCurve depthRedChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public AnimationCurve depthGreenChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
public AnimationCurve depthBlueChannel = new AnimationCurve(new Keyframe(0f,0f), new Keyframe(1f,1f));
private Material ccMaterial;
private Material ccDepthMaterial;
private Material selectiveCcMaterial;
private Texture2D rgbChannelTex;
private Texture2D rgbDepthChannelTex;
private Texture2D zCurveTex;
public float saturation = 1.0f;
public bool selectiveCc = false;
public Color selectiveFromColor = Color.white;
public Color selectiveToColor = Color.white;
public ColorCorrectionMode mode;
public bool updateTextures = true;
public Shader colorCorrectionCurvesShader = null;
public Shader simpleColorCorrectionCurvesShader = null;
public Shader colorCorrectionSelectiveShader = null;
private bool updateTexturesOnStartup = true;
new void Start ()
{
base.Start ();
updateTexturesOnStartup = true;
}
void Awake () { }
public override bool CheckResources ()
{
CheckSupport (mode == ColorCorrectionMode.Advanced);
ccMaterial = CheckShaderAndCreateMaterial (simpleColorCorrectionCurvesShader, ccMaterial);
ccDepthMaterial = CheckShaderAndCreateMaterial (colorCorrectionCurvesShader, ccDepthMaterial);
selectiveCcMaterial = CheckShaderAndCreateMaterial (colorCorrectionSelectiveShader, selectiveCcMaterial);
if (!rgbChannelTex)
rgbChannelTex = new Texture2D (256, 4, TextureFormat.ARGB32, false, true);
if (!rgbDepthChannelTex)
rgbDepthChannelTex = new Texture2D (256, 4, TextureFormat.ARGB32, false, true);
if (!zCurveTex)
zCurveTex = new Texture2D (256, 1, TextureFormat.ARGB32, false, true);
rgbChannelTex.hideFlags = HideFlags.DontSave;
rgbDepthChannelTex.hideFlags = HideFlags.DontSave;
zCurveTex.hideFlags = HideFlags.DontSave;
rgbChannelTex.wrapMode = TextureWrapMode.Clamp;
rgbDepthChannelTex.wrapMode = TextureWrapMode.Clamp;
zCurveTex.wrapMode = TextureWrapMode.Clamp;
if (!isSupported)
ReportAutoDisable ();
return isSupported;
}
public void UpdateParameters ()
{
CheckResources(); // textures might not be created if we're tweaking UI while disabled
if (redChannel != null && greenChannel != null && blueChannel != null)
{
for (float i = 0.0f; i <= 1.0f; i += 1.0f / 255.0f)
{
float rCh = Mathf.Clamp (redChannel.Evaluate(i), 0.0f, 1.0f);
float gCh = Mathf.Clamp (greenChannel.Evaluate(i), 0.0f, 1.0f);
float bCh = Mathf.Clamp (blueChannel.Evaluate(i), 0.0f, 1.0f);
rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(rCh,rCh,rCh) );
rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 1, new Color(gCh,gCh,gCh) );
rgbChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 2, new Color(bCh,bCh,bCh) );
float zC = Mathf.Clamp (zCurve.Evaluate(i), 0.0f,1.0f);
zCurveTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(zC,zC,zC) );
rCh = Mathf.Clamp (depthRedChannel.Evaluate(i), 0.0f,1.0f);
gCh = Mathf.Clamp (depthGreenChannel.Evaluate(i), 0.0f,1.0f);
bCh = Mathf.Clamp (depthBlueChannel.Evaluate(i), 0.0f,1.0f);
rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 0, new Color(rCh,rCh,rCh) );
rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 1, new Color(gCh,gCh,gCh) );
rgbDepthChannelTex.SetPixel ((int) Mathf.Floor(i*255.0f), 2, new Color(bCh,bCh,bCh) );
}
rgbChannelTex.Apply ();
rgbDepthChannelTex.Apply ();
zCurveTex.Apply ();
}
}
public void UpdateTextures ()
{
UpdateParameters ();
}
void OnRenderImage (RenderTexture source, RenderTexture destination)
{
if (CheckResources()==false)
{
Graphics.Blit (source, destination);
return;
}
if (updateTexturesOnStartup)
{
UpdateParameters ();
updateTexturesOnStartup = false;
}
if (useDepthCorrection)
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
RenderTexture renderTarget2Use = destination;
if (selectiveCc)
{
renderTarget2Use = RenderTexture.GetTemporary (source.width, source.height);
}
if (useDepthCorrection)
{
ccDepthMaterial.SetTexture ("_RgbTex", rgbChannelTex);
ccDepthMaterial.SetTexture ("_ZCurve", zCurveTex);
ccDepthMaterial.SetTexture ("_RgbDepthTex", rgbDepthChannelTex);
ccDepthMaterial.SetFloat ("_Saturation", saturation);
Graphics.Blit (source, renderTarget2Use, ccDepthMaterial);
}
else
{
ccMaterial.SetTexture ("_RgbTex", rgbChannelTex);
ccMaterial.SetFloat ("_Saturation", saturation);
Graphics.Blit (source, renderTarget2Use, ccMaterial);
}
if (selectiveCc)
{
selectiveCcMaterial.SetColor ("selColor", selectiveFromColor);
selectiveCcMaterial.SetColor ("targetColor", selectiveToColor);
Graphics.Blit (renderTarget2Use, destination, selectiveCcMaterial);
RenderTexture.ReleaseTemporary (renderTarget2Use);
}
}
}
}

View File

@@ -0,0 +1,15 @@
fileFormatVersion: 2
guid: 2adfe5e4cdca8d740b1ae4b9ea08c040
MonoImporter:
serializedVersion: 2
defaultReferences:
- colorCorrectionCurvesShader: {fileID: 4800000, guid: 62bcade1028c24ca1a39760ed84b9487,
type: 3}
- simpleColorCorrectionCurvesShader: {fileID: 4800000, guid: 438ddd58d82c84d9eb1fdc56111702e1,
type: 3}
- colorCorrectionSelectiveShader: {fileID: 4800000, guid: e515e0f94cefc4c0db54b45cba621544,
type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
namespace DestroyIt
{
public class DustWall : MonoBehaviour
{
public GameObject playerDustPrefab; // A dust cloud particle effect that surrounds the player when the shockwave hits.
public float dustDurationSeconds = 10f; // How long (in seconds) to play the dust effect around a player after being hit by the shockwave.
public float dustStartDistance = 50f; // How far away from the player the dust effect starts.
public Vector3 fixedFromPosition;
void OnTriggerEnter(Collider collider)
{
if (collider.tag == "Player")
{
if (playerDustPrefab != null)
{
Transform player = collider.gameObject.transform;
GameObject dustCloud = Instantiate(playerDustPrefab, player.position, Quaternion.identity) as GameObject;
Follow followScript = dustCloud.AddComponent<Follow>();
followScript.isPositionFixed = true;
followScript.objectToFollow = player;
followScript.facingDirection = FacingDirection.FollowedObject;
followScript.fixedFromPosition = fixedFromPosition;
followScript.fixedDistance = dustStartDistance;
FadeParticleEffect fadeParticleEff = dustCloud.AddComponent<FadeParticleEffect>();
fadeParticleEff.delaySeconds = dustDurationSeconds - 2f; // allow for a two-second fadeout time.
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9b13f8a31b5777a45a2ed5eef02d5e7d
timeCreated: 1426122767
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
using System.Collections.Generic;
using UnityEngine;
namespace DestroyIt
{
public class Explode : MonoBehaviour
{
[Tooltip("The maximum amount of damage the blast can do. This is separate from, and does not affect, the force of the blast on rigidbodies.")]
public float blastDamage = 250f;
[Tooltip("The strength (or force) of the blast. Higher numbers push rigidbodies around more.")]
public float blastForce = 250f;
[Tooltip("The distance from point of impact where objects are considered to be hit at point blank range. Point Blank radius is checked first, then Near, then Far.")]
public float pointBlankBlastRadius = 2f;
[Tooltip("The percentage of blast damage applied to objects hit at point blank distance from the rocket's impact point.")]
[Range(0f, 1f)]
public float pointBlankDamagePercent = 1f;
[Tooltip("The distance from the point of impact where objects are nearby, but not considered point blank. Point Blank radius is checked first, then Near, then Far.")]
public float nearBlastRadius = 5f;
[Tooltip("The percentage of blast damage applied to objects hit at a distance near to the rocket's impact point.")]
[Range(0f, 1f)]
public float nearDamagePercent = .5f;
[Tooltip("The distance from the point of impact where objects are far away, but still considered to be in the blast zone. Point Blank radius is checked first, then Near, then Far.")]
public float farBlastRadius = 10f;
[Tooltip("The percentage of blast damage applied to objects hit within maximum effective distance from the rocket's impact point.")]
[Range(0f, 1f)]
public float farDamagePercent = .25f;
[Tooltip("The amount of upward \"push\" explosions have. Higher numbers make debris fly up in the air, but can get unrealistic.")]
[Range(0f, 3f)]
public float explosionUpwardPush = 1f;
private List<Rigidbody> affectedRigidbodies;
private Dictionary<ChipAwayDebris, float> affectedChipAwayDebris;
private Dictionary<Destructible, ExplosiveDamage> affectedDestructibles;
public void Start()
{
Vector3 currPos = transform.position;
affectedRigidbodies = new List<Rigidbody>();
affectedChipAwayDebris = new Dictionary<ChipAwayDebris, float>();
affectedDestructibles = new Dictionary<Destructible, ExplosiveDamage>();
// POINT BLANK RANGE - Apply force and damage to colliders and rigidbodies
int pointBlankCounter = Physics.OverlapSphereNonAlloc(currPos, pointBlankBlastRadius, DestructionManager.Instance.overlapColliders);
ExplosiveDamage pointBlankExplosiveDamage = new ExplosiveDamage()
{
Position = currPos,
DamageAmount = blastDamage * pointBlankDamagePercent,
BlastForce = blastForce,
Radius = farBlastRadius,
UpwardModifier = explosionUpwardPush
};
AddAffectedObjects(pointBlankCounter, pointBlankExplosiveDamage, .75f);
// NEAR RANGE - Apply force and damage to colliders and rigidbodies
int nearCounter = Physics.OverlapSphereNonAlloc(currPos, nearBlastRadius, DestructionManager.Instance.overlapColliders);
ExplosiveDamage nearExplosiveDamage = new ExplosiveDamage()
{
Position = currPos,
DamageAmount = blastDamage * nearDamagePercent,
BlastForce = blastForce,
Radius = farBlastRadius,
UpwardModifier = explosionUpwardPush
};
AddAffectedObjects(nearCounter, nearExplosiveDamage, .50f);
// FAR RANGE - Apply force and damage to colliders and rigidbodies
int farCounter = Physics.OverlapSphereNonAlloc(currPos, farBlastRadius, DestructionManager.Instance.overlapColliders);
ExplosiveDamage farExplosiveDamage = new ExplosiveDamage()
{
Position = currPos,
DamageAmount = blastDamage * farDamagePercent,
BlastForce = blastForce,
Radius = farBlastRadius,
UpwardModifier = explosionUpwardPush
};
AddAffectedObjects(farCounter, farExplosiveDamage, .25f);
// Apply blast force to all affected rigidbodies
foreach (Rigidbody rbody in affectedRigidbodies)
rbody.AddExplosionForce(blastForce, transform.position, farBlastRadius, explosionUpwardPush); // NOTE: farBlastRadius is used because we need the max radius for rigidbody force.
// Apply blast to ChipAwayDebris
foreach (KeyValuePair<ChipAwayDebris, float> chipAwayDebris in affectedChipAwayDebris)
{
if (Random.Range(1, 100) <= 100 * chipAwayDebris.Value) // Chip off debris pieces a fraction of the time, depending on how close they were to the blast point.
chipAwayDebris.Key.BreakOff(blastForce, farBlastRadius, explosionUpwardPush);
}
// Apply blast to Destructibles
foreach (KeyValuePair<Destructible, ExplosiveDamage> destructible in affectedDestructibles)
{
if (destructible.Value.DamageAmount > 0f)
destructible.Key.ApplyDamage(destructible.Value);
}
}
private void AddAffectedObjects(int colliderCount, ExplosiveDamage explosiveDamage, float chipAwayPercentage)
{
for (int i=0; i<colliderCount; i++)
{
Collider col = DestructionManager.Instance.overlapColliders[i];
// Ignore terrain colliders
if (col is TerrainCollider)
continue;
// Ignore self (the rocket)
if (col == GetComponent<Collider>())
continue;
// Check for Rigidbodies
Rigidbody rbody = col.attachedRigidbody;
if (rbody != null && !rbody.isKinematic && !affectedRigidbodies.Contains(rbody))
affectedRigidbodies.Add(rbody);
// Check for Chip-Away Debris
ChipAwayDebris chipAwayDebris = col.gameObject.GetComponent<ChipAwayDebris>();
if (chipAwayDebris != null && !affectedChipAwayDebris.ContainsKey(chipAwayDebris))
{
affectedChipAwayDebris.Add(chipAwayDebris, chipAwayPercentage);
continue; // Don't process destructible components on chip-away debris.
}
// Check for Destructible objects
Destructible destructible = col.gameObject.GetComponentInParent<Destructible>();
if (destructible != null && !affectedDestructibles.ContainsKey(destructible))
affectedDestructibles.Add(destructible, explosiveDamage);
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4ca94c4cbadf1ec46bb54a9f30ae10aa
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,38 @@
using UnityEngine;
namespace DestroyIt
{
/// <summary>
/// This script produces a screen-wide fade-in effect. It starts from one color and fades that color out over the specified number of seconds.
/// </summary>
public class FadeIn : MonoBehaviour
{
public Color startColor = Color.black;
[Range(0f, 10f)]
public float fadeLength = 2f; // how long (in seconds) the fade effect lasts
private Texture2D blackTexture;
private float alphaFadeValue = 1f;
void Start()
{
blackTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
blackTexture.SetPixel(0, 0, startColor);
blackTexture.Apply();
}
void Update()
{
alphaFadeValue -= Mathf.Clamp01(Time.deltaTime / fadeLength);
if (alphaFadeValue <= 0f)
Destroy(this);
}
void OnGUI()
{
GUI.color = new Color(alphaFadeValue, alphaFadeValue, alphaFadeValue, alphaFadeValue);
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), blackTexture);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f9f2b43d9f0c502408b07cee6e222d2b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
using UnityEngine;
namespace DestroyIt
{
/// <summary>This script fades out all the child particle effects for the game object it is attached to.</summary>
public class FadeParticleEffect : MonoBehaviour
{
[Range(0f, 60f)]
public float delaySeconds = 10f; // How long to delay before starting the fade.
[Range(0f, 60f)]
public float fadeSeconds = 2f; // How long to spend fading out the particle effect.
[Range(1, 30)]
public int updatesPerSecond = 15; // How often to update the fade effect. Higher values have smoother fade-out, but higher performance cost.
private float fadeTiming;
private int stepCounter;
private float totalFadeSteps;
private List<ParticleEffectPropertyBag> particleEffectProperties;
void Start()
{
particleEffectProperties = new List<ParticleEffectPropertyBag>();
fadeTiming = 1 / (float)updatesPerSecond;
totalFadeSteps = fadeSeconds / fadeTiming;
Destroy(transform.gameObject, delaySeconds + fadeSeconds);
if (fadeSeconds > 0f)
InvokeRepeating("Fade", delaySeconds, fadeTiming);
}
void Fade()
{
stepCounter += 1;
if (particleEffectProperties.Count == 0)
{
ParticleSystem[] particleSystems = this.GetComponentsInChildren<ParticleSystem>();
foreach (ParticleSystem particleSystem in particleSystems)
{
Material mat = particleSystem.GetComponent<Renderer>().material;
if (!mat.HasProperty("_TintColor")) continue;
Color tintColorStart = mat.GetColor("_TintColor");
particleEffectProperties.Add(new ParticleEffectPropertyBag() { ParticleSystem = particleSystem, TintColorStart = tintColorStart });
}
}
foreach (ParticleEffectPropertyBag particleSystemPropBag in particleEffectProperties)
{
Material mat = particleSystemPropBag.ParticleSystem.GetComponent<Renderer>().material;
if (!mat.HasProperty("_TintColor")) continue;
Color tintColor = particleSystemPropBag.TintColorStart;
float fadeAmountPerStep = ((1.0f - particleSystemPropBag.TintColorStart.a) / 1.0f) / totalFadeSteps;
float newAlphaValue = Mathf.Clamp01(particleSystemPropBag.TintColorStart.a - (fadeAmountPerStep * stepCounter));
Color newTintColor = new Color(tintColor.r, tintColor.g, tintColor.b, newAlphaValue);
mat.SetColor("_TintColor", newTintColor);
}
}
}
public class ParticleEffectPropertyBag
{
public ParticleSystem ParticleSystem { get; set; }
public Color TintColorStart { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05d89a5f64f3434468210dcef454a3f2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,33 @@
using UnityEngine;
namespace DestroyIt
{
public class FlareFadeOut : MonoBehaviour
{
[Range(0f, 10f)]
public float flareFadeSeconds = 5f;
private float startBrightness;
private LensFlare flare;
// Use this for initialization
void Start()
{
flare = GetComponent<LensFlare>();
startBrightness = flare.brightness;
}
// Update is called once per frame
void Update()
{
flare.brightness -= Mathf.Clamp01(Time.deltaTime / (flareFadeSeconds / startBrightness));
if (flare.brightness <= 0f)
{
Destroy(flare);
Destroy(this);
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7376e4ac713bc3b40b71287dc2417142
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
namespace DestroyIt
{
public class FloatUp : MonoBehaviour
{
[Range(0f, 10f)]
public float floatSpeed = 5f;
private float checkFrequency = 0.05f; // The time (in seconds) this script checks for updates.
private float nextUpdateCheck;
// Use this for initialization
void Start()
{
nextUpdateCheck = Time.time + checkFrequency;
}
// Update is called once per frame
void Update()
{
if (Time.time > nextUpdateCheck)
{
// float up
this.gameObject.transform.position = this.gameObject.transform.position + (Vector3.up * floatSpeed);
// reset the counter
nextUpdateCheck = Time.time + checkFrequency;
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ec141900e15553f4d8ef3cc6b55aed82
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,69 @@
using UnityEngine;
namespace DestroyIt
{
/// <summary>
/// Put this script on your main camera if you want camera effects when the nuke explodes.
/// </summary>
[RequireComponent(typeof(Camera))]
public class NukeCameraEffect : MonoBehaviour
{
[Tooltip("Stores the initial, regular tonemapping settings of the main camera for later use.")]
public Tonemapping regularTonemapping;
[Tooltip("Alternate tonemapping settings to make the scene look over-exposed and strange while the nuke is active.")]
public Tonemapping nukeTonemapping;
[Tooltip("Optional additional color correction curves to use on the main camera to make the scene look strange while the nuke is active.")]
public ColorCorrectionCurves nukeColorCorrection;
public void Start()
{
// Use whichever tonemapper is enabled on the scene by default as the "regular" tonemapping.
// The other one will be used for "nuke effect" tonemapping.
Tonemapping[] toneMappers = GetComponents<Tonemapping>();
if (toneMappers != null && toneMappers.Length == 2)
{
if (toneMappers[0].enabled)
{
regularTonemapping = toneMappers[0];
nukeTonemapping = toneMappers[1];
}
else
{
nukeTonemapping = toneMappers[0];
regularTonemapping = toneMappers[1];
}
nukeTonemapping.enabled = false;
}
ColorCorrectionCurves colorCorrection = GetComponent<ColorCorrectionCurves>();
if (colorCorrection != null && !colorCorrection.enabled)
nukeColorCorrection = colorCorrection;
}
public void OnNukeStart()
{
// If the main camera has a ToneMapping component, switch it to the nuke tonemapping settings.
if (regularTonemapping != null && regularTonemapping.enabled)
{
regularTonemapping.enabled = false;
nukeTonemapping.enabled = true;
}
if (nukeColorCorrection != null && !nukeColorCorrection.enabled)
nukeColorCorrection.enabled = true;
}
public void OnNukeEnd()
{
// If the main camera has a ToneMapping component, deactivate it.
if (regularTonemapping != null && !regularTonemapping.enabled && nukeTonemapping != null && nukeTonemapping.enabled)
{
nukeTonemapping.enabled = false;
regularTonemapping.enabled = true;
}
if (nukeColorCorrection != null && nukeColorCorrection.enabled)
nukeColorCorrection.enabled = false;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 057f6fcdec714c445be9269b2346cce9
timeCreated: 1482263838
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,236 @@
using UnityEngine;
namespace DestroyIt
{
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
public class PostEffectsBase : MonoBehaviour
{
protected bool supportHDRTextures = true;
protected bool supportDX11 = false;
protected bool isSupported = true;
protected Material CheckShaderAndCreateMaterial ( Shader s, Material m2Create)
{
if (!s)
{
Debug.Log("Missing shader in " + ToString ());
enabled = false;
return null;
}
if (s.isSupported && m2Create && m2Create.shader == s)
return m2Create;
if (!s.isSupported)
{
NotSupported ();
Debug.Log("The shader " + s.ToString() + " on effect "+ToString()+" is not supported on this platform!");
return null;
}
else
{
m2Create = new Material (s);
m2Create.hideFlags = HideFlags.DontSave;
if (m2Create)
return m2Create;
else return null;
}
}
protected Material CreateMaterial (Shader s, Material m2Create)
{
if (!s)
{
Debug.Log ("Missing shader in " + ToString ());
return null;
}
if (m2Create && (m2Create.shader == s) && (s.isSupported))
return m2Create;
if (!s.isSupported)
{
return null;
}
else
{
m2Create = new Material (s);
m2Create.hideFlags = HideFlags.DontSave;
if (m2Create)
return m2Create;
else return null;
}
}
void OnEnable ()
{
isSupported = true;
}
protected bool CheckSupport ()
{
return CheckSupport (false);
}
public virtual bool CheckResources ()
{
Debug.LogWarning ("CheckResources () for " + ToString() + " should be overwritten.");
return isSupported;
}
protected void Start ()
{
CheckResources ();
}
protected bool CheckSupport (bool needDepth)
{
isSupported = true;
supportHDRTextures = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf);
supportDX11 = SystemInfo.graphicsShaderLevel >= 50 && SystemInfo.supportsComputeShaders;
if (needDepth && !SystemInfo.SupportsRenderTextureFormat (RenderTextureFormat.Depth))
{
NotSupported ();
return false;
}
if (needDepth)
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
return true;
}
protected bool CheckSupport (bool needDepth, bool needHdr)
{
if (!CheckSupport(needDepth))
return false;
if (needHdr && !supportHDRTextures)
{
NotSupported ();
return false;
}
return true;
}
public bool Dx11Support ()
{
return supportDX11;
}
protected void ReportAutoDisable ()
{
Debug.LogWarning ("The image effect " + ToString() + " has been disabled as it's not supported on the current platform.");
}
// deprecated but needed for old effects to survive upgrading
bool CheckShader (Shader s)
{
Debug.Log("The shader " + s.ToString () + " on effect "+ ToString () + " is not part of the Unity 3.2+ effects suite anymore. For best performance and quality, please ensure you are using the latest Standard Assets Image Effects (Pro only) package.");
if (!s.isSupported)
{
NotSupported ();
return false;
}
else
{
return false;
}
}
protected void NotSupported ()
{
enabled = false;
isSupported = false;
return;
}
protected void DrawBorder (RenderTexture dest, Material material)
{
float x1;
float x2;
float y1;
float y2;
RenderTexture.active = dest;
bool invertY = true; // source.texelSize.y < 0.0ff;
// Set up the simple Matrix
GL.PushMatrix();
GL.LoadOrtho();
for (int i = 0; i < material.passCount; i++)
{
material.SetPass(i);
float y1_; float y2_;
if (invertY)
{
y1_ = 1.0f; y2_ = 0.0f;
}
else
{
y1_ = 0.0f; y2_ = 1.0f;
}
// left
x1 = 0.0f;
x2 = 0.0f + 1.0f/(dest.width*1.0f);
y1 = 0.0f;
y2 = 1.0f;
GL.Begin(GL.QUADS);
GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
// right
x1 = 1.0f - 1.0f/(dest.width*1.0f);
x2 = 1.0f;
y1 = 0.0f;
y2 = 1.0f;
GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
// top
x1 = 0.0f;
x2 = 1.0f;
y1 = 0.0f;
y2 = 0.0f + 1.0f/(dest.height*1.0f);
GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
// bottom
x1 = 0.0f;
x2 = 1.0f;
y1 = 1.0f - 1.0f/(dest.height*1.0f);
y2 = 1.0f;
GL.TexCoord2(0.0f, y1_); GL.Vertex3(x1, y1, 0.1f);
GL.TexCoord2(1.0f, y1_); GL.Vertex3(x2, y1, 0.1f);
GL.TexCoord2(1.0f, y2_); GL.Vertex3(x2, y2, 0.1f);
GL.TexCoord2(0.0f, y2_); GL.Vertex3(x1, y2, 0.1f);
GL.End();
}
GL.PopMatrix();
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 89db801485ee4814a930357b9bbacc17
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:

View File

@@ -0,0 +1,16 @@
using UnityEngine;
namespace DestroyIt
{
public class ResetSkybox : MonoBehaviour
{
void Start()
{
// Reset the skybox blend amount to zero. This is only used for the demo scene.
if (RenderSettings.skybox.HasProperty("_Blend"))
RenderSettings.skybox.SetFloat("_Blend", 0f);
Destroy(this);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 117a70a4471544147b194fe2d4fcc39a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,198 @@
using UnityEngine;
namespace DestroyIt
{
[ExecuteInEditMode]
[RequireComponent (typeof(Camera))]
[AddComponentMenu("Image Effects/Rendering/Screen Space Ambient Occlusion")]
public class ScreenSpaceAmbientOcclusion : MonoBehaviour
{
public enum SSAOSamples
{
Low = 0,
Medium = 1,
High = 2,
}
public float m_Radius = 0.4f;
public SSAOSamples m_SampleCount = SSAOSamples.Medium;
public float m_OcclusionIntensity = 1.5f;
public int m_Blur = 2;
public int m_Downsampling = 2;
public float m_OcclusionAttenuation = 1.0f;
public float m_MinZ = 0.01f;
public Shader m_SSAOShader;
private Material m_SSAOMaterial;
public Texture2D m_RandomTexture;
private bool m_Supported;
private static Material CreateMaterial (Shader shader)
{
if (!shader)
return null;
Material m = new Material (shader);
m.hideFlags = HideFlags.HideAndDontSave;
return m;
}
private static void DestroyMaterial (Material mat)
{
if (mat)
{
DestroyImmediate (mat);
mat = null;
}
}
void OnDisable()
{
DestroyMaterial (m_SSAOMaterial);
}
void Start()
{
if (!SystemInfo.SupportsRenderTextureFormat (RenderTextureFormat.Depth))
{
m_Supported = false;
enabled = false;
return;
}
CreateMaterials ();
if (!m_SSAOMaterial || m_SSAOMaterial.passCount != 5)
{
m_Supported = false;
enabled = false;
return;
}
//CreateRandomTable (26, 0.2f);
m_Supported = true;
}
void OnEnable () {
GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
}
private void CreateMaterials ()
{
if (!m_SSAOMaterial && m_SSAOShader.isSupported)
{
m_SSAOMaterial = CreateMaterial (m_SSAOShader);
m_SSAOMaterial.SetTexture ("_RandomTexture", m_RandomTexture);
}
}
[ImageEffectOpaque]
void OnRenderImage (RenderTexture source, RenderTexture destination)
{
if (!m_Supported || !m_SSAOShader.isSupported) {
enabled = false;
return;
}
CreateMaterials ();
m_Downsampling = Mathf.Clamp (m_Downsampling, 1, 6);
m_Radius = Mathf.Clamp (m_Radius, 0.05f, 1.0f);
m_MinZ = Mathf.Clamp (m_MinZ, 0.00001f, 0.5f);
m_OcclusionIntensity = Mathf.Clamp (m_OcclusionIntensity, 0.5f, 4.0f);
m_OcclusionAttenuation = Mathf.Clamp (m_OcclusionAttenuation, 0.2f, 2.0f);
m_Blur = Mathf.Clamp (m_Blur, 0, 4);
// Render SSAO term into a smaller texture
RenderTexture rtAO = RenderTexture.GetTemporary (source.width / m_Downsampling, source.height / m_Downsampling, 0);
float fovY = GetComponent<Camera>().fieldOfView;
float far = GetComponent<Camera>().farClipPlane;
float y = Mathf.Tan (fovY * Mathf.Deg2Rad * 0.5f) * far;
float x = y * GetComponent<Camera>().aspect;
m_SSAOMaterial.SetVector ("_FarCorner", new Vector3(x,y,far));
int noiseWidth, noiseHeight;
if (m_RandomTexture) {
noiseWidth = m_RandomTexture.width;
noiseHeight = m_RandomTexture.height;
} else {
noiseWidth = 1; noiseHeight = 1;
}
m_SSAOMaterial.SetVector ("_NoiseScale", new Vector3 ((float)rtAO.width / noiseWidth, (float)rtAO.height / noiseHeight, 0.0f));
m_SSAOMaterial.SetVector ("_Params", new Vector4(
m_Radius,
m_MinZ,
1.0f / m_OcclusionAttenuation,
m_OcclusionIntensity));
bool doBlur = m_Blur > 0;
Graphics.Blit (doBlur ? null : source, rtAO, m_SSAOMaterial, (int)m_SampleCount);
if (doBlur)
{
// Blur SSAO horizontally
RenderTexture rtBlurX = RenderTexture.GetTemporary (source.width, source.height, 0);
m_SSAOMaterial.SetVector ("_TexelOffsetScale",
new Vector4 ((float)m_Blur / source.width, 0,0,0));
m_SSAOMaterial.SetTexture ("_SSAO", rtAO);
Graphics.Blit (null, rtBlurX, m_SSAOMaterial, 3);
RenderTexture.ReleaseTemporary (rtAO); // original rtAO not needed anymore
// Blur SSAO vertically
RenderTexture rtBlurY = RenderTexture.GetTemporary (source.width, source.height, 0);
m_SSAOMaterial.SetVector ("_TexelOffsetScale",
new Vector4 (0, (float)m_Blur/source.height, 0,0));
m_SSAOMaterial.SetTexture ("_SSAO", rtBlurX);
Graphics.Blit (source, rtBlurY, m_SSAOMaterial, 3);
RenderTexture.ReleaseTemporary (rtBlurX); // blurX RT not needed anymore
rtAO = rtBlurY; // AO is the blurred one now
}
// Modulate scene rendering with SSAO
m_SSAOMaterial.SetTexture ("_SSAO", rtAO);
Graphics.Blit (source, destination, m_SSAOMaterial, 4);
RenderTexture.ReleaseTemporary (rtAO);
}
/*
private void CreateRandomTable (int count, float minLength)
{
Random.seed = 1337;
Vector3[] samples = new Vector3[count];
// initial samples
for (int i = 0; i < count; ++i)
samples[i] = Random.onUnitSphere;
// energy minimization: push samples away from others
int iterations = 100;
while (iterations-- > 0) {
for (int i = 0; i < count; ++i) {
Vector3 vec = samples[i];
Vector3 res = Vector3.zero;
// minimize with other samples
for (int j = 0; j < count; ++j) {
Vector3 force = vec - samples[j];
float fac = Vector3.Dot (force, force);
if (fac > 0.00001f)
res += force * (1.0f / fac);
}
samples[i] = (samples[i] + res * 0.5f).normalized;
}
}
// now scale samples between minLength and 1.0
for (int i = 0; i < count; ++i) {
samples[i] = samples[i] * Random.Range (minLength, 1.0f);
}
string table = string.Format ("#define SAMPLE_COUNT {0}\n", count);
table += "const float3 RAND_SAMPLES[SAMPLE_COUNT] = {\n";
for (int i = 0; i < count; ++i) {
Vector3 v = samples[i];
table += string.Format("\tfloat3({0},{1},{2}),\n", v.x, v.y, v.z);
}
table += "};\n";
Debug.Log (table);
}
*/
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9f372122fe30c144b93cadbedbf22d8d
MonoImporter:
serializedVersion: 2
defaultReferences:
- m_SSAOShader: {fileID: 4800000, guid: 43ca18288c424f645aaa1e9e07f04c50, type: 3}
- m_RandomTexture: {fileID: 2800000, guid: a181ca8e3c62f3e4b8f183f6c586b032, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,44 @@
using UnityEngine;
namespace DestroyIt
{
public class ShockWall : MonoBehaviour
{
public float blastForce = 200f;
public float damageAmount = 200f;
public Vector3 origin;
private void OnTriggerEnter(Collider col)
{
// If it has a rigidbody, apply force
Rigidbody rbody = col.attachedRigidbody;
if (rbody != null && !rbody.isKinematic)
rbody.AddExplosionForce(blastForce, origin, 0f, 0.5f);
// Check for Chip-Away Debris
ChipAwayDebris chipAwayDebris = col.gameObject.GetComponent<ChipAwayDebris>();
if (chipAwayDebris != null)
{
if (Random.Range(1, 100) > 50) // Do this about half the time...
{
chipAwayDebris.BreakOff(blastForce, 0f, 0.5f);
return; //Skip the destructible check if the debris hasn't chipped away yet.
}
return;
}
// If it's a destructible object, apply damage
// Only do this for the first active and enabled Destructible script found in parent objects
// Special Note: Destructible scripts are turned off on terrain trees by default (to save resources), so we will make an exception for them and process the damage anyway
Destructible[] destObjs = col.gameObject.GetComponentsInParent<Destructible>(false);
foreach (Destructible destObj in destObjs)
{
if (!destObj.isActiveAndEnabled && !destObj.isTerrainTree) continue;
ExplosiveDamage explosiveDamage = new ExplosiveDamage { DamageAmount = damageAmount, BlastForce = blastForce, Position = origin, Radius = 0f, UpwardModifier = 0.5f };
destObj.ApplyDamage(explosiveDamage);
break;
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: aca012ace7354df46ac42baa938124fe
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,124 @@
using UnityEngine;
namespace DestroyIt
{
[RequireComponent(typeof(SphereCollider))]
[RequireComponent(typeof(Rigidbody))]
public class ShockWaveSphere : MonoBehaviour
{
[Tooltip("How many seconds to wait before the shockwave starts.")]
public float timer = 10f;
[Tooltip("The particle effect to use for the shockwave.")]
public ParticleSystem visualEffect;
[Tooltip("How much force to apply to rigidbodies hit by the shockwave.")]
public float blastForce = 500f;
[Tooltip("How much damage to apply to Destructible objects that are hit by the shockwave.")]
public float damageAmount = 200f;
[Tooltip("How fast the shockwave spreads out.")]
public float shockwaveSpeed = 30f;
[Tooltip("The maximum radius of the shockwave. Once it reaches this size, it is disabled and removed from the scene.")]
public float maxRadius = 300f;
private Vector3 _originPos; // the world position where the shockwave originates
private float _timeLeft;
private bool _isInitialized;
private bool _hasStarted;
private SphereCollider _sphereCollider;
private Rigidbody _rigidbody;
public void Start()
{
Initialize();
}
public void OnEnable()
{
Initialize();
}
private void Initialize()
{
if (_isInitialized) return;
_originPos = transform.position;
_timeLeft = timer;
_sphereCollider = gameObject.GetComponent<SphereCollider>();
_sphereCollider.isTrigger = true;
_sphereCollider.radius = 0f;
_rigidbody = gameObject.GetComponent<Rigidbody>();
_rigidbody.useGravity = false;
_isInitialized = true;
}
public void Update()
{
if (!_isInitialized) return;
if (_hasStarted)
{
// Check if the shockwave has reached its max size. If so, destroy it.
if (_sphereCollider.radius >= maxRadius)
{
gameObject.SetActive(false);
Destroy(gameObject);
return;
}
// Grow the shockwave based on the shockwave speed
_sphereCollider.radius += Time.deltaTime * shockwaveSpeed;
return;
}
_timeLeft -= Time.deltaTime;
if (_timeLeft <= 0)
{
// Start the shockwave
if (visualEffect != null)
Instantiate(visualEffect, _originPos, Quaternion.identity);
_hasStarted = true;
}
}
public void OnTriggerEnter(Collider col)
{
// If it has a rigidbody, apply force
Rigidbody rbody = col.attachedRigidbody;
if (rbody != null && !rbody.isKinematic)
rbody.AddExplosionForce(blastForce, _originPos, 0f, 0.5f);
// Check for Chip-Away Debris
ChipAwayDebris chipAwayDebris = col.gameObject.GetComponent<ChipAwayDebris>();
if (chipAwayDebris != null)
{
if (Random.Range(1, 100) > 50) // Do this about half the time...
{
chipAwayDebris.BreakOff(blastForce, 0f, 0.5f);
return; //Skip the destructible check if the debris hasn't chipped away yet.
}
return;
}
// If it's a destructible object, apply damage
// Only do this for the first active and enabled Destructible script found in parent objects
// Special Note: Destructible scripts are turned off on terrain trees by default (to save resources), so we will make an exception for them and process the damage anyway
Destructible[] destObjs = col.gameObject.GetComponentsInParent<Destructible>(false);
foreach (Destructible destObj in destObjs)
{
if (!destObj.isActiveAndEnabled && !destObj.isTerrainTree) continue;
ExplosiveDamage explosiveDamage = new ExplosiveDamage { DamageAmount = damageAmount, BlastForce = blastForce, Position = _originPos, Radius = 0f, UpwardModifier = 0.5f };
destObj.ApplyDamage(explosiveDamage);
break;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3631767c8c3d4029aea8d849d9c5bbc0
timeCreated: 1648252882

View File

@@ -0,0 +1,85 @@
using UnityEngine;
using System.Collections.Generic;
namespace DestroyIt
{
public class SmoothMouseLook : MonoBehaviour
{
// Public variables
public float sensitivityX = 2.0f;
public float sensitivityY = 2.0f;
public float minimumY = -60f;
public float maximumY = 60f;
public int frameCounterX = 20;
public int frameCounterY = 20;
// Private variables
private float rotationX;
private float rotationY;
private Quaternion xQuaternion;
private Quaternion yQuaternion;
private Quaternion origRotation;
private List<float> rotationsX = new List<float>();
private List<float> rotationsY = new List<float>();
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
if (GetComponent<Rigidbody>())
GetComponent<Rigidbody>().freezeRotation = true;
origRotation = transform.localRotation;
}
void Update()
{
if (Cursor.lockState == CursorLockMode.Locked)
{
// Add X rotation
rotationX += Input.GetAxis("Mouse X") * sensitivityX;
rotationsX.Add(rotationX);
// Add Y rotation
rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationY = ClampAngle(rotationY, minimumY, maximumY);
rotationsY.Add(rotationY);
// Average rotations
float rotAverageX = AverageRotations(rotationsX, frameCounterX);
float rotAverageY = AverageRotations(rotationsY, frameCounterY);
// Perform rotation based on averages
xQuaternion = Quaternion.AngleAxis(rotAverageX, Vector3.up);
yQuaternion = Quaternion.AngleAxis(rotAverageY, Vector3.left);
transform.localRotation = origRotation * xQuaternion * yQuaternion;
}
else
Cursor.visible = true;
}
private static float AverageRotations(List<float> rotations, int frameCounter)
{
float rotAverage = 0f;
if (rotations.Count >= frameCounter)
rotations.RemoveAt(0);
for (int i = 0; i < rotations.Count; i++)
rotAverage += rotations[i];
rotAverage /= rotations.Count;
return rotAverage;
}
private float ClampAngle(float angle, float min, float max)
{
if (angle < -360f)
angle += 360f;
if (angle > 360f)
angle -= 360f;
return Mathf.Clamp(angle, min, max);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f4b44c5f660801648ac6d666e3d0dbef
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,271 @@
using UnityEngine;
namespace DestroyIt
{
[ExecuteInEditMode]
[RequireComponent(typeof (Camera))]
[AddComponentMenu("Image Effects/Color Adjustments/Tonemapping")]
public class Tonemapping : PostEffectsBase
{
public enum TonemapperType
{
SimpleReinhard,
UserCurve,
Hable,
Photographic,
OptimizedHejiDawson,
AdaptiveReinhard,
AdaptiveReinhardAutoWhite,
};
public enum AdaptiveTexSize
{
Square16 = 16,
Square32 = 32,
Square64 = 64,
Square128 = 128,
Square256 = 256,
Square512 = 512,
Square1024 = 1024,
};
public TonemapperType type = TonemapperType.Photographic;
public AdaptiveTexSize adaptiveTextureSize = AdaptiveTexSize.Square256;
// CURVE parameter
public AnimationCurve remapCurve;
private Texture2D curveTex = null;
// UNCHARTED parameter
public float exposureAdjustment = 1.5f;
// REINHARD parameter
public float middleGrey = 0.4f;
public float white = 2.0f;
public float adaptionSpeed = 1.5f;
// usual & internal stuff
public Shader tonemapper = null;
public bool validRenderTextureFormat = true;
private Material tonemapMaterial = null;
private RenderTexture rt = null;
private RenderTextureFormat rtFormat = RenderTextureFormat.ARGBHalf;
public override bool CheckResources()
{
CheckSupport(false, true);
tonemapMaterial = CheckShaderAndCreateMaterial(tonemapper, tonemapMaterial);
if (!curveTex && type == TonemapperType.UserCurve)
{
curveTex = new Texture2D(256, 1, TextureFormat.ARGB32, false, true);
curveTex.filterMode = FilterMode.Bilinear;
curveTex.wrapMode = TextureWrapMode.Clamp;
curveTex.hideFlags = HideFlags.DontSave;
}
if (!isSupported)
ReportAutoDisable();
return isSupported;
}
public float UpdateCurve()
{
float range = 1.0f;
if (remapCurve.keys.Length < 1)
remapCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(2, 1));
if (remapCurve != null)
{
if (remapCurve.length > 0)
range = remapCurve[remapCurve.length - 1].time;
for (float i = 0.0f; i <= 1.0f; i += 1.0f/255.0f)
{
float c = remapCurve.Evaluate(i*1.0f*range);
curveTex.SetPixel((int) Mathf.Floor(i*255.0f), 0, new Color(c, c, c));
}
curveTex.Apply();
}
return 1.0f/range;
}
private void OnDisable()
{
if (rt)
{
DestroyImmediate(rt);
rt = null;
}
if (tonemapMaterial)
{
DestroyImmediate(tonemapMaterial);
tonemapMaterial = null;
}
if (curveTex)
{
DestroyImmediate(curveTex);
curveTex = null;
}
}
private bool CreateInternalRenderTexture()
{
if (rt)
{
return false;
}
rtFormat = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.RGHalf) ? RenderTextureFormat.RGHalf : RenderTextureFormat.ARGBHalf;
rt = new RenderTexture(1, 1, 0, rtFormat);
rt.hideFlags = HideFlags.DontSave;
return true;
}
// attribute indicates that the image filter chain will continue in LDR
[ImageEffectTransformsToLDR]
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (CheckResources() == false)
{
Graphics.Blit(source, destination);
return;
}
#if UNITY_EDITOR
validRenderTextureFormat = true;
if (source.format != RenderTextureFormat.ARGBHalf)
{
validRenderTextureFormat = false;
}
#endif
// clamp some values to not go out of a valid range
exposureAdjustment = exposureAdjustment < 0.001f ? 0.001f : exposureAdjustment;
// SimpleReinhard tonemappers (local, non adaptive)
if (type == TonemapperType.UserCurve)
{
float rangeScale = UpdateCurve();
tonemapMaterial.SetFloat("_RangeScale", rangeScale);
tonemapMaterial.SetTexture("_Curve", curveTex);
Graphics.Blit(source, destination, tonemapMaterial, 4);
return;
}
if (type == TonemapperType.SimpleReinhard)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 6);
return;
}
if (type == TonemapperType.Hable)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 5);
return;
}
if (type == TonemapperType.Photographic)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 8);
return;
}
if (type == TonemapperType.OptimizedHejiDawson)
{
tonemapMaterial.SetFloat("_ExposureAdjustment", 0.5f*exposureAdjustment);
Graphics.Blit(source, destination, tonemapMaterial, 7);
return;
}
// still here?
// => adaptive tone mapping:
// builds an average log luminance, tonemaps according to
// middle grey and white values (user controlled)
// AdaptiveReinhardAutoWhite will calculate white value automagically
bool freshlyBrewedInternalRt = CreateInternalRenderTexture(); // this retrieves rtFormat, so should happen before rt allocations
RenderTexture rtSquared = RenderTexture.GetTemporary((int) adaptiveTextureSize, (int) adaptiveTextureSize, 0, rtFormat);
Graphics.Blit(source, rtSquared);
int downsample = (int) Mathf.Log(rtSquared.width*1.0f, 2);
int div = 2;
var rts = new RenderTexture[downsample];
for (int i = 0; i < downsample; i++)
{
rts[i] = RenderTexture.GetTemporary(rtSquared.width/div, rtSquared.width/div, 0, rtFormat);
div *= 2;
}
// downsample pyramid
var lumRt = rts[downsample - 1];
Graphics.Blit(rtSquared, rts[0], tonemapMaterial, 1);
if (type == TonemapperType.AdaptiveReinhardAutoWhite)
{
for (int i = 0; i < downsample - 1; i++)
{
Graphics.Blit(rts[i], rts[i + 1], tonemapMaterial, 9);
lumRt = rts[i + 1];
}
}
else if (type == TonemapperType.AdaptiveReinhard)
{
for (int i = 0; i < downsample - 1; i++)
{
Graphics.Blit(rts[i], rts[i + 1]);
lumRt = rts[i + 1];
}
}
// we have the needed values, let's apply adaptive tonemapping
adaptionSpeed = adaptionSpeed < 0.001f ? 0.001f : adaptionSpeed;
tonemapMaterial.SetFloat("_AdaptionSpeed", adaptionSpeed);
#if UNITY_EDITOR
if (Application.isPlaying && !freshlyBrewedInternalRt)
Graphics.Blit(lumRt, rt, tonemapMaterial, 2);
else
Graphics.Blit(lumRt, rt, tonemapMaterial, 3);
#else
Graphics.Blit (lumRt, rt, tonemapMaterial, freshlyBrewedInternalRt ? 3 : 2);
#endif
middleGrey = middleGrey < 0.001f ? 0.001f : middleGrey;
tonemapMaterial.SetVector("_HdrParams", new Vector4(middleGrey, middleGrey, middleGrey, white*white));
tonemapMaterial.SetTexture("_SmallTex", rt);
if (type == TonemapperType.AdaptiveReinhard)
{
Graphics.Blit(source, destination, tonemapMaterial, 0);
}
else if (type == TonemapperType.AdaptiveReinhardAutoWhite)
{
Graphics.Blit(source, destination, tonemapMaterial, 10);
}
else
{
Debug.LogError("No valid adaptive tonemapper type found!");
Graphics.Blit(source, destination); // at least we get the TransformToLDR effect
}
// cleanup for adaptive
for (int i = 0; i < downsample; i++)
{
RenderTexture.ReleaseTemporary(rts[i]);
}
RenderTexture.ReleaseTemporary(rtSquared);
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 984c820fad35bd149ab5d581d2296070
MonoImporter:
serializedVersion: 2
defaultReferences:
- tonemapper: {fileID: 4800000, guid: 003377fc2620a44939dadde6fe3f8190, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName: