入门图形学:光照模型(四)

转载自: https://blog.csdn.net/yinhun2012/article/details/81061129


上一篇我们用cg中比较常见的vertex fragment函数去实现了通用光照模型的效果,功能和效果虽然很详细的实现了,但是从代码复用性来讲,不那么友好,这次就按照unity cg编译器的规范去实现一个通用光照模型的函数。

     首先为了系统的学习unity cg的一些自定义代码规则,我们需要先去下载unity cgbuildin文件,具体下载方法就是去unity官网选择unity旧版本,然后选择要下载的unity版本的内置着色器文件,截图和地址如下:

unity文件下载

    

 

     因为我暂时用的5.x版本,所以一切以5.x版本来讲解,下载完毕后打开CGIncludes文件夹,其中有很多.cginc文件,这些就是unity编译器能识别编译的c源码文件,这些源码文件的作用就很大了:

    ①.让你查看unity内部着色器这块一些实现代码。

   ②.因为这些代码包含我们编写.shader文件的函数接口和数据结构,比如UnityCG.cginc这个代码文件,可以很清晰的看出.shader文件中使用的各种数据结构体和字段,以及各种计算辅助函数。

    ③.再比如打开UnityStandardInput.cginc这个文件(以及其包含的头文件),可以看到很多.shader中使用的数据定义以及其含义。

    ...

    因为文件太多暂时讲不完,我会在额外开一个unity c for graphic栏目详细讲解,这个栏目会从基础语法到unity着色器源码进行学习。

    言归正传,接下来找到UnityPBSLighting.cginc打开,你会看到一个名为SurfaceOutputStandard的结构体,结构体的如下:

    

上面的注释写着用于物理上的表面着色器输出结构体。

顺便看下结构体下面的LightingStandard函数,如下图:

这就是一个unity自定义的标准光照通用函数。这个函数具体怎么用呢?我就来写CGshader代码演示一下,如下图:


 
 
  1. Shader "Custom/StandardSurfaceShader" {
  2. Properties {
  3. _Color ( "Color", Color) = ( 1, 1, 1, 1)
  4. _MainTex ( "Texture", 2D) = "white" {}
  5. _Glossiness ( "Smoothness", Range( 0, 1)) = 0.5
  6. _Metallic ( "Metallic", Range( 0, 1)) = 0.0
  7. }
  8. SubShader {
  9. Tags { "RenderType"= "Opaque" }
  10. CGPROGRAM
  11. #pragma surface surf Standard
  12. #include "UnityPBSLighting.cginc"
  13. #pragma target 3.0
  14. struct Input {
  15. float2 uv_MainTex;
  16. };
  17. sampler2D _MainTex;
  18. half _Glossiness;
  19. half _Metallic;
  20. fixed4 _Color;
  21. void surf (Input IN, inout SurfaceOutputStandard o) {
  22. fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
  23. o.Albedo = c.rgb;
  24. o.Metallic = _Metallic;
  25. o.Smoothness = _Glossiness;
  26. o.Alpha = c.a;
  27. }
  28. ENDCG
  29. }
  30. FallBack "Diffuse"
  31. }

  这里我就要详细讲解一下这个标准StandardSurfaceShader一些让人迷惑的地方。

        1.Properties字段定义

        ①._Color,定义材质基本颜色

        ②._MainTex,材质表面贴图

        ③._Glossiness,材质表面平滑性

        ④._Metallic,材质金属光泽

        2.#pragma surface surf Standard预处理指令,这个是什么意思呢?作用和c预处理指令一样,语法上经过了unity自己的着色器编译器的规范化处理,比如surface代表我这是一个surface着色函数,surf就是需要调用的程序员们实现的函数,Standard就是标准光照模型LightingStandard,这里特别提示一下,这个就是unity官方自己的编译规范,Standard隐去了Lighting这个字符串,实际上就是LightingStandard,可以这么说,官方就是这么任性,就是要去掉Lighting前缀,不爽咬我啊!

        3.Surf函数

        ①.SurfaceOutputStandard这个参数的作用就很大了,这是unity标准光照模型LightingStandard处理需要的封装结构体,结构体数据我上面有截图,可以翻上去详细看一下。

        ②.inout形参修饰符,这个修饰符的作用跟c#的ref out差不多,直接传递一个引用结构体给我们填充数据,填充完毕就被拿回去使用。

        ③.我们将SurfaceOutputStandard的几个重要参数填充完毕后,提交给标准光照模型LightingStandard去计算最终光照效果。

最后发下,这个标准surface着色器的最终效果,如下图:

     可以明显感觉到这些参数提供的具体效果变化。

   最后,当我们学习理解完毕这种cg写法后,下一篇我们要自己实现通用自定义光照模型,亲自感受一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值