透明度混合
//这里每个人得到名字不一样,自己修改
Shader "Custom/AlphaTest"
{
Properties
{
_Color("Main Tint",Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {}
//控制透明度,范围是0-1。
_AlphaScale("_AlphaScale",float)= 1
_Speed("_Speed",float) = 0.1
}
SubShader
{
//定义Tags,IgnoreProjector 决定 shader 是否会受投影器的影响,RenderType 可以让 shader 归入提前定义的组(这里是 TransparentCutout)
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
//渲染后面
Pass
{
Tags{"LightMode" = "ForwardBase"}
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引入dll文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//声明变量
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _AlphaScale;
float _Speed;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert (a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
//TRANSFORM_TEX宏来确保正确应用纹理比例和偏移
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
// o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_TARGET0
{
fixed2 tmpUv = i.uv;
tmpUv.x += _Time.y * _Speed;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texcolor = tex2D(_MainTex,tmpUv);
fixed3 albedo = texcolor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffues = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
// just invert the colors
// col.rgb = 1 - col.rgb;
return fixed4(ambient + diffues,texcolor.a * _AlphaScale);
}
ENDCG
}
//渲染前面
Pass
{
Tags{"LightMode" = "ForwardBase"}
Cull Back
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引入dll文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//声明变量
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _AlphaScale;
float _Speed;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert (a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
//TRANSFORM_TEX宏来确保正确应用纹理比例和偏移
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
// o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_TARGET0
{
fixed2 tmpUv = i.uv;
tmpUv.x += 1-_Time.y * _Speed;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texcolor = tex2D(_MainTex,tmpUv);
fixed3 albedo = texcolor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffues = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
// just invert the colors
// col.rgb = 1 - col.rgb;
return fixed4(ambient + diffues,texcolor.a * _AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
通过滑动条控制透明度与uv的速度
源码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AlphaCtrl : MonoBehaviour
{
public Slider[] Allslider;
void Start()
{
//给每一个slider注册事件
foreach (Slider item in Allslider)
{
//用lamuda表达式解决函数的回调,改变滑动条的值就可以改变,材质的参数
item.onValueChanged.AddListener((float value)=> ValueChange(value,item));
}
}
public void ValueChange(float value, Slider EventSender)
{
switch (EventSender.name)
{
//控制Alpha值
case "Alpha":
GetComponent().material.SetFloat("_AlphaScale", value);
Debug.Log("Alpha value == " + value.ToString("f2"));
break;
//控制UV速度
case "UVspeed":
GetComponent().material.SetFloat("_Speed", value*5);
Debug.Log("UvSpeed value == " + (value * 5).ToString("f2"));
break;
}
}
void Update()
{
}
}
学了shader后,发现之前的很多无法实现的效果,现在都可以实现了
在制作类似这种半透明的时候,首先要指定队列,要渲染的半透明的物体的时候,就需要
在Tags里面写下"Queue" = “Transparent”。
遇到的Bug:
第一个:由于我用的vs code编辑器所以提示效果不好,很多都是手打上去的,在编写字符串的时候要注意,没有高亮显示,所以要细心,如字母的大小写,虽然shader对大小写不是很敏感,但是调用Unity写的方法或者接口的时候,规定了格式就要遵守。
第二个,算是拓展我想通过Slider(滑动条)来控制透明度参数与uv的速度,在获取参数的时候发生了一个比较有趣的事情,由于我用了两个滑动条,我不想写两遍控制滑动条的方法,所以用了一个数组,存放两个滑动条,因为UI要用回调(可以用mvc框架实现),如果不知道mvc框架的,我下次更新在说,就用了匿名函数
**拉姆达表达式(float value)=> ValueChange(value,item)**来代替了回调那整个过程,(偷懒写法)
然后在ValueChange()中分别写对应要控制的sahder的参数GetComponent().material.SetFloat("_AlphaScale", value);这里就获取到了shader中控制透明度的参数,这里是我纠结了很久的地方,我第一次写的参数是AlphaScale,在shader中可以运行,但是通过滑动条始终无法控制,无法获取参数,我去看了一下SetFloat方法(可以双击这个方法,然后vs的按F12就可以看到Unity封装的的方法)
在后面name哪里,必须是下划线加变量名(我当时就是…)无语,改了之后完美运行。所以多看一下官方的东西,有些不够的可以去找资料补充。
当在Unity中创建一个shader脚本的时候,就会有一个默认的框架,如果是刚学shader的,建议先看一下
shader1.0(固定管线渲染),开关式的编程,有助于理解shader的基本语法,当学完shader1.0后就可以去看shader2.0了,最好的学习资料就是官方文档,虽然是英文的,不过都不是什么复杂的英语,查一查,问一问就能理解的差不多。
距离上一次的更新是好久了,要坚持下去。
参考文章:
[https://blog.csdn.net/weixin_37027464/article/details/82878815]
UGUI Slider的onValueChanged事件