Last active
September 29, 2024 06:33
-
-
Save Shitakami/bb075299ea9a434426a48e9bd18b57fb to your computer and use it in GitHub Desktop.
Unity URP Graphics.RenderMeshIndirect サンプルコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Shader "Custom/ForRenderMeshIndirect" | |
{ | |
Properties | |
{ | |
// Specular vs Metallic workflow | |
_WorkflowMode("WorkflowMode", Float) = 1.0 | |
[MainTexture] _BaseMap("Albedo", 2D) = "white" {} | |
[MainColor] _BaseColor("Color", Color) = (1,1,1,1) | |
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 | |
_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5 | |
_SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 | |
_Metallic("Metallic", Range(0.0, 1.0)) = 0.0 | |
_MetallicGlossMap("Metallic", 2D) = "white" {} | |
_SpecColor("Specular", Color) = (0.2, 0.2, 0.2) | |
_SpecGlossMap("Specular", 2D) = "white" {} | |
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 | |
[ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0 | |
_BumpScale("Scale", Float) = 1.0 | |
_BumpMap("Normal Map", 2D) = "bump" {} | |
_Parallax("Scale", Range(0.005, 0.08)) = 0.005 | |
_ParallaxMap("Height Map", 2D) = "black" {} | |
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 | |
_OcclusionMap("Occlusion", 2D) = "white" {} | |
[HDR] _EmissionColor("Color", Color) = (0,0,0) | |
_EmissionMap("Emission", 2D) = "white" {} | |
_DetailMask("Detail Mask", 2D) = "white" {} | |
_DetailAlbedoMapScale("Scale", Range(0.0, 2.0)) = 1.0 | |
_DetailAlbedoMap("Detail Albedo x2", 2D) = "linearGrey" {} | |
_DetailNormalMapScale("Scale", Range(0.0, 2.0)) = 1.0 | |
[Normal] _DetailNormalMap("Normal Map", 2D) = "bump" {} | |
// SRP batching compatibility for Clear Coat (Not used in Lit) | |
[HideInInspector] _ClearCoatMask("_ClearCoatMask", Float) = 0.0 | |
[HideInInspector] _ClearCoatSmoothness("_ClearCoatSmoothness", Float) = 0.0 | |
// Blending state | |
_Surface("__surface", Float) = 0.0 | |
_Blend("__blend", Float) = 0.0 | |
_Cull("__cull", Float) = 2.0 | |
[ToggleUI] _AlphaClip("__clip", Float) = 0.0 | |
[HideInInspector] _SrcBlend("__src", Float) = 1.0 | |
[HideInInspector] _DstBlend("__dst", Float) = 0.0 | |
[HideInInspector] _SrcBlendAlpha("__srcA", Float) = 1.0 | |
[HideInInspector] _DstBlendAlpha("__dstA", Float) = 0.0 | |
[HideInInspector] _ZWrite("__zw", Float) = 1.0 | |
[HideInInspector] _BlendModePreserveSpecular("_BlendModePreserveSpecular", Float) = 1.0 | |
[HideInInspector] _AlphaToMask("__alphaToMask", Float) = 0.0 | |
[ToggleUI] _ReceiveShadows("Receive Shadows", Float) = 1.0 | |
// Editmode props | |
_QueueOffset("Queue offset", Float) = 0.0 | |
// ObsoleteProperties | |
[HideInInspector] _MainTex("BaseMap", 2D) = "white" {} | |
[HideInInspector] _Color("Base Color", Color) = (1, 1, 1, 1) | |
[HideInInspector] _GlossMapScale("Smoothness", Float) = 0.0 | |
[HideInInspector] _Glossiness("Smoothness", Float) = 0.0 | |
[HideInInspector] _GlossyReflections("EnvironmentReflections", Float) = 0.0 | |
[HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {} | |
[HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {} | |
[HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {} | |
} | |
SubShader | |
{ | |
// Universal Pipeline tag is required. If Universal render pipeline is not set in the graphics settings | |
// this Subshader will fail. One can add a subshader below or fallback to Standard built-in to make this | |
// material work with both Universal Render Pipeline and Builtin Unity Pipeline | |
Tags | |
{ | |
"RenderType" = "Opaque" | |
"RenderPipeline" = "UniversalPipeline" | |
"UniversalMaterialType" = "Lit" | |
"IgnoreProjector" = "True" | |
} | |
LOD 300 | |
HLSLINCLUDE | |
StructuredBuffer<float4x4> _TransformMatrixArray; | |
half3 _BoundsOffset; | |
void transform_vertex(inout float3 position, inout float3 normal, uint instanceId) | |
{ | |
float4x4 mat = _TransformMatrixArray[instanceId]; | |
position = mul(mat, float4(position, 1.0)).xyz - _BoundsOffset; | |
normal = normalize(mul((float3x3)mat, normal)); | |
} | |
ENDHLSL | |
// ------------------------------------------------------------------ | |
// Forward pass. Shades all light in a single pass. GI + emission + Fog | |
Pass | |
{ | |
// Lightmode matches the ShaderPassName set in UniversalRenderPipeline.cs. SRPDefaultUnlit and passes with | |
// no LightMode tag are also rendered by Universal Render Pipeline | |
Name "ForwardLit" | |
Tags | |
{ | |
"LightMode" = "UniversalForward" | |
} | |
// ------------------------------------- | |
// Render State Commands | |
Blend[_SrcBlend][_DstBlend], [_SrcBlendAlpha][_DstBlendAlpha] | |
ZWrite[_ZWrite] | |
Cull[_Cull] | |
AlphaToMask[_AlphaToMask] | |
HLSLPROGRAM | |
#pragma target 2.0 | |
// ------------------------------------- | |
// Shader Stages | |
#pragma vertex LitPassVertexForRenderMeshIndirect | |
#pragma fragment LitPassFragment | |
// ------------------------------------- | |
// Material Keywords | |
#pragma shader_feature_local _NORMALMAP | |
#pragma shader_feature_local _PARALLAXMAP | |
#pragma shader_feature_local _RECEIVE_SHADOWS_OFF | |
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED | |
#pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT | |
#pragma shader_feature_local_fragment _ALPHATEST_ON | |
#pragma shader_feature_local_fragment _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON | |
#pragma shader_feature_local_fragment _EMISSION | |
#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP | |
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A | |
#pragma shader_feature_local_fragment _OCCLUSIONMAP | |
#pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF | |
#pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF | |
#pragma shader_feature_local_fragment _SPECULAR_SETUP | |
// ------------------------------------- | |
// Universal Pipeline keywords | |
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN | |
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS | |
#pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX | |
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS | |
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING | |
#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION | |
#pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH | |
#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION | |
#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3 | |
#pragma multi_compile_fragment _ _LIGHT_COOKIES | |
#pragma multi_compile _ _LIGHT_LAYERS | |
#pragma multi_compile _ _FORWARD_PLUS | |
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl" | |
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl" | |
// ------------------------------------- | |
// Unity defined keywords | |
#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING | |
#pragma multi_compile _ SHADOWS_SHADOWMASK | |
#pragma multi_compile _ DIRLIGHTMAP_COMBINED | |
#pragma multi_compile _ LIGHTMAP_ON | |
#pragma multi_compile _ DYNAMICLIGHTMAP_ON | |
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE | |
#pragma multi_compile_fog | |
#pragma multi_compile_fragment _ DEBUG_DISPLAY | |
//-------------------------------------- | |
// GPU Instancing | |
#pragma multi_compile_instancing | |
#pragma instancing_options renderinglayer | |
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl" | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl" | |
#define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs | |
#include "UnityIndirect.cginc" | |
Varyings LitPassVertexForRenderMeshIndirect(Attributes input, uint instanceID : SV_InstanceID) | |
{ | |
InitIndirectDrawArgs(0); | |
Varyings output = (Varyings)0; | |
UNITY_SETUP_INSTANCE_ID(input); | |
UNITY_TRANSFER_INSTANCE_ID(input, output); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); | |
transform_vertex(input.positionOS.xyz, input.normalOS.xyz, instanceID); | |
input.tangentOS.xyz = normalize(mul((float3x3)_TransformMatrixArray[instanceID], input.tangentOS.xyz)); | |
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); | |
// normalWS and tangentWS already normalize. | |
// this is required to avoid skewing the direction during interpolation | |
// also required for per-vertex lighting and SH evaluation | |
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); | |
half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS); | |
half fogFactor = 0; | |
#if !defined(_FOG_FRAGMENT) | |
fogFactor = ComputeFogFactor(vertexInput.positionCS.z); | |
#endif | |
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); | |
// already normalized from normal transform to WS. | |
output.normalWS = normalInput.normalWS; | |
#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR) || defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR) | |
real sign = input.tangentOS.w * GetOddNegativeScale(); | |
half4 tangentWS = half4(normalInput.tangentWS.xyz, sign); | |
#endif | |
#if defined(REQUIRES_WORLD_SPACE_TANGENT_INTERPOLATOR) | |
output.tangentWS = tangentWS; | |
#endif | |
#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR) | |
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS); | |
half3 viewDirTS = GetViewDirectionTangentSpace(tangentWS, output.normalWS, viewDirWS); | |
output.viewDirTS = viewDirTS; | |
#endif | |
OUTPUT_LIGHTMAP_UV(input.staticLightmapUV, unity_LightmapST, output.staticLightmapUV); | |
#ifdef DYNAMICLIGHTMAP_ON | |
output.dynamicLightmapUV = input.dynamicLightmapUV.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; | |
#endif | |
OUTPUT_SH(output.normalWS.xyz, output.vertexSH); | |
#ifdef _ADDITIONAL_LIGHTS_VERTEX | |
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight); | |
#else | |
output.fogFactor = fogFactor; | |
#endif | |
#if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR) | |
output.positionWS = vertexInput.positionWS; | |
#endif | |
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) | |
output.shadowCoord = GetShadowCoord(vertexInput); | |
#endif | |
output.positionCS = vertexInput.positionCS; | |
return output; | |
} | |
ENDHLSL | |
} | |
Pass | |
{ | |
Name "ShadowCaster" | |
Tags | |
{ | |
"LightMode" = "ShadowCaster" | |
} | |
// ------------------------------------- | |
// Render State Commands | |
ZWrite On | |
ZTest LEqual | |
ColorMask 0 | |
Cull[_Cull] | |
HLSLPROGRAM | |
#pragma target 2.0 | |
// ------------------------------------- | |
// Shader Stages | |
#pragma vertex ShadowPassVertexForRenderMeshIndirect | |
#pragma fragment ShadowPassFragment | |
// ------------------------------------- | |
// Material Keywords | |
#pragma shader_feature_local _ALPHATEST_ON | |
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A | |
//-------------------------------------- | |
// GPU Instancing | |
#pragma multi_compile_instancing | |
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl" | |
// ------------------------------------- | |
// Universal Pipeline keywords | |
// ------------------------------------- | |
// Unity defined keywords | |
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE | |
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias | |
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW | |
// ------------------------------------- | |
// Includes | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl" | |
#define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs | |
#include "UnityIndirect.cginc" | |
Varyings ShadowPassVertexForRenderMeshIndirect(Attributes input, uint instanceID : SV_InstanceID) | |
{ | |
InitIndirectDrawArgs(0); | |
Varyings output; | |
UNITY_SETUP_INSTANCE_ID(input); | |
UNITY_TRANSFER_INSTANCE_ID(input, output); | |
#if defined(_ALPHATEST_ON) | |
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); | |
#endif | |
transform_vertex(input.positionOS.xyz, input.normalOS.xyz, instanceID); | |
output.positionCS = GetShadowPositionHClip(input); | |
return output; | |
} | |
ENDHLSL | |
} | |
Pass | |
{ | |
Name "DepthOnly" | |
Tags | |
{ | |
"LightMode" = "DepthOnly" | |
} | |
// ------------------------------------- | |
// Render State Commands | |
ZWrite On | |
ColorMask R | |
Cull[_Cull] | |
HLSLPROGRAM | |
#pragma target 2.0 | |
// ------------------------------------- | |
// Shader Stages | |
#pragma vertex DepthOnlyVertexForRenderMeshIndirect | |
#pragma fragment DepthOnlyFragment | |
// ------------------------------------- | |
// Material Keywords | |
#pragma shader_feature_local _ALPHATEST_ON | |
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A | |
// ------------------------------------- | |
// Unity defined keywords | |
#pragma multi_compile_fragment _ LOD_FADE_CROSSFADE | |
//-------------------------------------- | |
// GPU Instancing | |
#pragma multi_compile_instancing | |
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl" | |
// ------------------------------------- | |
// Includes | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" | |
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl" | |
#define UNITY_INDIRECT_DRAW_ARGS IndirectDrawIndexedArgs | |
#include "UnityIndirect.cginc" | |
Varyings DepthOnlyVertexForRenderMeshIndirect(Attributes input, uint instanceID : SV_InstanceID) | |
{ | |
InitIndirectDrawArgs(0); | |
Varyings output = (Varyings)0; | |
UNITY_SETUP_INSTANCE_ID(input); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); | |
float3 _ = float3(0, 0, 1); | |
transform_vertex(input.position.xyz, _, instanceID); | |
#if defined(_ALPHATEST_ON) | |
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap); | |
#endif | |
output.positionCS = TransformObjectToHClip(input.position.xyz); | |
return output; | |
} | |
ENDHLSL | |
} | |
} | |
FallBack "Hidden/Universal Render Pipeline/FallbackError" | |
CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Runtime.InteropServices; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
public class SampleRenderMeshIndirect : MonoBehaviour | |
{ | |
[SerializeField] private int _count; | |
[SerializeField] private Mesh _mesh; | |
[SerializeField] private Material _material; | |
[SerializeField] private ShadowCastingMode _shadowCastingMode; | |
[SerializeField] private bool _receiveShadows; | |
private GraphicsBuffer _drawArgsBuffer; | |
private GraphicsBuffer _dataBuffer; | |
private void Start() | |
{ | |
var maxPosition = transform.position + transform.localScale / 2; | |
var minPosition = transform.position - transform.localScale / 2; | |
_drawArgsBuffer = CreateDrawArgsBufferForRenderMeshIndirect(_mesh, _count); | |
_dataBuffer = CreateDataBuffer<Matrix4x4>(_count); | |
var transformMatrixArray = TransformMatrixArrayFactory.Create(_count, maxPosition, minPosition); | |
_dataBuffer.SetData(transformMatrixArray); | |
_material.SetBuffer("_TransformMatrixArray", _dataBuffer); | |
_material.SetVector("_BoundsOffset", transform.position); | |
transformMatrixArray.Dispose(); | |
} | |
private void Update() | |
{ | |
var renderParams = new RenderParams(_material) | |
{ | |
receiveShadows = _receiveShadows, | |
shadowCastingMode = _shadowCastingMode, | |
worldBounds = new Bounds(transform.position, transform.localScale) | |
}; | |
Graphics.RenderMeshIndirect( | |
renderParams, | |
_mesh, | |
_drawArgsBuffer | |
); | |
} | |
private void OnDestroy() | |
{ | |
_drawArgsBuffer?.Dispose(); | |
_dataBuffer?.Dispose(); | |
} | |
private static GraphicsBuffer CreateDrawArgsBufferForRenderMeshIndirect(Mesh mesh, int instanceCount) | |
{ | |
var commandData = new GraphicsBuffer.IndirectDrawIndexedArgs[1]; | |
commandData[0] = new GraphicsBuffer.IndirectDrawIndexedArgs | |
{ | |
indexCountPerInstance = mesh.GetIndexCount(0), | |
instanceCount = (uint)instanceCount, | |
startIndex = mesh.GetIndexStart(0), | |
baseVertexIndex = mesh.GetBaseVertex(0), | |
}; | |
var drawArgsBuffer = new GraphicsBuffer( | |
GraphicsBuffer.Target.IndirectArguments, | |
1, | |
GraphicsBuffer.IndirectDrawIndexedArgs.size | |
); | |
drawArgsBuffer.SetData(commandData); | |
return drawArgsBuffer; | |
} | |
private static GraphicsBuffer CreateDataBuffer<T>(int instanceCount) where T : struct | |
{ | |
return new GraphicsBuffer( | |
GraphicsBuffer.Target.Structured, instanceCount, | |
Marshal.SizeOf(typeof(T)) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using UnityEngine; | |
public static class TransformMatrixArrayFactory | |
{ | |
public static NativeArray<Matrix4x4> Create( | |
int count, | |
float3 maxPosition, | |
float3 minPosition | |
) | |
{ | |
var transformMatrixArray = new NativeArray<Matrix4x4>(count, Allocator.Persistent); | |
var job = new InitializeMatrixJob | |
{ | |
_transformMatrixArray = transformMatrixArray, | |
_maxPosition = maxPosition, | |
_minPosition = minPosition | |
}; | |
var jobHandle = job.Schedule(count, 64); | |
jobHandle.Complete(); | |
return transformMatrixArray; | |
} | |
[BurstCompile] | |
private struct InitializeMatrixJob : IJobParallelFor | |
{ | |
[WriteOnly] public NativeArray<Matrix4x4> _transformMatrixArray; | |
[ReadOnly] public float3 _maxPosition; | |
[ReadOnly] public float3 _minPosition; | |
public void Execute(int index) | |
{ | |
var random = new Unity.Mathematics.Random((uint)index + 1); | |
var x = random.NextFloat(_minPosition.x, _maxPosition.x); | |
var y = random.NextFloat(_minPosition.y, _maxPosition.y); | |
var z = random.NextFloat(_minPosition.z, _maxPosition.z); | |
_transformMatrixArray[index] = Matrix4x4.TRS(new Vector3(x, y, z), random.NextQuaternionRotation(), Vector3.one); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment