• shader学习之路(1)- half lambert


    在学习这个shader之前先提个经常使用概念。即光照模型。LightModel(光照模型)即是对于物体怎么对打在其上的光做出视觉反应的数学模型。意即表达物体对光反应产生的视觉效果与入射光、物体表面属性等数值相关联的数学表达。
    大致了解了光照模型的概念,接下来介绍下今天的主角,Half Lambert模型,该模型是Valve在开发经典游戏《Half-Life(半衰期)》(半条命这个译名真是后无古人的误翻啊……)是发明的,在曾经的游戏中。一旦模型背对着光源,模型表面的亮度会立马减少。使得整个模型显得平面化,毕竟游戏世界并不是像现实中有各种漫散射光能照亮背光的一面。所以half-lambert算法提高了物体在背对光源时的亮度,由于其并不是依据真实物理推算出来的结果。而不过一种视觉感受的提升,所以事实上现方式并不复杂。非常多shader入门书籍都介绍过这样的算法,不必操心全然看不懂。

    未启用/启用half-lambert算法(右側为启用)
    如今我们来看看怎么实现这个算法,首先由于vs对shaderkeyword高亮支持并不太好(联网工具包中的shader高亮插件事实上还行)。所以能够用引擎自带的mono dev或者sublime text来编写Cg文件,这个看大家个人喜好了,有空我会介绍下vs和sublime text对shaderkeyword高亮的设置。
    打开unity3d,在project栏中的Assets下建立Materials Shader两个目录(良好的资源管理是开发工程的必要前提),在shader中创建一个surface shader并将之命名为halfLambert。



    打开shader文件,能够看到默认的属性栏Properties。这以下的变量不仅要在以下的代码中使用。同一时候也能在引擎的inspector中进行调整。



    如今我们将其改动为例如以下属性:

    接下来在SubShader块中,能够看到这样一段定义

    这是定义shader所使用的光照模型,由于我们是自己定义模型,所以要改为

    还记得先前在Properties定义的三个变量吗,只在Properties中声明的话尽管能在inspector中看到。但还不能在subshader中使用,所以在SubShader块中须要再次声明,例如以下图

    接下来我们開始编写该模型的主要部分,例如以下

    这个函数的命名是有规则的,Lighting+模型名,该模型名称就是你刚才是在#pragma surface中命名的模型名称。这样unity就能自行编译链接该shader所使用的模型。
    整个half-lambert模型的关键在于此
    Lambert模型中的difLight在dot()方法下,处于[0,1]的范围中。因此hLambert的范围就在[0.5,1]中,提高了总体的漫反射值,其值的变化例如以下

    剩余的则是surf代码

    写完了shader代码后。如今须要将shader使用在物体上,在Material中建立一个新的Material,并将该shader拖入当中

    在场景中建立一个Sphere后,将该Material赋予当中

    最后效果如图,右側是未使用half-lambert算法的效果,能够看到half-lambert的确是明显提升了物体材质表面的亮度,在视觉上更加明亮。


    完整代码例如以下:
    Shader "Custom/halfLambert" {
    	Properties {
    		_EmissiveColor("Emissive Color", Color) = (1, 1, 1, 1)
    		_AmbientColor("Ambient Color", color) = (1, 1, 1, 1)
    		_SliderValue("Slider", Range(0,10)) = 2.5
    	}
    	SubShader {
    		Tags { "RenderType"="Opaque" }
    		LOD 200
    		
    		CGPROGRAM
    		// Physically based Standard lighting model, and enable shadows on all light types
    		#pragma surface surf HalfLambert
    
    		// Use shader model 3.0 target, to get nicer looking lighting
    		#pragma target 3.0
    
    		float4 _EmissiveColor;
    		float4 _AmbientColor;
    		float _SliderValue;
    
    		inline float4 LightingHalfLambert(SurfaceOutput s, fixed3 lightDir, fixed atten)
    		{
    			float difLight = max(0, dot(s.Normal, lightDir));
    			float hLambert = difLight * 0.5 + 0.5;
    
    			float4 col;
    			col.rgb = s.Albedo * _LightColor0.rgb * (hLambert * atten * 2);
    			col.a = s.Alpha;
    			return col;
    		}
    
    		struct Input
    		{
    			float2 uv_MainTex;
    		};
    		
    		void surf(Input IN, inout SurfaceOutput o)
    		{
    			float4 c;
    			c = pow((_EmissiveColor + _AmbientColor), _SliderValue);
    
    			o.Albedo = c.rgb;
    			o.Alpha = c.a;
    		}
    		ENDCG
    	}
    	FallBack "Diffuse"
    }


    P.S 初次写有关3d图形学的博客,时间仓促。还有好多内容没有说明确,还请各路大佬多多指导!
    參考书目:
    1.Unity Shaders and Effects Cookbook - (美)Kenny Lammers
    2.Unity3d shader 编程 - 98jy.net,化石(编) 


  • 相关阅读:
    gitolite 丢失管理密钥/访问权限 解决办法
    4/20
    socket套接字模块
    网络编程part2
    网络编程part1
    异常处理
    类的属性查找
    多继承带来的菱形问题
    property装饰器
    类的继承派生
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8341220.html
Copyright © 2020-2023  润新知