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

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

Shader "Unlit/SimpleMatCapShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_MatCap("MatCap", 2D) = "white" {}
_MatCapFactor("MatCapFactor", Range(,)) =
_EnvTex("EnvTex (CubeMap)", Cube) = "_SkyBox" {}
_EnvFactor("EnvStrength", Range(,)) = 0.8
} SubShader
{
Tags { "RenderType"="Opaque" }
LOD 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的效果也变得很直观了。

尝试MatCap类型shader的更多相关文章

  1. 【Unity Shader编程】之十六 基于MatCap实现适于移动平台的“次时代”车漆Shader

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/55803629 渲染本文配图使用的 ...

  2. Asp.net 面向接口可扩展框架之类型转化基础服务

    新框架正在逐步完善,可喜可贺的是基础服务部分初具模样了,给大家分享一下 由于基础服务涉及面太广,也没开发完,这篇只介绍其中的类型转化部分,命名为类型转化基础服务,其实就是基础服务模块的类型转化子模块 ...

  3. Unity3d 着色器语法(Shader)

    Shader "name" { [Properties] Subshaders [Fallback] } 定义了一个着色器.着色器拥有一个 Properties 的列表.着色器包含 ...

  4. WCF 已知类型和泛型解析程序 KnownType

    数据协定继承 已知类型和泛型解析程序 Juval Lowy 下载代码示例 自首次发布以来,Windows Communication Foundation (WCF) 开发人员便必须处理数据协定继承方 ...

  5. (CLR-Via-C#) 类型基础

    CLR要求每个类型最终都派生自System.Object Object提供的公共方法: Equals: 如果两个对象具有相同的值,就返回true GetHashCode: 返回对象的哈希码 ToStr ...

  6. 【Unity Shader实战】卡通风格的Shader(一)

    写在前面 本系列其他文章: 卡通风格的Shader(二) 呜,其实很早就看到了这类Shader,实现方法很多,效果也有些许不一样.从这篇开始,陆续学习一下接触到的卡通类型Shader的编写. 本篇的最 ...

  7. 变量和基本类型——复合类型,const限定符,处理类型

    一.复合类型 复合类型是指基于其他类型定义的类型.C++语言有几种复合类型,包括引用和指针. 1.引用 引用并非对象,它只是为一个已存在的对象所起的另外一个名字. 除了以下2种情况,其他所有引用的类型 ...

  8. CLR-基元类型以及溢出检查 (CLR-Via-C#) 类型基础

    CLR-基元类型以及溢出检查   =========(CLR via C#阅读笔记)======== 基元类型(primitive type): 基元类型也不做过多的解释,举个例子即可清晰的辨别 在j ...

  9. Unity Built-In Shader造成的运行时内存暴涨

    在某个PC项目中使用了大量的材质球, 并且都使用了自带的Standard Shader, 在编辑器运行的时候, 一切良好, 运行内存只在1G左右, 然而在进行AssetBundle打包之后, EXE运 ...

随机推荐

  1. 使用Flask开发简单接口(3)--引入MySQL

    前言 前面的两篇文章中,我们已经学习了通过Flask开发GET和POST请求接口,但一直没有实现操作数据库,那么我们今天的目的,就是学习如何将MySQL数据库运用到当前的接口项目中. 本人环境:Pyt ...

  2. NCoreCoder.Aop 国庆更新

    原本的IAopActors如下 public interface IAopActors { object Execute(AopContext context); Task<TResult> ...

  3. ORACLE在linux下的启动方法

    一.启动方法 方法1: Sql代码 cd $ORACLE_HOME/bin #进入到oracle的安装目录  ./dbstart #重启服务器  ./lsnrctl start #重启监听器 ---- ...

  4. 017_go语言中的指针

    代码演示 package main import "fmt" func zeroval(ival int) { ival = 0 } func zeroptr(iptr *int) ...

  5. 8、Builder 建造者模式 组装复杂的实例 创造型模式

    1.什么是Builder模式 定义: 将一个复杂对象的构建与表示相分离,使得同样的构建过程可以创建不同的表示.大白话就是,你不需要知道这个类的内部是什么样的,只用把想使用的参数传进去就可以了,达到了解 ...

  6. java_流程控制语句、权限修饰符

    判断语句 if语句第一种格式: if if(关系表达式){ 语句体; } if语句第二种格式: if…else if(关系表达式) { 语句体1; } else { 语句体2; } if语句第三种格式 ...

  7. 初识TypeScript:查找指定路径下的文件按类型生成json

    如果开发过node.js的话应该对js(javascript)非常熟悉,TypeScript(以下简称ts)是js的超集. 下面是ts的官网: https://www.tslang.cn/ 1.环境配 ...

  8. Vue组件通信之父传子

    一般情况下,子组件中无法直接使用父组件的变量.借助子组件的props选项可以实现这一点. 这里我将一个vue实例作为一个父组件: const app = new Vue({ el:'#div1', d ...

  9. Java 二维数组及方法概况

    数组 数组是指一组数据的集合,数组中的每个数据被称作元素.在数组中可以存放任意类型的元素,但同一个数组里存放的元素类型必须一致. 数组的定义 在Java中,可以使用以下格式来定义一个数组. 数据类型[ ...

  10. MQC集群配置错误

    这个错误说明配置里面,MQC环境配置错了 运行war包时会读到本地的配置system-config.propertites文件