【Unity3D】物体发光插件
一、前言
本篇文章讲的是如何让3D物体放光的方法
二、效果
三、实现
这个是一个插件,但是主要就是这两个脚本
HighlightableObject.cs
HighlightingEffect.cs
其他的先不做讨论
HighlightableObject.cs脚本
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class HighlightableObject : MonoBehaviour
{
#region Editable Fields
// Builtin layer reserved for the highlighting
public static int highlightingLayer = 7;
// Constant highlighting turning on speed
private static float constantOnSpeed = 4.5f;
// Constant highlighting turning off speed
private static float constantOffSpeed = 4f;
// Default transparent cutoff value used for shaders without _Cutoff property
private static float transparentCutoff = 0.5f;
#endregion
#region Private Fields
// 2 * PI constant required for flashing
private const float doublePI = 2f * Mathf.PI;
// Cached materials
private List<HighlightingRendererCache> highlightableRenderers;
// Cached layers of highlightable objects
private int[] layersCache;
// Need to reinit materials flag
private bool materialsIsDirty = true;
// Current state of highlighting
private bool currentState = false;
// Current materials highlighting color
private Color currentColor;
// Transition is active flag
private bool transitionActive = false;
// Current transition value
private float transitionValue = 0f;
// Flashing frequency
private float flashingFreq = 2f;
// One-frame highlighting flag
private bool once = false;
// One-frame highlighting color
private Color onceColor = Color.red;
// Flashing state flag
private bool flashing = false;
// Flashing from color
private Color flashingColorMin = new Color(0.0f, 1.0f, 1.0f, 0.0f);
// Flashing to color
private Color flashingColorMax = new Color(0.0f, 1.0f, 1.0f, 1.0f);
// Constant highlighting state flag
private bool constantly = false;
// Constant highlighting color
private Color constantColor = Color.yellow;
// Occluder
private bool occluder = false;
// Currently used shaders ZWriting state
private bool zWrite = false;
// Occlusion color (DON'T TOUCH THIS!)
private readonly Color occluderColor = new Color(0.0f, 0.0f, 0.0f, 0.005f);
//
private Material highlightingMaterial
{
get
{
return zWrite ? opaqueZMaterial : opaqueMaterial;
}
}
// Common (for this component) replacement material for opaque geometry highlighting
private Material _opaqueMaterial;
private Material opaqueMaterial
{
get
{
if (_opaqueMaterial == null)
{
_opaqueMaterial = new Material(opaqueShader);
_opaqueMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _opaqueMaterial;
}
}
// Common (for this component) replacement material for opaque geometry highlighting with Z-Buffer writing enabled
private Material _opaqueZMaterial;
private Material opaqueZMaterial
{
get
{
if (_opaqueZMaterial == null)
{
_opaqueZMaterial = new Material(opaqueZShader);
_opaqueZMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _opaqueZMaterial;
}
}
//
private static Shader _opaqueShader;
private static Shader opaqueShader
{
get
{
if (_opaqueShader == null)
{
_opaqueShader = Shader.Find("Hidden/Highlighted/StencilOpaque");
}
return _opaqueShader;
}
}
//
private static Shader _transparentShader;
public static Shader transparentShader
{
get
{
if (_transparentShader == null)
{
_transparentShader = Shader.Find("Hidden/Highlighted/StencilTransparent");
}
return _transparentShader;
}
}
//
private static Shader _opaqueZShader;
private static Shader opaqueZShader
{
get
{
if (_opaqueZShader == null)
{
_opaqueZShader = Shader.Find("Hidden/Highlighted/StencilOpaqueZ");
}
return _opaqueZShader;
}
}
//
private static Shader _transparentZShader;
private static Shader transparentZShader
{
get
{
if (_transparentZShader == null)
{
_transparentZShader = Shader.Find("Hidden/Highlighted/StencilTransparentZ");
}
return _transparentZShader;
}
}
#endregion
#region Common
// Internal class for renderers caching
private class HighlightingRendererCache
{
public Renderer rendererCached;
public GameObject goCached;
private Material[] sourceMaterials;
private Material[] replacementMaterials;
private List<int> transparentMaterialIndexes;
// Constructor
public HighlightingRendererCache(Renderer rend, Material[] mats, Material sharedOpaqueMaterial, bool writeDepth)
{
rendererCached = rend;
goCached = rend.gameObject;
sourceMaterials = mats;
replacementMaterials = new Material[mats.Length];
transparentMaterialIndexes = new List<int>();
for (int i = 0; i < mats.Length; i++)
{
Material sourceMat = mats[i];
if (sourceMat == null)
{
continue;
}
string tag = sourceMat.GetTag("RenderType", true);
if (tag == "Transparent" || tag == "TransparentCutout")
{
Material replacementMat = new Material(writeDepth ? transparentZShader : transparentShader);
if (sourceMat.HasProperty("_MainTex"))
{
replacementMat.SetTexture("_MainTex", sourceMat.mainTexture);
replacementMat.SetTextureOffset("_MainTex", sourceMat.mainTextureOffset);
replacementMat.SetTextureScale("_MainTex", sourceMat.mainTextureScale);
}
replacementMat.SetFloat("_Cutoff", sourceMat.HasProperty("_Cutoff") ? sourceMat.GetFloat("_Cutoff") : transparentCutoff);
replacementMaterials[i] = replacementMat;
transparentMaterialIndexes.Add(i);
}
else
{
replacementMaterials[i] = sharedOpaqueMaterial;
}
}
}
// Based on given state variable, replaces materials of this cached renderer to the highlighted ones and back
public void SetState(bool state)
{
rendererCached.sharedMaterials = state ? replacementMaterials : sourceMaterials;
}
// Sets given color as the highlighting color on all transparent materials for this cached renderer
public void SetColorForTransparent(Color clr)
{
for (int i = 0; i < transparentMaterialIndexes.Count; i++)
{
replacementMaterials[transparentMaterialIndexes[i]].SetColor("_Outline", clr);
}
}
}
//
private void OnEnable()
{
StartCoroutine(EndOfFrame());
// Subscribe to highlighting event
HighlightingEffect.highlightingEvent += UpdateEventHandler;
}
//
private void OnDisable()
{
StopAllCoroutines();
// Unsubscribe from highlighting event
HighlightingEffect.highlightingEvent -= UpdateEventHandler;
// Clear cached renderers
if (highlightableRenderers != null)
{
highlightableRenderers.Clear();
}
// Reset highlighting parameters to default values
layersCache = null;
materialsIsDirty = true;
currentState = false;
currentColor = Color.clear;
transitionActive = false;
transitionValue = 0f;
once = false;
flashing = false;
constantly = false;
occluder = false;
zWrite = false;
/*
// Reset custom parameters of the highlighting
onceColor = Color.red;
flashingColorMin = new Color(0f, 1f, 1f, 0f);
flashingColorMax = new Color(0f, 1f, 1f, 1f);
flashingFreq = 2f;
constantColor = Color.yellow;
*/
if (_opaqueMaterial)
{
DestroyImmediate(_opaqueMaterial);
}
if (_opaqueZMaterial)
{
DestroyImmediate(_opaqueZMaterial);
}
}
#endregion
#region Public Methods
/// <summary>
/// Materials reinitialization.
/// Call this method if your highlighted object changed his materials or child objects.
/// Can be called multiple times per update - renderers reinitialization will occur only once.
/// </summary>
public void ReinitMaterials()
{
materialsIsDirty = true;
}
/// <summary>
/// Immediately restore original materials. Obsolete. Use ReinitMaterials() instead.
/// </summary>
public void RestoreMaterials()
{
Debug.LogWarning("HighlightingSystem : RestoreMaterials() is obsolete. Please use ReinitMaterials() instead.");
ReinitMaterials();
}
/// <summary>
/// Set color for one-frame highlighting mode.
/// </summary>
/// <param name='color'>
/// Highlighting color.
/// </param>
public void OnParams(Color color)
{
onceColor = color;
}
/// <summary>
/// Turn on one-frame highlighting.
/// </summary>
public void On()
{
// Highlight object only in this frame
once = true;
}
/// <summary>
/// Turn on one-frame highlighting with given color.
/// Can be called multiple times per update, color only from the latest call will be used.
/// </summary>
/// <param name='color'>
/// Highlighting color.
/// </param>
public void On(Color color)
{
// Set new color for one-frame highlighting
onceColor = color;
On();
}
/// <summary>
/// Set flashing parameters.
/// </summary>
/// <param name='color1'>
/// Starting color.
/// </param>
/// <param name='color2'>
/// Ending color.
/// </param>
/// <param name='freq'>
/// Flashing frequency.
/// </param>
public void FlashingParams(Color color1, Color color2, float freq)
{
flashingColorMin = color1;
flashingColorMax = color2;
flashingFreq = freq;
}
/// <summary>
/// Turn on flashing.
/// </summary>
public void FlashingOn()
{
flashing = true;
}
/// <summary>
/// Turn on flashing from color1 to color2.
/// </summary>
/// <param name='color1'>
/// Starting color.
/// </param>
/// <param name='color2'>
/// Ending color.
/// </param>
public void FlashingOn(Color color1, Color color2)
{
flashingColorMin = color1;
flashingColorMax = color2;
FlashingOn();
}
/// <summary>
/// Turn on flashing from color1 to color2 with given frequency.
/// </summary>
/// <param name='color1'>
/// Starting color.
/// </param>
/// <param name='color2'>
/// Ending color.
/// </param>
/// <param name='freq'>
/// Flashing frequency.
/// </param>
public void FlashingOn(Color color1, Color color2, float freq)
{
flashingFreq = freq;
FlashingOn(color1, color2);
}
/// <summary>
/// Turn on flashing with given frequency.
/// </summary>
/// <param name='f'>
/// Flashing frequency.
/// </param>
public void FlashingOn(float freq)
{
flashingFreq = freq;
FlashingOn();
}
/// <summary>
/// Turn off flashing.
/// </summary>
public void FlashingOff()
{
flashing = false;
}
/// <summary>
/// Switch flashing mode.
/// </summary>
public void FlashingSwitch()
{
flashing = !flashing;
}
/// <summary>
/// Set constant highlighting color.
/// </summary>
/// <param name='color'>
/// Constant highlighting color.
/// </param>
public void ConstantParams(Color color)
{
constantColor = color;
}
/// <summary>
/// Fade in constant highlighting.
/// </summary>
public void ConstantOn()
{
// Enable constant highlighting
constantly = true;
// Start transition
transitionActive = true;
}
/// <summary>
/// Fade in constant highlighting with given color.
/// </summary>
/// <param name='color'>
/// Constant highlighting color.
/// </param>
public void ConstantOn(Color color)
{
// Set constant highlighting color
constantColor = color;
ConstantOn();
}
/// <summary>
/// Fade out constant highlighting.
/// </summary>
public void ConstantOff()
{
// Disable constant highlighting
constantly = false;
// Start transition
transitionActive = true;
}
/// <summary>
/// Switch Constant Highlighting.
/// </summary>
public void ConstantSwitch()
{
// Switch constant highlighting
constantly = !constantly;
// Start transition
transitionActive = true;
}
/// <summary>
/// Turn on constant highlighting immediately (without fading in).
/// </summary>
public void ConstantOnImmediate()
{
constantly = true;
// Set transition value to 1
transitionValue = 1f;
// Stop transition
transitionActive = false;
}
/// <summary>
/// Turn on constant highlighting with given color immediately (without fading in).
/// </summary>
/// <param name='color'>
/// Constant highlighting color.
/// </param>
public void ConstantOnImmediate(Color color)
{
// Set constant highlighting color
constantColor = color;
ConstantOnImmediate();
}
/// <summary>
/// Turn off constant highlighting immediately (without fading out).
/// </summary>
public void ConstantOffImmediate()
{
constantly = false;
// Set transition value to 0
transitionValue = 0f;
// Stop transition
transitionActive = false;
}
/// <summary>
/// Switch constant highlighting immediately (without fading in/out).
/// </summary>
public void ConstantSwitchImmediate()
{
constantly = !constantly;
// Set transition value to the final value
transitionValue = constantly ? 1f : 0f;
// Stop transition
transitionActive = false;
}
/// <summary>
/// Enable occluder mode
/// </summary>
public void OccluderOn()
{
occluder = true;
}
/// <summary>
/// Disable occluder mode
/// </summary>
public void OccluderOff()
{
occluder = false;
}
/// <summary>
/// Switch occluder mode
/// </summary>
public void OccluderSwitch()
{
occluder = !occluder;
}
/// <summary>
/// Turn off all types of highlighting.
/// </summary>
public void Off()
{
// Turn off all types of highlighting
once = false;
flashing = false;
constantly = false;
// Set transition value to 0
transitionValue = 0f;
// Stop transition
transitionActive = false;
}
/// <summary>
/// Destroy this HighlightableObject component.
/// </summary>
public void Die()
{
Destroy(this);
}
#endregion
#region Private Methods
// Materials initialisation
private void InitMaterials(bool writeDepth)
{
currentState = false;
zWrite = writeDepth;
highlightableRenderers = new List<HighlightingRendererCache>();
MeshRenderer[] mr = GetComponentsInChildren<MeshRenderer>();
CacheRenderers(mr);
SkinnedMeshRenderer[] smr = GetComponentsInChildren<SkinnedMeshRenderer>();
CacheRenderers(smr);
//#if !UNITY_FLASH
//ClothRenderer[] cr = GetComponentsInChildren<ClothRenderer>();
//CacheRenderers(cr);
//#endif
currentState = false;
materialsIsDirty = false;
currentColor = Color.clear;
}
// Cache given renderers properties
private void CacheRenderers(Renderer[] renderers)
{
for (int i = 0; i < renderers.Length; i++)
{
Material[] materials = renderers[i].sharedMaterials;
if (materials != null)
{
highlightableRenderers.Add(new HighlightingRendererCache(renderers[i], materials, highlightingMaterial, zWrite));
}
}
}
// Update highlighting color to a given value
private void SetColor(Color c)
{
if (currentColor == c)
{
return;
}
if (zWrite)
{
opaqueZMaterial.SetColor("_Outline", c);
}
else
{
opaqueMaterial.SetColor("_Outline", c);
}
for (int i = 0; i < highlightableRenderers.Count; i++)
{
highlightableRenderers[i].SetColorForTransparent(c);
}
currentColor = c;
}
// Set new color if needed
private void UpdateColors()
{
// Don't update colors if highlighting is disabled
if (currentState == false)
{
return;
}
if (occluder)
{
SetColor(occluderColor);
return;
}
if (once)
{
SetColor(onceColor);
return;
}
if (flashing)
{
// Flashing frequency is not affected by Time.timeScale
Color c = Color.Lerp(flashingColorMin, flashingColorMax, 0.5f * Mathf.Sin(Time.realtimeSinceStartup * flashingFreq * doublePI) + 0.5f);
SetColor(c);
return;
}
if (transitionActive)
{
Color c = new Color(constantColor.r, constantColor.g, constantColor.b, constantColor.a * transitionValue);
SetColor(c);
return;
}
else if (constantly)
{
SetColor(constantColor);
return;
}
}
// Calculate new transition value if needed.
private void PerformTransition()
{
if (transitionActive == false)
{
return;
}
float targetValue = constantly ? 1f : 0f;
// Is transition finished?
if (transitionValue == targetValue)
{
transitionActive = false;
return;
}
if (Time.timeScale != 0f)
{
// Calculating delta time untouched by Time.timeScale
float unscaledDeltaTime = Time.deltaTime / Time.timeScale;
// Calculating new transition value
transitionValue += (constantly ? constantOnSpeed : -constantOffSpeed) * unscaledDeltaTime;
transitionValue = Mathf.Clamp01(transitionValue);
}
else
{
return;
}
}
// Highlighting event handler (main highlighting method)
private void UpdateEventHandler(bool trigger, bool writeDepth)
{
// Update and enable highlighting
if (trigger)
{
// ZWriting state changed?
if (zWrite != writeDepth)
{
materialsIsDirty = true;
}
// Initialize new materials if needed
if (materialsIsDirty)
{
InitMaterials(writeDepth);
}
currentState = (once || flashing || constantly || transitionActive || occluder);
if (currentState)
{
UpdateColors();
PerformTransition();
if (highlightableRenderers != null)
{
layersCache = new int[highlightableRenderers.Count];
for (int i = 0; i < highlightableRenderers.Count; i++)
{
GameObject go = highlightableRenderers[i].goCached;
// cache layer
layersCache[i] = go.layer;
// temporary set layer to renderable by the highlighting effect camera
go.layer = highlightingLayer;
highlightableRenderers[i].SetState(true);
}
}
}
}
// Disable highlighting
else
{
if (currentState && highlightableRenderers != null)
{
for (int i = 0; i < highlightableRenderers.Count; i++)
{
highlightableRenderers[i].goCached.layer = layersCache[i];
highlightableRenderers[i].SetState(false);
}
}
}
}
IEnumerator EndOfFrame()
{
while (enabled)
{
yield return new WaitForEndOfFrame();
// Reset one-frame highlighting state after each HighlightingEffect in the scene has finished rendering
once = false;
}
}
#endregion
}
HighlightingEffect.cs
using UnityEngine;
// Delegate for the highlighting event
public delegate void HighlightingEventHandler(bool state, bool zWrite);
[RequireComponent(typeof(Camera))]
public class HighlightingEffect : MonoBehaviour
{
// Event used to notify highlightable objects to change their materials before rendering to the highlighting buffer begins
public static event HighlightingEventHandler highlightingEvent;
#region Inspector Fields
// Stencil (highlighting) buffer depth
public int stencilZBufferDepth = 0;
// Stencil (highlighting) buffer size downsample factor
public int _downsampleFactor = 4;
// Blur iterations
public int iterations = 2;
// Blur minimal spread
public float blurMinSpread = 0.65f;
// Blur spread per iteration
public float blurSpread = 0.25f;
// Blurring intensity for the blur material
public float _blurIntensity = 0.3f;
// These properties available only in Editor - we don't need them in standalone build
#if UNITY_EDITOR
// Z-buffer writing state getter/setter
public bool stencilZBufferEnabled
{
get
{
return (stencilZBufferDepth > 0);
}
set
{
if (stencilZBufferEnabled != value)
{
stencilZBufferDepth = value ? 16 : 0;
}
}
}
// Downsampling factor getter/setter
public int downsampleFactor
{
get
{
if (_downsampleFactor == 1)
{
return 0;
}
if (_downsampleFactor == 2)
{
return 1;
}
return 2;
}
set
{
if (value == 0)
{
_downsampleFactor = 1;
}
if (value == 1)
{
_downsampleFactor = 2;
}
if (value == 2)
{
_downsampleFactor = 4;
}
}
}
// Blur alpha intensity getter/setter
public float blurIntensity
{
get
{
return _blurIntensity;
}
set
{
if (_blurIntensity != value)
{
_blurIntensity = value;
if (Application.isPlaying)
{
blurMaterial.SetFloat("_Intensity", _blurIntensity);
}
}
}
}
#endif
#endregion
#region Private Fields
// Highlighting camera layers culling mask
private int layerMask = (1 << HighlightableObject.highlightingLayer);
// This GameObject reference
private GameObject go = null;
// Camera for rendering stencil buffer GameObject
private GameObject shaderCameraGO = null;
// Camera for rendering stencil buffer
private Camera shaderCamera = null;
// RenderTexture with stencil buffer
private RenderTexture stencilBuffer = null;
// Camera reference
private Camera refCam = null;
// Blur Shader
private static Shader _blurShader;
private static Shader blurShader
{
get
{
if (_blurShader == null)
{
_blurShader = Shader.Find("Hidden/Highlighted/Blur");
}
return _blurShader;
}
}
// Compositing Shader
private static Shader _compShader;
private static Shader compShader
{
get
{
if (_compShader == null)
{
_compShader = Shader.Find("Hidden/Highlighted/Composite");
}
return _compShader;
}
}
// Blur Material
private static Material _blurMaterial = null;
private static Material blurMaterial
{
get
{
if (_blurMaterial == null)
{
_blurMaterial = new Material(blurShader);
_blurMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _blurMaterial;
}
}
// Compositing Material
private static Material _compMaterial = null;
private static Material compMaterial
{
get
{
if (_compMaterial == null)
{
_compMaterial = new Material(compShader);
_compMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return _compMaterial;
}
}
#endregion
void Awake()
{
go = gameObject;
refCam = GetComponent<Camera>();
}
void OnDisable()
{
if (shaderCameraGO != null)
{
DestroyImmediate(shaderCameraGO);
}
if (_blurShader)
{
_blurShader = null;
}
if (_compShader)
{
_compShader = null;
}
if (_blurMaterial)
{
DestroyImmediate(_blurMaterial);
}
if (_compMaterial)
{
DestroyImmediate(_compMaterial);
}
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
}
void Start()
{
// Disable if Image Effects is not supported
if (!SystemInfo.supportsImageEffects)
{
Debug.LogWarning("HighlightingSystem : Image effects is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if Render Textures is not supported
//if (!SystemInfo.supportsRenderTextures)
//{
// Debug.LogWarning("HighlightingSystem : RenderTextures is not supported on this platform! Disabling.");
// this.enabled = false;
// return;
//}
// Disable if required Render Texture Format is not supported
if (!SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGB32))
{
Debug.LogWarning("HighlightingSystem : RenderTextureFormat.ARGB32 is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingStencilOpaque shader is not supported
if (!Shader.Find("Hidden/Highlighted/StencilOpaque").isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaque shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingStencilTransparent shader is not supported
if (!Shader.Find("Hidden/Highlighted/StencilTransparent").isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparent shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingStencilOpaqueZ shader is not supported
if (!Shader.Find("Hidden/Highlighted/StencilOpaqueZ").isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingStencilOpaqueZ shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingStencilTransparentZ shader is not supported
if (!Shader.Find("Hidden/Highlighted/StencilTransparentZ").isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingStencilTransparentZ shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingBlur shader is not supported
if (!blurShader.isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingBlur shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Disable if HighlightingComposite shader is not supported
if (!compShader.isSupported)
{
Debug.LogWarning("HighlightingSystem : HighlightingComposite shader is not supported on this platform! Disabling.");
this.enabled = false;
return;
}
// Set the initial intensity in blur shader
blurMaterial.SetFloat("_Intensity", _blurIntensity);
}
// Performs one blur iteration
public void FourTapCone(RenderTexture source, RenderTexture dest, int iteration)
{
float off = blurMinSpread + iteration * blurSpread;
blurMaterial.SetFloat("_OffsetScale", off);
Graphics.Blit(source, dest, blurMaterial);
}
// Downsamples source texture
private void DownSample4x(RenderTexture source, RenderTexture dest)
{
float off = 1.0f;
blurMaterial.SetFloat("_OffsetScale", off);
Graphics.Blit(source, dest, blurMaterial);
}
// Render all highlighted objects to the stencil buffer
void OnPreRender()
{
#if UNITY_4_0
if (this.enabled == false || go.activeInHierarchy == false)
#else
if (this.enabled == false || go.active == false)
#endif
return;
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
// Turn on highlighted shaders
if (highlightingEvent != null)
{
highlightingEvent(true, (stencilZBufferDepth > 0));
}
// We don't need to render the scene if there's no HighlightableObjects
else
{
return;
}
stencilBuffer = RenderTexture.GetTemporary((int)GetComponent<Camera>().pixelWidth, (int)GetComponent<Camera>().pixelHeight, stencilZBufferDepth, RenderTextureFormat.ARGB32);
if (!shaderCameraGO)
{
shaderCameraGO = new GameObject("HighlightingCamera", typeof(Camera));
shaderCameraGO.GetComponent<Camera>().enabled = false;
shaderCameraGO.hideFlags = HideFlags.HideAndDontSave;
}
if (!shaderCamera)
{
shaderCamera = shaderCameraGO.GetComponent<Camera>();
}
shaderCamera.CopyFrom(refCam);
//shaderCamera.projectionMatrix = refCam.projectionMatrix; // Uncomment this line if you have problems using Highlighting System with custom projection matrix on your camera
shaderCamera.cullingMask = layerMask;
shaderCamera.rect = new Rect(0f, 0f, 1f, 1f);
shaderCamera.renderingPath = RenderingPath.VertexLit;
shaderCamera.hdr = false;
shaderCamera.useOcclusionCulling = false;
shaderCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
shaderCamera.clearFlags = CameraClearFlags.SolidColor;
shaderCamera.targetTexture = stencilBuffer;
shaderCamera.Render();
// Turn off highlighted shaders
if (highlightingEvent != null)
{
highlightingEvent(false, false);
}
}
// Compose final frame with highlighting
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// If stencilBuffer is not created by some reason
if (stencilBuffer == null)
{
// Simply transfer framebuffer to destination
Graphics.Blit(source, destination);
return;
}
// Create two buffers for blurring the image
int width = source.width / _downsampleFactor;
int height = source.height / _downsampleFactor;
RenderTexture buffer = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
RenderTexture buffer2 = RenderTexture.GetTemporary(width, height, stencilZBufferDepth, RenderTextureFormat.ARGB32);
// Copy stencil buffer to the 4x4 smaller texture
DownSample4x(stencilBuffer, buffer);
// Blur the small texture
bool oddEven = true;
for (int i = 0; i < iterations; i++)
{
if (oddEven)
{
FourTapCone(buffer, buffer2, i);
}
else
{
FourTapCone(buffer2, buffer, i);
}
oddEven = !oddEven;
}
// Compose
compMaterial.SetTexture("_StencilTex", stencilBuffer);
compMaterial.SetTexture("_BlurTex", oddEven ? buffer : buffer2);
Graphics.Blit(source, destination, compMaterial);
// Cleanup
RenderTexture.ReleaseTemporary(buffer);
RenderTexture.ReleaseTemporary(buffer2);
if (stencilBuffer != null)
{
RenderTexture.ReleaseTemporary(stencilBuffer);
stencilBuffer = null;
}
}
}
接下来就是写控制这个插件的脚本了
test.cs
using UnityEngine;
public class test : MonoBehaviour
{
public GameObject m_High;
private HighlightableObject ho;
Color col = new Color(0f, 1f, 0f, 1f);
void Start()
{
ho = m_High.GetComponent<HighlightableObject>();
ho.ConstantOnImmediate(col);
}
}
然后在场景中把脚本添加上去
主摄像机上面添加HighlightingEffect脚本
要发光的物体上面添加这两个脚本
OK,搞定了