目录
课时70:FragmentShader-Alpha和blend运算
课时71:FragmentShader-实现半透明1
课时72:FragmentShader-实现半透明2
课时70:FragmentShader-Alpha和blend运算
简单透明
Shader "Custom/NewSurfaceShader 30"
{
SubShader
{
pass
{
blend srcalpha oneminussrcalpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f{
float4 pos:POSITION;
};
v2f vert(appdata_base v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
return o;
}
fixed4 frag(v2f IN) :COLOR
{
fixed4 color = fixed4(0,0,1,0.5);
return color;
}
ENDCG
}
}
}
有问题
https://docs.unity3d.com/Manual/SL-CullAndDepth.html
Cull Back|Front|Off
ZWrite On|Off
ZTest
Offset
blend srcalpha oneminussrcalpha
zwrite off
颜色缓冲区,像素点颜色
Depth Buffer,深度缓冲区,和颜色缓冲区大小一样。
0-1
近裁剪面 0
远裁剪面 1
ztest,深度测试
LEqual ,是否比深度缓冲区的深度 小于等于,true:则颜色进入颜色缓冲区
zwrite :要不要把当前计算的深度值写入深度缓冲区,要通过深度测试。
通过深度,但是zwrite off,则只输出颜色,不改写深度缓冲区。
深度是有系统提供,根据摄像机和物体位置
课时71:FragmentShader-实现半透明1
半透明,zwrite off
被物体遮挡则材质变成穿透+半透明的效果
半遮挡的情况
ztest greater:
pass
{
blend srcalpha oneminussrcalpha
ztest greater
zwrite on
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f{
float4 pos:POSITION;
};
v2f vert(appdata_base v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
return o;
}
fixed4 frag(v2f IN) :COLOR
{
fixed4 color = fixed4(0,0,1,0.5);
return color;
}
ENDCG
}
两个pass,一个greater,一个lequal
pass是按照顺序执行的,lequal要在前面,greater要在后面
Shader "Custom/NewSurfaceShader 31"
{
SubShader
{
pass
{
blend srcalpha oneminussrcalpha
ztest lequal
zwrite on
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f{
float4 pos:POSITION;
};
v2f vert(appdata_base v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
return o;
}
fixed4 frag(v2f IN) :COLOR
{
fixed4 color = fixed4(0,0,1,0.5);
return color;
}
ENDCG
}
pass
{
blend srcalpha oneminussrcalpha
ztest greater
zwrite on
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f {
float4 pos:POSITION;
};
v2f vert(appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//屏幕坐标
return o;
}
fixed4 frag(v2f IN) :COLOR
{
fixed4 color = fixed4(1,0,0,1);
return color;
}
ENDCG
}
}
}
教程没有提到这个顺序问题,
教程里面greater在前,lequal在后,或者在pass1里面,zwrite off,或者在pass2里面改成ztest less,或者pass2中的blend去掉。
在透明的墙后面,效果就不行了,因为透明墙的材质里面的zwrite off,这样ztest greater其实就没有效果了,不和透明的墙比较深度了。
另外其实我的练习结果和教程有差异,摄像头的位置不同,看到的效果不一样。
课时72:FragmentShader-实现半透明2
没有深度写入的情况下,如何进行深度比较
深度贴图,Depth Texture
https://docs.unity3d.com/500/Documentation/Manual/SL-CameraDepthTexture.html
通过摄像机进行Shader置换
置换
没听懂....
虽然没有写入深度缓存
可以通过shader写入深度信息
Camera.SetReplacementShader
ResetReplacementShader
tags{"queue"="transparent","rendertype"="transparent"}
一个用来替换的,获取深度信息的shader
Shader "Custom/Depth"
{
SubShader
{
tags{"rendertype"="transparent"}
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f{
float4 pos:POSITION;
float2 depth:TEXCOORD0;
};
v2f vert(appdata_base v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//屏幕坐标
o.depth = o.pos.zw;
return o;
}
fixed4 frag(v2f IN) :COLOR
{
float depth = Linear01Depth(IN.depth.x / IN.depth.y);
fixed4 color = fixed4(depth,0,0,1);
return color;
}
ENDCG
}
}
}
一个原来的透明shader,加上"rendertype"="transparent"
tags{"queue"="transparent" "rendertype"="transparent"}
一个替换的脚本
public class RepalcementShader : MonoBehaviour
{
void Start()
{
Camera.main.SetReplacementShader(Shader.Find("Custom/Depth"), "rendertype");
}
}
结果只渲染了rendertype=transparent的物体
没有深度信息,就给它深度信息。
然后,没有了,不给出完整实现....就说一个思路。
最后给出个完整实现的效果图
Camera.main.SetReplacementShader(Shader.Find("Custom/Depth"), ""); 可以替换所有的材质,这个替换材质好像挺好用的,比如把所有材质替换成透明的。