MatCap && Cocos Creator Shader
在某些层面能替代PBR的次世代渲染方案。
效果
动图

视频
https://www.bilibili.com/video/BV1B64y147xc
实现
实现原理是,用一张特制的纹理图(采样出来的纹理),加上一段shader代码(法向量映射纹理),模拟出次世代的效果(场景中无需光照)。

代码
参考 https://github.com/nidorx/matcaps 中的核心代码,在 Cocos Creator 3.1.0
中实现的effect
代码如下。
CCEffect %{
techniques:
- name: opaque
passes:
- vert: unlit-vs:vert # builtin header
frag: unlit-fs:frag
properties: &props
mainTexture: { value: white }
- name: transparent
passes:
- vert: unlit-vs:vert # builtin header
frag: unlit-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
blendSrcAlpha: src_alpha
blendDstAlpha: one_minus_src_alpha
properties: *props
}%
CCProgram unlit-vs %{
precision highp float;
#include <input-standard>
#include <cc-global>
#include <cc-local-batch>
out vec2 v_uv;
out vec3 v_normal;
vec4 vert () {
StandardVertInput In;
CCVertInput(In);
vec4 position = In.position;
mat4 matWorld, matWorldIT;
CCGetWorldMatrixFull(matWorld, matWorldIT);
v_normal = normalize((matWorldIT * vec4(In.normal.xyz, 0.0)).xyz);
v_uv = a_texCoord;
return cc_matProj * (cc_matView * matWorld) * position;
}
}%
CCProgram unlit-fs %{
precision highp float;
#include <output>
#include <cc-global>
in vec2 v_uv;
in vec3 v_normal;
uniform sampler2D mainTexture;
vec4 frag () {
highp vec2 muv = vec2(cc_matView * vec4(normalize(v_normal), 0))*0.5+vec2(0.5,0.5);
// read texture inverting Y value
vec4 col = texture(mainTexture, vec2(muv.x, 1.0-muv.y));
return CCFragOutput(col);
}
}%
关于如何移植shader
代码,可参考上一篇文章《如何抄一个 shader 到 Cocos Creator》
MatCap
MatCap (Material Capture
) 是一个包含了光照和反射等信息的贴图,运行时使用法线方向进行采样。

MatCap
有以下几个特点
无需光照的计算,运行效率高。 对于同一材质,只需一个纹理球贴图,贴图通用。 因为光照是写在贴图里的,不适合精准光照的情况(例如旋转摄像机角度)。

对于法向量纹理映射方法,在https://github.com/nidorx/matcaps中使用的是法向量的x,y
值。(本demo也是采用这种实现方式)
在相机空间下的物体法线,可以不考虑Z轴。因为法线是一个单位向量,如果法线在XY方向上的投影权重很大,那么说明在Z方向的权重就很小,对应到二维的MatCap上采样的位置越靠近边缘;而如果法线在XY方向的投影权重很小,那么Z方向的权重就很大,对应到二维的MatCap上的采样位置就越靠近中心。

在https://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader/介绍了一种基于反射向量的实现。

既可以逐顶点实现,也可逐像素实现,参考代码如下。

有几张方法可以制作 MatCap
贴图
3d建模软件 用游戏引擎渲染 真实相机拍摄 艺术家手绘

小结
完整代码工程:https://github.com/baiyuwubing/cocos-creator-examples/tree/master/awesome-shader
以上为白玉无冰使用 Cocos Creator 3.1.0
实现 "MatCap Shader"
的技术分享。
扩展阅读
https://github.com/nidorx/matcaps
https://www.clicktorelease.com/blog/creating-spherical-environment-mapping-shader/
https://medium.com/playkids-tech-blog/matcap-render-art-pipeline-optimization-for-mobile-devices-4e1a520b9f1a
https://zhuanlan.zhihu.com/p/347947799
https://zhuanlan.zhihu.com/p/27339998
更多
点击“阅读原文”查看精选导航
“点赞“ ”在看” 鼓励一下▼