zoukankan      html  css  js  c++  java
  • U3D Shader 表面[Surface]着色器

    表面着色器简介:

           在使用Surface Shader时,它可以自动生成一些代码,比直接去使用低阶的顶点和像素着色器来说要容易的多。但是需要注意的是Surface Shader并不是一种定制的语言,也不是一种神奇的东西,它只不过是自动生成了以前必须去手写的代码。Surface Shader 还是使用CG或HLSL语言编写 Surface Shader实际上就是对定点和像素着色器一种包装,它让我们不用去关注更多的顶点和片段程序的细节,能够快速的得到想要的着色器。

    基本属性:

      _Color为颜色值

      _MainTex是主纹理

      _Glossiness 是一个浮点值,用于计算高光的光泽度。

      _Metallic 也是一个浮点值,用于计算表现金属的关泽度。

           表面着色器,在该shader中有一个SubShader【子着色器】,在这个子着色器中没有Pass通道。因为SurfaceShader是对顶点或片段着色器的一种包装,能够自动生成着色器代码,生成过程中不需要任何干预,Pass也会自己生成。如果手动的添加一个Pass反而会报错。当然该shader后面也有 FallBack

    stuct SurfaceOutput
    {
    fixed3 Albedo;
    fixed3 Normal;
    fixed3 Emission;
    half Specular;
    fixed Gloss;
    fixed Alpha;
    }
    struct SurfaceOUtputStandard
    {
    fixed3 Albedo;
    fixed3 Normal;
    half3 Emisson;
    half Metallic;
    half Smoothness;
    half Occlusion;
    fixed Alpha;
    }
    //表面着色器
    Shader "CustomLearn/First_Surface"
    {
        Properties{
            _Color("Color",color)=(1,1,1,1)
            //2D、Rect、Cube这三种都是对于贴图来说的,其初始值可以是代表Tint
            //颜色的字符串来表示,其值也可以为空,可填写的类型有:white,black
            //,gray,bump(凹凸),对于后面的大括号表示打开当前图片的特殊设置,这
            //些设置可以是:ObjectLinear、SphereMap、CubeNomal等,这些值可以省略
            _MainTex("Albedo(RGB)",2D)="white"{}
            _Glossiness("Smoothness",Range(0,1))=0.5
            _Metallic("Metallic",Range(0,1))=0
        }
        SubShader{
            //表面着色器中,可以对若干个标签所修饰,而硬件就会根据这些标签决定什么时候来调用这些着色器
            //1、"RenderType"="Opaque":表示渲染不透明物体是调用
            //2、"RenderType"="Transparent":表示渲染不透明物体时,或者粒子特效时,使用这个
            //3、"RenderType"="Background":表示天空盒和背景时使用这个
            //4、"RenderType"="Overlay":表示渲染叠加效果,比如镜头光晕
            Tags{"RenderType"="Opaque"}
            //LOD时Level Of Detail的缩写,我们能够使用什么类型的shader,是需要
            //它来决定,如果我们在Unity中设置了LOD的最大值,当小于SubShader中所指
            //定放入LOD值时,则这个SubShader就不可用
            //在Unity内部的shader中,制定了一种LOD值,我们在编写shader时,可以将
            //这些值作为参考,这样以后根据设备图形性能调整画质时,就可以进行比较精准
            //的控制,形同提供的LOD值:
            //VertexLit=100(顶点光照)及其系列
            //Reflective Vertex Lit(反射顶点光照)=150
            //Diffuse(漫反射光照)=200
            //Diffuse Detail(漫反射细节)、Reflective Bumped VertexLit = 250
            //Bumped、Specular(凹凸高光)=400
            //Parallax(视差、更加逼近)= 500
            //Parallax Specular(视差高光)=600
            LOD 200
            //表面着色器实现代码需要放在CGPROGRAM...ENDCG之间,而不是放在Pass通道中
            //CG: C for Graphics是计算机图形编程语言,是C的超集,CG程序可以根据运行时
            //的需要实现编译成GPU汇编代码
            CGPROGRAM
            //下面是一条编译指令,他声明了我们要写的一个表面着色器,并且指定了光照模型
            //它的语法格式为:
            //#pragma surface surfaceFuctionName lightModel [optional params]
            //surface:表示声明表面着色器
            //surfaceFuctionName:着色器中处理渲染的函数名字
            //lightModel:使用的光照模型,Lambert表示普通的diffuse光照模型
            //optional params:表示可选参数,是可设置包括透明度、顶点与颜色的
            //函数、投影等相关的一些配置
            #pragma surface surf Standard fullforwardshadows
            //表示使用Shader3.0版本
            #pragma target 3.0
    
            //我们在使用shader文件时,所实例化的shader是由两个独立的模块组成,属性声明和
            //回调都是Unity可直接使用或编译的shader语法而在CG代码块中,想要访问Properties
            //中的所定义的变量,必须声明和属性名字相同的变量来进行使用,这里的sampler2D _MainTex
            //是和Properties中声明的2D类型的_MainTex关联,之后的CG程序使用的都是变量
            sampler2D _MainTex;
    
            //输入结构体,float2和Vector2一样,里面可以存放两个float类型的数据,这里定义的
            //变量包含的两个数据可以使用 变量名.x 的方式得到某个值,在CG程序中约定一个贴图的变量
            //名前加uv_,就表示提取这个贴图的uv值(uv值表示两个代表贴图上的二维坐标点),后续
            //的CG代码中就可以通过这个变量名获取图片上的坐标值
            struct Input{
                //输入结构体中一般会包含着色器所需要的纹理坐标,为例坐标命名为uv+纹理名
                //其他成员:float3 viewDir:表示视角的方向
                //    float4 COLOR:表示每个顶点的颜色差值
                //    float3 worldPos:表示世界坐标
                //    float3 screenPOS:表示屏幕坐标
                //    float3 worldRef:表示坐标系中的发射向量
                //    float3 worldNormal:世界坐标系中的法线向量
                float2 uv_MainTex;
            };
            //half:浮点类型,表示半精度浮点,精度最低,但是运算的性能比高精度的浮现类型要高一些
            //在GPU编程中大量使用
            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
    
            //CG规定了表面着色器代码的方法的参数类型和语法结构
            //语法格式:surf(Input IN,inout SurfaceOutputStandard o)
            //作用是将其接收到的uv坐标挥着附加数据进行处理,最后将结果填充到输出的结构体中。
            //第一个参数:Input是我们要定义的输入结构体,可以把所需要的参与计算的数据都放到
            //这个结构体中,传入方法使用
            //第二个参数:定义输出的结构体的类型,需要把方法里得到的结构赋值给该结构体里面的
            //成员变量
            //SurfaceOutputStandard:标准输出结构定义如下:
            //1、fixed3 Albedo:基础颜色
            //2、fixed3 Normal:切线空间法线
            //3、half Metallic:表示是否有金属特性:0--非金属,1--金属
            //4、half Smoothness:是否光滑:0--粗糙,1--光滑
            //5、half Occlusion :遮挡(默认)
            //6、fixed Alpha :透明度
    
            //SurfaceOutput:的输出结构体定义如下:
            //1、half3 Albedo:像素的颜色
            //2、half3 Normal:像素的法向向量值
            //3、half3 Emission:像素的发散颜色
            //4、half Specular:像素的镜面高光
            //5、half Alpha:像素的透明度
            void surf(Input IN,inout SurfaceOutputStandard o){
            //tex2D方法是CG程序里面的用来在一张贴图上对某一个点进行采样的方法,
            //返回一个fixed4 类型的值
                fixed4 c=tex2D(_MainTex,IN.uv_MainTex)*_Color;
                //获取基础颜色值
                o.Albedo=c.rgb;
                //金属含量
                o.Metallic=_Metallic;
                //平滑值
                o.Smoothness=_Glossiness;
                //设置透明度
                o.Alpha=c.a;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

    案例1:

    效果图:

     

    //法线贴图案例,为了解决模型不能有一些凹凸之类的细节表现问题
    Shader "CustomLearn/Fourth_Bump" 
    {
        //属性值
        Properties{
            //普通纹理属性
            _MainTex("Texture",2D)="white"{}
            //法线纹理属性
            _BumpMap("BumpMap",2D)="bump"{}
        }
        //子着色器
        SubShader{
            //渲染非透明物体
            Tags{"RenderType"="Opaque"}
            //CG代码块
            CGPROGRAM
            //指定着色器处理函数以及光照模型
            #pragma surface surf Lambert
            //参与计算的结构体
            struct Input{
                //普通图片uv坐标
                float2 uv_MainTex;
                //法线贴图uv坐标
                float2 uv_BumpMap;
            };
            //在CG中获取属性中的两张图片
            sampler2D _MainTex;
            sampler2D _BumpMap;
    
            void surf(Input IN,inout SurfaceOutput o)
            {
                //采样获取普通纹理上的像素点的颜色值
                o.Albedo=tex2D(_MainTex,IN.uv_MainTex).rgb;
                //在计算法线时,需要根据采样获取到法先贴图的像素点信息,传递给UnpackNormal
                //函数即可,这个函数可以实现区间的重新映射,或者说UnpackNormal函数是对法线纹理进行采样的方法
                o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap));
            }
    
            ENDCG
        }
        FallBack "Diffuse"
    }

    案例二:渲染数带有自转效果的球

     

    Shader "CustomLearn/Fifth_Bubble" {
        //属性
        Properties{
            _MainTex("Albedo(RGB)",2D)="white"{}
            _Color("Color",color)=(0,0,0,0)
            _Alpha("Alpha",Range(0,1))=0.5
            //设置水平速度
            _SpeedX("X_Speed",Range(0.5,10))=0.6
            //设置垂直速度
            _SpeedY("Y_Speed",Range(0.5,10))=0.6
            }
    
        SubShader{
            Tags{"RenderType"="Transparent"}
            //CG代码块儿
            CGPROGRAM
            //alpha表示透明兰伯特(Diffuse)光照模型
            #pragma surface surf Lambert alpha
            //在CG代码中声明属性中对应的各个属性
            sampler2D _MainTex;
            fixed _Alpha;
            fixed _SpeedX;
            fixed _SpeedY;
            fixed4 _Color;
            //声明输入纹理结构体
            struct Input{
                float2 uv_MainTex;
            };
    
            //实现surf函数
            void surf(Input IN,inout SurfaceOutput o)
            {
                //速度
                fixed xSpeed=_SpeedX*_Time*0.1;
                fixed ySpeed=_SpeedY*_Time*0.1;
                //获取uv坐标
                fixed2 uv=IN.uv_MainTex-fixed2(xSpeed,ySpeed);
                //获取采样信息
                fixed4 c=tex2D(_MainTex,uv) * _Color;
                //
                o.Albedo= c.rgb;
                o.Alpha=_Color.a*c.a*_Alpha;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

         

  • 相关阅读:
    Java之多线程(实现Runnable接口)
    Java之使用HttpClient发送GET请求
    hbase中文内容编码转换
    Java之utf8中文编码转换
    Java之正则表达式
    Java之List排序功能举例
    maven测试时中文乱码问题解决方法
    Hbase之IP变更后无法启动问题解决
    Hbase远程连接:Can't get the locations
    重启Hbase命令
  • 原文地址:https://www.cnblogs.com/zpy1993-09/p/13180584.html
Copyright © 2011-2022 走看看