使用表面着色器的属性
现在我们已经为着色器创建了一些属性,这里我们将要正式的把这些属性跟着色器关联起来,这些属性就像着色器的调节器一样,可以让材质拥有更好的交互性。
我们可以在材质的 检查器面板(Inspector tab) 使用着色器属性的值,因为我们为这个属性添加了一个变量名,但是如果你在着色器代码中想要通过这个变量名来获得这个值,我们仍然还有很多事情要做。
操作步骤
下面的步骤展示了如何在表面着色器中使用属性:
- 开始之前,我们先删除下面的行的代码,就好像我们在章节 创建一个基本的标准着色器 中删除属性的操作步骤一样,删除 _MainTex 属性:
_MainTex ("Albedo (RGB)", 2D) = "white" {}
sampler2D _MainTex;
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
- 下一步,添加下面这些行的代码到着色器代码中,添加到 CGPROGRAM 下面, add the following lines of code to the shader, below the CGPROGRAM line:
float4 _AmbientColor; float _MySliderValue;
- 当第二部完成之后,我们就可以在着色器中使用属性的值了。我们把 _Color 属性的值与 _AmbientColor 值相加,并且把两者的结果赋值给 o.Albedo 。为了达成目的,我们需要在着色器代码中的 surf() 方法中添加如下代码:
void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = pow((_Color + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; }
- 最终你的代码将会是如下所示。如果你在你的VSCode中保存好然后返回Unity编辑器,你的着色器将会重新编译。 如果没有什么错误,那么现在你可以修改材质的环境光和自发光的颜色,当然也可以通过滑动条增加最终颜色的饱和度。听巧妙的噢。
Shader "CookbookShaders/StandardDiffuse3" { // We define Properties in the properties block Properties { _Color ("Color", Color) = (1,1,1,1) _AmbientColor("Ambient Color", Color) = (1,1,1,1) _MySliderValue("This is a Slider", Range(0,10)) = 2.5 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 // We need to declare the properties variable type inside of the //CGPROGRAM so we can access its value from the properties block. CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 struct Input { float2 uv_MainTex;}; fixed4 _Color; float4 _AmbientColor; float _MySliderValue; void surf (Input IN, inout SurfaceOutputStandard o) { // We can then use the properties values in our shader fixed4 c = pow((_Color + _AmbientColor), _MySliderValue); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
提示
下载示例代码
你可以在 Packt 网站登陆后,下载所有已购买书籍的所有示例代码文件,下载地址:http://www.packtpub.com。如果你是在别处购买的书,那么请访问: http://www.packtpub.com/support然后注册,以便通过邮件直接获取相关的代码文件。注意
pow(arg1, arg2) 这个方法是内建的,他的功能跟数学的幂函数 power 是等价的。第一个参数是底数,第二参数是指数 。想了解更深入的了解 pow() 方法,请去看Cg语言的教程。下面这个网址提供了非常棒的资源,能让你学习更多有关着色器的知识,并且里面有Cg着色器语言的所有函数的表:
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html 下面的屏幕截图展示了通过材质的 检查器面板(Inspector tab) 来控制材质的属性,从而控制材质的颜色和饱和度:原理介绍
当你在 属性(Properties ) 代码块中声明一个新的属性时,等于是在材质的 检查器面板( Inspector tab) 给着色器添加了可以访问调整值[tweaked value]的方式。这个值存储在这个属性的变量名中。在这个例子中,_AmbientColor ,_Color 和 _MySliderValue 这三个变量就是我们用来保存调整值的。为了让你能够在 SubShader{} 这个代码块中使用这些值,你需要在这个代码块中对应创建三个变量,而且这三个变量的名字要跟属性代码块中的变量名保持一致。这样的话Unity会自动把 SubShader{} 代码块和属性代码块中的变量关联起来,然后让着色器知道这些变量使用的是相同的数据。另外,这个属性声明同时也告诉我们在 SubShader{} 代码块中对应的变量的数据类型,在后续有关着色器的优化相关的章节中,会用到这些。
当你再 subshader 代码块中创建好变量后,接下来你就可以再 surf() 方法中使用它们的值。在这个例子中,_Color ,_AmbientColor 与 _MySliderValue 这三个变量获得了来自材质的 检查器面板(Inspector tab) 对应的值。变量 _Color 跟变量 _AmbientColor 这两个值相加,并且把这个值当作底数,_MySliderValue 的值当作指数,进行幂运算。
大多数着色器都是从一个标准着色器开始,然后一步一步修改它直到它们符合设计的样子。我们现如的这个例子为以后需要散射组件的表面着色器打好了基础。
注意
材质时一种 资源(assets) 。这意味着,当你的游戏在编辑器中运行时,你对它的任何改变都将会是永久的[这里解释一下,一般在Unity编辑器运行时,你对游戏做的修改,在停止运行后,又会恢复到运行之前的状态,这里材质不一样,修改之后,即使停止运行,它也不会恢复]。如果你不小心错误修改了属性的值,你可以通过快捷键 Ctrl + Z 取消这个修改。
相关补充
跟其他一些编程语言一样,Cg也是不允许有错误。如果你的着色器代码中有错误的话,着色器将不会起作用。当着色器不起作用时,你的材质会因为没有着色器而以品红的方式渲染: 当一个脚本没有被编译,Unity引擎会禁止你的游戏导出或者运行。 然而,着色器中有错误,Unity并不会阻止你运行你的游戏。如果你的着色器呈现出品红色,那么就应该检查一下到底哪里出现了问题。当你在Unity的编辑器中选中这个报错的着色器,那么你可以在 检查器面板(Inspectortab) 中看到一大串错误: 尽管错误提示展示了错误所在的行,但是通常不一定是引起错误的正真原因。上一张示例图所展示的错误是因为删除了了 SubShader{} 代码块中的 sampler2D _MainTex 变量引起的。 然而报错的地方是试图去访问这个未定义的变量所在的代码行。找到错误并且修复的过程就是我们常说的 debug 。你最常用的一些错误检查如下:忘记括号匹配。 如果忘记用花括号对代码块进行配对匹配,那么编译器就会在代码文档的最后,开始或者新的代码块中提示错误。
忘记写分号结束语句。这是最常见的错误,同时也是最容易定位和修复的错误。通常会在下一行开始产生一个错误。
在 属性(Properties) 代码块中定义了一个属性,但是没有在 SubShader{} 代码块中定义对应的变量。【这两者是需要成对出现的,也就是说在 属性(Properties) 块里面定义了一个新的属性,那么在 SubShader{} 代码块中就需要声明一个与之对应的变量】
更Unity中的C#脚本不一样,Cg语言中的浮点值不需要在后面加 f 来表示浮点类型:浮点值1.0就写作 1.0 ,而不是 1.0f 。
着色器中提示的错误很具有误导性,特别是因为它们那严格的语法约束。如果看不懂错误什么意思,那就直接百度或者谷歌。 或者去Unity的论坛搜索一下看看,里面可能就有跟你遇到相同问题(修复了相同问题)的开发者。
额外内容
在第二章,表面着色器和纹理纹理 ,我们会了解如何去掌握 表面着色器(Surface Shaders) 跟它们的 属性(properties) 。如果使用着色器的所有潜能和特性,到底能做些什么?如果你对这个问题感兴趣,你应该去看一看第十章,更高级的着色器技术 。里面有本书的一些最高级的着色器技术。
希望它能帮到你或者帮你找到思路(^_^)选个表情,或者留个评论吧!