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

文章目录

  • 前言
  • 一、实现思路
  • 二、实现原理
    • 我们可以由下图直观的感受到 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 100Pass{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 OnHLSLPROGRAM#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.hqwc.cn/news/283268.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gitlab 通过svn hook 触发

jenkins 起一个item 配置: 我选的自由风格的 源码管理配置 先选subversion 就是svn类型 url 设置project 的路径, 注意是工程,不是svn 顶层 添加一个账户来进行pull 等操作 选择添加的账号 构建触发器: ,重要的是要自…

游戏运行中突然掉线是什么原因导致的

游戏平稳运行的原因只有一个,掉线的原因各有个的不同。这些不同的原因有常见,也有不常见的。但不管出于什么原因的掉线,带来的损失又是相同的。 首先最常见的原因就是攻击造成的 像CC,DDOS。CC会造成服务器资源的浪费&…

【PHP入门】1.1-PHP初步语法

-PHP语法初步- PHP是一种运行在服务器端的脚本语言&#xff0c;可以嵌入到HTML中。 1.1.1PHP代码标记 在PHP历史发展中&#xff0c;可以使用多种标记来区分PHP脚本 ASP标记&#xff1a; <% php代码 %>短标记&#xff1a; <? Php代码 ?>&#xff0c;以上两种…

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

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

1.1 【应用开发】应用开发简介

写在前面 Screen图形子系统基于客户端/服务器模型,其中应用程序是请求图形服务的客户端(Screen)。它包括一个合成窗口系统作为这些服务之一,这意味着所有应用程序渲染都是在离屏缓冲区上执行的,然后可以在稍后用于更新显示。 一,Screen架构 Screen支持硬件加速的应用程…

第一个程序(STM32F103点灯)

点亮LED 看原理图确定控制LED的引脚看主芯片手册确定如何设置/控制引脚写程序 LED有很多种&#xff0c;像插脚的&#xff0c;贴片的。 它们长得完全不一样&#xff0c;因此我们在原理图中将它抽象出来。 嵌入式系统中&#xff0c;一个LED的电阻非常低&#xff0c;I U/R&…

1.新入手的32位单片机资源和资料总览

前言&#xff1a; 学了将近1年的linux驱动和uboot&#xff0c;感觉反馈不足&#xff0c;主要是一直在学各种框架&#xff0c;而且也遇到了门槛&#xff0c;比如驱动部分&#xff0c;还不能随心所欲地编程&#xff0c;原因是有些外设的原理还不够深刻、有些复杂的底层驱动的代码…

Kafka本地安装⭐️(Windows)并测试生产消息以及消费消息的可用性

2023.12.17 天气晴 温度较低 十点半&#xff0c;不是不想起实在是阳光浴太nice了日常三连&#xff0c;喂&#xff0c;刷&#xff0c;肝刷会儿博客&#xff0c;看会儿设计模式冷冷冷 进被窝 刷视频 睡觉看看kafka的本地部署 》》实践》》成功写会儿博客&#xff0c…

面向对象三大特征——继承

目录 1. 概述 2. 继承的限制 2.1 单继承 2.2 访问修饰符 2.3 . final 3. 重写 4. super 4.1super的作用 4.2访问父类的成员和被重写方法 4.3调用父类的构造器 1. 概述 多个类中存在相同属性和行为时&#xff0c;将这些内容抽取到单独一个类中&#xff0c;那么就无需在…

Leetcode 37 解数独

题意理解&#xff1a; 填充数独。每个九宫格内&#xff0c;9个数字各出现一个次&#xff0c;每行&#xff0c;每列上&#xff0c;9个数字各出现一次。数独部分空格内已填入了数字&#xff0c;空白格用 . 表示。 这道题要比N皇后问题更难&#xff1a; N皇后只放置N个皇后的位置&…

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

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

计算机服务器中了mkp勒索病毒怎么办,mkp勒索病毒解密恢复

在计算机技术飞速发展的今天&#xff0c;越来越多的企业走向了数字化办公模式&#xff0c;极大地方便了企业的生产运营&#xff0c;为企业带来了更高的效率。但网络威胁无处不在&#xff0c;网络威胁手段随着计算机技术的不断发展也在不断增加。近期&#xff0c;云天数据恢复中…