unity shader学习(一)

看到一篇文档,讲的还蛮好的就转载过来。

 

前言

  关于UnityShader方面的知识有很多,但真正能让读者读懂并很快上手操作的少之又少,在这里我简单介绍下关于Shader的一些入门知识,如有出入请大佬们多多指点!

图形学的基础知识

  1.Unity游戏物体上需挂载Mesh Filter组件,Mesh Filter中存储一个Mesh网格(用于存储形成图形的所有三角面的顶点信息)。

  2.Unity游戏物体上需挂载Mesh Renderer组件,Mesh Renderer为渲染组件,通俗来讲就是按照Mesh网格上的顶点信息将图形显示出来,赋予皮肤、颜色等等。

  3.Mesh Renderer中Material(材质)及我们编写的Shader所依赖的,用于实现效果的依托。

Shader、OpenGL、DirectX之间的关系

  通俗来讲,Shader是一种渲染命令,由OpenGL或者DirectX进行解析进而渲染出丰富多彩的图形。

  其中OpenGL一般用于移动平台,DirectX一般用于PC平台。

  

Shader的语言分类

  1.GLSL OpenGL语言

  2.HLSL DirectX语言

  3.CG  夸平台语言

  4.ShaderLab Unity中对上述语言的通用封装

关于Shader中的属性代码

复制代码

Shader"Mocha/01 myshader"{//这里制定Shader的名字,不要求与文件名保持一致

    Properties{
    //属性
    _Color("Color",Color)=(1,1,1,1)        //颜色float4
    _Vector("Vector",Vector)=(1,2,3,4)    //向量float4
    _Int("Int",Int)=1234                //整数float
    _Float("Float",Float)=4.5            //小数float
    _Range("Range",Range(1,11))=6        //随机数float
    _2D("Texture",2D)="white"{}            //图片sampler2D(其中white代表当未指定图片时默认其未一张白色的图片,也可改为其他颜色)
    _Cube("Cube",Cube)="White"{}        //立方体纹理samplerCube(其中white代表当未指定图片时默认其未一张白色的图片,也可改为其他颜色)用于天空盒子等
    _3D("Texure",3D) = "White"{}        //3D贴图sampler3D(其中white代表当未指定图片时默认其未一张白色的图片,也可改为其他颜色)
    }

    //SubShader可以有很多个,显卡运行效果的时候,从第一个SubShader开始,如果里面的效果全部可以实现,那么就使用第一个SubShader,如果不支持则进行下一个
    SubShader{
        
        //每个SubShader至少有一个Pass块  相当于一个方法
        Pass{
        
        //在这里编写Shader代码
            CGPROGRAM
            //使用CG语言编写Shader代码
            //每次使用上面定义好的属性时需要重新定义一下并且此处每行代码“;”结束
            //取到的值为上述默认定义好的值
            float4 _Color;
            float4 _Vector;
            float _Int;
            float _Float;
            float _Range;
            sampler2D _2D;
            samplerCube _Cube;
            sampler3D _3D;

            //float half fixed 的区别
            //一般小数这三个都可以声明定义
            float t1;
            half t2;
            fixed t3;
            half2 t4;
            fixed2 t5;
            //区别在于范围不同 
            //float 32位
            //half 16位  -6万 -- +6万
            //fixed 11位  -2 -- +2 (一般颜色用fixed)

            ENDCG

        }

    }

    //当所有的SubShader都不符合的时候,则用此备胎Shader效果可自定义备胎Shader
    Fallback "VertexLit"
}

复制代码

 关于Shader中的常用语义

  1.从应用程序传递到顶点函数的语义有哪些a2v
    POSITION 顶点坐标(模型空间下的)
    NORMAL 法线( 模型空间下)
    TANGENT 切线(模型空间)
    TEXCOORD0 ~n 纹理坐标
    COLOR 顶点颜色

  2.从顶点函数传递给片元函数的时候可以使用的语义
    SV_POSITION 剪裁空间中的顶点坐标(一般是系统直接使用)
    COLOR0 可以传递一组值 4个
    COLOR1 可以传递一组值 4个
    TEXCOORD0~7 传递纹理坐标

  3.片元函数传递给系统
    SV_Target 颜色值,显示到屏幕上的颜色

复制代码

Shader "Mocha/02 secondshader can run"{

    SubShader{
    
        Pass{
            CGPROGRAM
            //顶点函数 这里只是声明了顶点函数的函数名
            //基本作用 完成顶点坐标从模型空间到剪裁空间的转换(从游戏环境到相机视野屏幕上)
#pragma vertex vert
            //片元函数 这里只是声明了片元函数的函数名
            //基本作用 返回模型对应的屏幕上的每一个像素的颜色值
#pragma fragment frag
            
            float4 vert(float4 v : POSITION) : SV_POSITION{//通过语义来告诉系统我这个参数是干嘛的
            //比如POSITION是告诉系统我需要顶点坐标
            //比如SV_POSITION用来解释说明返回值,返回值是剪裁空间下的顶点坐标

            //转换剪裁空间坐标的算法,也可直接调用包装好的方法
            float4 pos=mul(UNITY_MATRIX_MVP,v);
            return pos;
            
            }
            fixed4 frag() : SV_Target{
            return fixed4(0.5,0.5,1,1);
            }


            ENDCG
        }
    
    }
    Fallback "VertexLit"

}

复制代码

使用结构体进行存储传递数据

复制代码

Shader "Mocha/03 Use Struct"{

    SubShader{
    
        Pass{
            CGPROGRAM
            //顶点函数 这里只是声明了顶点函数的函数名
            //基本作用 完成顶点坐标从模型空间到剪裁空间的转换(从游戏环境到相机视野屏幕上)
#pragma vertex vert
            //片元函数 这里只是声明了片元函数的函数名
            //基本作用 返回模型对应的屏幕上的每一个像素的颜色值
#pragma fragment frag
            
            //使用结构体存储
            //a2v 即 application to vertex
            struct a2v{ 
                float4 vertex:POSITION;//告诉Unity把模型空间下的顶点坐标填充给vertex
                float3 normal:NORMAL;//告诉Unity把模型空间下的法线方向填充给normal
                float4 texcoord:TEXCOORD0;//告诉Unity把第一套纹理坐标填充给texcoord
            };

            //使用结构体存储
            struct v2f{
                float4 position:SV_POSITION;//告诉Unity存储剪裁空间下的顶点坐标
                float3 temp:COLOR0;//临时测试顶点到片元函数之间的数据传递,此处将顶点中的法线作为颜色传递给片元函数显示
            };

            v2f vert(a2v v){
                v2f f;
                f.position=mul(UNITY_MATRIX_MVP,v.vertex); 
                f.temp=v.normal;
                return f;
            }
            fixed4 frag(v2f f) : SV_Target{
            return fixed4(f.temp,1);
            }


            ENDCG
        }
    
    }
    Fallback "VertexLit"

}

复制代码