首页 > 其他分享 >Unity URP 仿原神渲染解析

Unity URP 仿原神渲染解析

时间:2023-09-17 17:11:43浏览次数:36  
标签:仿原 hlsl VertexNormalInputs Unity URP 顶点 float4 input float3

Outline Pass

用于渲染轮廓。这个 Pass 看起来比较简单,就是对模型正面剔除后,将背面沿法线偏移线宽的距离,然后直接用轮廓线的颜色渲染背面。

ShaderLab

Pass {
    Name "Outline"
    Tags {
        "LightMode" = "SRPDefaultUnlit"
    }

    Cull Front  // 进行了正面剔除

    HLSLPROGRAM
    #pragma vertex OutlinePassVertex        // 顶点着色器: OutlinePassVertex
    #pragma fragment OutlinePassFragment    // 片段着色器: OutlinePassFragment

    #include "ToonInput.hlsl"
    #include "ToonOutlinePass.hlsl"
    ENDHLSL
}

ToonOutlinePass.hlsl

先来看一些 ToonOutlinePass.hlsl 里用到的东西。


VertexPositionInputs

其中顶点位置输入 VertexPositionInputs 结构体定义在 "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 中,内容如下:

struct VertexPositionInputs {
    float3 positionWS; // World space position
    float3 positionVS; // View space position
    float4 positionCS; // Homogeneous clip space position
    float4 positionNDC;// Homogeneous normalized device coordinates
};

GetVertexPositionInputs(float3 positionOS) 将物体空间下的顶点坐标转换为世界空间、观察空间、裁剪空间、NDC下的坐标,填充给 VertexPositionInputs 结构体并返回。

VertexPositionInputs GetVertexPositionInputs(float3 positionOS) {
    VertexPositionInputs input;
    input.positionWS = TransformObjectToWorld(positionOS);
    input.positionVS = TransformWorldToView(input.positionWS);
    input.positionCS = TransformWorldToHClip(input.positionWS);

    float4 ndc = input.positionCS * 0.5f;
    input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
    input.positionNDC.zw = input.positionCS.zw;

    return input;
}

VertexNormalInputs

顶点法线输入 VertexNormalInputs 结构体同样定义在 "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 中,内容如下:

struct VertexNormalInputs { // 存储了世界空间下的 TBN 向量
    real3 tangentWS;
    real3 bitangentWS;
    float3 normalWS;
};

GetVertexNormalInputs(float3 normalOS, float4 tangentOS) 接收物体空间下的法线和切线,填充 VertexNormalInputs 结构体并返回。

VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS) {
    VertexNormalInputs tbn;

    // mikkts space compliant. only normalize when extracting normal at frag.
    real sign = real(tangentOS.w) * GetOddNegativeScale();
    tbn.normalWS = TransformObjectToWorldNormal(normalOS);
    tbn.tangentWS = real3(TransformObjectToWorldDir(tangentOS.xyz));
    tbn.bitangentWS = real3(cross(tbn.normalWS, float3(tbn.tangentWS))) * sign;
    return tbn;
}

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

struct Attributes {                     // 顶点着色器的输入
    float4 positionOS : POSITION;       // 物体空间下的顶点坐标
    float3 normalOS : NORMAL;           // 物体空间下的法线
    float4 tangentOS : TANGENT;         // 物体空间下的切线
    float2 uv : TEXCOORD0;              // uv坐标
};

struct Varyings {                       // 片段着色器的输入
    float2 uv : TEXCOORD0;              // uv坐标
    float4 positionCS : SV_POSITION;    // 裁剪空间下的顶点坐标
};

float3 GetOutlinePosition(VertexPositionInputs vertexInput, VertexNormalInputs normalInput) {
    float z = abs(vertexInput.positionVS.z);                        // 观察空间下的z分量
    float width = _OutlineWidth * saturate(z) * 0.001;              // 宽度和 z 的大小成正比,离摄像机越远,宽度越大
                                                                    // 抵消透视造成的远处的线条变细
                                                                    // 使得远近的线条看起来差不多宽

    return vertexInput.positionWS + normalInput.normalWS * width;   // 将世界空间下的顶点坐标沿法线偏移线宽的距离
}

// 顶点着色器
Varyings OutlinePassVertex(Attributes input) {
    // 填充顶点位置输入结构体
    VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
    // 填充顶点法线输入结构体
    VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);

    float3 positionWS = GetOutlinePosition(vertexInput, normalInput);   // 获取轮廓线的位置

    Varyings output = (Varyings)0;
    output.uv = TRANSFORM_TEX(input.uv, _BaseMap);              // 填充 uv 坐标
    output.positionCS = TransformWorldToHClip(positionWS);      // 填充裁剪空间下的顶点坐标

    return output;
}

// 片段着色器
half4 OutlinePassFragment(Varyings input) : SV_TARGET {
    return _OutlineColor;   // 直接返回顶点颜色
}

标签:仿原,hlsl,VertexNormalInputs,Unity,URP,顶点,float4,input,float3
From: https://www.cnblogs.com/AEMShana/p/17709203.html

相关文章

  • 【小沐学Unity3d】3ds Max 骨骼动画制作(蒙皮修改器skin)
    1、简介“蒙皮”修改器是一种骨骼变形工具,主要设计用于通过另一个对象对一个对象进行变形来创建角色动画。可使用骨骼、样条线和其他对象变形网格、面片和NURBS对象。如果将“蒙皮”修改器应用到网格,然后使用修改器指定骨骼,则每个骨骼都将收到一个胶囊形状的“封套”。这些封......
  • 关于Unity2021 Timeline
    谨以我的第一篇游戏&图形学(可能没啥关系)相关blog缅怀带我入门的毛星云前辈。总感觉想说点什么,却又什么都说不出来。我大概很长时间都不会忘记这个名字。作为一个unity初学者,记录一下自己的unitytimeline使用过程。突发奇想了解了一下,说不定未来能自己做个avg(笑[toc]#1、Tim......
  • Unity 游戏开发、03 基础篇 | C#初级编程
    C#初级编程https://learn.u3d.cn/tutorial/beginner-gameplay-scripting8Update和FixedUpdateUpdate(不是按固定时间调用的)经常用于移动非物理特性的物体(不是物理对象)简单定时器接收输入FixedUpdate(调用时间间隔相同)进行任何必要的物理计算(任何物理对象)最好使用力......
  • Unity 修改 FixedUpdate 时间间隔
    1.依次点击Edit->ProjectSetting->Time后,在打开的窗口中修改FixedTimestep即可。如下图所示: ......
  • visual studio community 2015 clodelens功能
    关于community版本中增加codelens功能,网上能搜索到不少安装ssdt后出现该功能的文章,之前我也是参照这些文章来安装codelens功能的,但前几天重装系统后,再次安装ssdt时codelens功能并没有像预期那样出现,经过一系列的折腾,发现是ssdt版本的问题,在最新版的ssdt(14.0.61712.50)中阉割......
  • 【小沐学Unity3d】3ds Max 骨骼动画制作(Physique 修改器)
    1、简介官方网址:https://help.autodesk.com/view/3DSMAX/2018/CHS/?guid=GUID-22E831B0-8B6B-4759-B5FB-4B86B6276A00使用Physique修改器可将蒙皮附加到骨骼结构上,比如Biped。蒙皮是一个3dsMax对象:它可以是任何可变形的、基于顶点的对象,如网格、面片或图形。当以附加蒙皮......
  • Unity - UGUI
    UI系统1UGUI是什么它是基于Unity游戏对象的UI系统,只能用来做游戏UI功能,不能用于开发Unity编辑器中内置的用户界面。2UGUI六大基础组件Canvas对象上依附的:Canvas:画布组件,主要用于渲染UI控件。CanvasScaler:画布分辨率自适应组件,主要用于分辨率自适应。GraphicRaycaster:......
  • Unity Shader顶点数据疑问
    1)UnityShader顶点数据疑问2)Unity2018发布在iOS16.3偶尔出现画面不动的问题3)安卓游戏启动后提示“应用程序异常”这是第352篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习。UWA社区主页:community.uwa4d.comU......
  • 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用
    在我们创建界面元素的时候,不管在Vue3+ElementPlus的前端上,还是Winform桌面端上,都是会利用自定义用户控件来快速重用一些自定义的界面内容,对自定义用户控件的封装处理,也是我们开发WPF应用需要熟悉的一环。本篇随笔继续深入介绍介绍基于CommunityToolkit.Mvvm和HandyControl的WPF应......
  • Unity 游戏开发、02 基础篇 | 知识补充、简单使用动画、动画状态机
    前置笔记(由浅入深)Unity游戏开发、01基础篇2场景操作3D场景Q手型工具(鼠标中键):上下左右移动场景ALT+鼠标左键:以视图为中心旋转鼠标右键:以观察者为中心旋转SHIFT+Gizmo方块:Y轴归位物体节点+F:观察者定位至物体窗口布局3D项目一般窗口布局如下3全局光照全......