精华内容
下载资源
问答
  • shaderlab开发实战 unity
    2019-11-24 20:44:13

    漫反射(Lambert)

    • Lum = C * max(0, cos(L, N))
      • Lum:漫反光亮度。
      • C:漫反光强度(漫反光颜色)。
      • L:入射光方向。
      • N:法线方向。

    镜面发射(Phong)

    • Lum = C * pow(max(0, cos(R, V)), gloss)
      • Lum:高光亮度。
      • C:高光强度(高光颜色)。
      • R:反射光方向。
      • V:视角方向。
      • gloss:镜面光滑程度。

    半角向量(BlinnPhong)

    • Lum = C * pow(max(0, cos(H, N)), gloss)
      • Lum:高光亮度。
      • C:高光强度(高光颜色)。
      • H:半角向量。
      • N:法线方向。
      • gloss:镜面光滑程度。

    Unity 内部的光照函数

    • Forward下的漫反射光照函数:
    inline fixed4 LightingLambert(SurfaceOutput s, fixed3 lightDir, fixed atten){
    	fixed diff = max(0, dot(s.Normal, lightDir));
    	fixed4 c;
    	c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);
    	c.a = s.Alpha;
    	return c;
    }
    
    • Forward下的高光函数:
    inline fixed4 LightingBlinnPhong(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten){
    	half3 h = normalize(lightDir + viewDir);
    	fixed diff = max(0, dot(s.Normal, lightDir));
    	float nh = max(0, dot(s.Normal, h));
    	float spec = pow(nh, s.Specular * 128.0) * s.Gloss;
    
    	fixed4 c;
    	c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
    	c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
    	return c;
    }
    
    更多相关内容
  • 非常非常详细的shaderlabl教程
  • Unity3d Shaderlab开发实战详解(第二版) 配套光盘 完整源码工程 Unity3d Shaderlab开发实战详解(第二版) 配套光盘 完整源码工程
  • Unity3d Shaderlab开发实战详解(第二版) 配套光盘\ShaderLab源程序 Unity3d Shaderlab开发实战详解(第二版) 配套光盘\ShaderLab源程序
  • Unity 3D ShaderLab开发实战详解 pdf扫描版[238MB] 附随书源码这是part1,一共有2部分,都下载后一起解压才能用
  • Unity 3D Shaderlab开发实战详解,Unity 3D Shaderlab开发实战详解 以及源代码
  • 最顶部是shaderlab编写的属性Properties,它在shaderlab中定义,它是着色器的输入或者外部控制面板可任意调节的参数,unity会自动根据shaderlab中定义的不同数据类型生成不同类型的UI界面。 第二个部分是Subshader...

    一、着色器如何工作

    假如要画一张由顶点组成的网格。第一步是先绘制顶点,即包含顶点信息的数据包一一发送到顶点着色器,这一步称为顶点输入。这些顶点信息包括顶点位置position、顶点法线normal、顶点颜色color等。之后顶点着色器会输出包含处理过的顶点信息的数据包,这一步称为顶点输出。此时数据包包括新顶点位置position和其他来自顶点着色器的信息。例如有一个由几个顶点组成的旗帜,现在将这些顶点一一传递给顶点着色器,顶点着色器可以让顶点基于sin函数移动顶点,从而得到一个挥动的旗帜,此时顶点着色器输出来新的位置信息。

    e4d9a5b26449d69ea52f89725754502a.png

    顶点着色器输出的数据包加入光栅化器Rasterizer。光栅化器是一个硬件,它将根据特定的规则找到屏幕上被几何图形覆盖的对应像素。光栅化器的第一个任务是找到几何区域中的像素,另一个任务是把顶点着色器给的数据进行插值,使数据得以进入像素着色器。例如,我们要在屏幕上画一个三角形,光栅化器要找到顶点组成的区域中找到那些被几何图元覆盖的像素,另外它还要对屏幕上的每一个片段或像素进行插值。如图提供了两个顶点法线(0,1,0)和(1,0,1),将他们进行插值计算取得两点连线中点的坐标(0.5,0.5,0)。接着,光栅化器会将数据给像素着色器,像素着色器会按照指令对每一个被光栅化器识别的像素进行着色,像素着色器会输出每个像素的颜色color、像素的透明度alpha,帮助像素在屏幕上最终的着色。

    b63ce5c95631e7ad323319453825fc04.png

    光栅化器是如果通过采样找到图元区域上对应的像素的? 每一个像素可以有一个或多个采样 ,如果采样的地方是被几何区域覆盖的,那这个mesh就会被特定的像素绘制上去。但是简单采样出来的三角区域的边缘是锯齿状的。这就有了后来的对像素的多采样,可以是同时采样2个像素、4个像素等,采样后根据是否被图元区域覆盖进行像素颜色计算随着多采样像素增多计算的代价也提高了。

    二、Unity中一个着色器的组成成分

    unity中写shader时包含两种语言:Shaderlab和Cg语言。unity中写shader的结构如下图,上下两个部分是shaderlab,中间是cg代码。shaderlab包含有为shader属性创建GUI,它设置了着色器的其他属性如对透明和不透明颜色进行混合的混合选项,它可以设置render passes渲染通道,它还可以设置FallBack硬件回退。cg语言是英伟达开发的着色语言,它让我们可以控制图形硬件,它让我们可以编写顶点和像素着色器。在unity中编程cg语言时,我们有两个编写着色器的选择,一个是unity提供的一种快速编写shader的surface shader,这是一种自动生成代码的方法,一个是限制较少的Vertex/Pixel shader的组合。

    97c1fc8472adf2aa6f37118b1a636613.png

    unity中写shader时包含7个组成部分。

    287587024c5ea55759a2bffc589a8ce2.png

    最顶部是shaderlab编写的属性Properties,它在shaderlab中定义,它是着色器的输入或者外部控制面板可任意调节的参数,unity会自动根据shaderlab中定义的不同数据类型生成不同类型的UI界面。

    1b64d717624e5453454d50cb55c76c12.png

    第二个部分是Subshader,它是着色器的子集。一个着色器可以包含多个子着色器,不同的子着色器可以支持不同的硬件功能。而这些硬件功能是指支持某些图形API的硬件,这些图形API有metal、OpenGL ES、OpenGL ES 3、XBOX 360等等。比如要让一个游戏能在多种硬件下运行,比如要在IOS设备上做一些特殊的功能,可以用metal图形API专为IOS设备写一个Subshader,而只有支持metal的设备才会运行这个Subshader。如果一个shader中有几个Subshader,unity会选择能由硬件支持的第一个Subshader来执行顶点和像素着色器;而如果硬件都不支持这几个Subshader,unity会选择作为备用选项的Fallback退回到默认的着色器,这些默认的着色器可以保证在任何硬件上运行。

    第三个部分是Pass,一个Subshader可以有多个渲染通道Pass。不同的渲染通道有如occlusion pass遮蔽、lighting pass灯光、beauty pass。这些渲染通道会选择一个着色器就渲染一次到几何Geometry或网格Mesh上,比如着色器应用到一个三角形上,每个pass会渲染一次这个三角形。这就是为什么运行一次pass就是一个draw call,所以要尽量只写在一个pass里。

    第四部分是pass中要提供的输入顶点着色器的顶点数据信息的结构体;第五部分是顶点着色器代码;第六部分是输入像素着色器的顶点输出数据信息结构体;第七部分是最后输出颜色和透明度的像素着色器代码。

    6a73d34bec5c1c4461d43ada29a8dcf0.png

    三、unity中编写一个最基础的shader

    HLSL/CG语法参考链接:

    https://docs.unity3d.com/Manual/SL-ShaderPrograms.html​docs.unity3d.com Semantics - Win32 apps​docs.microsoft.com
    30ff3f82d92dece59daca8b30c32fbef.png

    unity中最基础的shader,EG:

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    展开全文
  • ShaderLab开发实战详解中的代码升级到的Unity5,在Unity5.3.5f1中亲测,运行完美
  • Unity3D ShaderLab开发实战详解》源代码
  • Unity3d Shaderlab开发实战详解 源码工程 直接下载,学去吧
  • 《untiy3d ShaderLab实战详解》pdf电子版书籍,还有源程序
  • Unity 3D ShaderLab开发实战详解 pdf扫描版[238MB] 附随书源码这是part2,一共有2部分,都下载后一起解压才能用
  • Unity 3D ShaderLab开发实战详解》全面讲解了Unity Shader渲染的实战技术,全书分为五篇共33章,主要内容为:Shader在3D游戏中的作用、Shader的实例化、Shader的实现语言等;Unity中Shader的形态、SubShader的重要...
  • Unity ShaderLab开发实战(四)描边

    千次阅读 2018-12-10 17:25:17
    (以下效果图来自Unity3D ShaderLab开发实战详解)  原理:这是一个最简单的描边,使用面剔除:Cull指令,上图中 ,最左边的球使用的是Cull Front, 中间的使用Cull Back。最右边的球第一个Pass使用了Cull Front...

          之前可能在面剔除中提到过,面剔除可以用来实现描边效果。(以下效果图来自Unity3D ShaderLab开发实战详解)

           原理:这是一个最简单的描边,使用面剔除:Cull指令,上图中 ,最左边的球使用的是Cull Front, 中间的使用Cull Back。最右边的球第一个Pass使用了Cull Front并且将球体沿法线挤出一点点,第二个Pass使用Cull Back正常渲染,从而产生了描边效果。下面开始讲一下各种描边。

    1.最简单的方式,一个pass讲物体沿法线挤出,形成轮廓。

    效果:

    代码:

    Shader "Tut/Shader/Toon/Outline_1" {
        Properties {
            _Outline("Outline",range(0,0.2))=0.02
        }
        SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Off
            ZWrite Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {
                v2f o;
                v.vertex.xyz+=v.normal*_Outline;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=0;
                return c;
            }
            ENDCG
            }//end of pass
            pass{
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            float4 _LightColor0;
            struct v2f {
                float4 pos:SV_POSITION;
                float3 lightDir:TEXCOORD0;
                float3 viewDir:TEXCOORD1;
                float3 normal:TEXCOORD2;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.lightDir=ObjSpaceLightDir(v.vertex);
                o.viewDir=ObjSpaceViewDir(v.vertex);

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=1;
                float3 N=normalize(i.normal);
                float3 viewDir=normalize(i.viewDir);
                float diff=dot(N,i.lightDir);
                diff=(diff+1)/2;
                diff=smoothstep(diff/12,1,diff);
                c=_LightColor0*diff;
                return c;
            }
            ENDCG
            }
        } 
    }

           这个方法有两个问题:1.重叠物体区域没有描边,因为关闭了ZWrite,后面渲染的物体根据ZTest的结果将物体自己渲染输出写入,把轮廓擦掉了;2.轮廓的粗细和相机远近有关,距离越远,轮廓越细;3.有些地方轮廓是间断的,比如上图中cube,相邻两个面的法线方向是分离的,再沿法线挤出去后当然就被分开了。

    2.先解决第一和第二个问题,打开ZWrite,第一个问题就解决了,第二个问题我们希望最终的输出是在屏幕上看到的那样挤出来,而不是模型上,不希望考虑镜头的远近,也就是在视空间下挤。

    效果:

    代码:

    Shader "Tut/Shader/Toon/Outline_1x" {
        Properties {
            _Outline("Out line",range(0,0.1))=0.02
        }
        SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Front
            ZWrite On
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
                float2 offset = TransformViewToProjection(norm.xy);
                //offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return 0;
            }
            ENDCG
            }//end of pass
            pass{
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float4 _LightColor0;
            sampler2D _MainTex;

            struct v2f {
                float4 pos:SV_POSITION;
                float3 lightDir:TEXCOORD0;
                float3 viewDir:TEXCOORD1;
                float3 normal:TEXCOORD2;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.lightDir=ObjSpaceLightDir(v.vertex);
                o.viewDir=ObjSpaceViewDir(v.vertex);

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=1;
                float3 N=normalize(i.normal);
                float3 viewDir=normalize(i.viewDir);
                float diff=dot(N,i.lightDir);
                diff=(diff+1)/2;
                diff=smoothstep(diff/12,1,diff);
                c=_LightColor0*diff;
                return c;
            }
            ENDCG
            }
        } 
    }
    3.接下来解决间断的问题:如果相邻的面法线方向不太一致,挤出来后的方向就会产生断裂。如果不把顶点数据当作位置,而当作是一个方向矢量,则不管它被多少面共享,这些共享顶点的方向是唯一的。这样交接处就不会因为往不同方向挤出而导致断裂了。

    效果:

    代码:

    Shader "Tut/Shader/Toon/Outline_2" {
        Properties {
            _Outline("Out line",range(0,0.1))=0.02
        }
        SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Front
            ZWrite On
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                float3 dir=normalize(v.vertex.xyz);
                dir   = mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                
                float2 offset = TransformViewToProjection(dir.xy);
                //offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return 0;
            }
            ENDCG
            }//end of pass
            pass{
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float4 _LightColor0;
            sampler2D _MainTex;

            struct v2f {
                float4 pos:SV_POSITION;
                float3 lightDir:TEXCOORD0;
                float3 viewDir:TEXCOORD1;
                float3 normal:TEXCOORD2;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.lightDir=ObjSpaceLightDir(v.vertex);
                o.viewDir=ObjSpaceViewDir(v.vertex);

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=1;
                float3 N=normalize(i.normal);
                float3 viewDir=normalize(i.viewDir);
                float diff=dot(N,i.lightDir);
                diff=(diff+1)/2;
                diff=smoothstep(diff/12,1,diff);
                c=_LightColor0*diff;
                return c;
            }
            ENDCG
            }
        } 
    }
    4.上面对第三个问题的解决方法还有点小问题,当物体的模型空间的原点不在几何中心时,就会出现某些地方沿顶点挤出的方向看不到,描边会很不均匀(下图),需要调和法线和顶点方向(其实就是顶点的方向和法线的方向相互拉一拉,靠拢一下)。

    解决方法,简单的,比如第一个Pass的顶点shader改为法线和顶点方向的调和:

    v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;
                return o;
            }

    也可以通用一些,试用于复杂图形。通过顶点方向和法线的点积为正或负来判断是指向几何中心还是背离几何中心,并且可以得到指向或背离的程度。

    效果:

    代码:

    Shader "Tut/Shader/Toon/Outline_3x" {
        Properties {
            _Outline("Out line",range(0,0.1))=0.02
            _Factor("Factor",range(1,100))=1
        }
        SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Front
            ZWrite On
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            float _Factor;
            struct v2f {
                float4 pos:SV_POSITION;
            };
            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                float D=dot(dir,dir2);
                D=(D/_Factor+1)/(1+1/_Factor);
                dir=lerp(dir2,dir,D);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return 0;
            }
            ENDCG
            }//end of pass
            pass{
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float4 _LightColor0;

            struct v2f {
                float4 pos:SV_POSITION;
                float3 lightDir:TEXCOORD0;
                float3 viewDir:TEXCOORD1;
                float3 normal:TEXCOORD2;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
                o.normal=v.normal;
                o.lightDir=ObjSpaceLightDir(v.vertex);
                o.viewDir=ObjSpaceViewDir(v.vertex);
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=1;
                float3 N=normalize(i.normal);
                float3 viewDir=normalize(i.viewDir);
                float diff=max(0,dot(N,i.lightDir));
                diff=(diff+1)/2;
                diff=smoothstep(0,1,diff);
                c=_LightColor0*diff;
                return c;
            }
            ENDCG
            }
        } 
    }
    5.上面的方法导致出现一个新问题,cube中间的棱没描出来,解决方法:可以使用两个Pass中和,第一个Pass沿法线方向挤出,这个时候有裂痕了,第二个Pass在裂痕的基础上更多的向顶点方向挤出,这样就在裂痕处形成描边。

    SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Back
            ZWrite On
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            float _Factor;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return float4(1,1,1,1);
            }
            ENDCG
            }//end of pass .1
            pass{
            Tags{"LightMode"="Always"}
            Cull Front
            ZWrite Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline2;
            float _Factor2;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {//.2
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor2);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline2;
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return float4(0,0,0,0);
            }
            ENDCG
            }//end of pass .2
        } 

        _Factor2在第一个系数_Factor的结果上来调整描边。但是现在还缺少一个光照上色的Pass,所以使用混合,最终效果(自行调整参数):

    代码:

    Shader "Tut/Shader/Toon/Outline_4.1" {
        Properties {
            _Outline("Out line",range(0,0.1))=0.02
            _Outline2("Out line2",range(0,0.1))=0.02
            _Factor("Factor",range(0,1))=0.5
            _Factor2("Factor",range(0,1))=0.5
        }
        SubShader {
            pass{
            Tags{"LightMode"="Always"}
            Cull Back
            ZWrite On
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline;
            float _Factor;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return float4(1,1,1,1);
            }
            ENDCG
            }//end of pass .1
            pass{
            Tags{"LightMode"="Always"}
            Cull Front
            ZWrite Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            float _Outline2;
            float _Factor2;
            struct v2f {
                float4 pos:SV_POSITION;
            };

            v2f vert (appdata_full v) {//.2
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor2);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline2;
                return o;
            }
            float4 frag(v2f i):COLOR
            {
                return float4(0,0,0,0);
            }
            ENDCG
            }//end of pass .2
            pass{
            Tags{"LightMode"="ForwardBase"}
            Blend DstColor Zero
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            float4 _LightColor0;
            sampler2D _MainTex;
            float _Factor;
            float _Outline;

            struct v2f {
                float4 pos:SV_POSITION;
                float3 lightDir:TEXCOORD0;
                float3 viewDir:TEXCOORD1;
                float3 normal:TEXCOORD2;
            };

            v2f vert (appdata_full v) {
                v2f o;
                o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                float3 dir=normalize(v.vertex.xyz);
                float3 dir2=v.normal;
                dir=lerp(dir,dir2,_Factor);
                dir= mul ((float3x3)UNITY_MATRIX_IT_MV, dir);
                float2 offset = TransformViewToProjection(dir.xy);
                offset=normalize(offset);
                o.pos.xy += offset * o.pos.z *_Outline;

                o.normal=v.normal;
                o.lightDir=ObjSpaceLightDir(v.vertex);
                o.viewDir=ObjSpaceViewDir(v.vertex);

                return o;
            }
            float4 frag(v2f i):COLOR
            {
                float4 c=1;
                float3 N=normalize(i.normal);
                float3 viewDir=normalize(i.viewDir);
                float diff=max(0,dot(N,i.lightDir));
                diff=(diff+1)/2;
                diff=smoothstep(0,1,diff);
                c=_LightColor0*diff;
                return c;
            }
            ENDCG
            }
        } 
    }

    补充:通过视线和法线的夹角来判定是否是物体边缘进行描边不稳定,这个方法常用于Rim效果,下节讲Rim。

    展开全文
  • VertexLMRGBM(已弃用):顶点光照,可以获得unity_Lightmap处理光照贴图(用于PC)。 VertexLM:顶点光照,可以获得unity_Lightmap处理光照贴图(用于移动设备)。 PassFlags: RequireOptions: ...

    Shader结构

    Shader "Tut/NewBie/FirstShader"{
    	Properties{
    		//[可选的特性]用来控制在编辑器上如何显示,可写可不写。
    		//2D纹理,默认值为""、"white"、"back"、"gray"、"bump"、"red"。
    		[可选的特性] _MyTex2D("Tex2D Value", 2D) = "white"{}
    		
    		_MyTex3D("Tex3D Value", 3D) = "white"{}//3D纹理
    		_MyCube("Cube Value", Cube) = "white"{}//Cube纹理
    		_MyColor("Color Value", Color) = (1,1,1,1)
    		_MyVertor("Vector Value", vector) = (1,1,1,1)
    		_MyInt("Int Value", int) = 1
    		_MyFloat("Float Value", float) = 1
    		_MyRange("Range Value", range(0,1) = 1
    	}
    	SubShader{
    		Tags{"Queue"="Background" "RenderType"="Opaque"}
    		
    		Pass{
    			//定义名字(必须大写),可以在其它Pass中用UsePass "路径/Pass名字"引用。
    			Name "MYPASS"
    			
    			[Pass Tags]
    			[RenderSetup]
    			
    			//使用之前要先声明一下。
    			sampler2D _MyTex2D;
    			sampler3D _MyTex3D;
    			samplerCUBE _MyCube;
    			
    			float4 _MyColor;
    			float4 _MyVector;
    			
    			float _MyFloat;
    			float _MyRange;
    		}
    	}
    	SubShader{
    		...
    	}
    	FallBack "Diffuse"
    }
    
    • [可选的特性]:用来控制在编辑器上如何显示,可写可不写。
      • [HideInInspector]:不在编辑器中显示.
      • [NoScaleOffset]:不在编辑器中显示纹理的tiling/offset编辑项。
      • [Normal]:这个纹理是一个法线纹理。
      • [HDR]:这个纹理是一个(HDR) 纹理.
      • [Gamma]:在编辑器界面中将float/vector属性指定为sRGB值。
      • [PerRendererData]:纹理属性将以MaterialPropertyBlock的形式传入着色器。
    • [RenderSetup]:
      • Cull Back | Front | Off
      • ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
      • ZWrite On | Off
      • Offset 因子, 单位(偏移 = m * 因子 + r * 单位)
        • m:多边形的最大深度斜率(z变化 / x变化和y变化中最小的)。
        • r:是个常量(具体依赖特定实现)。
      • Blend :
        • Blend Off:不混合。
        • Blend src dst:(源颜色 * src) + (目标颜色 * dst),值为zero、one、SrcColor、SrcAlpha、DstColor、DstAlpha、OneMinusSrcColor、OneMinusSrcAlpha、OneMinusDstColor、OneMinusSrcAlpha。
        • BlendOp colorOp:colorOp为Add、Min、Max、Sub。
        • BlendOp colorOp, alphaOp
        • AlphaToMask On | Off
      • ColorMask RGB | A | 0 | R, G, B, A的任意组合
    • SubShader Tags:SubShader里的Tags(不是Pass中的Tags)。
      • Queue:渲染顺序,值为Background、Geometry、AlphaTest、Transparent、Overlay、具体数字。
      • RenderType:渲染类型,值为Opaque、Transparent、自定义字符串,经常用于渲染替换。
      • DisableBatching:是否禁用批处理。True、False、LODFading,
      • ForceNoShadowCasting:
      • IgnoreProjector:忽略投影,值为True、False。
      • CanUseSpriteAtlas:
      • PreviewType:编辑器如何显示材质,值为Sphere、Plane、Skybox。
    • Pass Tags:Pass里的Tags。
      • LightMode:灯光模式。
        • Always:
        • ForwardBase:前向渲染,用于环境光、主平行光、球谐光、光照贴图。
        • ForwardAdd:前向渲染,附加的每个像素光照执行一次。
        • Deferred:延迟渲染,渲染到GBuffer中。
        • ShadowCaster:渲染物体深度到深度或者阴影贴图中。
        • MotionVectors:用来计算每个物体的移动向量。
        • PrepassBase:用于老的延迟渲染,渲染法线和高光指数。
        • PrepassFinal:用于老的延迟渲染,渲染最终的颜色,光照和发光。
        • Vertex:顶点光照,如果物体没有光照贴图,将启用所用的顶点光。
        • VertexLMRGBM(已弃用):顶点光照,可以获得unity_Lightmap处理光照贴图(用于PC)。
        • VertexLM:顶点光照,可以获得unity_Lightmap处理光照贴图(用于移动设备)。
      • PassFlags:
      • RequireOptions:
    • FallBack "Diffuse":如果没有找到适合的SubShader,就用“Diffuse”默认是Shader实现。
    • Shader语言:
      • GLSL:在GLSLPROGRAM和ENDGLSL之间写GLSL代码。
      • CG:在CGPROGRAM和ENDCG之间写CG代码。

    ShaderLab

    • ShaderLab:如果想写一个支持照明、阴影等功能的Shader,可以直接写Surface Shader,它已经为我们封装好了所有的复杂性。
    Shader "Tul/NewBie/SurfShader"{
    	SubShader{
    		Tags{"RenderType"="Opaque"}
    		LOD 200
    		
    		CGPROGRAM
    		#pragma surface surf Lambert
    		sampler2D _MainText;
    		struct Input{
    			float2 uv_MainTex;
    		}
    		vodi surf(Input IN, inout SurfaceOutput o){
    			half4 c = tex2D(_MainTex, IN.uv_MainTex);
    			o.Albedo= c.rgb;
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }
    
    struct SurfaceOutput{
    	half3 Albedo;
    	half3 Normal;
    	half3 Emission;
    	half Specular;
    	half Gloss;
    	half Alpha;
    }
    

    在C#中向Material传递数据

    • 向Shader的Properties中传递数据:
      • Material.SetTexture("_MyTexture", MyTexture);
      • Material.SetTexture("_MyCube", MyCube);
      • Material.SetColor("_MyColor", MyColor);
      • Material.SetVector("_MyVector", MyVector);
      • Material.SetFloat("_MyFloat", MyFloat);
      • Material.SetFloat("_MyRange", MyRange);
    • 矩阵的传递:
      • 矩阵不能在Properties中定义。
      • 在Shader中定义uniform float4x4 m;
      • 在C#中赋值Material.SetMatrix(“m”, mat);

    未完待续…

    展开全文
  • 渲染路径决定了光照如何...Unity--Edit--Project Setting--Player--Other Setting--Rendering Path里可以设置,也可以在相机的渲染路径设置中覆盖Project Setting中的设置。三种(前向渲染路径(Forward Rendering...
  • 从本博客开始,本人主要是通过《Unity3D ShaderLab开发实战讲解》这本书,同读者学习和分享Unity3D中Shader编程的相关知识。 本文首先介绍下《Unity3D ShaderLab开发实战讲解》这本书的内容和简介。 说句题外...
  • Shader中3种光源变量 第一种: ...float4 unity_4LightPos{X/Y/Z}0:四个点光源位置(世界空间)。 float4 unity_4LightAtten0:4个光源的衰减。 float4 unity_LightColor[4]:4个光源的颜色。 ...
  • "UnityCG.cginc" #include "Lighting.cginc" # pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON //开启LIGHTMAP_OFF LIGHTMAP_ON这两个宏。 struct vertOut { float4 pos : SV_POSITION ; ...
  • 不过这里我为了更好的管理项目我把 router分离开来了,放在一个单独的router文件夹进行管理了,前面我已经对vue如何配置路由已经做了详解,大家可以参考:vue实战开发007:vue引入Element-UI并配置路由 ,这里是按照...
  •  最终结果,如果上述值为全局设为600,特定shader的设为800时,那么Unity所有的Shader(除设置了LOD为800的shader)中LOD为600的SubShader,特定shader的设为800时,选用了LOD为800的SubShader。 测试代码: ...
  • "unitycG.cginc" struct v2f { float4 pos : SV_POSITION ; float2 depth : TEXCOORD0 ; } ; v2f vert ( appdata_base v ) { v2f o ; o . pos = mul ( UNITY_MATRIX_MVP , v . ...
  • 知名汽车厂商BMW近几年来一直在借助Unity引擎的实时渲染技术引领行业创新,将Unity引入到了汽车生命周期的各个环节中,无论是用AR、VR来优化生产流程,还是突破性的沉浸式汽车营销案例,都在拓展技术的应用边界,让...
  •  fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _Diffuse.xyz;  //归一化法线,即使在vert归一化也不行,从vert到frag阶段有差值处理,传入的法线方向并不是vertex shader直接传出的  fixed3 worldNormal =...
  • //UNITY_MATRIX_IT_MV是用来专门变换normal的 float2 offset = TransformViewToProjection ( norm . xy ) ; o . pos . xy + = offset * o . pos . z * _Outline ; //乘以o.pos.z是为了抵消透视除法...
  • Unity3d ShaderLab开发实战详解的读书笔记>>,作者郭浩瑜,人民邮电出版社,在这里感谢作者。  Unity使用自定义shaderLab来组织shader的内容。  SubShader:之所以用subshader,是为了能让开发者...
  • UNITY_MATRIX_MVP , v . vertex ) ; o . color . rgb = ShadeSH9 ( half4 ( worldN , 1 ) ) ; o . color . a = 1 ; return o ; } float4 frag ( vertOut i ) : COLOR { ...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 208
精华内容 83
关键字:

shaderlab开发实战 unity