Spine 局部高亮 - daaoling/daaoling.github.io GitHub Wiki
Spine 局部高亮
一个摄像机照出 正常 一个摄像机照出的人渲黑 一个摄像机只照人物身上的白色小球
取黑色和白色的的交集 白色color+正常区域的颜色 其他区域取正常区域的颜色
mTestRenderImageV2.cs 挂摄像机
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using com.kuxiong.battlemodule;
/// <summary>
/// 远程英雄局部高亮管理
/// </summary>
public class mTestRenderImageV2 : View
{
public Dictionary<string, RenderUnit> renderUnits = new Dictionary<string, RenderUnit>();
public class RenderUnit
{
public Renderer renderer;
public Material[] initMaterials;
public Material[] replaceMaterials;
public GameObject instanceHightPoint;
}
private Camera camera;
private Camera _setShotHeroBlackCamera; //不照光晕 打枪英雄变黑
private Camera _onlySeePointLightCamera;//只照光晕
public Shader outlineRepShader;
private Material outlineRepMaterial; //如果导出的不止一个 renader 每一个render需要的replace material 都要生成一份
public Shader outlineBiltShader; //shader for blit
private Material outlineBiltMaterial; //material for blit
public RenderTexture renderTexture { get; set; }
public RenderTexture renderTextureV2 { get; set; }
void Start()
{
if (!SystemInfo.supportsImageEffects) {
this.enabled = false;
return;
}
RegisterMessage(this, this.notist);
//cache
camera = Camera.main;
outlineRepShader = Resources.Load<Shader>(ResourcePath.FxTmp.highlight.OutLineBuff2_Shader);
outlineBiltShader = Resources.Load<Shader>(ResourcePath.FxTmp.highlight.LocalHighLightImageEffect);
CreateMaterialsIfNeeded();
}
void OnPreCull()
{
if (this.renderUnits.Count > 0)
{
int width = (int)camera.pixelWidth;
int height = (int)camera.pixelHeight;
renderTexture = RenderTexture.GetTemporary(width, height, 32, RenderTextureFormat.Default);
renderTextureV2 = RenderTexture.GetTemporary(width, height, 32, RenderTextureFormat.Default);
/// Create Render Camera
if (_setShotHeroBlackCamera == null)
{
GameObject cameraGameObject = new GameObject("setShotHeroBlack");
cameraGameObject.hideFlags = HideFlags.HideAndDontSave;
_setShotHeroBlackCamera = cameraGameObject.AddComponent<Camera>();
}
if (_onlySeePointLightCamera == null)
{
GameObject cameraGameObject = new GameObject("onlySeePointLight");
cameraGameObject.hideFlags = HideFlags.HideAndDontSave;
_onlySeePointLightCamera = cameraGameObject.AddComponent<Camera>();
}
_setShotHeroBlackCamera.CopyFrom(camera); // is copy pos
_setShotHeroBlackCamera.enabled = false;
_onlySeePointLightCamera.CopyFrom(camera);
_onlySeePointLightCamera.enabled = false;
_onlySeePointLightCamera.renderingPath = RenderingPath.Forward;
_onlySeePointLightCamera.backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
_onlySeePointLightCamera.clearFlags = CameraClearFlags.SolidColor;
int layerMask = 1 << ((int)com.kuxiong.battlemodule.Layers.HeroOutLine);
_onlySeePointLightCamera.cullingMask = layerMask;
foreach (var curKey in this.renderUnits.Keys)
{
RenderUnit unit = this.renderUnits[curKey];
unit.initMaterials = unit.renderer.sharedMaterials;
for (int z = 0; z < unit.replaceMaterials.Length; z++)
{
Material curMaterial = unit.replaceMaterials[z];
var texture = unit.initMaterials[z].GetTexture("_MainTex");
curMaterial.SetTexture("_MainTex", texture);
unit.replaceMaterials[z] = curMaterial;
}
unit.renderer.sharedMaterials = unit.replaceMaterials;
}
_setShotHeroBlackCamera.targetTexture = renderTexture;
_setShotHeroBlackCamera.Render();
_onlySeePointLightCamera.targetTexture = renderTextureV2;
_onlySeePointLightCamera.Render();
foreach (var curKey in this.renderUnits.Keys)
{
RenderUnit unit = this.renderUnits[curKey];
unit.renderer.sharedMaterials = unit.initMaterials;
}
}
else {
if (this.enabled) this.enabled = false;
}
}
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
outlineBiltMaterial.SetTexture("_heroWithBlackArea", renderTexture);
outlineBiltMaterial.SetTexture("_pointLightArea", renderTextureV2);
Graphics.Blit(sourceTexture, destTexture, this.outlineBiltMaterial);
RenderTexture.ReleaseTemporary(renderTexture);
RenderTexture.ReleaseTemporary(renderTextureV2);
}
void OnDestroy()
{
RemoveMessage(this, this.notist);
if (_setShotHeroBlackCamera)
{
DestroyImmediate(_setShotHeroBlackCamera.gameObject);
_setShotHeroBlackCamera = null;
}
if (_onlySeePointLightCamera)
{
DestroyImmediate(_onlySeePointLightCamera.gameObject);
_onlySeePointLightCamera = null;
}
DestroyMaterials();
}
public List<string> notist = new List<string>() { NotiConst.hL };
public override void OnMessage(IMessage message)
{
switch (message.Name)
{
case NotiConst.hL:
object[] args = (object[])message.Body;
string name = args[0] as string; ///高亮预设名字
Transform invoker = args[1] as Transform;
///加载高亮预设
string prefabPath = ResourcePath.FxTmp.highlight.prefabPrePath + "/" + name;
GameObject prefab = NGUITools.LoadAsset<GameObject>(prefabPath);
GameObject instance = NGUITools.AddChild(invoker.transform.Find("graphic").gameObject, prefab);
instance.transform.localPosition = prefab.transform.localPosition;
instance.transform.localRotation = prefab.transform.localRotation;
instance.transform.localScale = prefab.transform.localScale;
instance.layer = prefab.layer;
///加载高亮预设配置
string configPath = ResourcePath.FxTmp.highlight.configPrePath + "/" + name;
trigger_highlight_effect hightLight_effect_cofig = NGUITools.LoadAsset<trigger_highlight_effect>(configPath);
///新加一个枪口火花光晕特效
AddStartShotEffect(
invoker.name,
invoker.transform.Find("graphic/renderer").renderer,
hightLight_effect_cofig.delay, instance);
break;
default:
break;
}
}
/// <summary>
/// 新加一个枪口火花光晕特效
/// </summary>
/// <param name="nowOutlineRenders"></param>
void AddStartShotEffect(string key, Renderer renderer, float delayTime, GameObject highLight)
{
if (!SystemInfo.supportsImageEffects) return;
if (!this.enabled) this.enabled = true;
RenderUnit resUnit = new RenderUnit()
{
renderer = renderer,
initMaterials = null,
replaceMaterials = null
};
//set replaceMaterials
resUnit.replaceMaterials = new Material[resUnit.renderer.sharedMaterials.Length];
for (int i = 0; i < resUnit.replaceMaterials.Length; i++)
{
resUnit.replaceMaterials[i] = new Material(this.outlineRepMaterial);
resUnit.replaceMaterials[i].hideFlags = HideFlags.HideAndDontSave;
}
//set 设置高亮图片
resUnit.instanceHightPoint = highLight;
renderUnits.Add(key, resUnit);
vp_Timer.In(delayTime, delegate() {
renderUnits.Remove(key);
for (int i = 0; i < resUnit.replaceMaterials.Length; i++)
{
DestroyImmediate(resUnit.replaceMaterials[i]);
resUnit.replaceMaterials[i] = null;
}
UnityEngine.Object.Destroy(resUnit.instanceHightPoint);
});
}
#region Util
private void CreateMaterialsIfNeeded()
{
this.outlineBiltMaterial = new Material(this.outlineBiltShader);
this.outlineBiltMaterial.hideFlags = HideFlags.HideAndDontSave;
this.outlineRepMaterial = new Material(this.outlineRepShader);
this.outlineRepMaterial.hideFlags = HideFlags.HideAndDontSave;
}
private void DestroyMaterials()
{
DestroyImmediate(outlineBiltMaterial);
DestroyImmediate(outlineRepMaterial);
this.outlineBiltMaterial = null;
this.outlineRepMaterial = null;
//this.outlineBiltShader = null;
//this.outlineRepShader = null;
}
#endregion
}
LocalHighLightImageEffect.shader
Shader "Custom/LocalHighLightImageEffect" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _heroWithBlackArea;
sampler2D _pointLightArea;
struct vertex_input
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float4 color : COLOR;
};
struct v2f {
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
v2f vert(vertex_input v)
{
v2f o;
o.position = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
o.color = v.color;
return o;
}
half4 frag (v2f input) : COLOR
{
half4 initPixel = tex2D(_MainTex, input.uv);
half4 heroWithBlackArea = tex2D(_heroWithBlackArea, input.uv);
half4 pointLightArea = tex2D(_pointLightArea, input.uv);
half4 result = initPixel;
if(heroWithBlackArea.r == 0 && heroWithBlackArea.g == 0 && heroWithBlackArea.b == 0)
{
if(pointLightArea.a > 0)
{
result.rgb = initPixel.rgb + pointLightArea.rgb;
//result.rgb = half3(0,0,0);
}
}
return result;
}
ENDCG
}
}
FallBack "Diffuse"
}
spine人物渲黑shader
OutLineBuff2.shader
Shader "Custom/OutLineBuff2" {
Properties {
_MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
}
SubShader {
Tags {
"Queue"="Transparent"
"IgnoreProjector"="False"
"RenderType"="Transparent"
}
Fog { Mode Off }
Blend One OneMinusSrcAlpha
ZWrite Off
Cull Off
Pass
{
Tags {"LightMode" = "ForwardBase"} // This Pass tag is important or Unity may not give it the correct light information.
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//#pragma multi_compile_fwdbase // This line tells Unity to compile this pass for forward base.
#include "UnityCG.cginc"
//#include "AutoLight.cginc"
struct vertex_input
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float4 color : COLOR;
};
struct vertex_output
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
};
sampler2D _MainTex;
vertex_output vert (vertex_input v)
{
vertex_output o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
o.color = v.color;
return o;
}
fixed4 frag(vertex_output i) : COLOR
{
fixed4 tex = tex2D(_MainTex, i.uv);
fixed4 finalTex = tex * (i.color * tex.a);
if(finalTex.a > 0) finalTex.rgb = fixed3(0,0,0);
return finalTex;
}
ENDCG
}
}
}