unity 着色器shader 语法快速入门、复习(一)

这是对unity shader语法的快速入门、复习
主要参考链接:

Lesson 1 渲染管线

此部分可以参考我之前的文章:百人计划学习 图形 1.1 渲染流水线
主要分清楚顶点着色器、片段着色器阶段的输入和输出,以及这两个阶段是做什么的

Lesson 2 Shader的基本结构

Shader "Custom/ShaderLearning"
{
   Properties {     
        _MainTex("Main Tex",2D) = "white"
    }
    SubShader{
       Tags{"LightMode" = "ForwardBase"}
        Pass{  
            Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            fixed4 _Diffuse;
            fixed4 _Specular;   //因为Specular是0-1所以精度更高用fixed4
            float _Gloss;
            struct a2v{
                float4 vertex : POSITION; 将模型的顶点坐标填充到vertex变量中
                float2 uv : TEXCOORD0;
            };
            struct v2f{
                float2 uv : TEXCOORD0;  //
                float4 pos : SV_POSITION; //pos包含了顶点在裁剪空间中的位置信息
            };
            sampler2D _MainTex;
            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);  //转换到屏幕空间
                o.uv = v.uv;
                return o;
            }
            fixed4 frag(v2f i) :SV_Target {
                fixed4 color = tex2D(_MainTex,i.uv);
                color *= fixed4(i.uv.x,i.uv.y,0,1);
                return color;
            }
        ENDCG
        }
    }
    FallBack "Diffuse"
}

解析一下上面的各部分:

properties属性部分

在这里插入图片描述

 Properties {     
        _Tex("Tex", 2D) = "white" {}
        _Intensity("Intensity", Range(0, 20)) = 2  //锐化强度
        _MainTex("Main Tex",2D) = "white"
    }
  • Subshader,定义了一系列pass以及可选状态,pass是子着色器
  • Fallback,告诉unity,如果上面所有的subshader在这块显卡上都不执行,那么使用这个最低级的shader

在这里插入图片描述

Lesson 3 纹理输入

将带有透明通道的PNG图片渲染出来
如果没有设置透明通道,会出现以下情况

在这里插入图片描述

注意:在属性区块内被定义的数据在CGPROGRAM内被使用之前都要预定义一遍,不然会报错。在CGPROGRAM内加入纹理的定义:

 sampler2D _Tex;
 float4 _Tex_ST;
 float _Intensity;

要返回纹理,片段着色器应该写为:

fixed4 frag(v2f i) :SV_Target {            
        return tex2D(_MainTex,i.uv);
  }

设置透明度,
使用Alpha Blend :
Blend SrcAlpha OneMinusSrcAlpha
OutColor = SrcColor * ScrAlpha + DstColor * (1 - SrcAlpha)
代码如下:

Shader "Custom/TextureShader"
{
   Properties {     
        _MainTex ("Main Tex", 2D) = "white"
    }
    SubShader{
       Tags{"LightMode" = "ForwardBase"}
       Tags{"Queue" = "Transparent"}
        Pass{
        Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            sampler2D _MainTex;
            #include "Lighting.cginc"
            
            struct a2v{
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            struct v2f{
                float2 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
            };
            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);  
                o.uv = v.uv;
                return o;
            }
            fixed4 frag(v2f i) :SV_Target {            
                return tex2D(_MainTex,i.uv);
            }
        ENDCG
        }
    }
    FallBack "Diffuse"
}

在这里插入图片描述

Lesson 4 屏幕后处理效果

  1. 在颜色缓冲区的内容真正被喷到屏幕上之前,我们仍然有机会更改其中的内容。而unity也为我们考虑到了这一点,因此它提供了一个叫OnRenderImage的函数,这是个monobehaviour事件。

  2. Called after scene rendering is complete to allow post-processing
    of the image,

  3. Blit 将 dest 设置为渲染目标,在材质上设置 source _MainTex 属性, 并绘制全屏四边形。所以在material上要设置 _MainTex

  • 完整shader是lesson1中的代码
  • 下面的脚本添加到camera中
using UnityEngine;
[ExecuteInEditMode]  
public class PostEffects : MonoBehaviour
{
    public Material material;
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source,destination,material);
    }
}

在这里插入图片描述

Lesson 5 扭曲效果制作

需要添加位移图、和扭曲强度参数
位移图红色作为uv的x值,所以取到红色就是向右移动
绿色同理,向上移动

在这里插入图片描述

在这里插入图片描述

这里实现的是动态扭曲的效果,有两点需要注意
一是_Time的使用,
二十disp*2 -1 将范围划到(-1,1)中uv值就随着时间的推移而改变,我们在对位移图进行采样的时候,uv值就已经改变过了
会重复的原因是tex2D的原因,最终会把纹理uv的值映射到0-1中(没有完全明白)

 float4 frag(v2f i) :SV_Target {   
     float2 distuv = float2(i.uv.x + _Time.x ,i.uv.y + _Time.x*2);
     float2 disp = tex2D(_DisplaceTex,distuv).xy;
     disp = ((disp*2) - 1) * _Magnitude;
     float4 color = tex2D(_MainTex,i.uv + disp);
     return color;
}

Lesson 6 小练习

小练习1
实现两个图片的替换
添加两个参数:

  • _SubTex (“Sub Tex”,2D) = “white” {}
  • _Between (“Tween”,Range(0,1)) = 0
    在frag shader里
fixed4 frag(v2f i) :SV_Target {            
       return tex2D(_MainTex,i.uv)*(1-_Between) + tex2D(_SubTex,i.uv)*(_Between);
  }

在这里插入图片描述

2.设置灰度值并乘以自定义颜色
使用明亮度(luminance)公式来算出一个明亮度值,然后将红绿蓝通道都设置为明亮度值,透明度通道则用对图片采样获得的透明度,最终获得灰度效果
luminance = 0.2125 * Red + 0.07154 * Green + 0.0721 * Blue

 fixed4 frag(v2f i) :SV_Target {            
       fixed4 colorVal =  tex2D(_MainTex,i.uv)*(1-_Between) + tex2D(_SubTex,i.uv)*(_Between);
       fixed luminance = 0.2125 * colorVal.r + 0.07154 * colorVal.g + 0.0721 * colorVal.b;
       return fixed4(luminance,luminance,luminance,tex2D(_MainTex,i.uv).a);
 }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值