Unity Shaders——屏幕特效混合模式(Blend mode with screen effects)
Posted 御雪妃舞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shaders——屏幕特效混合模式(Blend mode with screen effects)相关的知识,希望对你有一定的参考价值。
参考《Unity Shaders and Effects CookBook》
屏幕特效不仅仅限于颜色控制RenderTexture,同事还可以结合图片和RenderTexture的混合,这种技术和PhotoShop新建一个 层级,然后选择混合模式,混合两张图片是一样的,但是Untiy里的效果更艺术,整个场景的立体效果都蒙上这种效果,混合模式有Multiplay,Add,Overlay三种模式。
然后基本的原理和动作跟上一篇灰度屏幕特效类似。
下面我们分别看下三种混合模式的屏幕特效:
1.Multiply混合模式
首先看脚本:
Shader脚本:
Shader "MyShaders/BlendImageEffect"
Properties
_MainTex("Base (RGB)", 2D) = "white"
_BlendTex("Blend Texture", 2D) = "white"
_Opacity("Blend Opacity", Range(0,1)) = 1
SubShader
Pass
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform sampler2D _BlendTex;
fixed _Opacity;
fixed4 frag(v2f_img i) : COLOR
//Get the colors from the RenderTexture and the uv's
//from the v2f_img struct
fixed4 renderTex = tex2D(_MainTex, i.uv);
fixed4 blendTex = tex2D(_BlendTex, i.uv);
//Perform a multiply Blend mode
fixed4 blendedMultiply = renderTex * blendTex;
//Adjust amount of Blend Mode with a lerp
renderTex = lerp(renderTex, blendedMultiply, _Opacity);
return renderTex;
ENDCG
FallBack off
cs脚本:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class BlendImageEffect : MonoBehaviour
#region Variables
public Shader curShader;
public Texture2D blendTexture;
public float blendOpacity = 1.0f;
private Material curMaterial;
#endregion
#region Properties
Material material
get
if (curMaterial == null)
curMaterial = new Material(curShader);
curMaterial.hideFlags = HideFlags.HideAndDontSave;
return curMaterial;
#endregion
void Start()
if (!SystemInfo.supportsImageEffects)
enabled = false;
return;
if (!curShader && !curShader.isSupported)
enabled = false;
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
if (curShader != null)
material.SetTexture("_BlendTex", blendTexture);
material.SetFloat("_Opacity", blendOpacity);
Graphics.Blit(sourceTexture, destTexture, material);
else
Graphics.Blit(sourceTexture, destTexture);
void Update()
blendOpacity = Mathf.Clamp(blendOpacity, 0.0f, 1.0f);
void OnDisable()
if (curMaterial)
DestroyImmediate(curMaterial);
最终效果如图:(混合图片的Opacity可以调)
Opacity=1
Opacity=0.5
与之混合的是如下的图片:
2.Add Blend模式
相对上面的Shader只做了小小的改动:
最终效果如图:
Opacity=1:
Opacity=0.5:
再增加一种混合模式,叫做ScreenBlend屏幕混合,这个设计一点数学计算,与上面相似,只做简单的改动:
最后效果如图: 同时混合了两张图片。
3.Overlay混合模式
这种混合模式实际上根据条件状态,决定最终的每个通道的每个像素的颜色,所以这个过程需要一点变成来实现:
Shader脚本如下:
Shader "MyShaders/Overlay_Effect"
Properties
_MainTex ("Base (RGB)", 2D) = "white"
_BlendTex ("Blend Texture", 2D) = "white"
_Opacity ("Blend Opacity", Range(0,1)) = 1
SubShader
Pass
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
uniform sampler2D _BlendTex;
fixed _Opacity;
fixed OverlayBlendMode(fixed basePixel, fixed blendPixel)
if(basePixel < 0.5)
return (2.0 * basePixel * blendPixel);
else
return (1.0 - 2.0 * (1.0 - basePixel) * (1.0 - blendPixel));
fixed4 frag(v2f_img i) : COLOR
//Get the colors from the RenderTexture and the uv's
//from the v2f_img struct
fixed4 renderTex = tex2D(_MainTex, i.uv);
fixed4 blendTex = tex2D(_BlendTex, i.uv);
fixed4 blendedImage = renderTex;
blendedImage.r = OverlayBlendMode(renderTex.r, blendTex.r);
blendedImage.g = OverlayBlendMode(renderTex.g, blendTex.g);
blendedImage.b = OverlayBlendMode(renderTex.b, blendTex.b);
//Adjust amount of Blend Mode with a lerp
renderTex = lerp(renderTex, blendedImage, _Opacity);
return renderTex;
ENDCG
FallBack off
cs脚本:
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class Overlay_ImageEffect : MonoBehaviour
#region Variables
public Shader curShader;
public Texture2D blendTexture;
public float blendOpacity = 1.0f;
private Material curMaterial;
#endregion
#region Properties
Material material
get
if(curMaterial == null)
curMaterial = new Material(curShader);
curMaterial.hideFlags = HideFlags.HideAndDontSave;
return curMaterial;
#endregion
void Start()
if(!SystemInfo.supportsImageEffects)
enabled = false;
return;
if(!curShader && !curShader.isSupported)
enabled = false;
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
if(curShader != null)
material.SetTexture("_BlendTex", blendTexture);
material.SetFloat("_Opacity", blendOpacity);
Graphics.Blit(sourceTexture, destTexture, material);
else
Graphics.Blit(sourceTexture, destTexture);
void Update()
blendOpacity = Mathf.Clamp(blendOpacity, 0.0f, 1.0f);
void OnDisable()
if(curMaterial)
DestroyImmediate(curMaterial);
最终效果如图:
以上是关于Unity Shaders——屏幕特效混合模式(Blend mode with screen effects)的主要内容,如果未能解决你的问题,请参考以下文章
Unity Shaders——屏幕灰度效果(Screen Effect)
Unity Shaders and Effects Cookbook (2-4) 压缩和混合纹理贴图:使用灰度图存储插值信息
Unity Shaders学习笔记——SurfaceShader混合纹理