查看原文
其他

MatCap && Cocos Creator Shader

lamyoung 白玉无冰 2022-06-10

在某些层面能替代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 是什么

MatCap 有以下几个特点

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

对于法向量纹理映射方法,在https://github.com/nidorx/matcaps中使用的是法向量的x,y值。(本demo也是采用这种实现方式)

在相机空间下的物体法线,可以不考虑Z轴。因为法线是一个单位向量,如果法线在XY方向上的投影权重很大,那么说明在Z方向的权重就很小,对应到二维的MatCap上采样的位置越靠近边缘;而如果法线在XY方向的投影权重很小,那么Z方向的权重就很大,对应到二维的MatCap上的采样位置就越靠近中心。

MatCap的 基于法向量的实现

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

MatCap 基于反射向量的实现原理

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

MatCap 基于反射向量的实现glsl

有几张方法可以制作 MatCap 贴图

  • 3d建模软件
  • 用游戏引擎渲染
  • 真实相机拍摄
  • 艺术家手绘
制作 MatCap 的方法

小结

完整代码工程: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

更多

如何抄shader  3D折纸  渐变色文字3.0  水排序效果  转向行为AI


点击“阅读原文”查看精选导航

“点赞“ ”在看” 鼓励一下

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存