Shader半透明物体的制作

Shader 04

透明度混合

先来一张效果图
Shader半透明物体的制作_第1张图片
先放源代码

//这里每个人得到名字不一样,自己修改
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封装的的方法)
Shader半透明物体的制作_第2张图片
在后面name哪里,必须是下划线加变量名(我当时就是…)无语,改了之后完美运行。所以多看一下官方的东西,有些不够的可以去找资料补充。

当在Unity中创建一个shader脚本的时候,就会有一个默认的框架,如果是刚学shader的,建议先看一下
shader1.0(固定管线渲染),开关式的编程,有助于理解shader的基本语法,当学完shader1.0后就可以去看shader2.0了,最好的学习资料就是官方文档,虽然是英文的,不过都不是什么复杂的英语,查一查,问一问就能理解的差不多。

距离上一次的更新是好久了,要坚持下去。

参考文章:
[https://blog.csdn.net/weixin_37027464/article/details/82878815]
UGUI Slider的onValueChanged事件

你可能感兴趣的:(个人学习)