当前位置: 首页 > news >正文

UE 【材质编辑】自定义ShadingMode

【UE 4.27.2】

在UE中提供了多种多样的ShadingMode,相当于一种风格化的处理方案(整体全面的流程调整),切换ShadingMode可以看到不同的显示效果:

通过简单的拓展,我们可以实现自定义的ShadingMode,使得我们切换到自己的ShadingMode时可以直接应用上我们自己的一套风格化效果(极大的提高材质编辑效率)。

1.编辑器添加ShadingMode选项

材质编辑面板

为了能让自定义的ShadingMode显示在材质编辑面板,首先找到EMaterialShadingModel这个枚举(EngingTypes.h),在其中键入我们自定义ShadingModel的枚举值:

【EngingTypes.h定义了大量的系统枚举值,都值得好好的研究使用】

有了此枚举值,编译代码时,会自动在EngineTypes.generateed.h生成对应的字段

我们还可以为我们自定义的ShadingMode启用材质面板上可以连接的Pin接口:在Material.cpp的IsPropertyActive_Internal,使得我们使用自定义ShadingMode时,启用CustomData0这个Pin

并且还可以在MaterialShader.cpp :: FMaterialAttributeDefinitionMap::GetAttributeOverrideForMaterial中定制,在我们这个ShadingModel下,Pin接口显示的名字:

控制Shader逻辑

以上我们完成了对材质编辑面板的显示改造,但Shader还并不受控制。对于Shader的控制,则通过宏来实现:在FHLSLMaterialTranslator::GetMaterialEnvironment中根据ShadingModel向Shader中压入一条宏”MATERIAL_SHADINGMODEL_MY_CUSTOM_MODE“

那么在Shader中就可以根据这个宏来决定执行流程。

2.Shader中执行

根据压入的宏,我们定义自己的一套算法:

在ShadingModelsMaterial.ush::setGBufferForShadingModel中:

在GBuffer中存入我们算法所需的数据。

要完成这一步,还需要如下两步:

定义Shader中的ShadingModel

如上图:GBuffer.ShadingModelID = SHADINGMODELIG_MY_CUSTOM_MODEL;

SHADINGMODELIG_MY_CUSTOM_MODEL从何而来?预定义

要注意不仅要自定义这个宏,还要把NUM在原有基础上+1;

允许往GBuffer写数据

部分Shader需要往customData通道写数据,多个条件使用||连接(注意换行带Tab可能编译出错)

完成了上述两步,我们的数据就能写入到GBuffer里边了。

应用GBuffer中数据实现自定义逻辑

根据我们传递到GBuffer中的数据,我们可以组织实现自己的算法逻辑:

一个很简单的实现:直接控制着色表现,将该ShadingModel模式下的着色完全改变为某个纯色

编译,查看此时的效果:

当我们不往CustomDta接口上连节点:

因为GBuffer.CustomData.x==0,则return float4(0.0,1.0,0.0,1.0);

当我们连接一个固定值“1”:

奇怪的是结果并没有改变,此时,尝试对比SHADINGMODELID_EYE,发现Shader中有这么一个可以的函数:

继续查看其使用:仅对特殊的ShadingModel才支持GBufferD的数据,否则就是0

于是我们在HasCustonGBufferData中拓展:

当我们将时间值接入做成动画:

3.添加ShadingModel的显示色

当作一个debug工具来用吧,看到这个颜色表示我们的ShadingModel应用是成功的。

在ShadingsCommon.ush::GetShadingModelColor中,指定对应ShadingModel的演示色:

那么在编辑器中,做如下切换时,就能看到对应的颜色:

4.卡通效果ShadingModel

接着上述成果,已经可以做到控制输出结果。那么要实现卡通效果,则是对光照计算过程的修正,即替换这里的计算逻辑。

向下:

深入GetDynamicLightingSplit:

里边会调用IntegrateBxDF,进入发现:这里根据不同的ShadingModel选择了不同的反射方案

为此,我们定义卡通效果的BxDF:

FDirectLighting CartoonCustomBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow )
{
#if GBUFFER_HAS_TANGENThalf3 X = GBuffer.WorldTangent;half3 Y = normalize(cross(N, X));
#elsehalf3 X = 0;half3 Y = 0;
#endifBxDFContext Context;Init( Context, N, X, Y, V, L );SphereMaxNoH( Context, AreaLight.SphereSinAlpha, true );Context.NoV = saturate( abs( Context.NoV ) + 1e-5 );FDirectLighting Lighting;//====================================//自定义diffuse实现float customValue=GBuffer.CustomData.x*0.5f;float diffValue=smoothstep(0.5f-customValue,0.5f+customValue,Falloff*NoL);Lighting.Diffuse=AreaLight.FalloffColor*diffValue*Diffuse_Lambert(GBuffer.DiffuseColor);//====================================if( AreaLight.bIsRect )Lighting.Specular = RectGGXApproxLTC( GBuffer.Roughness, GBuffer.SpecularColor, N, V, AreaLight.Rect, AreaLight.Texture );elseLighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX( GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, Context, NoL, AreaLight );Lighting.Transmission = 0;return Lighting;
}

向上:

已经定义好卡通效果的BxDF,那么什么地方调用?即GetDynamicLighting在哪里调用:

通过全局搜索,可知:

分析这个结果,主要是两个函数:

再对这两个函数的调用进行查看:

于是补充GET_LIGHT_GRID_LOCAL_LIGHTING_SINGLE_SM部分

另一处与之类似,也做对应补充。

【最终效果看上去有点问题】

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [Labview]图片叠加下的表格视图拖拽功能:挖坑粗糙版
  • IP SSL证书——为IP升级加密
  • 力扣1235.规划兼职工作
  • 住宅代理将如何保护您的品牌?
  • 如何在 MySQL 中匹配列
  • 微电网光储充用什么电能表?
  • SpringBoot教程(二十七) | SpringBoot集成AOP实现异常处理
  • Kubernetes 1.20 上将容器从 Docker Engine 改为 Containerd
  • 视频智能分析打手机检测算法安防监控打手机检测算法应用场景、算法源码、算法模型介绍
  • 【杭州】目前就业情况-自述
  • Docker安装Neo4j图数据库和APOC插件
  • 指尖疯2024年下半年软考报名快报:赛程过半,你报名成功了吗?
  • Python爬虫案例四:爬取某个博主的所有文章保存成PDF格式
  • 好文分类汇总
  • leetcode209. Minimum Size Subarray Sum
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 《深入 React 技术栈》
  • 10个最佳ES6特性 ES7与ES8的特性
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Create React App 使用
  • iOS编译提示和导航提示
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • spring学习第二天
  • v-if和v-for连用出现的问题
  • Webpack 4x 之路 ( 四 )
  • 基于axios的vue插件,让http请求更简单
  • 坑!为什么View.startAnimation不起作用?
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 每天10道Java面试题,跟我走,offer有!
  • 如何在GitHub上创建个人博客
  • 原生JS动态加载JS、CSS文件及代码脚本
  • mysql面试题分组并合并列
  • scrapy中间件源码分析及常用中间件大全
  • ​flutter 代码混淆
  • # 飞书APP集成平台-数字化落地
  • #java学习笔记(面向对象)----(未完结)
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • $.ajax()参数及用法
  • (1) caustics\
  • (1)(1.11) SiK Radio v2(一)
  • (function(){})()的分步解析
  • (动态规划)5. 最长回文子串 java解决
  • (二)c52学习之旅-简单了解单片机
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (十七)Flink 容错机制
  • (十三)Flask之特殊装饰器详解
  • (转)关于pipe()的详细解析
  • (转)原始图像数据和PDF中的图像数据
  • **python多态
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?