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

版权声明: https://blog.csdn.net/yinhun2012/article/details/81061129

    紧接上一篇:https://blog.csdn.net/yinhun2012/article/details/80924102

    上一篇我们用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代码演示一下,如下图:

Shader "Custom/StandardSurfaceShader" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Texture", 2D) = "white" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		
		CGPROGRAM
		#pragma surface surf Standard

		#include "UnityPBSLighting.cginc"

		#pragma target 3.0

		struct Input {
			float2 uv_MainTex;
		};

		sampler2D _MainTex;
		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		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"
}

  这里我就要详细讲解一下这个标准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写法后,下一篇我们要自己实现通用自定义光照模型,亲自感受一下。

猜你喜欢

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