Shader入门学习

Shader学习笔记
相关博客http://www.cnblogs.com/polobymulberry/p/4314147.html
相关视频 Siki Shader着色器

什么是OpenGL、DirectX
CPU不直接与GPU交互,需要通过一些接口来进行交互
shader可以认为是一种渲染命令 ,由opengl 或者dx进行解析,来控制渲染丰富多彩的图形。

编写Shader语言
OpenGL 使用GLSL 编写shader
DirectX 使用HSSL 编写shader
英伟达 CG 编写shader(跨平台) 使用
使用ShaderLab来编写Unity中Shader
ShaderLab是CG的封装

Unity Shader 分类
1. 表面着色器 Surface Shader
2. 顶点/片元着色器 Vertex/Fragment Shader(功能强大,但是相对比较上一个编写较复杂)
3. 固定函数着色器 Fixed Function Shader(已弃用)
当光源比较多的时候,推荐使用表面着色器

Properties属性值简介

属性值(property)定义的形式:

_Name(“Displayed Name”,type) = default value[{options}]

  • _Name 属性值的名称,是在shader代码内部使用的,区别于下面的Displayed Name,后者是在Inspector 面板上显示的,作为外界(用户)的输入提示。
  • Displayed Name 呈现在材质编辑器中的属性值名称,在Inspector面板上显示。
  • type 属性值的类型,包括:
    Color – 表示纯色,使用了RGBA表示法
    2D – 代表尺寸为2的幂次的纹理(如2,4,8,16…256,512)
    Rect – 代表纹理(texture),不同于上面的纹理,此处纹理的大小不一定是2的幂次。
    Cube – 用于3d中的cube map,经常提到的天空盒就是使用了cube map。
    Range(min, max) – 在min和max之间的一个值,在面板中可用滑动条改变其值大小。
    Float – 任意一浮点数。
    Vector – 4维向量值,本质就是4个浮点数组成的类型。
  • default value 属性值的初始值,就相当于你的变量初始化的那个值。
    Color – (red,green,blue,alpha) 使用了RGBA这种格式的颜色,alpha指的是透明度– 比如 (1,1,1,1)
    2D/Rect/Cube – 纹理的类型,上面已经介绍过了。初始化值可以使一个空字符串,或者”white”, “black”, “gray”, “bump”(说明此纹理是一个凹凸纹理)
    Float/Range – 这个没啥说的,跟浮点数初始化一样一样的
    Vector – 4维向量,其中4个数均为浮点数 (x,y,z,w)

标签(Tags)

  • Background – 在所有其他物体渲染之前渲染,被用于天空盒或类似的背景效果。
  • Geometry(默认tags为geometry) – 适用于大多数物体。非透明物体使用这种渲染顺序。
  • AlphaTest – 进行alpha测试的像素(alpha-test是指当前像素的alpha小于一定的值就舍弃该像素)应该使用该渲染顺序。单独设置该渲染顺序是因为当在渲染完所有实体过后,渲染alpha测试的物体将更有效率。
  • Transparent – 该渲染标签所属的物体将在标签为Geometry和AlphaTest之后的物体渲染,并且这些贴着Transparent的所有物体本身是从后往前依次渲染的。任何经过alpha-blended的物体都应该使用该标签(译者注:alpha-blended是指使用当前像素的alpha作为混合因子,来混合之前写入到缓存中像素值,注意此时shader是不能写入深度缓存的,因为关闭了写入深度缓存的功能,如果不关闭写入深度缓存,那么在进行深度检测的时候,它背后的物体本来我们是可以透过它被我们看到的,但由于深度检测时,小于它的深度就被剔除了,从而我们就看不到它后面的物体了),玻璃和粒子效果比较适合该渲染标签。
  • Overlay – 该渲染标签适合覆盖效果,任何最后渲染的效果都可以使用该标签,比如透镜光晕。
    有趣的是你可以给这些基本的渲染标签进行加加减减。这些预定义的值本质上是一组定义整数,Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000,最后Overlay = 4000。(译者注:从此处我们也可以一窥究竟,貌似数值大的后渲染。)这些预设值这对透明物体有很大影响,比如一个湖水的平面覆盖了你用广告牌制作的树,你可以对你的树使用“Queue”=”Transparent-102”,这样你的树就会绘制在湖水前面了。

Shader的整体结构

Shader "Holo/Diffuser Texture"
{
    Properties{
        _MainTex("Texture",2D) = "white"{}
    }
        SubShader
    {
        Pass{

        Tags{"RenderType" = "Opaque"}
        CGPROGRAM
#pragma suiface surf Lambert
        struct Input {  //结构体
            float2 uv_MainTex;
        };
        sampler2D _MainTex;
        void surf(Input IN, inout Surfaceutput o)
        {
            o.Albedo = tex2D(_MainTex, IN.uv_MainTex.rgb);
        }
        ENDCG
            }
    }
        Fallback "Diffuse"
}
//tex2d的作用是利用IN.uv_MainTex所代表的uv坐标(注意我们上面指定了uv坐标产生的方式,所以此处的IN.uv_MainTex是自动生成的)对纹理_MainTex进行采样。此处,对于o.Albedo我们只取颜色分量中的rgb三分量,其中alpha值(透明度)目前不需要,至少对于非透明物体alpha值得作用不大。
//顶点函数  完成顶点坐标到模型空间到剪裁空间的转换(从游戏环境到相机视野上)
//片元函数  返回模型对应屏幕上的每一个像素的颜色值
//POSITION 传入系统顶点坐标
//SV_POSITION  返回值是剪裁空间的顶点坐标

你将会遇到half(半精度)和double(双精度)类型,half(一般16bit)即正常float(一般32bit)的一半精度,double(一般64bit)是正常float的两倍精度(此处的倍数衡量的方式不是指表示的范围,而是表示可以使用的bit位数)。使用half经常是出于性能考虑的原因。还有一种区别于浮点数的定点数fixed,精度更低。

当你想将颜色值规范到0~1之间时,你可能会想到使用saturate函数(saturate(x)的作用是如果x取值小于0,则返回值为0。如果x取值大于1,则返回值为1。若x在0到1之间,则直接返回x的值.),当然saturate也可以使用变量的swizzled版本,比如saturate(somecolor.rgb);

使用结构体

Shader "Holo/03UseStruct"
{
    SubShader{
        Pass{

        CGPROGRAM
#pragma vertex vert
#pragma fragment frag

        struct a2v
        {
            float4 vertex:POSITION;  //把模型空间下的顶点坐标填充给vertex
            float4 normal:NORMAL;  //把模型空间下的法线方向填充给normal
            float4 texcoord :TEXCOORD0;  //把第一套纹理坐标填充给texcoord
        };

        //结构体的变量必须有语义定义
        struct v2f
        {
            float4 position:SV_POSITION;  //SV_POSITION语义告诉Unity,pos里包含了顶点在裁剪空间的位置信息
            float3 temp:COLOR0;
        };

        v2f vert(a2v v)  //返回值是v2f
        {
            v2f f;
            f.position = UnityObjectToClipPos(v.vertex);
            f.temp = v.normal;
            return f;
        }

        fixed4 frag(v2f f) :SV_Target  //将颜色显示在屏幕上,SV_Tagrget表示把输出的数据当作颜色存储到渲染目标中。
        {
            return fixed4(f.temp,1);
        }

        ENDCG
    }
    }
        Fallback "VertexLit"
}

语义集合

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

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

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

猜你喜欢

转载自blog.csdn.net/gsm958708323/article/details/80211877