Unity-URP
Posted 莉萝爱萝莉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity-URP相关的知识,希望对你有一定的参考价值。
目录
1. 简单使用
1. 简介
- SRP:可编程渲染管线
剔除 culling
渲染 rendering
后处理 postprocessing - URP 通用可编程渲染管线
2. 安装
1. 新工程
可直接选择LWRP(URP)【通用渲染管线】创建工程.
2. 升级已有工程
- 在包管理器中找到LWRP(URP)【通用渲染管线】。
- 右键创建->渲染(Rendering)->创建Render Pipeline Asset(渲染管线 with U Renderer),并赋给项目设置->图形中的渲染管线设置。
此外,还需为Quality设置渲染管线。 - 这时,项目原本的材质均会出错丢失。需在编辑->渲染管线中升级已有材质。路径如下
但这只能修复少量unity自带的材质。
3. URP注意事项
URP想要副光源也能够产生阴影,需要先在URP管线的Inspector面板下为Additional Lights勾选上Cast Shadows。(接受阴影)
2. URP运行流程
1. 创建RenderPipelineAsset和RendererData
- 如果使用SRP,需要创建RenderPipelineAsset的子类, 在URP中即UniversalRenderPipelineAsset,将其指定到项目Graphics设定里
- URP框架中有ScriptableRenderData类型用于创建Renderer,目前可用的是UniversalRenderData (用于替代之前版本的ForwardRenderData )和Render2DData
- 资源创建UniversalRenderPipelineAsset时会自动创建一个UniversalRenderData或者Render2DData并矢联_上,RenderPipelineAsset至少要有一个RenderData,多个RenderPipelineAsset可以使用同一个RenderData,例如做高中低画质配置(使用不同RenderPipelineAsset,而不是RenderData)
- 运行时可以通过GraphicsSettings.renderPipelineAsset动态修改使用的RenderPipelineAsset
2. 创建Pipeline和Renderer
- 引擎调用CreatePipeline
- UniversalRenderPipelineAsset -> UniversalRenderPipeline
- UniversalRenderData -> UniversalRenderer
- RenderPipelineAsset & RenderPipelineÆ5 I 是引擎c++类,RenderData Renderer是URР расkаgе里的c#脚本类
3. 摄像机与灯光的变化
1. 摄像机
- 渲染器改到URP之后,Camera会被自动带上UniversalAdditionalCameraData脚本,并且Camera参数和Built-in 。RP不同
- 摄像机可选择Overlay类型,这时将其添加到主摄像机的Stack中,即可实现Overlay摄像机对主摄像机的覆盖。
2. 灯光
- Light也会被自动添加UniversalAddiitionalLightData组件,且参数变了。
4. 原理
引擎每帧会调用会这些接口,以便在渲染的不同阶段执行你想要的操作
RenderPipeline:Render
protected override void Render( renderContext, List cameras)
- BeginContextRendering
- render Cameras (RenderCameraStack)
- EndContextRendering (EndFrameRendering)
5. 行为列表
1. 场景剔除Cull
- 执行 context.Cull() 得到 cullResults,初始化RenderingData(本帧Camera用的数据容器)
2. Renderer. Setup
- 决定本帧有哪些RenderPass ( m_ ActiveRenderPassQueue ), forward deferred管线pass不同
- RenderPass渲染步骤。简单地说,渲染pass是渲染管道的单个执行。渲染pass将输出图像渲染到内存中的一组帧缓冲区附件中。
- 根据RenderingData决定是否需要每个pass
3. Renderer. Execute
- 按照RenderPassEvent(渲染队列)对pass列表排序
- 分阶段执行RenderBlock ( BeforeRendering, MainRenderingOpaque,MainRenderingTransparent, AfterRendering),每 个RenderBlock含有这个阶段的所有RenderPass
- 阶段之间执行一些shader uniform ( light, camera, time )设置工作
- 执行每个RenderPass的Execute,内部调用Context的各种底层接口
- Execute完成后 , 执行Context.Submit()提交渲染命令
4. 总结
- 使用SRP之后,由RenderPipelineAsset创建RenderPipeline,每帧走RenderPipeline.Render()
- URP内部RenderData创建Renderer,Camera可以指定使用的Renderer
- URP中,RenderPipeline.Render()主要对每个Camera执行RenderCameraStack,其中对stack里的每个Camera执行RenderSingleCamera
- RenderSingleCamera创建RenderPass队列,并逐个Execute
- RenderPass内部调用ScriptableRenderContext的底层接口,实现制定渲染任务
3. 贴画效果
1. 实现方法
- 为当前使用的URP RendererData添加组件Decal renderer feature ( 否则无法使用Projector)
- 为空对象添加Decal Projector
- 为Decal Projector添加Decal材质
2. Decal设置 Technique(贴花渲染技术)
1. DBuffer
- 用于贴花的几个buffer,需要支持MRT,先将贴花信息(base color, normal, MAOS金属度AO光滑度)信息输出到3个
buffer上,之后渲染场景时将DBuffer信息考虑进去,一并画到物体上(先算贴花,再画物体) - 对于DBuffer,添加三个pass:
- CopyDepthPass
- DBufferRenderPass
- ForwardEmissivePass
- DBufferRenderPass内部有DecalDrawSystem,每个Decal Projector对应一个entity,逐个Draw,实际上就是画Cube
2. Screen Space
- 不用MRT,先画物体得到屏幕空间深度,再画贴花,因为缺乏一些其他信息,效果可能比DBuffer差
3. GBuffer
- 延迟管线下使用
3. 实现原理
Shader "Decal/DepthDecal"
Properties
_MainTex ("Texture", 2D) = "white"
SubShader
Tags "Queue"="Transparent+100"
Pass
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
float4 vertex : POSITION;
;
struct v2f
float4 vertex : SV_POSITION;
float4 screenPos : TEXCOORD1;
float3 ray : TEXCOORD2;
;
sampler2D _MainTex;
sampler2D_float _CameraDepthTexture;
v2f vert (appdata v)
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
// 屏幕坐标
o.screenPos = ComputeScreenPos(o.vertex);
// 从屏幕发出的射线
o.ray =UnityObjectToViewPos(v.vertex) * float3(-1,-1,1);
return o;
fixed4 frag (v2f i) : SV_Target
//深度重建视空间坐标
float2 screenuv = i.screenPos.xy / i.screenPos.w;
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenuv);
// 深度
float viewDepth = Linear01Depth(depth) * _ProjectionParams.z;
// 射线方向✖️深度得到表面坐标
float3 viewPos = i.ray * viewDepth / i.ray.z;
//转化到世界空间坐标
float4 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1.0));
//转化为物体空间坐标
float3 objectPos = mul(unity_WorldToObject, worldPos);
//剔除掉在立方体外面的内容
clip(float3(0.5, 0.5, 0.5) - abs(objectPos));
//使用物体空间坐标的xz坐标作为采样uv
float2 uv = objectPos.xz + 0.5;
fixed4 col = tex2D(_MainTex, uv);
return col;
ENDCG
4. URP的pass通道
1. 基础pass
2. 插入额外pass
- URP内置RenderObjects Decal ScreenSpaceAmbientOcclusion ScreenSpaceShadows,可自行添加 ScriptableRendererFeature 子类并插入Renderer
- 每帧Setup时走RendererFeature的AddRenderPasses添加pass
- 对所有pass排序,逐个执行
5. Renderer Feature
1. 使用
在和上文贴花的相同位置添加,用于在特定渲染后执行渲染
2. 参数
01 Name:首先是这个Feature的名字;
02 Event (事件):当Unity执行这个Renderer Feature 的时候,这个事件Event在通用渲染管线中的执行顺序;
03 Filters:这个设置允许我们给这个Renderer Feature 去配置要渲染哪些对象;这里面有两个参数,一个是Queue,一个是Layer Mask。
Queue:这个Feature选择渲染透明物体还是不透明物体;
Layer Mask:这个Feature选择渲染哪个图层中的对象;
04 Shader Passes Name:如果shader中的一个pass具有 LightMode Pass 这个标记的话,那我们的Renderer Feature仅处理 LightMode Pass Tag 等于这个Shader Passes Name的Pass。
05 Overrides:使用这个Renderer Feature 进行渲染时,这部分的设置可让我们配置某些属性进行重写覆盖。
Material:渲染对象时,Unity会使用该材质替换分配给它的材质。
Depth:选择此选项可以指定这个Renderer Feature如何影响或使用深度缓冲区。此选项包含以下各项:
Write Depth:写入深度,此选项定义渲染对象时这个Renderer Feature是否更新深度缓冲区。
Depth Test:深度测试,决定renderer feature是否渲染object的片元。
Stencil:选中此复选框后,Renderer将处理模板缓冲区值。
Camera:选择此选项可让您覆盖以下“摄像机”属性:
Field of View:渲染对象时,渲染器功能使用此Field of View(视场),而不是在相机上指定的值。
Position Offset:渲染对象时,Renderer Feature将其移动此偏移量。
Restore:选中此选项,在此Renderer Feature中执行渲染过程后,Renderer Feature将还原原始相机矩阵。
6. URP的shader
1. 声明为URP shader
需要在SubShader的tag中注明
Tags"RenderPipeline"="UniversalPipeline"
2. 定义不同的Pass通道
- 这个是urp的默认渲染pass,里面可以处理多光源,自发光,以及环境光和雾等等。
Tags"LightMode"="UniversalForward"
- 这个是用来渲染物体阴影投射的
Tags"LightMode" = "ShadowCaster"
- 这个是渲染深度图的,如果你要在屏幕空间做一些东西,需要渲染此pass渲染。
Tags"LightMode" = "DepthOnly"
- 这个是渲染一张带有深度和法向的纹理图的
Tags"LightMode" = "DepthNormals"
- 这个pass是用来烘焙光照贴图的
Tags"LightMode" = "Meta"
- 这个是用作2d渲染中的,一般我们用unity都是3d,所以这个pass我是直接忽略了。
Tags "LightMode" = "Universal2D"
3. HlSL
- ShaderLab是一个包含Shader语言的代码声明块。在Built-In管线中我们常使用CG语言来写Shader,但是在URP中,一般使用HLSL。CG语言和HLSL语言都是C风格的语言,写法上没有太大差别。
- 由于使用语言不同,用于包含CG语言的CGPROGRAM和ENDCG需要改成包含HLSL的HLSLPROGRAM和ENDHLSL。
HLSLPROGRAM
……
ENDHLSL
4. 头文件
使用的底层代码发生了变化,默认包含的头文件需要从CG的 #include "UnityCG.cginc"
改为#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
除了核心的工具库外,其他如光照、阴影等要包含的头文件也需要修改。
使用了不同的头文件后,自然一些使用各种工具函数也不一样,比如顶点着色器中转换空间的方法UnityObjectToClipPos(v.vertex);在URP中就使用GetVertexPositionInputs(IN.positionOS.xyz);来获取一个存储了各个空间Position坐标的结构体,再从中获取裁剪空间中的位置坐标。
VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
OUT.positionCS = positionInputs.positionCS;
5. CBUFFER
为了支持SRP Batcher,Shader中要将所有暴露出的参数(贴图除外)给包含到CBUFFER_START(UnityPerMaterial)与CBUFFER_END之间。并且为了保证之后的每个Pass都能拥有一样的CBUFFER,这一段代码需要写在SubShader之内,其它Pass之前。
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float _Color;
CBUFFER_END
6. 贴图采样
在CG中我们一般使用sampler2D _Texture来采样贴图。在HLSL中,贴图采样需要声明为Sampler。具体的采样方法也从原来的tex2D(Texture tex,float uv)
;变为SAMPLE_TEXTURE2D(Texture tex, Sampler sampler,float uv);
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
……
float4 frag(Varings IN):SV_Target
……
half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
……
7. 示例
外描边效果
Shader "Unlit/outline"
Properties
_BaseMap ("Base Texture", 2D) = "white"
_BaseColor ("Color", color) = (0, 0, 0, 0)
_Outline ("Outline", Range(0, 1)) = 0.1
SubShader
Tags
// 表明这是一个URP Shader
"RenderPipeline"="UniversalPipeline"
Cull Front
HLSLINCLUDE
// 引入头文件,类似于 CG中核心代码库 "UnityCG.cginc"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// 除了贴图外,要暴露在Inspector面板上的变量都需要缓存到CBUFFER中
CBUFFER_START(UnityPerMaterial)
// 在CG中会写成sampler2D _MainTex;
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
float4 _BaseMap_ST;
float4 _BaseColor;
float _Outline;
CBUFFER_END
ENDHLSL
Pass
// 这个是urp的默认渲染pass,里面可以处理多光源,自发光,以及环境光和雾等等。
Tags"LightMode"="UniversalForward"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
struct Attributes
float4 positionOS : POSITION;
float2 uv : TEXCOORD;
float3 normal : NORMAL;
;
struct Varings
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD;
;
Varings vert(Attributes IN)
Varings OUT;
IN.positionOS.xyz += IN.normal * _Outline;
//在CG里面,我们这样转换空间坐标 o.vertex = UnityObjectToClipPos(v.vertex);
VertexPositionInputs positionInputs = GetVertexPositionInputs(IN.positionOS.xyz);
OUT.positionCS = positionInputs.positionCS;
OUT.uv=TRANSFORM_TEX(IN.uv,_BaseMap);
return OUT;
float4 frag(Varings IN):SV_Target
//在CG里,我们这样对贴图采样 fixed4 col = tex2D(_MainTex, i.uv);
half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
return baseMap * _BaseColor;
ENDHLSL
10分钟搭建一个小型网页(python django)(hello world!)
10分钟搭建一个小型网页(python django)(hello world!)
1、安装django
pip install django
安装成功后,在Scripts目录下存在django-admin.py的文件。
2、安装 mysql接口
pip install MySQL-python
2、创建项目HelloWorld
通过调用django-admin文件中的startproject命令进行安装。
cd到目录下,执行命令
django-admin startproject HelloWorld
3、 runserver启动项目服务器
接下来进入HelloWorld项目,并输入如下命令,启动项目服务器。
命令:
cd helloworld
python manage.py runserver 9090
4、通过浏览器方位127.0.0.1:9090,显示It worked表示配置成功。
5、创建视图views.py文件
在HelloWorld目录下创建一个views.py文件,用于书写业务处理逻辑。自定义hello方法,参数request固定的,用于返回HttpResponse。代码如下:
#-*- coding:utf-8 -*-
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world,世界你好,我是程序员!")
6、配置URL
修改urls.py文件内容,将访问的内容改为views.py文件中的hello函数。
如下所示:
"""
HelloWorld URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r‘^$‘, views.home, name=‘home‘)
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r‘^$‘, Home.as_view(), name=‘home‘)
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r‘^blog/‘, include(‘blog.urls‘))
"""
from django.conf.urls import url
from HelloWorld.views import * #应该是从项目根目录计算
urlpatterns = [
url(r‘^$‘, hello),
]
代码需要导入views文件内容,才能引用hello方法。views.py视图文件在编译后会产生对应的views.pyc文件。
7、edit configrations 输入host:127.0.0.1,port输入8000
然后启动Django服务器,在浏览器中访问
http://127.0.0.1:8000/ 正常访问
以上是关于Unity-URP的主要内容,如果未能解决你的问题,请参考以下文章