unity5, custom PBS shader

unity5中引入了基于物理着色(PBS)的Standard shader。由于这种着色器通过调节参数和贴图可逼真模拟各种硬质表面,所以不必再像unity4时代那样需要对各种质感材质单独编写着色器,而且能得到更好的效果(参考:http://docs.unity3d.com/Manual/shader-StandardShader.html)。这种“万能着色器”仿佛给人一种不再需要自己编写着色器的假象,但做游戏跟做虚拟现实不一样,除了真实性,还要追求趣味性和艺术夸张。所以老古语不过时:没有使用自定义着色器的游戏,不是好游戏。

但自己实现PBS是很困难的,如果我们想既继承Standard shader的PBS特性又加入自己的定制效果,最好我们的自定义shader能在Standard shader的基础上进行编写,即实现自定义PBS着色器(custom PBS shader)。

由于是新东西,资料不全,google了一整天也没能找到现成方法,unity官方文档中对此完全没有作说明(在surface shader自定义光照模型 部分只给了不带PBS的例子),unity论坛里有多个帖子问到类似问题,但都没有满意解答。最后在下面两个连接里找到了一点儿线索:

http://forum.unity3d.com/threads/for-those-in-u5-beta-is-pbr-really-that-good.283867/page-3#post-1886525

http://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/ (文章下面 MIG 的提问)

此线索是:“

  from the release notes for beta 12:

  • Shaders: Surface shaders can use physically based shading now; the same as Standard shader uses.
    • Use "Standard" lighting function, and "SurfaceOutputStandard" output structure.
    • Do an #include "UnityPBSLighting.cginc" in your shader to get it.
    • Default options require shader model 3.0, so add a "#pragma target 3.0" too.

然后又结合了UnityPBSLighting.cginc中的源代码(注1),当然,只是从UnityPBSLighting.cginc中拷贝一些代码出来(而不是修改它),最后终于把custom PBS shader试验成功了。

注1:UnityPBSLighting.cginc这个文件在哪儿?有三个途径获得:

(1),在 http://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html 中写道:“file inside Unity ({unity install path}/Data/CGIncludes/ on Windows, /Applications/Unity/Unity.app/Contents/CGIncludes/ on Mac)”,需要注意的是"/Applications/Unity/Unity.app/Contents/CGIncludes/"这个路径是在Unity.app的“包内容”里,所以这就是为什么在Mac上虽然UnityPBSLighting.cginc已经随unity一起安装了,但确不能通过文件搜素找到。

(2),通过网址http://docs.unity3d.com/Manual/StandardShaderMakeYourOwn.html进入在线的"Make your own"页面下载builtin_shaders的最新版本(也包括历史版本)。因为我的unity是最新的,所以通过此途径下载到的最新版的builtin_shaders与途径(1)中的是一致的,但如果你的unity不是最新的,一定要根据你的unity版本号下载相应版本的builtin_shaders,否则你拷贝其中的代码用到自定义shader中可能报错。

(3),在浏览器地址栏输入file:///Applications/Unity/Unity.app/Contents/Documentation/en/Manual/StandardShaderMakeYourOwn.html进入离线的"Make your own"页面(从地址上你可以看出这个页面实际上保存在你的电脑中),下载builtin_shaders,但要注意,通过这个离线文档下载的builtin_shaders可能不是最新的,我今天就被此坑了一回,通过此途径下载的UnityPBSLighting.cginc文件中的代码拷贝到自定义shader中报错,搞了半天没找到原因,直到我又通过途径(1)重新获得UnityPBSLighting.cginc。。。

综上,途径(1)是最好的。

下图第一个球用的是Standard shader,第二个球用的是“将法线当作颜色值”的自定义shader(不带PBS),第三个球是今天的试验成果:在Standard shader的PBS基础上添加了“将法线当作颜色值”效果的杂交shader。

第一个球的shader用的是unity(version 5.0.1f1 Personal)里新建shader时生成的默认shader:

Shader "Custom/NewShader" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

在此基础上参照UnityPBSLighting.cginc中的源代码将光照模型以自定义光照模型的形式暴露出来,得到下面等价shader:

(这里需要注意的是,一般自定义光照模型只要实现一个 Lightning+自定义光照模型名称 的函数即可,但是对于PBS shader来说,要实现自定义光照模型还要多写一个 Lightning+自定义光照模型名称_GI 的函数。)

Shader "Custom/customPBS" {
      Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" "MyReplaceTag"="Other"}
        LOD 200
        
        CGPROGRAM
    
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf MyCustomStandard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
        #include "UnityPBSLighting.cginc"


        inline void LightingMyCustomStandard_GI (
            SurfaceOutputStandard s,
            UnityGIInput data,
            inout UnityGI gi)
        {
            gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
        }

        inline half4 LightingMyCustomStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
        {
            s.Normal = normalize(s.Normal);

            half oneMinusReflectivity;
            half3 specColor;
            s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

            // shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
            // this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
            half outputAlpha;
            s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);

            half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
            c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
            c.a = outputAlpha;
            

            return c;
        }


        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        
        
        ENDCG
    } 
    FallBack "Diffuse"
}

 

上面shader和默认shader效果完全一样,但是由于暴露出来光照模型(即上面的LightingMyCustomStandard函数),便使得我们可以在光照模型层次上对其进行修改,实现出自己的变种shader效果。

例如下面shader,就是在LightingMyCustomStandard中插入一行代码,实现前面图中第三个球的效果:


Shader "Custom/customPBSAndShowNormalAsColor" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
    
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf MyCustomStandard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
        #include "UnityPBSLighting.cginc"


        inline void LightingMyCustomStandard_GI (
            SurfaceOutputStandard s,
            UnityGIInput data,
            inout UnityGI gi)
        {
            gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal);
        }

        inline half4 LightingMyCustomStandard (SurfaceOutputStandard s, half3 viewDir, UnityGI gi)
        {
            s.Normal = normalize(s.Normal);

            half oneMinusReflectivity;
            half3 specColor;
            s.Albedo = DiffuseAndSpecularFromMetallic (s.Albedo, s.Metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);

            // shader relies on pre-multiply alpha-blend (_SrcBlend = One, _DstBlend = OneMinusSrcAlpha)
            // this is necessary to handle transparency in physically correct way - only diffuse component gets affected by alpha
            half outputAlpha;
            s.Albedo = PreMultiplyAlpha (s.Albedo, s.Alpha, oneMinusReflectivity, /*out*/ outputAlpha);

            half4 c = UNITY_BRDF_PBS (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, gi.light, gi.indirect);
            c.rgb += UNITY_BRDF_GI (s.Albedo, specColor, oneMinusReflectivity, s.Smoothness, s.Normal, viewDir, s.Occlusion, gi);
            c.a = outputAlpha;
            
            c.rgb*=s.Normal *1.5;//added by wantnon


            return c;
        }

 
        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        
        
        ENDCG
    } 
    FallBack "Diffuse"
}
 

当然,如果不需要在光照模型的层次上对unity自带的PBS shader进行定制,是没有必要这么麻烦的。

比如就拿上面这个customPBS+ShowNormalAsColor来说,其实没必要深入到光照模型层次上去实现,下面shader就可以实现基本相同的效果:

(其中蓝字是在前面Custom/NewShader基础上新增的语句)

Shader "Custom/NewShaderAndShowNormalAsColor" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;

    float3 worldNormal;//ref: http://wiki.unity3d.com/index.php?title=Shader_Code
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

      c.rgb*=IN.worldNormal;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

转载于:https://www.cnblogs.com/wantnon/p/4395286.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win服务器文件夹权限设置密码,win服务器 文件夹权限设置

win服务器 文件夹权限设置 内容精选换一换开发过程中,您有任何问题可以在github上提交issue,或者在华为云对象存储服务论坛中发帖求助。接口参考文档详细介绍了每个接口的参数和使用方法。在OBS中,用户操作的基本数据单元是对象。OBS PHP SDK…

手机文件管理ftp服务器,ftp工具手机版(ftp文件传输管理工具)V1.0.2 手机版

ftp工具手机版(ftp文件传输管理工具)是一款非常实用的ftp文件管理应用工具。主要作用是将手机ftp上的文件数据快速传输到电脑上,或者将电脑上的文件传输到手机上,实现双向传输,并且传输速度十分快,ftp工具是一款很专业的传输软件&…

Android 获得ImageView中Image的绘制大小

2019独角兽企业重金招聘Python工程师标准>>> ImageView在显示图片的时候,受限于屏幕大小,和图片宽高。通常图片是被缩放过,且不是宽和高都充满ImageView的。 此时,我们如何获得Image被实际绘制的宽高呢? //…

Quartz2D指定显示范围

在qq中,可以看到头像是圆形显示的,通过CGContextClip可以设置 CGContextRef contextUIGraphicsGetCurrentContext();CGContextAddEllipseInRect(context, CGRectMake(100, 100, 100, 100));CGContextClip(context);UIImage *img[UIImage imageNamed:&quo…

当前系统时间与服务器时间,操作系统时间和服务器时间

操作系统时间和服务器时间 内容精选换一换文章目录计算机操作系统(一)1 操作系统的目标和作用1.1 操作系统的目标 1.2 操作系统的目标 2 操作系统的发展历程2.1 未配置操作系统的计算机2.2 单道批处理系统2.3 多道批处理系统2.4 分时系统2.5 实时系统 3 操作系统的基本特性3.1 …

【学神-RHEL7】1-3-Linux基本命令和配置服务器来电后自动开机

本节所讲内容:Linux终端介绍Shell提示符Bash Shell基本语法基本命令的使用:ls、pwd、cd查看系统和BIOS硬件时间Linux如何获得帮助Linux关机命令:shutdow、init等Linux 7个启动级别创建一个方便快捷实验环境快照设置服务器在来电后自动开机Lin…

服务器节点信息管理,华为云管理节点服务器

华为云管理节点服务器 内容精选换一换不想看文字,请直接戳视频链接。可以不做备案吗?根据《互联网信息服务管理办法》等相关规定,使用中国大陆节点服务器开办的网站,必须先办理网站备案,备案成功并获取通信管理局下发的…

全国小学四则运算1.0

程序:全国小学四则运算1.0 源代码: import javax.swing.*; import java.awt.*; import java.awt.event.*; //一开始的界面 public class Menu extends JFrame implements ActionListener{JButton enter;public Menu(){super("小学生四则运算大考验&…

Chrome开发者工具详解

作为一名前端开发者,打交道最多的可能是和浏览器。市面上各种浏览器多不胜数,主流的有Chrome,Firefox,Safari,IE,Opera,非主流的如360,遨游,QQ浏览器,搜狗浏览…

redis学习笔记-安装与入门

Linux下安装redis mkdir /usr/local/redis && cd /usr/local/redis 下载:wget http://download.redis.io/releases/redis-3.0.5.tar.gz 解压:tar xzf redis-3.0.5.tar.gz 安装到指定目录: cd redis-3.0.5 make PREFIX/usr/local/red…

靠能力赚大钱,是最最可笑的谎言

很多人其实到现在也没弄明白他们是怎么赚钱的,很多人都会把自己成功归结为能力的结果,事实上这个是最大的可悲……靠能力赚钱,是一个弥天大谎!我自己一直在反思这些年里的很多事情,突然发现所有的成功失败,…

WPF自定义控件与样式(1)-矢量字体图标(iconfont)

原文:WPF自定义控件与样式(1)-矢量字体图标(iconfont)一.图标字体 图标字体在网页开发上运用非常广泛,具体可以网络搜索了解,网页上的运用有很多例子,如Bootstrap。但在C/S程序中使用还不多,字体图标其实就是把矢量图…

css3 loading 效果1

代码&#xff1a; <!doctype html> <html lang"en"> <head> <meta charset"UTF-8"> <title>Document</title> <style> #box{position: relative;margin: 100px;} #box span{display: block;width: 9px;height: …

类成员函数解析

1、 构造函数&#xff1a; &#xff08;1&#xff09; 定义&#xff1a;是一个特殊的成员函数&#xff0c;名字与类名相同&#xff0c;创建类类型对象时&#xff0c;由编译器自动调用&#xff0c;在对象的生命周期内只且只调用一次&#xff0c;以保证每个数据成员都有一…

add-apt-repository cloud-archive:liberty

apt-get update && apt-get upgrade; v

C++ 继承解析

继承 1、概念&#xff1a; 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能。这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体…

[傅里叶变换及其应用学习笔记] 九. 继续卷积的讨论

这份是本人的学习笔记&#xff0c;课程为网易公开课上的斯坦福大学公开课&#xff1a;傅里叶变换及其应用。 卷积在滤波中的应用 浑浊度&#xff08;Turbidity&#xff09;研究是关于测量水的清澈度的研究。大致方法是把光传感器放置到深水区域&#xff0c;然后测量光线的昏暗程…

C++多态相关关问题及虚表剖析

关于C多态的问题&#xff1a;&#xff08;基于Visual Studio 2012编译器&#xff09; 一、多态引入 1、对象的类型&#xff1a; &#xff08;1&#xff09; 静态的类型&#xff1a;对象声明时的类型&#xff0c;在编译的时候确定 &#xff08;2&#xff09; 动态的类型&…

C++调用约定

<div class"markdown_views"><p>有一定C开发经验的人一定对”__cdecl、__stdcall、__fastcall”肯定不陌生吧&#xff01;但你真正理解了吗&#xff1f;是的&#xff0c;我曾在这采了无数个坑&#xff0c;栽了无数个跟头&#xff0c;终于忍无可忍要把它总…

C++动态绑定及返回类型协变

C多态之动态绑定&#xff1a; 1、概念&#xff1a;在程序执行期间(非编译期)判断所引用对象的实际类型&#xff0c;根据其实际类型调用相应的方法。 使用virtual关键字修饰类的成员函数时&#xff0c;指明该函数为虚函数&#xff0c;派生类需要重新实现&#xff0c;编译器将实…