zoukankan      html  css  js  c++  java
  • 尝试MatCap类型shader

    听说MatCap能在低端机上做出很漂亮的pbr效果,就尝试了一下。

    MatCap全称MaterailCapture,里面存的是光照信息,通过法线的xy分量去采样matcap,得到在该方向法线的光照信息,因为不是实时光照,所以性能好,好不好看就看你的Matcap做得好不好了。下面是简单的matcap尝试:

    Shader "Unlit/SimpleMatCapShader"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _MatCap("MatCap", 2D) = "white" {}
            _MatCapFactor("MatCapFactor", Range(0,5)) = 1
            _EnvTex("EnvTex (CubeMap)", Cube) = "_SkyBox" {}
            _EnvFactor("EnvStrength", Range(0,1)) = 0.8
        }
    
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float3 normal : NORMAL;
                };
    
                struct v2f
                {
                    float4 twoUv : TEXCOORD0;//主纹理uv存xy,matCapUv存在zw,这算一种优化
                    float4 vertex : SV_POSITION;
                    float3 RefDir : TEXCOORD1;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                sampler2D _MatCap;
                half _MatCapFactor;
                samplerCUBE _EnvTex;
                half _EnvFactor;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.twoUv.xy = TRANSFORM_TEX(v.uv, _MainTex);
                    //matcap存的其实是:法线中xy分量作为uv,对应的光照颜色信息,即用xy去采样就好,注:xy必须是归一化法线中的分量,故z才没必要
                    o.twoUv.zw = UnityObjectToWorldNormal(v.normal).xy;
                    o.twoUv.zw = o.twoUv.zw * 0.5 + 0.5;//(-1,1)->(0,1)
                    float3 wolrdN = UnityObjectToWorldNormal(v.normal);
                    o.RefDir = reflect(-WorldSpaceViewDir(v.vertex), wolrdN);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {
                    // sample the texture
                    fixed4 col = tex2D(_MainTex, i.twoUv.xy);
                    fixed4 mapCapCol = tex2D(_MatCap, i.twoUv.zw);
                    fixed4 reflection = texCUBE(_EnvTex, i.RefDir);
                    col.rgb = col.rgb * mapCapCol.rgb * _MatCapFactor + reflection.rgb * _EnvFactor;
                    return col;
                }
                ENDCG
            }
        }
    }

    各种效果如下:

    matCap贴图的获取:

    这边提供几个可以获取MatCap贴图的网址:

    [1] https://www.pinterest.com/evayali/matcap/

    [2]https://www.google.com.hk/search?q=MatCap&newwindow=1&safe=strict&hl=zh-CN&biw=1575&bih=833&tbm=isch&tbo=u&source=univ&sa=X&ved=0ahUKEwju8JDTpZnSAhUGn5QKHawODTIQsAQIIg

    [3]http://pixologic.com/zbrush/downloadcenter/library/#prettyPhoto

    总结,如果matcap做得好,确实能得到非常漂亮的效果,关键是,只是多一张tex就能获得如此效果,不错不错。

      许多资料都没有讲到,但我个人以为,matcap其实是缤纷多彩的高光效果。普通高光一般是单一的白色,或其他单色,matcap因为用图片存不同“斜率”的法线的高光颜色,所以可以做得更加漂亮,这个可以看下图:

                                

                                    一个matcap纹理图

                   (因为法线先x,y,z归一化(一个单位球体),后取其中的x,y采用,所以[x,y]必定束缚在圆中,

                            所以matcap都是圆,即使不是,也只有圆内纹理有效)

    从上面shader可知我们先把法线从[-1,1]映射到[0,1]后再采样,这个是由于matcap坐标是从0开始的,为了更加直观的理解,我们反其道行之:

      把matcap图片的坐标从[0,1]映射到[-1,1]。

    则,明显地,图片中间就是[0,0],即普通笛卡尔坐标系的原点,此时,法线区间是[-1,1],matcap图的坐标区间也是[-1,1],一一对应,每个像素的法线根据其大小和方向在matcap图中取值,得到的就是这个像素的高光颜色,这样,matcap的效果也变得很直观了。

  • 相关阅读:
    曾经收藏过的好文,唯快不破
    思想上的差距,各种差距,看完再说
    GO的初始简书(一)简介安装
    php 使用composer
    微信开发~又来一拨(本人崇尚开源)
    PHP 底层的运行机制与原理 --转
    关于cgi、FastCGI、php-fpm、php-cgi
    winows 服务器环境搭建 (碰到了windows服务器,小记一下吧~)
    python方法的重写
    python继承简介
  • 原文地址:https://www.cnblogs.com/Tearix/p/6878954.html
Copyright © 2011-2022 走看看