您的位置:首页 > 其它

Shader实例:一台旧电视

2016-05-13 15:43 253 查看
准备:

1.一段小视频

2.一张电视机贴图

3.一张过滤图

效果:

让视频内容只在电视机屏幕区域显示



Shader代码:有注释

Shader "Joe/old_tv"
{
Properties
{
_MainTex("main tex", 2d) = ""{}//主贴图
_TVTex("TV tex",2d) = ""{}//屏幕内容
_TVMask("TV mask",2d) = ""{}//过滤贴图
}

SubShader
{
Tags
{
"Queue"  = "Transparent"
}

Blend SrcAlpha OneMinusSrcAlpha

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct v2f
{
float4 vertex:POSITION;
float4 uv:TEXCOORD0;
};

sampler2D _MainTex;
sampler2D _TVTex;//视频内容从脚本本中设置
sampler2D _TVMask;

v2f vert(appdata_base v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv.xy = v.texcoord.xy;
return o;
}

half4 frag(v2f i):COLOR
{
//采样电视机贴图
half4 tv = tex2D(_MainTex,i.uv.xy);

//采样过滤贴图
half4 mask = tex2D(_TVMask,i.uv.xy);

//得到用过滤图的alpha值作为权重 影响过后的uv
half2 maskuv = i.uv.xy * mask.a;

//用该uv,采样屏幕内容,根据过滤图的alpha值,得到内容只在电视机屏幕区域显示的效果
half4 tvcontent = tex2D(_TVTex,maskuv);
tvcontent.a = mask.a;

//return tvcontent;
//return tv;

half4 result = tv;
//是屏幕上的区域
if(mask.a==1)
{
//和屏幕内容颜色混合
result = tv + tvcontent;
result.rgb=result.rgb/2;
}
else
{
//是电视机外壳区域,什么也不做,保持原来的颜色
}
return result;
}

ENDCG
}
}

FallBack "Diffuse"
}


C#脚本代码:就是把视频内容传递给shader代码里面的uniform sampler2D _TVTex

using UnityEngine;
using System.Collections;

public class playTv : MonoBehaviour
{
public MovieTexture movie;

void Start ()
{
this.GetComponent<Renderer>().material.SetTexture("_TVTex",movie);
movie.loop = true;
movie.Play();
}
}


不足:

以为这样就完美了吗?

不是,既然是旧电视,必然有那种,吱~吱~吱~ 的闪烁。

屏幕绘制不完美的断裂,从左到右的一个uv移动。

Try it yourself!

我是个怀旧之人,小时候爷爷房间里就有这样的一台电视机。

你完全可以搞一张IMAX的图片,然后在上面播放好莱坞大片。

本文固定链接: http://www.shihuanjue.com/?p=227

转载请注明: 2016年01月01日 于 是幻觉 发表
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: