您的位置:首页 > 其它

Shader学习的基础知识( 三十四)表面着色器上

2019-03-18 02:55 204 查看
版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ww1351646544/article/details/88631537

表面着色器是什么

表面着色器实际上是在顶点/片元着色器之上又添加了一个层抽象。表面着色器让我们关注的细节就更少了,自由度也就更底。但是好处里代码量也是少得惊人。而且性能上也不如顶点/片元着色器。

  • 如果你需要和各种光打交到,尤其是想要使用全局光源,你可能更喜欢表面着色器,但你要小心它的性能。
  • 如果光源少,那可以使用顶点片元着色器。
  • 如果有很多自定义的效果,则使用顶点/片元着色器

一个表面着色器的例子:

这里只有30几行代码,如果使用顶点/片元着色器则需要150多行。

Shader "Unity Shaders Book/Chapter 17/Bumped Diffuse" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
//主图
_MainTex ("Base (RGB)", 2D) = "white" {}
//法线纹理
_BumpMap ("Normalmap", 2D) = "bump" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 300

CGPROGRAM
#pragma surface surf Lambert
#pragma target 3.0

sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;

struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = tex.rgb * _Color.rgb;
o.Alpha = tex.a * _Color.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}

ENDCG
}

FallBack "Legacy Shaders/Diffuse"
}

编译指令

编译指令最重要的作用是指明该表面着色器使用的“表面函数”和"光照函数",格式如下:

#pragma surface   surfaceFunction   lightModel    [optionalparams]

#pragma指明该编译指令是个表面着色器,在它后面是表面函数和光照模型,还有一些可选参数。

表面函数
表面着色器的优点在于抽像出了“表面”这一概念。和顶点/片元着色器不同的是,一个对象的表面属性定义了它的反射率、光滑度、透明度等。而surfaceFunction用于定义这些表面属性。sunfaceFunction通常名为surf的函数它的函数格式是固定的:

void surf(Input IN,inout SurfaceOutput o)
void surf(Input IN,inout SurfaceOutputStandard o)
void surf(Input IN,inout SurfaceOutputStandardSpecular o)

光照函数
指定物体表面模拟的光照效果,内置的有基于物理光照的Standard和StandardSpecular,简单光照的Lambert和BlinnPhong,也可以自己定义光照。

其他可选
例如是否开启透明度混合/测试、自定义修改顶点(vertex:VertexFunction)、最后颜色修改(finalcolor:ColorFunciton),例如我们可以修改顶点位置来实现顶点动画等。
阴影 :例如可以使用addshadow或fullforwardshadows等
光照:例如使用noambient告诉Unity不要响应任何逐顶点光照,novertexlight不要应用任何顶点光照等…
控制代码生成:默认会使用前向渲染、延迟渲染路径这些导致文件较大。可以使用exclude_path:deferred、exclude_path:forward等不要为后写路径生成代码。

表面着色器的指令参数很多,慢慢探讨吧。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: