精华内容
下载资源
问答
  • 渲染路径(Rendering Path) 决定了光照如何应用到Unity Shader中的。 很关键的就是光照, 光源可能很多,在shader中如何处理这些光源信息。
    渲染路径(Rendering Path) 决定了光照是如何应用到Unity Shader中的。 很关键的就是光照, 光源可能很多,在shader中如何处理这些光源信息。  
    
    展开全文
  • 在前置中已经了解了什么是表面着色器,下面这Standard Surface Shader,也创建 Shader 时的默认代码之一 Shader "Custom/NewSurfaceShader" { Properties { _Color("Color", Color) = (1,1,1,1) _MainTex...

     

    前置:UnityShader2:Shader与材质

    一、Standard Surface Shader 代码解析

    在前置中已经了解了什么是表面着色器,下面这是 Standard Surface Shader,也是创建 Shader 时的默认代码之一

    Shader "Custom/NewSurfaceShader"
    {
        Properties
        {
            _Color("Color", Color) = (1,1,1,1)
            _MainTex("Albedo (RGB)", 2D) = "white" {}
            _Glossiness("Smoothness", Range(0,1)) = 0.5
            _Metallic("Metallic", Range(0,1)) = 0.0
        }
        SubShader
        {
            Tags { "RenderType" = "Opaque" }
            LOD 200
    
            CGPROGRAM
            #pragma surface surf Standard fullforwardshadows
            #pragma target 3.0
    
            sampler2D _MainTex;
            struct Input
            {
                float2 uv_MainTex;
            };
            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
    
            UNITY_INSTANCING_BUFFER_START(Props)
            UNITY_INSTANCING_BUFFER_END(Props)
    
            void surf (Input IN, inout SurfaceOutputStandard o)
            {
                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"
    }
    

    直接一行一行注释(对于紫色的内容,可以暂时不用去详细了解):

    • Tags { "RenderType" = "Opaque" }:这个在 UnityShader3:ShaderLab 这一章中有过讲解,声明为不透明着色器
    • LOD 200:设置当前着色器的 LOD(Shader Level of Detail) 值,只有其小于 Shader.globalMaximumLOD 全局最大细节级别时这个 SubShader 才会被执行,注意这个和模型 LOD 不是一个东西
    • CGPROGRAM  ……  CGEND:在这两句声明之间的代码是着色器语言的主要部分,并且是用 CG(C for Graphics) 编写的,CG 和 GLSL 一样,是一种着色器语言
    • #pargma 关键词 函数名 光照模型 [其它选项]:编译指令声明,代码中的含义为:表明当前为表面着色器、函数名为 surf、使用 Standard 基于物理系统的光照模式、有一个完整的向前的阴影
    • #pragma target 3.0:设置着色器模型等级,越高支持的功能越多,可以参考文档
    • sampler2D:对应二维纹理,在 Properties 中为 2D 属性
    • half:描述的是一个16位浮点数,同理 float 为32位浮点数
    • fixed4:对应4维颜色属性,同理 half4 就是4个 float 属性组成的4维向量
    • struct Input { float2 uv_MainTex; }:输入结构体用于模述 UV 的坐标,里面的 float2 变量必须以 uv_开头,后面的 _MainTex 自动对应 Properties 中的 _MainTex,理论上这个结构体里还可以有其它成员,不过目前只需要关心纹理坐标
    • UNITY_INSTANCING_BUFFER_START:用于批量渲染,减少 DrawCall 次数,超纲了,可以先去了解下 OpenGL 的实例化操作:《OpenGL基础42:实例化》

    void surf (Input IN, inout SurfaceOutputStandard o) {}:第一个参数 Input IN 就是前面定义的 Input 结构体,第二个参数用了 inout 声明,这表示这个参数既是输入的也是输出的,这个 surf 函数虽然没有返回值,但是它的第二个参数是有输出功能

    从上述程序中可以看出:表面着色器被定义在 SubShader 语义块中的 CGPROGRAM 和 ENDCG 之间,并且没有 Pass 语义块,这是因为表面着色器不需要开发者关心使用了多少个 Pass、每个 Pass 如何渲染等问题,Unity 会在背后为我们做好这些事情,我们要做的只是告诉它使用哪些纹理去填充颜色,如何填充法线,使用哪种光照模型等

    上面的代码对应的预览效果(无纹理):

     

    二、固定函数着色器

    固定渲染管线已经过时了,没有必要去学习/关心,但也可以在这一章顺便提一下

    一个非常简单的固定函数着色器例子如下:

    Shader "Tutorial/Basic" {
        Properties { 
            _Color("Main Color", Color) = (1,0.5,0.5,1)
        }
        SubShader {
            Pass { 
                Material {
                    Diffuse [_Color] 
                } 
                Lighting On
            }
        }
    }

    关于固定函数着色器可以了解的是:

    1. 固定函数着色器需要完全按照 ShaderLab 的语法,而非使用 CG/HLSL
    2. 在 Unity 5.2 以后的版本中,固定函数着色器也会被 Unity 编译成对应的顶点/片元着色器,因此真正意义上的固定函数着色器已经不存在了
    3. 部分旧设备只支持固定管线,这样就只能用固定函数着色器了,当然一般抛弃这些平台是最好的选择

     

    三、扩展

    UnityShader形式有三种,前面主要提到了表面着色器和固定函数着色器,然而事实上,最常用的还是顶点/片元着色器,可以自己实现一些五花八门的渲染效果,只不过关于顶点片元着色器,需要了解的东西不少,这篇就暂时不讲了

    传统的 Shader 和 UnityShader 的区别有:

    • UnityShader 可以在一个文件里同时包含需要的顶点着色器和片元着色器代码,而传统着色器需要一一对应
    • UnityShader 处理输入和输出非常的简单/方便,只需要在特定语句块中声明一些属性就可以依靠材质来方便地改变它们,而对于模型自带的数据:如顶点位置、纹理坐标、法线等, UnityShader 也提供了直接访问的方法
    • UnityShader 只需要通过一行特定的指令即可以完成一些渲染设置,例如是否开启混合、深度测试等,而对于传统 Shader 开发者需要自行在外环境设置
    • UnityShader 对曲面细分着色器(Tessellation Shader)、几何着色器(Geometry Shader)不能够很好的支持

    关于 CG/HLSL 和 GLSL:

    对于上面的表面着色器,是通过在 ShaderLab 内部嵌套 CG/HLSL 语言来编写这些着色器代码的,由于 CG 和 DX9 风格的 HLSL 从写法上来说几乎是同一种语言,因此在 Unity 里 CG 和 HLSL 等价

    当然也可以用 GLSL 来写,不过这样对于PC、Xbox 360这些的仅支持DirectX的平台来说,就不能正常的运行了

    本文[系列]参考于:UnityShader入门摘要

    其它参考资料:https://docs.unity3d.com/Manual/SL-Reference.html

    https://docs.unity3d.com/Manual/ShaderTut1.html

     

    展开全文
  • 我们刚开始接触Unity的时候,总是会遇到材质,但是不了解材质都是什么,为什么可以在很多材质中选择,为什么有时候选择了其他材质后就不能达到我们想要的结果,为什么资源商店有那么多的材质,山.

    在这里插入图片描述

    前言

    众所周知,要想当游戏开发工程师,Unity中的Shader编写不得不摸,这一系列文章我将描写我的Shader学习之路,致敬冯乐乐的书Unity Shader入门精要,此篇什么是Unity Shader?希望能给后人一点方向
    我们刚开始接触Unity的时候,总是会遇到材质,但是不了解材质都是什么,为什么可以在很多材质中选择,为什么有时候选择了其他材质后就不能达到我们想要的结果,为什么资源商店有那么多的材质,山川湖地,我们可以自己写材质吗,那么这篇正好可以讲明白材质是什么,和我的系列要说的UnityShader的关系,话不多说,进入正题-----

    什么是UnityShader

    对于计算机中的每一个物体,比如一个模型,想要让他显示出来,需要很多的步骤,这么一连串的步骤叫做渲染流水线,在这些流水线中,有一些步骤是可以由开发者自己编程的,比如顶点着色器,片元着色器,所以在游戏开发中,要渲染一个模型的时候,需要写很多GPU(图形处理器)使用的代码,但是这些接近底层的代码很复杂,所以Unity的出现改善了这个情况,Unity提供了一个地方能够让开发者更加轻松的管理着色器代码以及渲染设置(如开启混合模式,深度测试,设置渲染顺序),Unity提供的这个地方就是Unity Shader

    Unity Shader和材质的关系

    总之:Unity渲染物体需要结合Unity Shader和材质

    1创建材质
    2创建Unity Shader,赋给创建的材质
    3将材质赋给要渲染的对象
    4材质面板调整Unity Shader的属性

    演示:

    首先,我们创建一个Unity Shader和材质,Unity Shader就是中文的着色器,材质就是中文的材质
    在这里插入图片描述
    下面是新建的材质,上面是新建的Unity Shader
    在这里插入图片描述
    点开新建材质,材质的Shader属性里面可以发现我们创建的Unity Shader
    在这里插入图片描述

    结论:Unity Shader是材质的特殊属性

    上述的着色器代码以及渲染设置(如开启混合模式,深度测试,设置渲染顺序)定义于Unity Shader,将Unity Shader拖入材质后,可以在材质中调整这些属性

    Unity中的材质

    新建材质很简单,那么把新建的材质用到物体上,怎么操作呢
    我们可以看到这两个组件,其中Mesh Renderer可以拖入材质,这两个组件就是完成把新建的材质用到物体上任务所需要的了
    Mesh Renderer详解: 点这里.
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    Unity中的Unity Shader

    Unity Shader的分类

    当我们新建Unity Shader的时候,发现有很多选择,这是Unity提供的模板
    在这里插入图片描述

    标准表面着色器

    这是包含标准光照模型的表面着色器模板
    如果着色器需要受到光照和阴影的影响,则表面着色器是您的最佳选择。表面着色器以简洁的方式使编写复杂的着色器变得容易 - 这是与 Unity 光照管线进行交互的更高级别抽象。大多数表面着色器自动支持前向和延迟光照。您可以用几行 Cg/HLSL 编写表面着色器,随后就能在此基础上自动生成更多代码。
    如果您的着色器与光照没有任何关联,请不要使用表面着色器。对于后期处理效果或许多特殊效果着色器,表面着色器是次优选项,因为它们会无缘无故进行大量光照计算。

    无光照着色器

    这是不包含光照的基本顶点和片元着色器
    如果您的着色器不需要与光照交互,或者如果您需要无法由表面着色器处理的非常奇特的效果,则需要使用顶点和片元着色器。以这种方式编写的着色器程序是创建所需效果的最灵活方法(甚至表面着色器也会自动转换为一堆顶点和片元着色器),但这需要付出代价:必须编写更多的代码并且更难以让它与光照互动。这些着色器也是以 Cg/HLSL 编写。

    图片效果着色器

    这是包含各种屏幕后处理效果的着色器

    计算着色器

    与常规渲染无关的计算,对于初级不太用的上

    固定函数着色器

    固定函数着色器是传统的着色器语法,用于非常简单的效果。建议编写可编程的着色器,因为这样可以提供更大的灵活性。固定函数着色器完全用一种名为 ShaderLab 的语言编写,此语言类似于 Microsoft 的 .FX 文件或 NVIDIA 的 CgFX。在内部,所有固定函数着色器在导入着色器时转换为顶点和片元着色器。

    UnityShader的属性

    在这里插入图片描述
    着色器检视面板显示有关着色器的基本信息(主要是着色器标签), 并允许编译和检查低级编译代码。

    对于表面着色器 (Surface Shader),Show generated code 按钮将显示 Unity 生成的用于处理光照和阴影的所有代码。如果确实想要 自定义生成的代码,只需将其全部复制并粘贴回原始着色器文件 并开始调整即可。

    Compile and show code 按钮的弹出菜单可检查选定平台 最终编译的着色器代码(例如 Direct3D9 上的程序集,或适用于 OpenGL ES 的 低级优化 GLSL)。此功能在优化着色器性能时非常有用;通常情况下,您会想知道最后在此处生成了 多少低级指令。

    生成的低级代码可用于粘贴到 GPU 着色器性能分析工具(如 AMD GPU ShaderAnalyzer 或 PVRShaderEditor)。
    着色器检视面板有很多属性,这里不详细解释,后面我们写代码的时候会自己写属性,就会更理解

    UnityShader高级

    UnityShader编译详细信息

    在着色器导入时,Unity 不会编译整个着色器。这是因为大多数着色器 内部都有很多变体,因此为所有可能的平台编译所有这些变体 将需要很长时间。实际的操作过程为:

    在导入时,仅对着色器进行最低限度的处理(表面着色器生成等)。
    只在需要时实际编译着色器变体。
    不会在导入时执行编译 100–10000 个内部着色器的典型工作,此过程通常最终只编译少数着色器。
    在播放器构建时,所有“尚未编译”的着色器变体都将被编译,因此即使 Editor 不会使用这些着色器变体,它们也会存在于游戏数据中。

    但是,这确实意味着着色器可能具有在着色器导入时未检测到的 错误。例如,正在使用 Direct3D 11 运行 Editor,但如果着色器是针对 OpenGL 进行编译的, 则会出错。此外,还可能着色器的某些变体不符合着色器模型 2.0 指令限制等。如果 Editor 需要了解这些错误,它们将显示在检视面板中;但是,为了检查错误,手动为所需平台 完全编译着色器也是一种很好的做法。使用着色器检视面板 中的 Compile and show code 弹出菜单即可执行此操作。

    着色器编译是使用名为 UnityShaderCompiler 的后台进程执行的,该进程由 Unity 在需要编译着色器时即时启动。可启动多个编译器进程(通常在机器中每个 CPU 核心对应一个),这样在播放器构建时就可以并行完成着色器编译。当 Editor 不编译着色器时,编译器进程不执行任何操作,也不消耗计算机资源, 所以不必担心它们。Unity Editor 退出时也将关闭这些进程。

    各个着色器变体编译结果将缓存在项目中的 Library/ShaderCache 文件夹下。 这意味着 100% 相同的着色器或其代码片段将重用以前编译的结果。此外还 意味着,如果有许多经常更改的着色器,着色器缓存文件夹可能会变得 非常大。删除文件夹内容通常是安全的;只会导致重新编译着色器变体。

    展开全文
  • Unity一共支持4种光源类型:平行光、点光源、聚光灯和面光源 (area light) 。 面光源仅在烘焙时才可发挥作用。 光源类型有什么影响 最常使用的光源属性有光源的位置 、方向 (更具体说就是,到某点的方向)、...

    Unity一共支持4种光源类型:平行光、点光源、聚光灯和面光源 (area light) 。

    面光源仅在烘焙时才可发挥作用。

    光源类型有什么影响

    最常使用的光源属性有光源的位置 、方向 (更具体说就是,到某点的方向)、颜色 、强度以及衰减 强度(更具体说就是,到某点的衰减,与该点到光源的距离有关)这5个属性。而这些属性和它们的几何定义息息相关。

    1.平行光

    平行光可以照亮的范围是没有限制的,它通常是作为太阳这样的角色在场景中出现的。

    平行光之所以简单,是因为它没有一个唯一的位置,它可以放在场景中的任意位置。

    它的几何属性只有方向,我们可以调整平行光的Transform组件中的Rotation属性来改变它的光源方向, 而且平行光到场景中所有点的方向都是一样的,这也是平行光名字的由来。除此之外,由于平行光没有一个具体的位置,因此也没有衰减的概念,也就是说,光照强度不会随着距离而发生改变。

    2.点光源

    点光源的照亮空间则是有限的,它是由空间中的一个球体定义的。点光源可以表示由一个点发出的、向所有方向延伸的光。

    球体的半径可以由面板中的Range属性来调整,也可以在Scene视图中直接拖拉点光源的线框(如球体上的黄色控制点)来修改它的属性。

    点光源是有位置属性的,它是由点光源的Transform组件中的Position属性定义的。

    对于方向属性,我们需要用点光源的位置减去某点的位置来得到它到该点的方向。

    而点光源的颜色和强度可以在Light组件面板中调整。同时,点光源也是会衰减的,随着物体逐渐远离点光源,它接收到的光照强度也会逐渐减小。点光源球心处的光照强度最强,球体边界处的最弱,值为0。其中间的衰减值可以由一个函数定义。

    我们需要在Scene视图中开启光照才能看到预览光源是如何影响场景中的物体的。图9.7给出了开启Scene 视图光照的按钮。

    3.聚光灯

    聚光灯是这3种光源类型中最复杂的一种。它的照亮空间同样是有限的,但不再是简单的球体,而是由空间中的一块锥形区域定义的。聚光灯可以用于表示由一个特定位置出发、向特定方向延伸的光。

    这块锥形区域的半径由面板中的Range属性决定,而锥体的张开角度由Spot Angle属性决定。我们同样也可以在Scene视图中直接拖拉聚光灯的线框(如中间的黄色控制点以及四周的黄色控制点)来修改它的属性。聚光灯的位置同样是由Transform组件中的Position属性定义的。对于方向属性,我们需要用聚光灯的位置减去某点的位置来得到它到该点的方向。聚光灯的衰减也是随着物体逐渐远离点光源而逐渐减小,在锥形的顶点处光照强度最强,在锥形的边界处强度为0。其中间的衰减值可以由一个函数定义,这个函数相对于点光源衰减计算公式要更加复杂,因为我们需要判断一个点是否在锥体的范围内。

    在前向渲染中处理不同的光源类型

    如何在Unity Shader中访问它们的5个属性:位置 位置 、方向 方向 、颜色 颜色 、强度以及衰减。

    我们来实现一个前向渲染的 shader。

    首先做如下准备工作。

    (1)在Unity中新建一个场景。该场景名为Scene_9_Light,默认情况下场景将包含一个摄像机和 一个平行光,并且使用了内置的天空盒子。在Window → Lighting → Skybox中去掉场景中的天空盒子。

    (2)新建一个材质。材质名为ForwardRenderingMat。

    (3)新建一个Unity Shader。Shader名为Chapter9-ForwardRendering。把新的Unity Shader赋给第2步中创建的材质。

    (4)在场景中创建一个胶囊体,并把第2步中的材质赋给该胶囊体。

    (5)为了让物体受多个光源的影响,我们再新建一个点光源,把其颜色设为红色,以和平行光进行区分。

    前向渲染说明 
    先说明一下前向渲染,unity支持多种渲染路径,前向渲染是其中一种

    Tags { "LightMode"="ForwardBase" }

    一般使用以上规定前向渲染。 
    对前向渲染而言,一个shader通常会规定2个pass,一个是Bass Pass,仅执行一次,一个是Additional Pass,为每个光源会执行一次。

    代码实例 

    定义 Base Pass

    I. 定义 Properties 块,因为只计算光照,所以比较简单

    Properties
    	{
    		_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
    		_Specular ("Specular", Color) = (1, 1, 1, 1)
    		_Gloss ("Gloss", Range(8.0, 256)) = 20
    	}

    II. 先定义第一个 Pass : Base Pass

        Pass
    		{
    		 Tags { "LightMode"="ForwardBase" }
    		 
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#pragma multi_compile_fwdbase			
    			#include "Lighting.cginc"

    把 LightMode 定义为 ForwardBase,并添加编译指令 #pragma multi_compile_fwdbase

    III. 输入输出结构体

    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float3 normal : NORMAL;
    			};
    
    			struct v2f
    			{
    				float4 pos : SV_POSITION;
    				float3 worldNormal:TEXCOORD0;
    				float3 worldPos : TEXCOORD1;
    			};

    IV. 顶点着色器,进行简单的空间转换 

    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.pos = UnityObjectToClipPos(v.vertex);
    				o.worldNormal = UnityObjectToWorldNormal(v.normal);
    				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    				return o;
    			}

    V. 片元着色器,对最亮的平行光,环境光,自发光等做计算。但此处我们不考虑自发光

    			fixed4 frag (v2f i) : SV_Target
    			{
    				fixed3 worldNormal = normalize(i.worldNormal);
    				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
    				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    				fixed3 halfDir = normalize(worldLightDir + viewDir);
    				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
    				fixed atten = 1.0;				
    				return fixed4(ambient + (diffuse + specular) * atten, 1.0);
    				
    			}

     在这里 atten 表示光照衰减值,因为是平行光,所以固定为 1

     至此 Base Pass 块基本定义完成。下面我们来定义 Additional Pass

    定义 Additional Pass

    I. 定义标签,同时注意一定要开启混合

    		Pass{
    			Tags { "LightMode"="ForwardAdd" }
    			
    			Blend One One
    		
    			CGPROGRAM
    			
    			#pragma multi_compile_fwdadd
    			
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "Lighting.cginc"
    			#include "AutoLight.cginc"

    II. Additional Pass 中对光源的处理方式与 Base Pass 中基本一致,去掉了环境光,自发光,逐顶点光照,SH 光照部分,然后添加对不同光源类型的支持。因为在这里处理的光源可能是平行光,点光源和聚光灯中任意一种。所以我们需要对其进行判断,然后计算五个影响要素:位置,方向,颜色,强度和衰减
     

    III. 对光源进行判断,得到光源方向,记得归一化

    			fixed4 frag(v2f i) : SV_Target {
    			fixed3 worldNormal = normalize(i.worldNormal);
    				#ifdef USING_DIRECTIONAL_LIGHT
    					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    				#else
    					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
    				#endif

    IV. 常规的光照计算

    				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
    				
    				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    				fixed3 halfDir = normalize(worldLightDir + viewDir);
    				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);

     V. 最后,处理不同光源的衰减

    					#if defined (POINT)
    				        float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
    				        fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    				    #elif defined (SPOT)
    				        float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
    				        fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    				    #else
    				        fixed atten = 1.0;
    				    #endif
    				#endif
     
    				return fixed4((diffuse + specular) * atten, 1.0);

    可以看到的是,点光源和聚光灯求衰减比较复杂,要通过复杂的数学表达式计算得到。因为这种计算操作较大,所以 Unity 选择使用一张纹理作为查找表(LUT),我们首先得到光源空间下的坐标,然后用这个坐标对衰减纹理进行采样得到衰减值。

    最后,保存两部分的代码,查看效果,可以看到,平行光和点光源都照亮了物体

    完整代码整理如下:

    Shader "Unlit/ForwardRenderingMat"
    {
    	Properties
    	{
    		_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
    		_Specular ("Specular", Color) = (1, 1, 1, 1)
    		_Gloss ("Gloss", Range(8.0, 256)) = 20
    	}
    	SubShader
    	{
    		
    
    		Pass
    		{
    		 Tags { "LightMode"="ForwardBase" }
    		 
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#pragma multi_compile_fwdbase			
    			#include "Lighting.cginc"
    			
    			fixed4 _Diffuse;
    			fixed4 _Specular;
    			float _Gloss;
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float3 normal : NORMAL;
    			};
    
    			struct v2f
    			{
    				float4 pos : SV_POSITION;
    				float3 worldNormal:TEXCOORD0;
    				float3 worldPos : TEXCOORD1;
    			};
    
    
    			
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.pos = UnityObjectToClipPos(v.vertex);
    				o.worldNormal = UnityObjectToWorldNormal(v.normal);
    				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    				return o;
    			}
    			
    			fixed4 frag (v2f i) : SV_Target
    			{
    				fixed3 worldNormal = normalize(i.worldNormal);
    				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
    				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    				fixed3 halfDir = normalize(worldLightDir + viewDir);
    				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
    				fixed atten = 1.0;				
    				return fixed4(ambient + (diffuse + specular) * atten, 1.0);
    				
    			}
    			ENDCG
    		}
    		
    		Pass{
    			Tags { "LightMode"="ForwardAdd" }
    			
    			Blend One One
    		
    			CGPROGRAM
    			
    			#pragma multi_compile_fwdadd
    			
    			#pragma vertex vert
    			#pragma fragment frag
    			
    			#include "Lighting.cginc"
    			#include "AutoLight.cginc"
     
    			fixed4 _Diffuse;
    			fixed4 _Specular;
    			float _Gloss;
    			
    			struct a2v {
    				float4 vertex : POSITION;
    				float3 normal : NORMAL;
    			};
    			
    			struct v2f {
    				float4 pos : SV_POSITION;
    				float3 worldNormal : TEXCOORD0;
    				float3 worldPos : TEXCOORD1;
    			};
    
    			v2f vert(a2v v) {
    				v2f o;
    				o.pos = UnityObjectToClipPos(v.vertex);
    				
    				o.worldNormal = UnityObjectToWorldNormal(v.normal);
    				
    				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    				
    				return o;
    			}
    
    			fixed4 frag(v2f i) : SV_Target {
    			fixed3 worldNormal = normalize(i.worldNormal);
    				#ifdef USING_DIRECTIONAL_LIGHT
    					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
    				#else
    					fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
    				#endif
    				
    				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
    				
    				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    				fixed3 halfDir = normalize(worldLightDir + viewDir);
    				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
    				
    				#ifdef USING_DIRECTIONAL_LIGHT
    					fixed atten = 1.0;
    				#else
    					#if defined (POINT)
    				        float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
    				        fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    				    #elif defined (SPOT)
    				        float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
    				        fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    				    #else
    				        fixed atten = 1.0;
    				    #endif
    				#endif
     
    				return fixed4((diffuse + specular) * atten, 1.0);
    
    			}
    			ENDCG	
    		}
    		
    	}
    	FallBack "Specular"
    }
    

     

    展开全文
  • 主要参考《Unity Shader入门精要》一书,外加自己的一些总结 前言 通过前面的学习内容可以知道,Shader并不设么...什么是Unity Shader Unity中的Shader和之前提到的渲染流水线的Shader有很大不同,我们把
  • ShaderLab 是Unity3d自己封装的一个调用CG/HLSL/GLSL的接口。 Shader相关文件(扩展名): shader - 着色器的主要文件 cg/cginc - 着色器的公用文件,可以在cg/shader/cginc文件中被"include"(包含),一般...
  • shader的工作原理是什么? shader中文名叫着色器,顾名思义,它的作用可以先简单理解为给屏幕上的物体画上颜色。而什么东西负责给屏幕上画颜色?当然是GPU,所以我们写shader的目的就是告诉GPU往屏幕哪里画、怎么画...
  • 什么是Shader Shader(着色器)一段能够针对3D对象进行操作、并被GPU所执行的程序。Shader并不一个统一的标准,不同的图形接口的Shader并不相同。OpenGL的着色语言GLSL, NVidia开发了Cg,而微软的Direct3D...
  • UNITY SHADER

    2018-04-24 21:00:20
    Shader就是在GPU上运行的程序叫做着色器程序(一般的程序在CPU...Unity中的游戏对象只要可视的,就一定会调用shader渲染,最简单的shader就是diffuse类型,就是你给对象涂个什么颜色,这个对象在白光下就是什么颜色。
  • unity会自动渲染一张深度图,据说5.x之后depth map基于shadow map的机制 也就是说, shadow map设置与否,会影响到depthmap,又一个大坑 这里,没做什么特别设置,还是能用的 depthmap在手机上一个大坑,...
  • 众所周知,Unity3d是一款跨平台非常... 编写shader也是我工作内容的一部分,先来说说shader是什么吧,我以自己的理解说明一下: 首先shader是一种语言,一种在GPU,也就是显卡上执行的高级语言。shader的本意是着...
  • 1.什么是渲染流水线? 计算机将一系列的顶点数据,纹理数据转化为一张人眼可以看见的图像的过程,就叫做渲染流水线。 2.渲染流水线的过程 2.1:应用阶段主要处理哪些事情? 1.准备场景数据,摄像机,视...
  • 建立测试ShaderShader "Unlit/NewUnlitShader"{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{Name "MyShader"Tags { "LightMode" = "ForwardBase" }...
  • 学了12年英文,可能你还是不会说,唯一的方法就是去一个全英语的环境,那么你一个月的英语水平提高的速度将绝对比你学12年还快,什么时候去最好?怎么才能准备好,答案,根本不用准备,而且越快越好! 最近归纳了...
  • 1、shader 是什么? 2、shader 怎么用? 3、
  • Unity Shader 什么是法线贴图

    千次阅读 2015-11-08 13:26:20
    我们新创建一个材质,会发现有法线贴图这一项 法线贴图属于凹凸贴图的一种,它允许你增加物体表面的细节,比如凸起,凹槽,抓痕等。 我们如果把上图中的凸起和凹槽做成模型的一部分,...什么是表面法线? 简单来
  • Unity Shader 基础教程

    万次阅读 多人点赞 2018-05-27 19:14:23
    在Github上看到一篇关于Unity-Shader的教程,感觉还不错,作者写的很好,很适合Unity-Shader的基础入门,我在这里翻译一下,分享给大家,英文水平很烂,大致能明白Unity-Shader是什么,渲染管线的工作流程,以及...
  • Unity中可以通过#pragma multi_compile或者#pragma shader_feature指令来实现着色器多样化。在运行时,相应的着色器变体从材质的关键词中取得的(Material.EnableKeyword和 DisableKeyword),或者全局着色器...
  • )[+]本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。这里本书所有的插图。这里本书所需的代码和资源(当然你也可以从官网下载)。================...
  • UnityShader入门精要-Uinty复杂光照(此文为易于理解的演讲配合文档,设计到专业词汇和解释可能不当)一 渲染路径1.1 什么是渲染路径以及如何Unity(2018.4)设置之前我们在shader中使用了一些系统帮我们定好的变量如...
  • 今天扫项目的时候看到了很早之前下载的Unity Chan的项目,其实很早之前就想要分析下里面的卡通效果怎么做的。 Unity Chan 想必很多人都看到或听过Unity Chan,也可以说是Unity酱、Unity娘……她数次出现在早期的...
  • Unity有自己的一套Shader系统,叫ShaderLab,今天主要说一下ShaderLab的语法和Unity中的几种不同种类的Shader的区别及使用场景,并分别做一些例子说明。 什么是ShaderLab ShaderLab 是Unity3d自己封装的一个调用...
  • Unity Shader基础

    2021-03-24 10:23:25
    第三章 Unity Shader基础 一对好兄弟:材质和Unity ShaderUnity中需要配合材质和 Unity Shader 才能达到需要的效果。Unity Shader定义了渲染所需的各种代码(如顶点着色器和片元着色器)、属性和指令,而材质则...
  • 而通过允许开发人员控制Unity着色器编译器处理哪些着色器变体,并将其包含在播放器数据中,可大量减少播放器构建时间和数据大小。今天我们将为大家介绍Unity 2018.2 beta版中新功能可编程着色器变体移除功能。可编程...
  • 众所周知,要想当游戏开发工程师,Unity中的Shader编写不得不摸,这一系列文章我将描写我的Shader学习之路,致敬冯乐乐的书Unity Shader入门精要,此篇什么是ShaderLab?希望能给后人一点方向 看看上一篇的Unity ...
  • 正在学习unityshader,看官方的shader示例,其中有一个就是Rim Lighting,但是官方示例那个模型并没有把这个效果凸显出来,然后查了下Rim Lighting,看到了这个例子,才明白物体边缘高亮的效果,联想到玩的游戏,...
  • 众所周知,要想当游戏开发工程师,Unity中的Shader编写不得不摸,这一系列文章我将描写我的Shader学习之路,希望能给后人一点方向

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 730
精华内容 292
关键字:

shader是什么unity