您现在的位置是:首页 >其他 >SRP中的shader网站首页其他

SRP中的shader

异次元的归来 2024-06-17 10:19:51
简介SRP中的shader

SRP中的shader

在Unity中使用SRP时,我们需要使用HLSL来编写shader。HLSL语法与GLSL类似,在使用HLSL的地方我们需要用HLSLPROGRAMENDHLSL来包裹:

Shader "My Pipeline/Unlit" {
	Properties {}

	SubShader {

		Pass
		{
			HLSLPROGRAM

			#pragma vertex UnlitPassVertex
			#pragma fragment UnlitPassFragment

			#include "Unlit.hlsl"

			ENDHLSL
		}
	}
}

此时,unity_MatrixVPunity_ObjectToWorld这两个矩阵也不能直接使用,需要我们自行声明:

float4x4 unity_MatrixVP;
float4x4 unity_ObjectToWorld;

struct VertexInput {
	float4 pos : POSITION;
};

struct VertexOutput {
	float4 clipPos : SV_POSITION;
};

VertexOutput UnlitPassVertex (VertexInput input) {
	VertexOutput output;
	float4 worldPos = mul(unity_ObjectToWorld, input.pos);
	output.clipPos = mul(unity_MatrixVP, worldPos);
	return output;
}

float4 UnlitPassFragment (VertexOutput input) : SV_TARGET {
	return 1;
}

另外,这两个矩阵的更新频率实际上是不同的,unity_MatrixVP矩阵绘制每一帧画面时只需更新一次,而unity_ObjectToWorld跟绘制的物体还有关系,因此它需要每次绘制时都要更新一次。这样的话,我们可以利用unity提供的cbuffer,使得这两个矩阵可以按照自身需要的频率更新:

CBUFFER_START(UnityPerFrame)
	float4x4 unity_MatrixVP;
CBUFFER_END

CBUFFER_START(UnityPerDraw)
	float4x4 unity_ObjectToWorld;
CBUFFER_END

现在使用该shader的材质,来绘制一些gameobject试试:

SRP中的shader1

接下来,我们希望这些gameobject拥有不同的颜色,显然颜色这个是跟随材质变化的,因此我们要把它放到UnityPerMaterial中:

CBUFFER_START(UnityPerMaterial)
	float4 _Color;
CBUFFER_END

这下gameobject就可以五彩斑斓了:

SRP中的shader2

最后,我们希望在SRP中使用gpu instancing的方式来绘制这些gameobjects。首先在C#中把开关打开:

drawSettings.enableInstancing = true;

然后还要在shader中引入INSTANCING_ON关键字:

#pragma multi_compile_instancing

为了支持instancing,原先放在UnityPerMaterialbuffer中的_Color需要挪到UNITY_INSTANCING_BUFFER中:

UNITY_INSTANCING_BUFFER_START(PerInstance)
	UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_INSTANCING_BUFFER_END(PerInstance)

同时vertex shader和frag shader也要相应地改动:

struct VertexInput {
	float4 pos : POSITION;
	UNITY_VERTEX_INPUT_INSTANCE_ID
};

struct VertexOutput {
	float4 clipPos : SV_POSITION;
	UNITY_VERTEX_INPUT_INSTANCE_ID
};

VertexOutput UnlitPassVertex (VertexInput input) {
	VertexOutput output;
	UNITY_SETUP_INSTANCE_ID(input);
	UNITY_TRANSFER_INSTANCE_ID(input, output);
	float4 worldPos = mul(UNITY_MATRIX_M, float4(input.pos.xyz, 1.0));
	output.clipPos = mul(unity_MatrixVP, worldPos);
	return output;
}

float4 UnlitPassFragment (VertexOutput input) : SV_TARGET {
	UNITY_SETUP_INSTANCE_ID(input);
	return UNITY_ACCESS_INSTANCED_PROP(PerInstance, _Color);
}

这时我们再用frame debug看一下,可以发现draw call大大降低了:

SRP中的shader3

如果你觉得我的文章有帮助,欢迎关注我的微信公众号 我是真的想做游戏啊

Reference

[1] Custom Shaders

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。