Unity中URP下的菲涅尔效果实现(URP下的法线和视线向量怎么获取)

news2024/11/27 3:52:03

文章目录

  • 前言
  • 一、实现思路
  • 二、实现原理
    • 我们可以由下图直观的感受到 N 与 L夹角越小,点积越接近(白色)1。越趋近90°,点积越接近0(黑色)
  • 三、实现URP下的菲涅尔效果
    • 1、我们新建一个Shader,修改为最简
    • 2、获取世界空间下的顶点法线 N
    • 3、获取顶点指向摄像机的视线单位向量 L
    • 4、在片元着色器中,计算得到 NdotL 值
    • 5、用1 - NdotL 值得到菲尼尔效果
  • 四、测试代码


前言

我们在这篇文章中,了解一下URP中Shader怎么实现菲涅尔效果,同时学习一下URP下怎么获取法线 和 视线向量。


一、实现思路

Lambert光照模型公式:

Diffuse = Ambient + Kd * LightColor * max(0,dot(N,L))

  • 实现灯光照射中间亮 周围暗的效果,核心是dot(N,L)
    在这里插入图片描述

  • Unity中Shader的Lambert光照的实现

  • 光照效果下, 视线单位向量 点积 法线单位向量的效果是 中间亮周围暗。我们需要的效果刚好相反,用 1 减去该结果即可得到菲尼尔效果。

  • 所以,我们主要要获取 N 和 L

我们在之前的文章中,实现过一次菲涅尔效果(模型中间暗周围亮的效果)

  • Unity中Shader的XRay透视效果

二、实现原理

为什么 NdotL 可以得到中间亮,周围亮的的效果
在这里插入图片描述

我们可以由下图直观的感受到 N 与 L夹角越小,点积越接近(白色)1。越趋近90°,点积越接近0(黑色)

请添加图片描述


三、实现URP下的菲涅尔效果

我们这里用一个 BRP 下的Shader来修改为 URP 下的该效果

1、我们新建一个Shader,修改为最简

Shader "MyShader/URP/P3_2_4"
{
    Properties
    {
        
    }
    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;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return 1;
            }
            ENDCG
        }
    }
}

  • 在SubShader的Tags中,告诉引擎这是URP下的Shader

“RenderPipeline” = “UniversalPipeline”

  • 替换代码块申明

CGPROGRAM -> HLSLPROGRAM
ENDCG -> ENDHLSL

  • 替换我们的引入库为HLSL常用的几个

#include “Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl”
#include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
#include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
#include “Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl”

2、获取世界空间下的顶点法线 N

  • 在应用程序传入顶点着色器的 Attributes(appdata)结构体 加入本地法线
struct Attributes
{
	float3 vertexOS : POSITION;
	float3 normalOS : NORMAL;
};
  • 在顶点着色器传入片元着色器的 Varyings(v2f)结构体 加入世界法线
struct Varyings
{
	float4 vertexCS : SV_POSITION;
	float3 normalWS : TEXCOORD0;
};
  • 在顶点着色器进行法线坐标转化

o.normalWS = TransformObjectToWorld(v.normalOS);

3、获取顶点指向摄像机的视线单位向量 L

要获取该向量,需要知道 摄像机的世界空间坐标 和 我们顶点的世界空间坐标

  1. 摄像机的世界空间坐标

_WorldSpaceCameraPos

  1. 顶点世界空间下的坐标
  • 在顶点着色器传入片元着色器的 Varyings(v2f)结构体 加入世界顶点坐标

float3 vertexWS : TEXCOORD1;

  • 在顶点着色器进行顶点坐标的空间转化

o.vertexWS = TransformObjectToWorld(v.vertexOS);

  • 我们在片元着色器输出看看效果
    请添加图片描述
  1. 用世界空间下的 摄像机坐标 减去 模型顶点坐标 得到 L

half3 L = normalize(_WorldSpaceCameraPos - i.vertexWS);

4、在片元着色器中,计算得到 NdotL 值

half NdotL = dot(N,L);

  • 我们输出看看效果
    请添加图片描述

5、用1 - NdotL 值得到菲尼尔效果

需要调节效果强弱的话,我们使用pow函数即可

return 1 - NdotL;

请添加图片描述


四、测试代码

//URP下的菲涅尔效果
Shader "MyShader/URP/P3_2_4"
{
    Properties
    {
        
    }
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Opaque"
            //渲染队列
            "Queue"="Geometry"
        }
        
        Pass
        {
            Cull Back Blend One Zero ZTest LEqual ZWrite On
            
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            {
                float3 vertexOS : POSITION;
                float3 normalOS : NORMAL;
            };

            struct Varyings
            {
                float4 vertexCS : SV_POSITION;
                float3 normalWS : TEXCOORD0;
                float3 vertexWS : TEXCOORD1;
            };
            
            Varyings vert (Attributes v)
            {
                Varyings o;
                o.vertexWS = TransformObjectToWorld(v.vertexOS);
                o.vertexCS = TransformWorldToHClip(o.vertexWS);
                o.normalWS = TransformObjectToWorldNormal(v.normalOS);
                
                return o;
            }

            half4 frag (Varyings i) : SV_Target
            {
                //菲涅尔效果 1 - dot(N,L)
                half3 N = i.normalWS;
                half3 L = normalize(_WorldSpaceCameraPos - i.vertexWS);
                half NdotL = dot(N,L);
                return 1 - NdotL;
            }
            ENDHLSL
        }
    }
}

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

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

相关文章

机器学习笔记 - 时间序列分析基础概念解释

一、简述 时间序列分析是一种统计方法,可检查定期收集的数据点以揭示潜在的模式。该技术与各个行业高度相关,因为它可以根据历史数据做出决策和预测。通过了解过去并预测未来,时间序列分析在金融、医疗保健、能源、供应链管理、天气预报、营销等领域发挥着至关重要的作用。 …

关于mysql存储过程中N/A和null的使用注意事项

oracle和mysql的存储过程大同小异,但是一些细节还是需要留意的。最近发现mysql的N/A和null在存储过程中容易忽略的一点,这会导致我们的存储过程提前结束。今天突然想起来了就记录一下。   mysql的N/A和null区别网上也说得很详细了,我就不赘…

频谱论文:面向频谱地图构建的频谱态势生成技术研究

#频谱# [1]李竟铭.面向频谱地图构建的频谱态势生成技术研究.2019.南京航空航天大学,MA thesis.doi:10.27239/d.cnki.gnhhu.2019.000556. (南京航空航天大学) 频谱地图是对无线电环境的抽象表达,它可以直观、多维度地展现频谱态势信息&…

部署智能合约以及 javascript 调用合约函数(Web3项目二实战之三)

在上一篇 智能合约是Web3项目的核心要务(Web3项目二实战之二) ,我们已然为项目编写了智能合约,在攥写完智能合约后,该项目将完成了一大部分,剩下无非就是用户界面交互的内容。 然而,在码完了智能合约代码后,起着承前启后关键性的便是,前端界面与智能合约的交互。 智能…

scroll-behavior属性使用方法

定义和用法&#xff1a; scroll-behavior 属性规定当用户单击可滚动框中的链接时&#xff0c;是否平滑地&#xff08;具动画效果&#xff09;滚动位置&#xff0c;而不是直线跳转。 <style>element{/* 核心代码 */scroll-behavior: smooth;} </style> 属性值&am…

gitlab ci pages

参考文章 gitlab pages是什么 一个可以利用gitlab的域名和项目部署自己静态网站的机制 开启 到gitlab的如下页面 通过gitlab.ci部署项目的静态网站 # build ruby 1/3: # stage: build # script: # - echo "ruby1"# build ruby 2/3: # stage: build …

翻译: 如何分析你的工作是否被AI替代 比如程序员、律师 Additional job analysis examples

我发现对于许多职业角色&#xff0c;人们心中都有一个标志性的任务&#xff0c;这个任务独特地定义了那个职业角色。例如&#xff0c;计算机程序员编写代码。医生可能会看病人。律师去法庭上争论案件。我认为当人们考虑人工智能的机会时&#xff0c;通常会本能地问&#xff0c;…

力扣200. 岛屿数量(java DFS解法)

Problem: 200. 岛屿数量 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 该问题可以归纳为一类遍历二维矩阵的题目&#xff0c;此类中的一部分题目可以利用DFS来解决&#xff0c;具体到本题目&#xff1a; 1.我们首先要针对于二维数组上的每一个点&#xff0c;尝试展…

基于AT89C52单片机的计算器设计与仿真

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/88637995?spm1001.2014.3001.5503 源码获取 B 源码仿真图课程设计51 摘 要 计算器一般是指“电子计算器”,能进行数学运算的手持机器&#xff0c;拥有集成电路芯…

【Qt图书管理系统】4.系统设计与详细设计

文章目录 核心流程图软件架构设计流程图软件开发类图及功能点 核心流程图 用户登录图书查询图书借阅图书归还账户管理 软件架构设计 流程图 软件开发类图及功能点 Dlg_Login 登录界面 Cell_Main 主窗体 Cell_MyBook 我的书籍 Cell_BookMgr 书籍管理 Cell_RecoredMgr 借阅记录…

ASP.NET MVC实战之权限拦截Authorize使用

1&#xff0c;具体的实现方法代码如下 public class CustomAuthorizeAttribute : FilterAttribute, IAuthorizationFilter{/// <summary>/// 如果需要验证权限的时候&#xff0c;就执行进来/// </summary>/// <param name"filterContext"></par…

C# WPF上位机开发(知识产权ip保护)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 上位机软件如果是和硬件模块搭配开发&#xff0c;这个时候大部分上位机基本上都是白送的&#xff0c;不会收取相关的费用。但是&#xff0c;如果上…

气候灾害组织:全球红外降水站数据

气候灾害组织红外降水站数据-Prelim (CHIRPS-Prelim) 气候灾害中心红外降水站数据 Prelim (CHIRPS-Prelim) 融合了 CHIRPS 数据与原位降水数据&#xff0c;以消除数据偏差并提高其准确性。生成 CHIRPS-Prelim 的过程与 CHIRPS 过程类似&#xff0c;主要区别在于它仅依赖于近实…

【Unity自动寻路】使用Navigation系统实现物体自动寻路绕开障碍物

知识点流程图 自动导航Navigation系统 我们在游戏场景中经常会有一些障碍物、墙壁、树木等等&#xff0c;如果我想要让角色或者怪物去墙的另一边&#xff0c;我直接在墙另一边点击左键&#xff0c;我希望角色自动跑过去&#xff0c;但是他不能直接穿透墙&#xff0c;他需要“智…

【具身智能评估3】具身视觉语言规划(EVLP)度量标准汇总

参考论文&#xff1a;Core Challenges in Embodied Vision-Language Planning 论文作者&#xff1a;Jonathan Francis, Nariaki Kitamura, Felix Labelle, Xiaopeng Lu, Ingrid Navarro, Jean Oh 论文原文&#xff1a;https://arxiv.org/abs/2106.13948 论文出处&#xff1a;Jo…

华媒舍:怎样利用旅游业发展媒体套餐宣传推广分析7个经典案例

1.分析经典案例在旅游业发展中&#xff0c;依靠媒体套餐开展宣传推广成为了一种常见的方法。下面将详细介绍7个经典案例&#xff0c;从这当中我们可以得出一些宝贵经验。 案例一&#xff1a;目标市场定位成功宣传推广一定要明确市场定位&#xff0c;针对不同的受众群体制定合理…

力扣刷题-二叉树-找树左下角的值

513 找树左下角的值 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1&#xff1a; 示例 2&#xff1a; 思路 层序遍历 直接层序遍历&#xff0c;因为题目说了是最底层&#xff0c;最左边的值&a…

MATLAB图像处理技巧

MATLAB图片处理------动态绘图 1. 动态绘图2. XXXXX 1. 动态绘图 主要用到四个函数&#xff0c;分别为getframe、frame2im、rgb2ind以及imwrite&#xff1a; 1.getframe&#xff1a;获取当前绘图窗口的图片作为影片帧&#xff1b; 2.frame2im&#xff1a;从单个影片帧 F 返回索…

【JavaEE】多线程(5) -- 阻塞队列

目录 1.阻塞队列是什么? 2.生产者消费者模型 3.标准库中的阻塞队列 4.阻塞队列的实现 1.阻塞队列是什么? 阻塞队列是⼀种特殊的队列. 也遵守 "先进先出" 的原则 阻塞队列能是⼀种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续⼊队列就会阻塞, …

MATLAB break语句||MATLAB continue语句

MATLAB break语句 MATLAB中 break 语句用于终止 for 或 while 循环的执行&#xff0c;当在循环体内执行到该语句的时候&#xff0c;程序将会跳出循环&#xff0c;继续执行循环语句的下一语句。 注意&#xff1a;在嵌套循环中&#xff0c;break 退出只能在循环发生&#xff0c;后…