Unity 屏幕特效 之 分屏之 斜角(对角线) 分屏渲染不同相机画面功能的简单实现
Unity 屏幕特效 之 分屏之 斜角(对角线) 分屏渲染不同相机画面功能的简单实现
目录
Unity 屏幕特效 之 分屏之 斜角(对角线) 分屏渲染不同相机画面功能的简单实现
一、简介
所谓屏幕后处理,简单来说就是渲染流水线的最后阶段,对由整个场景生成的一张图片进行处理,比如HDR,运动模糊等等效果,通过屏幕空间的后处理,可以整体改变整个游戏的风格或者效果。所以,要制作屏幕后处理,我们需要两样东西,一个是用于渲染后处理效果的shader,而另一个是我们需要调用这个渲染的脚本。
实现原理:
-
斜角分屏,根据点再对角线的上或者下,进行分屏渲染
二、关键技术
1、在 Shader 中,根据数学公式得到 UV 对角线 上下的规律,进行斜角分屏渲染;
2、OnRenderImage函数每帧渲染完全部内容后执行,我们在每一帧设置Material的各项参数,通过Material.SetXXX("name",value)可以向shader中传递各种参数;
3、ceil 函数(向上求整), 返回大于或等于输入值的最小整数。
4、关键代码
// 斜角渲染不同相机的画面
// 斜角线有两条:y-x=0,y+x-1=0
// uv的 x y 值 带入上面斜角线,值大于0,在线上面,值小于 0 ,在线下面
if (_SpiltScreenMode) {
col = tex2D(_MainTex, i.uv)*ceil(i.uv.x+i.uv.y -1)+tex2D(_SecondCameraTexture,i.uv)*ceil(1-i.uv.x-i.uv.y);
}
else{
col = tex2D(_MainTex, i.uv)*ceil(i.uv.y-i.uv.x)+tex2D(_SecondCameraTexture,i.uv)*ceil(i.uv.x-i.uv.y);
}
三、注意事项
1、各种后处理效果可以叠加,这里的dest并不一定就是屏幕。不过后处理是很耗费性能的,一方面是pixel shader全屏幕overdraw,另一方面,一个rendertexture的内存占用很大,尤其是大分辨率手机上,多个后处理效果可能造成内存耗尽,程序崩溃;(不过网上有方式可以优化这个功能,到时候找找资料看看,在给大家试试哈,大家也可以自己先看看试试)
2、注意判断屏幕特效是否支持可以用;
3、注意参数值根据实际效果,合理调节;
四、效果预览
五、实现步骤
简单原理图:
具体实现步骤:
1、打开Unity,在场景中添加几个 Cube 和 camera
2、其中,可以调整两个camer 位置和方向,进行不一样的渲染,MainCamera 和 Camera 的渲染如下
3、在工程中,新建两个脚本和Shader,Shader 实现分屏,脚本把屏幕数据传给Shader
4、把脚本挂载到 MainCamera 上,并赋值
5、运行场景,效果如上
六、关键代码
1、ShaderSpiltScreen.shader
Shader "Unlit/ShaderSpiltScreen"
{
Properties
{
_MainTex ("主camera的渲染图", 2D) = "white" {}
_SecondCameraTexture("第二个camera的渲染图",2D)="white"{}
[MaterialToggle]_SpiltScreenMode("屏幕分屏模式切换",float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _SecondCameraTexture;
float4 _SecondCameraTexture_ST;
bool _SpiltScreenMode;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col;
// 斜角渲染不同相机的画面
// 斜角线有两条:y-x=0,y+x-1=0
// uv的 x y 值 带入上面斜角线,值大于0,在线上面,值小于 0 ,在线下面
if (_SpiltScreenMode) {
col = tex2D(_MainTex, i.uv)*ceil(i.uv.x+i.uv.y -1)+tex2D(_SecondCameraTexture,i.uv)*ceil(1-i.uv.x-i.uv.y);
}
else{
col = tex2D(_MainTex, i.uv)*ceil(i.uv.y-i.uv.x)+tex2D(_SecondCameraTexture,i.uv)*ceil(i.uv.x-i.uv.y);
}
return col;
}
ENDCG
}
}
}
2、SpiltScreen.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpiltScreen : ScreenPostEffectBase
{
public bool _SpiltScreenMode = true;
public Camera _SecondCamera;
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
if (_Material != null)
{
if (_SecondCamera.targetTexture == null) {
////根据主相机的宽高创建一个同样宽高的纹理,记录辅助相机的图像
_SecondCamera.targetTexture = new RenderTexture(_SecondCamera.pixelWidth,_SecondCamera.pixelHeight,0);
}
_Material.SetTexture("_SecondCameraTexture", _SecondCamera.targetTexture);
_Material.SetInt("_SpiltScreenMode", _SpiltScreenMode?1:0);
//Debug.Log(_SpiltScreenMode ? 1 : 0);
Graphics.Blit(sourceTexture, destTexture, _Material);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
}
3、ScreenPostEffectBase.cs
using UnityEngine;
//非运行时也触发效果
[ExecuteInEditMode]
//屏幕后处理特效一般都需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
//提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
public class ScreenPostEffectBase : MonoBehaviour
{
//Inspector面板上直接拖入
public Shader shader = null;
private Material _material = null;
public Material _Material
{
get
{
if (_material == null)
_material = GenerateMaterial(shader);
return _material;
}
}
//根据shader创建用于屏幕特效的材质
protected Material GenerateMaterial(Shader shader)
{
// 系统是否支持
if (!SystemInfo.supportsImageEffects)
{
return null;
}
if (shader == null)
return null;
//需要判断shader是否支持
if (shader.isSupported == false)
return null;
Material material = new Material(shader);
material.hideFlags = HideFlags.DontSave;
if (material)
return material;
return null;
}
void OnDisable()
{
if (_material != null)
{
DestroyImmediate(_material);
}
}
}
上一篇: CentOS时间、日期、计算器命令