MatCap模拟光照效果实现

news2024/11/26 7:35:19

大家好,我是阿赵
之前介绍过各种光照模型的实现方法。那些光照模型的实现虽然有算法上的不同,但基本上都是灯光方向和法线方向的计算得出的明暗结果。
下面介绍一种叫做MatCap的模拟光照效果,这种方式计算非常简单,脱离灯光的计算,并可以实现比较好的高光阴影效果。

一、什么是MatCap

1、MatCap的介绍:

在这里插入图片描述

MatCap是Material Capture的缩写,意思是“材质捕获”。
听名字好像很高端并且深奥,实际上却并不是什么很深奥的东西。
MatCap贴图的样子一般是这样的:
在这里插入图片描述

2、MatCap的实现原理

MatCap实现的原理很简单,把物体的世界空间法线,转换到观察空间,然后用这个值作为UV,采样MatCap贴图。所以,如果当物体是一个球体的时候,它的法线角度应该是刚刚好和MatCap贴图完全一样,所以,如果把MatCap材质赋给一个球体,它应该是会得到和MatCap贴图一样的效果,比如我拿上面那张MatCap贴图放到MatCap材质球里面,会得到这样的效果:
在这里插入图片描述

如果物体不是一个球形,由于各个面的法线变化,所以会得到这样的效果:
在这里插入图片描述

不过如果直接算世界法线转观察空间法线,会存在一个问题,如果物体偏离视窗中心点之后,会在物体边缘出现一些奇怪的颜色
在这里插入图片描述

这是因为我们的MatCap贴图只有中间圆形绘制了光影颜色,在贴图的边缘的颜色是不对的
在这里插入图片描述

在计算观察空间的时候,如果偏离屏幕中心点太多,会不小心采样到了贴图的边缘。
要解决这个问题其实也很简单,给算出来的MatCap的UV用一个变量来控制一下缩放,让UV坐标不要超出一定范围就行了。
在这里插入图片描述

二、MatCap实现的代码

下面是Unity引擎的shader

Shader "AzhaoMatCap"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
		_MatCapTex("MatCapTex", 2D) = "white" {}
		_MatCapIntensity("MatCapIntensity",Range(0,2)) = 1
		_MatCapPow("MatCapPow",Range(0,5)) = 1
		_MatCapUVScale("MatCapUVScale",Range(0,1)) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
			Cull off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float3 normal:NORMAL;
            };

            struct v2f
            {                
                float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 normal:TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
			sampler2D _MatCapTex;
			float _MatCapIntensity;
			float _MatCapPow;
			float _MatCapUVScale;

			float2 GetMatCapUV(float3 objNormal)
			{
				float3 normalWorld = mul(unity_ObjectToWorld, objNormal);
				float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld);
				return normalView.xy*0.5+0.5;
			}

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = v.normal;
                return o;
            }

			float4 frag (v2f i) : SV_Target
            {
                // sample the texture
                float4 col = tex2D(_MainTex, i.uv);
				float2 MatCapUV = GetMatCapUV(i.normal)*_MatCapUVScale;
				float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity;
				MatCapCol = pow(MatCapCol, _MatCapPow);
				float3 finalCol = col.rgb*MatCapCol.rgb;

                return float4(finalCol,col.a);
            }
            ENDCG
        }
    }
}

代码很简单,通过法线方向获取MatCap的UV,都写在GetMatCapUV方法里面了,就2、3行代码而已。
然后我个人习惯,为了控制一个叠加颜色的强度和对比度,我都是先乘再pow。
最后再给了一张MainTex贴图,作为混合固有色的例子。

三、MatCap的优缺点和应用

1、优点

1.比起真实的光照模型,MatCap计算量很少,只是算个UV采样一张贴图就可以了
2.光照效果非常的可控,可以自己绘制喜欢的高光、阴影和补光的效果
在固定摄像机角度和光照方向的情况下,用MatCap模拟物体的材质,通过使用不同的MatCap贴图,可以达到很强的质感

2、缺点

MatCap的缺点也很明显,因为它的光照效果是假的,所以从不同的角度观察物体,它的光照是不会变化的,也不能做到跟随灯光旋转变化而变化。
所以MatCap的效果一般只能用于固定摄像机和灯光角度的情况下。

3、应用

下面换了几张不同的MatCap贴图,可以看出,物体有了非常强的质感。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面的shader代码里面,我最后是用乘法来和MainTex颜色叠加,是因为我想MatCap同时产生亮部和暗部的效果。其实我们也可以单纯用MatCap来叠加某个部分的效果,比如,可以改成用加法,然后MatCap贴图只绘制高光部分,其余部分都涂黑。这样我们可以通过MatCap来单纯的叠加高光部分,然后暗部使用烘焙贴图或者顶点颜色来实现,也是可以的。
虽然说MatCap只能用于固定角度,但如果通过贴图遮罩,只限于模型的某些小局部的金属之类强高光的地方显示,其实也能在模型转动或者运动的时候,产生比较不错的质感。
MatCap的其他应用,各位可以再发挥一下想象力。

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

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

相关文章

javaWeb核心05-FilterListenerAjax(Axios)json

文章目录Filter&Listener&Ajax1,Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题1.6 案例1.6.1 需求1.6.2 分析1.6.3 代码实现1.6.3.1 创建F…

Linux 安装 nginx 详细教程

文章目录Linux 安装 nginx 详细步骤①安装依赖包②下载并解压安装包③安装 nginx④启动 nginx 服务⑤配置 nginx.conf提示:以下是本篇文章正文内容,Linux 系列学习将会持续更新 Linux 安装 nginx 详细步骤 ①安装依赖包 下载模块依赖性 Nginx 需要依赖…

resp无法连接Redis服务的解决方法

在保证Windows主机和Linux虚拟机能够相互ping通的前提下,resp仍无法连接到Linux上的redis服务,那么需要考虑以下原因: Linux防火墙问题,Linux未关闭防火墙,或防火墙未放通6379/tcp端口;redis配置问题&#…

Project ERROR: Unknown module(s) in QT: webenginewidgets

Qt系列文章目录 文章目录Qt系列文章目录前言一、问题定位二、解决方法1.引入WebEngine库2.重新打开工程3. 解决办法:运行结果前言 最近项目中需要用到:Qt中使用cesium三维引擎库,涉及到Qt和和JavaScript之间通信,工程源码报错&am…

202109-3 CCF 脉冲神经网络 66分题解 + 解题思路 + 解题过程

解题思路 根据题意&#xff0c;脉冲源的阈值大于随机数时&#xff0c;会向其所有出点发送脉冲 神经元当v>30时&#xff0c;会向其所有出点发送脉冲&#xff0c;unordered_map <int, vector > ne; //存储神经元/脉冲源的所有出点集合vector 所有脉冲会有一定的延迟&am…

opencv-图像操作

访问和修改像素值 我们先加载一个彩色图像&#xff1a; import cv2img cv2.imread(b.png) print(img)########### 打印结果 ########### [[[243 243 243][243 243 243][243 243 243]...[243 243 243][243 243 243][243 243 243]][[243 243 243][243 243 243][243 243 243].…

每天五分钟机器学习:你理解贝叶斯公式吗?

本文重点 贝叶斯算法是机器学习算法中非常经典的算法,也是非常古老的一个算法,但是它至今仍然发挥着重大的作用,本节课程及其以后的专栏将会对贝叶斯算法来做一个简单的介绍。 贝叶斯公式 贝叶斯公式是由联合概率推导而来 其中p(Y|X)称为后验概率,P(Y)称为先验概率…

mysql navicat忘记密码

mysql忘记密码是常用的事情&#xff0c;那么如何解决它呢&#xff1f;1、首先将MySQL的服务关闭&#xff0c;两种方法&#xff1a;&#xff08;1&#xff09;打开命令行cmd输入net stop mysql命令即可关闭MySQL服务。&#xff08;2&#xff09;打开任务管理器&#xff0c;找到服…

【观察】亚信科技:“飞轮效应”背后的数智化创新“延长线”

著名管理学家吉姆柯林斯在《从优秀到卓越》一书中提出“飞轮效应”&#xff0c;它指的是为了使静止的飞轮转动起来&#xff0c;一开始必须使很大的力气&#xff0c;每转一圈都很费力&#xff0c;但达到某一临界点后&#xff0c;飞轮的重力和冲力就会成为推动力的一部分&#xf…

海思ubootsd卡协议

在start_armboot()函数中调用mmc_initialize(0)初始化mmc;最终调用到int hi_mci_initialize(unsigned int dev_num)函数;内容如下:static int hi_mci_initialize(unsigned int dev_num) {struct mmc *mmc NULL;static struct himci_host *host;unsigned int regval;unsigned l…

磨皮插件portraiture2023最新中文版

Portraiture滤镜是一款 Photoshop&#xff0c;Lightroom 和 Aperture 插件&#xff0c;DobeLighttroom 的 Portraiture 消除了选择性掩蔽和逐像素处理的繁琐的手工劳动&#xff0c;以帮助您在肖像修整方面取得卓越的效果。它是一个强大的&#xff0c;但用户友好的插件照明.这是…

深度解析首个Layer3 链 Nautilus Chain,有何优势?

以流支付为主要概念的Zebec生态&#xff0c;正在推动流支付这种新兴的支付方式向更远的方向发展&#xff0c;该生态最初以Zebec Protocol的形态发展&#xff0c;并从初期的Solana进一步拓展至BNB Chian以及Near上。与此同时&#xff0c;Zebec生态也在积极的寻求从协议形态向公链…

观察UE4里“在外部存储Actor”功能的基础行为

目标 一般情况下&#xff0c;Actor保存于关卡文件中。 但是&#xff0c;如果将Actor的 packaging mode 设置为 External&#xff1a; 则此Actor就会存储在另一个文件而非关卡文件中。 本篇目标是&#xff1a; 观察此功能的基础行为观察外部文件的路径名规则 “在外部存储A…

Nacos安装指南,Windows安装

Nacos安装指南 1.Windows安装 1.1.下载安装包 在Nacos的GitHub页面&#xff0c;提供有下载链接&#xff0c;可以下载编译好的Nacos服务端或者源代码&#xff1a; GitHub主页&#xff1a;https://github.com/alibaba/nacos GitHub的Release下载页&#xff1a;https://githu…

一文打通Sleuth+Zipkin 服务链路追踪

1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位。主要体现在&#xff0c;一个请求可能需要…

学习服务器上运行论文代码(二)

文章目录程序运行异常VScode 报shell集成无法激活的问题无法加载文件 C:\Users\haoqi\Documents\WindowsPowerShell\profile.ps1&#xff0c;连接服务器插件程序运行异常 书接上回。 程序能跑起来&#xff0c;但是会出现两种异常。 异常一&#xff1a;运行进度条在走&#xff…

Lambda表达式和steram流

目录 引言&#xff1a; 语法: Lambda 表达式实例&#xff1a; demo演示&#xff1a; Stream流&#xff1a; 引言&#xff1a; Lambda 表达式&#xff0c;也可称为闭包&#xff0c;它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数&#xff08;函…

Redis技术分享——缓存常见应用场景问题?

什么是redis&#xff1f; Redis是Remote Dictionary Server的简称&#xff0c;是一个由意大利人Salvatore Sanfilippo开发的key-value存储系统&#xff0c;具有极高的读写性能&#xff0c;读的速度可达110000次/s&#xff0c;写的速度可达81000次/s 。今天主要是分享redis的缓…

Excel查找函数(VLOOKUP\SEARCH\FIND\MATCH)

文章目录查找纵向VLOOKUP函数eg1已知身份证查姓名eg2已知身份证查地区Find函数FindB函数SEARCH函数SEARCHBMATCH函数查找 纵向VLOOKUP函数 VLOOKUP(lookup_value,table_array,col_index_num,[range_lookup])lookup_value&#xff1a;要查找的值 table_array&#xff1a;要查找…

【测试】性能测试

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录目标一、性能测试概述二、常见的性能测试指标三、性能测试的分类四、loadrunner工具介绍&#xff08;LR&#xff09;一&#xff09;VUG&#xff1a;虚拟用户发生器二&#xff09;Controller三&#xff09;Analysis小…