【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1)

这篇具有很好参考价值的文章主要介绍了【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

[Toggle(_SupportOrthographicCamera)] _SupportOrthographicCamera(“_SupportOrthographicCamera (default = off)”, Float) = 0
}

SubShader
{
// 关于tags的内容可以查阅官网手册:https://docs.unity3d.com/Manual/SL-SubShaderTags.html
// 为了避免渲染顺序问题, Queue必须 >= 2501, 它位于透明队列中
// 在透明队列中,Unity总是从后到前渲染
// 2500以下是不透明物体队列,会进行渲染优化,比如被遮住的就剔除掉不进行渲染
// 2500以上是透明物体队列,它会根据距离摄像机的距离进行排序
// 从最远的开始渲染,到最近的结束
// 天空盒被渲染在所有不透明和透明物体之间
// “Queue” = “Transparent-499” 即 “Queue” = “2501”, 使得它早于所有透明物体进行渲染
Tags { “RenderType” = “Overlay” “Queue” = “Transparent-499” “DisableBatching” = “True” }

Pass
{
Stencil
{
Ref[_StencilRef]
Comp[_StencilComp]
}

Cull[_Cull]
ZTest[_ZTest]

// 为了支持透明度混合,关闭深度写入
ZWrite off
Blend[_SrcBlend][_DstBlend]

HLSLPROGRAM

#pragma vertex vert
#pragma fragment frag

// 雾效
#pragma multi_compile_fog

// 为了使用 ddx() & ddy()
#pragma target 3.0

#pragma shader_feature_local_fragment _ProjectionAngleDiscardEnable
#pragma shader_feature_local _UnityFogEnable
#pragma shader_feature_local_fragment _FracUVEnable
#pragma shader_feature_local_fragment _SupportOrthographicCamera

// 所有URP渲染管线的shader都必须引入这个Core.hlsl
// 它包含内置shader的变量,比如光照相关的变量,文档:https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
// 同时它也包含很多工具方法
#include “Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”

struct appdata
{
// 模型空间下的坐标,OS: Object Space
float3 positionOS : POSITION;
};

struct v2f
{
// 齐次裁剪空间坐标,CS: Clip Space
float4 positionCS : SV_POSITION;
// 屏幕坐标
float4 screenPos : TEXCOORD0;
// xyz分量: 表示viewRayOS, 即模型空间 (Object Space)下的摄像机到顶点的射线
// w分量: 拷贝positionVS.z的值,即观察空间 (View Space) 下的顶点坐标的z分量
float4 viewRayOS : TEXCOORD1;
// rgb分量:表示模型空间下的摄像机坐标,
// a分量:表示雾的强度
float4 cameraPosOSAndFogFactor : TEXCOORD2;
};

sampler2D _MainTex;
sampler2D _CameraDepthTexture;

// 支持SRP Batcher
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float _ProjectionAngleDiscardThreshold;
half4 _Color;
half2 _AlphaRemap;
half _MulAlphaToRGB;
CBUFFER_END

// 顶点着色器
v2f vert(appdata input)
{
v2f o;

// VertexPositionInputs包含多个空间坐标系中的位置(world, view, homogeneous clip space, ndc)
// Unity编译器将剥离所有未使用的引用 (比如你没有使用view space)
// 因此,这种结构具有更大的灵活性,无需额外的成本
VertexPositionInputs vertexPositionInput = GetVertexPositionInputs(input.positionOS);
// 得到齐次裁剪空间 (clip space) 下的坐标
o.positionCS = vertexPositionInput.positionCS;

// Unity雾效
#if _UnityFogEnable
o.cameraPosOSAndFogFactor.a = ComputeFogFactor(o.positionCS.z);
#else
o.cameraPosOSAndFogFactor.a = 0;
#endif

// 准备深度纹理的屏幕空间UV
o.screenPos = ComputeScreenPos(o.positionCS);

// 观察空间 (view space) 坐标,即在观察空间中摄像机到顶点的射线向量
float3 viewRay = vertexPositionInput.positionVS;

// [注意,这一步很关键]
//=========================================================
// viewRay除以z分量必须在片元着色器中执行,不能在顶点着色器中执行! (由于光栅化变化插值的透视校正)
// 我们先把viewRay.z存到o.viewRayOS.w中,等到片元着色器阶段在进行处理
o.viewRayOS.w = viewRay.z;
//=========================================================

// unity的相机空间是右手坐标系(z轴负方向指向屏幕),我们希望片段着色器中z射线是正的,所以取反
viewRay *= -1;

// 观察空间到模型空间的变换矩阵
float4x4 ViewToObjectMatrix = mul(UNITY_MATRIX_I_M, UNITY_MATRIX_I_V);

// 观察空间 (view space) 转模型空间 (object space)
o.viewRayOS.xyz = mul((float3x3)ViewToObjectMatrix, viewRay);
// 模型空间下摄像机的坐标
o.cameraPosOSAndFogFactor.xyz = mul(ViewToObjectMatrix, float4(0,0,0,1)).xyz;

return o;
}

half4 frag(v2f i) : SV_Target
{
// [注意,这一步很关键]
//========================================================================
// 去齐次
i.viewRayOS.xyz /= i.viewRayOS.w;
//========================================================================

// 深度纹理的UV
float2 screenSpaceUV = i.screenPos.xy / i.screenPos.w;
// 对深度纹理进行采样,得到深度信息
float sceneRawDepth = tex2D(_CameraDepthTexture, screenSpaceUV).r;

float3 decalSpaceScenePos;

// 正交相机
#if _SupportOrthographicCamera
// 我们必须支持正交和透视两种投影
// unity_OrthoParams:
// unity_OrthoParams是内置着色器遍历,存储的信息如下:
// x 是正交摄像机的宽度,y 是正交摄像机的高度,z 未使用,w 在摄像机为正交模式时是 1.0,而在摄像机为透视模式时是 0.0。
// 更多的内置着色器遍历可查看官方手册: https://docs.unity.cn/cn/2019.4/Manual/SL-UnityShaderVariables.html
// (这里要放 UNITY_BRANCH 吗?) 我决定不放,原因看这里: https://forum.unity.com/threads/correct-use-of-unity_branch.476804/
if(unity_OrthoParams.w)
{
// 如果是正交摄像机, _CameraDepthTexture在[0,1]内线性存储场景深度
#if defined(UNITY_REVERSED_Z)
// 如果platform使用反向深度,要使用1-depth
// https://docs.unity3d.com/Manual/SL-PlatformDifferences.html
sceneRawDepth = 1-sceneRawDepth;
#endif

// 使用简单的lerp插值: lerp(near,far, [0,1] linear depth), 得到观察空间 (view space)的深度信息
float sceneDepthVS = lerp(_ProjectionParams.y, _ProjectionParams.z, sceneRawDepth);

// 投影
float2 viewRayEndPosVS_xy = float2(unity_OrthoParams.xy * (i.screenPos.xy - 0.5) * 2 /* 裁剪空间 */);
// 构建观察空间坐标
float4 vposOrtho = float4(viewRayEndPosVS_xy, -sceneDepthVS, 1);
// 观察空间转世界空间
float3 wposOrtho = mul(UNITY_MATRIX_I_V, vposOrtho).xyz;
//----------------------------------------------------------------------------

// 世界空间转模型空间 (贴花空间)
decalSpaceScenePos = mul(GetWorldToObjectMatrix(), float4(wposOrtho, 1)).xyz;
}
else
{
#endif
// 如果是透视相机,LinearEyeDepth将为用户处理一切
// 记住,我们不能使用LinearEyeDepth处理正交相机!
// _ZBufferParams:
// 用于线性化 Z 缓冲区值。x 是 (1-远/近),y 是 (远/近),z 是 (x/远),w 是 (y/远)。
float sceneDepthVS = LinearEyeDepth(sceneRawDepth, _ZBufferParams);

// 在任何空间中,场景深度 = rayStartPos + rayDir * rayLength
// 这里所有的数据在 模型空间 (object space) 或 贴花空间 (decal space)
// 注意,viewRayOS 不是一个单位向量,所以不要规一化它,它是一个方向向量,视图空间z的长度是1
decalSpaceScenePos = i.cameraPosOSAndFogFactor.xyz + i.viewRayOS.xyz * sceneDepthVS;

#if _SupportOrthographicCamera
}
#endif

// unity 的 cube 的顶点坐标范围是 [-0.5, 0.5,],我们把它转到 [0,1] 的范围,用于映射UV
// 只有你使用 cube 作为 mesh filter 时才能这么干
float2 decalSpaceUV = decalSpaceScenePos.xy + 0.5;

// 剔除逻辑
//===================================================
// 剔除在 cube 以外的像素信息
float shouldClip = 0;
#if _ProjectionAngleDiscardEnable
// 也丢弃 “场景法向不面对贴花投射器方向” 的像素
// 使用 ddx 和 ddy 重建场景法线信息
// ddx 就是右边的像素块的值减去左边像素块的值,而ddy就是下面像素块的值减去上面像素块的值。
// ddx 和 ddy 的结果就是副切线和切线方向,利用右手定理,叉乘 (cross) 后就是法线,最后执行归一化 (normalize) 得到法线单位向量
float3 decalSpaceHardNormal = normalize(cross(ddx(decalSpaceScenePos), ddy(decalSpaceScenePos)));

// 判断是否进行剔除
// 注:decalSpaceHardNormal.z = dot(decalForwardDir, sceneHardNormalDir)
shouldClip = decalSpaceHardNormal.z > _ProjectionAngleDiscardThreshold ? 0 : 1;
#endif
// 执行剔除
// 如果 ZWrite 关闭,在移动设备上 clip() 函数是足够效率的,因为它不会写入深度缓冲,所以GPU渲染管线不会卡住(经过ARM官方人员确认过)
clip(0.5 - abs(decalSpaceScenePos) - shouldClip);
//===================================================

// 贴花UV计算
// _MainTex_ST.xy: 表示uv的tilling
// _MainTex_ST.zw: 表示uv的offset
float2 uv = decalSpaceUV.xy * _MainTex_ST.xy + _MainTex_ST.zw;//Texture tiling & offset
#if _FracUVEnable
// UV裂缝处理
uv = frac(uv);
#endif
// 贴花纹理采样
half4 col = tex2D(_MainTex, uv);
// 与颜色相乘
col *= _Color;
// 透明通道重新映射
col.a = saturate(col.a * _AlphaRemap.x + _AlphaRemap.y);
// 插值
col.rgb *= lerp(1, col.a, _MulAlphaToRGB);

#if _UnityFogEnable
// 混合像素颜色与雾色。你可以选择使用MixFogColor来覆盖雾色
col.rgb = MixFog(col.rgb, i.cameraPosOSAndFogFactor.a);
#endif
return col;
}
ENDHLSL
}
}
}

首先有一个前提,就是模型必须使用Cube
最核心的一步就是通过深度信息还原世界空间坐标,再转模型空间坐标(也就是贴花空间坐标),计算出贴花UV,对贴花图案采样输出。

其中关于如何通过深度纹理重建世界坐标,大家可以阅读 冯乐乐 写的 《Unity Shader 入门精要》 这本书第13章的13.3.1小结,她讲得很好,建议大家多看书学习

【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

我们把上面的Shader保存为UrpDecal.shader,如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

2、材质球

我们创建一个材质球,重命名为UrpDecal,并使用刚刚的shader,如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
设置一下材质球参数,如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

3、创建Cube

创建一个Cube,重命名为DecalCube
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
把上面的材质球赋给这个Cube
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

4、地面场景

简单搭建一下地面场景,
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

5、添加Renderer Feature: Decal

点击Universal Render Pipeline Asset_Renderer,点击Add Renderer Feature,然后点击Decal
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

6、移动DecalCube,与地面交叉

选中DecalCube,调整下角度和缩放,
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
然后移动DecalCube,让它与地面交叉,此时我们就可以看到想要的贴花效果了

7、运行效果

运行效果如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

三、方案二:使用URP Decal Projector

在默认渲染管线中,我们可以使用Projector来实现贴花效果,比较常见的是假阴影的实现。
URP渲染管线中,我们可以使用URP Decal Projector

1、添加Renderer Feature: Decal

跟上面一样,也得添加Decal

【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

2、创建Decal Shader Graph

点击菜单Create / Shader Graph / URP / Decal Shader Graph,如下
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1),程序员,unity,游戏引擎

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!文章来源地址https://www.toymoban.com/news/detail-852923.html

17339)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-HGvhZquP-1713003117339)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

到了这里,关于【游戏开发小技】Unity中实现Dota里的角色技能地面贴花效果(URP ShaderGraph Decal)(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity制作射击游戏案例01(控制角色+发射子弹+摄像机跟踪)

    //【业务逻辑】这个脚本用来1.控制物体移动旋转(WASD)、   2.发射子弹(空格键) //【程序逻辑2】 首先检测用户没有按下空格键 2.如果按下呢执行发射子弹函数    3.克隆子弹 4.让克隆的子弹往前跑 为子弹模板添加刚体,并且限制旋转 这个脚本需要挂在到摄像机,里面谈

    2024年02月06日
    浏览(56)
  • Unity DOTS《群体战斗弹幕游戏》核心技术分析之3D角色动画

    最近DOTS发布了正式的版本, 我们来分享现在流行基于群体战斗的弹幕类游戏,实现的核心原理。今天给大家介绍大规模战斗群体3D角色的动画如何来实现。 DOTS 对角色动画支持的局限性 截止到Unity DOTS发布的版本1.0.16,目前还是无法很好的支持3D角色动画。在DOTS 的baker过程种,

    2024年02月04日
    浏览(60)
  • 【unity】制作一个角色的初始状态(左右跳二段跳)【2D横板动作游戏】

            hi~ 大家好!欢迎大家来到我的全新unity学习记录系列。现在我想在2d横板游戏中,实现一个角色的初始状态-闲置状态、移动状态、空中状态。并且是利用 状态机 进行实现的。         本系列是跟着视频教程走的,所写也是作者个人的学习记录笔记。如有错误请联系

    2024年02月04日
    浏览(49)
  • 【Unity实战篇 】| 游戏中实现镂空遮罩效果【矩形、圆形镂空遮罩】

    前言 本文来写一下怎样在Unity中完成一个 镂空遮罩 的效果。 镂空遮罩 比较常用的有两种ÿ

    2024年02月15日
    浏览(146)
  • chatgpt在Unity里的开发和原理

    先放上教学视频链接 https://www.reddit.com/r/unity_tutorials/comments/10aic34/chatgpt_with_unity_in_todays_video_i_show_you_a/ https://www.youtube.com/watch?v=PRwfHajinSU 语音控制实现unity里的效果 或者语音控制实现Unity里的动画效果 用语音或者文字使得人物角色往前走 可以利用ChatGPT的接口实现半自动化开发

    2023年04月08日
    浏览(39)
  • Unity 新建你的第一个游戏,以及如何按WASD控制角色运动 (Unity Demo2D)

    当你打开 Unity Hub,初始化一个 2D 项目,进入了 Unity 编辑器,你会发现在 左侧 : 一个叫 SampleScene (或者其他) 的场景 场景下有一个 Main Camera,主相机 这就是一个新建的 2D 项目自带的内容。 在 Main Camera 同级目录新建: 2D Object - Sprites - Capsule ,这里 Capsule 是精灵的种类,我们

    2024年02月02日
    浏览(46)
  • Unity组件开发--相机跟随角色和旋转

    1.相机跟随组件,节点: 2.相机跟随组件脚本: 3.相机跟随角色视角旋转:

    2024年01月15日
    浏览(65)
  • Unity开发日记【第三天】——角色动画效果的实现

    目录 一、站立和跑步动画效果 二、跳跃动画 三、对移动过程中的一些优化和修正 本部分我们尝试给我们的角色添加各种动画效果 首先给角色添加组件Animator,我们可以看见该组件要求一个控制器。 接下来在根目录下新建一个文件夹Animation用来存放所有的动画效果,在文件

    2024年02月05日
    浏览(54)
  • 【MySQL】MySQL里的用户账户和角色是什么?如何管理?

    在MySQL中,用户是数据库访问的主要实体。每个用户都有自己的用户名和密码,用于验证和授权。通过合理的用户管理,可以控制谁能够访问数据库以及访问数据库的权限。 在连接到MySQL 服务器并执行查询时,会根据登录的用户来进行身份验证和活动授权。 验证 。这一步是

    2024年02月11日
    浏览(65)
  • 【Unity3D日常开发】Unity3D中实现单例模式详解

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 首先,说一下,什么是 单例模式(Singleton) 。 单例模式是设计模式中常见的一种设计模式,目的是为了

    2024年02月02日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包