Unity - Normal mapping - Reoriented normal mapping - 重定向法线、混合法线

news2025/6/24 14:22:14

文章目录

  • 目的
  • 核心代码
  • PBR - Filament - Normal mapping
  • Shader
  • 效果
    • BlendNormal_Hill12
    • BlendNormal_UDN
    • BlendNormals_Unity_Native - 效果目前最好
  • Project
  • References


目的

备份、拾遗


核心代码

half3 blended_normal = normalize(half3(n1.xy + n2.xy, n1.z*n2.z));

PBR - Filament - Normal mapping

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


Shader

// jave.lin : 测试 法线重定向 (混合)

Shader "Test/TestingNormalmapBlending"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BumpMap ("Normal Map", 2D) = "bump" {}
        _BumpDetailMap ("Normal Detail Map", 2D) = "bump" {}
        _BumpBlending ("Bump Blending", Range(0.0, 1.0)) = 1.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                half3 normal :  NORMAL;
                half4 tangent : TANGENT; // xyz : dir, w : sign
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                half3 tangentWS :   TEXCOORD1;  // xyz : dir, w : view dir.y
                half3 normalWS :    TEXCOORD2;  // xyz : dir, w : view dir.x
                half3 binormalWS :  TEXCOORD3;  // xyz : dir, w : view dir.z
                float3 posWS : TEXCOORD4;       // xyz : world position
            };

            sampler2D _MainTex;
            sampler2D _BumpMap;
            sampler2D _BumpDetailMap;
            float4 _MainTex_ST;
            fixed _BumpBlending;
            fixed4 _LightColor0;

            half3 CustomUnpackScaleNormal(half4 packednormal, half bumpScale)
            {
                #if defined(UNITY_NO_DXT5nm)
                    half3 normal = packednormal.xyz * 2 - 1;
                    #if (SHADER_TARGET >= 30)
                        // SM2.0: instruction count limitation
                        // SM2.0: normal scaler is not supported
                        normal.xy *= bumpScale;
                    #endif
                    return normal;
                #elif defined(UNITY_ASTC_NORMALMAP_ENCODING)
                    half3 normal;
                    normal.xy = (packednormal.wy * 2 - 1);
                    normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
                    normal.xy *= bumpScale;
                    return normal;
                #else
                    // This do the trick
                    packednormal.x *= packednormal.w;

                    half3 normal;
                    normal.xy = (packednormal.xy * 2 - 1);
                    #if (SHADER_TARGET >= 30)
                        // SM2.0: instruction count limitation
                        // SM2.0: normal scaler is not supported
                        normal.xy *= bumpScale;
                    #endif
                    normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
                    return normal;
                #endif
            } // end custom unpack scale normal

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

                float4 posWS = mul(unity_ObjectToWorld, v.vertex);

                half3 normalWS = UnityObjectToWorldNormal(v.normal);

                half4 tangentWS = half4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
                half sign = tangentWS.w * unity_WorldTransformParams.w;
                half3 binormalWS = cross(normalWS, tangentWS) * sign;

                o.tangentWS     = tangentWS.xyz;
                o.normalWS      = normalWS.xyz;
                o.binormalWS    = binormalWS.xyz;

                o.posWS.xyz = posWS.xyz;

                return o;
            }

            half3 BlendNormal_Hill12(half3 N1, half3 N2)
            {
                return normalize(N1 * dot(N1, N2) - N2 * N1.z);
            }

            half3 BlendNormal_UDN(half3 N1, half3 N2)
            {
                return normalize(half3(N1.xy + N2.xy, N1.z));
            }

            half3 BlendNormals_Unity_Native(half3 n1, half3 n2)
            {
                return normalize(half3(n1.xy + n2.xy, n1.z*n2.z));
            }

            fixed4 frag (v2f i, fixed isFrontFace : VFACE) : SV_Target
            {
                half3 N = normalize(i.normalWS);
                N = isFrontFace >= 0 ? N : -N;

                half3 V = normalize(_WorldSpaceCameraPos - i.posWS.xyz);
                half3 T = normalize(i.tangentWS);
                half3 B = normalize(i.binormalWS);

                half3x3 TBN = half3x3(T, B, N);

                half3 N1_ts = CustomUnpackScaleNormal(tex2D(_BumpMap, i.uv.xy), 1.0);
                half3 N1 = mul(N1_ts, TBN);
                // return half4(N1.xyz, 1.0);

                half3 N2_ts = CustomUnpackScaleNormal(tex2D(_BumpDetailMap, i.uv.xy), 1.0);
                half3 N2 = mul(N2_ts, TBN);
                // return half4(N2.xyz, 1.0);

                // N = BlendNormal_Hill12(N1, N2);
                // N = BlendNormal_UDN(N1, N2);
                N = BlendNormals_Unity_Native(N1, N2); // jave.lin : 目前看着是: unity native 的效果是最好的
                N = lerp(N1, N, _BumpBlending);
                // return half4(N.xyz, 1.0);

                half3 L = _WorldSpaceLightPos0.xyz;

                half3 H = normalize(L + V);

                half NdotL = saturate(dot(N, L));
                half NdotH = saturate(dot(N, H));

                half diffuse = (NdotL);
                // return diffuse;
                half specular = pow((NdotH), 32) * 4.0;
                // return specular;

                fixed4 baseCol = tex2D(_MainTex, i.uv.xy);
                // half kd = 1 - specular;
                // diffuse *= kd;

                // return diffuse + specular;
                half3 finalCol = (diffuse + specular) * baseCol.rgb * _LightColor0.rgb + UNITY_LIGHTMODEL_AMBIENT.rgb * baseCol.rgb;

                return half4(finalCol.xyz, 1.0);
            }
            ENDCG
        }
    }
}


效果

                half3 N1_ts = CustomUnpackScaleNormal(tex2D(_BumpMap, i.uv.xy), 1.0);
                half3 N1 = mul(N1_ts, TBN);
                // return half4(N1.xyz, 1.0);

                half3 N2_ts = CustomUnpackScaleNormal(tex2D(_BumpDetailMap, i.uv.xy), 1.0);
                half3 N2 = mul(N2_ts, TBN);
                // return half4(N2.xyz, 1.0);

                N = BlendNormal_Hill12(N1, N2);
                // N = BlendNormal_UDN(N1, N2);
                // N = BlendNormals_Unity_Native(N1, N2); // jave.lin : 目前看着是: unity native 的效果是最好的
                N = lerp(N1, N, _BumpBlending);
                return half4(N.xyz, 1.0);

BlendNormal_Hill12

            half3 BlendNormal_Hill12(half3 N1, half3 N2)
            {
                return normalize(N1 * dot(N1, N2) - N2 * N1.z);
            }

在这里插入图片描述


BlendNormal_UDN

            half3 BlendNormal_UDN(half3 N1, half3 N2)
            {
                return normalize(half3(N1.xy + N2.xy, N1.z));
            }

在这里插入图片描述


BlendNormals_Unity_Native - 效果目前最好

            half3 BlendNormals_Unity_Native(half3 n1, half3 n2)
            {
                return normalize(half3(n1.xy + n2.xy, n1.z*n2.z));
            }

在这里插入图片描述


Project

Testing_NormalMap_Blending_2023.3.37f1_BRP.rar
提取码:ozgt


References

  • PBR filament normal mapping

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

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

相关文章

不是钉钉管理员如何批量复制公司全部人员名单到execl表格里

环境: Win10 专业版 钉钉V7.10.0 问题描述: 不是钉钉管理员,如何批量复制公司全员群里面全面人员名单 公司人员有388多个 解决方案: 1.打开公司全员群,右上角点开设置,点查看全部群成员 2.右侧成员一次复制几个&…

Vue-2.7自定义指令

自定义指令 自己定义的指令,可以封装一些dom操作,扩展额外功能 例如需求:当页面加载时,让元素将获得焦点(autofucus在safari浏览器有兼容性) 操作dom:dom元素.focus() 太麻烦!…

datax同步数据简介

概述 业务中经常会用到数据全量同步和增量同步,用sqlDump只能全量同步,而且数据量大的时候很慢。 阿里的datax目前是一款不错的同步工具 环境要求: jdk:1.8 python:2.7 maven:3.0 3.0的python跑不起来 ps:开源版的datax的mysql驱动还是用…

“零代码”能源管理平台:智能管理能源数据

随着能源的快速增长,有效管理和监控能源数据变得越来越重要。为了帮助企业更好的管理能源以及降低能源成本,越来越多的能源管理平台出现在市面上。 “零代码”形式的能源管理平台,采用IT与OT深度融合为理念,可进行可视化、拖拽、…

【C语言】每日一题(半月斩)——day4

目录 选择题 1、设变量已正确定义&#xff0c;以下不能统计出一行中输入字符个数&#xff08;不包含回车符&#xff09;的程序段是&#xff08; &#xff09; 2、运行以下程序后&#xff0c;如果从键盘上输入 65 14<回车> &#xff0c;则输出结果为&#xff08; &…

RabbitMQ消息中间件概述

1.什么是RabbitMQ RabbitMQ是一个由erlang开发的AMQP&#xff08;Advanced Message Queue &#xff09;的开源实现。AMQP 的出现其实也是应了广大人民群众的需求&#xff0c;虽然在同步消息通讯的世界里有很多公开标准&#xff08;如 COBAR的 IIOP &#xff0c;或者是 SOAP 等&…

皕杰报表中填报控件显示模式控制问题

填报报表是指能够向数据库上传数据的报表&#xff0c;皕杰报表填报单元格支持多种控件类型&#xff0c;包括文本框、文本域、下拉框、下拉树、单选框、复选框、时间、日期、日期时间… 这些控件类型在web页面上的显示模式在皕杰报表里设置了三种模式&#xff0c;只读、显式显示…

游戏反虚拟机检测方案

近年来&#xff0c;游戏市场高速发展&#xff0c;随之而来的还有图谋利益的游戏黑产。在利益吸引下&#xff0c;游戏黑产扩张迅猛&#xff0c;攻击趋势呈现出角度多样化的特点。 在这一趋势下&#xff0c;游戏安全防护的检测覆盖率显得尤为重要。如果游戏在某一环节出现被绕过…

小白网络安全学习手册

作为一个合格的网络安全工程师&#xff0c;应该做到攻守兼备&#xff0c;毕竟知己知彼&#xff0c;才能百战百胜。 谈起黑客&#xff0c;可能各位都会想到&#xff1a;盗号&#xff0c;其实不尽然&#xff1b;黑客是一群喜爱研究技术的群体&#xff0c;在黑客圈中&#xff0c;一…

毫末AI DAY的智驾弹药:上有「世界模型」,下有3000元方案

作者 | 张祥威 编辑 | 德新 「我们的感知能力可以说能做到识别万物了。」毫末智行在第九届毫末AI DAY上抛出这一豪言。 识别万物的底气&#xff0c;源于毫末的DriveGPT自动驾驶大模型引入了通用语义大模型&#xff0c;可以对交通参与者者、道路环境等做到全面感知。 今年是智…

python pip安装超时使用国内镜像

网络环境差的时候需要我们独立的进行相对应的包下载离线安装&#xff0c;或者给pip 加上 国内的镜像源比如加上清华的镜像源&#xff1a; 参考网址&#xff1a;pypi | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror https://mirrors.tuna.tsinghua…

简单写个JS插件替换网页上的文本

背景&#xff1a; 使用Grafana监控面板&#xff0c;随着项目迭代&#xff0c;页面上几百个图表了&#xff0c;相当一部分和错误码有关&#xff0c;逐个图表单替换维护过于繁琐&#xff0c;于是尝试一键替换grafana面板上的错误码(也就替换网页上特定的文本元素)&#xff0c;原…

禅道如何编辑项目模块

禅道是一个用于项目管理和软件开发的开源工具&#xff0c;它的主要作用包括&#xff1a; 1. 项目管理&#xff1a;禅道可以帮助项目团队进行任务分配、进度跟踪、沟通协作、测试管理等方面的工作&#xff0c;以确保项目能够按时完成。 2. 缺陷追踪&#xff1a;禅道可以记录和…

钉钉数字校园小程序开发:开启智慧教育新时代

随着信息技术的快速发展和校园管理的日益复杂化&#xff0c;数字校园已成为现代教育的重要趋势。钉钉数字校园小程序作为一种创新应用&#xff0c;以其专业性、思考深度和逻辑性&#xff0c;为学校提供了全新的管理、教学和沟方式。本文从需求分析、技术实现和应用思考三个方面…

JAVA学习第一天,java的运行方式

对未来很迷茫&#xff0c;不知道以后能出去干什么&#xff0c;好像掌握的东西很少&#xff0c;从今天开始学习学习java吧&#xff0c;让自己充实起来&#xff0c;记录一下。 jav…

QT快速下载

官网下载安装包后&#xff0c;打开命令行CMD&#xff0c;将qt安装包拖入cmd中 添加–mirror https://mirrors.tuna.tsinghua.edu.cn/qt 回车 按安装步骤安装即可

大模型评测指标与方法

中文大模型评测和英文评测方法是不一致的&#xff0c;原因&#xff1a; 第一、数据集的差异性。中文和英文的文本数据集在种类、规模、质量等方面存在很大的差异&#xff0c;需要针对中文特点开发相应的数据集&#xff0c;以确保评测结果的准确性和公正性。 第二、语言结构和…

计算机毕业设计选什么题目好?springboot 航司互售系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

M-LVDS收发器MS2111可pin对pin兼容SN65MLVD206

MS2111 是多点低压差分(M-LVDS)线路驱动器和接收器&#xff0c;经过优化可在高达 200 Mbps 的信令速率下运行。可pin对pin兼容SN65MLVD206。所有部件均符合 M-LVDS 标准 TIA / EIA-899。该驱动器输出已设计为支持负载低至 30Ω 的多点总线。 MS2111 的接收器属于 Type-2, 它们可…