Unity 2019.4 - Using Unity’s existing rendering architecture (not SRP)
Hi folks, I’ve been able to use BatchRendererGroups succesfully with MaterialPropertyBlocks to set values on a per-instance shader property. However it looks like I should be able to do the same using GetBatchScalarArray and so far I’ve not been able to get it to work. My test is below.
The test is very simple. We expose a float property called _BRG_TestVal which controls an x offset applied to verts in the vertex stage.
On the cpu side I have working code that shows that the approach using MaterialPropertyBlocks works. The issue is that if I comment out this bit:
_matBlockForBatch.SetFloatArray(_shaderPropId, new float[] { wobble });
_brg.SetInstancingData(_batch, 1, _matBlockForBatch);
and uncomment this bit
// var instVals = _brg.GetBatchScalarArray(_batch, _shaderPropId);
// instVals[0] = wobble;
I no longer see the horizontal translation (and so we know the property is not being set correctly)
Any clues you can give me as to how to correctly use GetBatchScalarArray would be very much appreciated.
Cheers
Shader:
// Made with Amplify Shader Editor
Shader "BatchRenderGroupTest"
{
Properties
{
_BRG_TestVal("_BRG_TestVal", Float) = 0
[HideInInspector] __dirty( "", Int ) = 1
}
SubShader
{
Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+0" }
Cull Back
CGPROGRAM
#pragma target 3.0
#pragma multi_compile_instancing
#pragma surface surf Standard keepalpha addshadow fullforwardshadows vertex:vertexDataFunc
struct Input
{
half filler;
};
UNITY_INSTANCING_BUFFER_START(BatchRenderGroupTest)
UNITY_DEFINE_INSTANCED_PROP(float, _BRG_TestVal)
#define _BRG_TestVal_arr BatchRenderGroupTest
UNITY_INSTANCING_BUFFER_END(BatchRenderGroupTest)
void vertexDataFunc( inout appdata_full v, out Input o )
{
UNITY_INITIALIZE_OUTPUT( Input, o );
float _BRG_TestVal_Instance = UNITY_ACCESS_INSTANCED_PROP(_BRG_TestVal_arr, _BRG_TestVal);
float4 appendResult7 = (float4(_BRG_TestVal_Instance , 0.0 , 0.0 , 0.0));
v.vertex.xyz += appendResult7.xyz;
}
void surf( Input i , inout SurfaceOutputStandard o )
{
float4 color1 = IsGammaSpace() ? float4(1,0,0,0) : float4(1,0,0,0);
o.Albedo = color1.rgb;
o.Alpha = 1;
}
ENDCG
}
Fallback "Diffuse"
CustomEditor "ASEMaterialInspector"
}
Cpu-side
using UnityEngine;
using UnityEngine.Rendering;
using Unity.Jobs;
public class BatchRendererGroupTest : MonoBehaviour
{
public GameObject ExampleObject; // an object that is my sanity check that the shader works without using BatchRendererGroup
BatchRendererGroup _brg;
int _batch;
int _shaderPropId;
MaterialPropertyBlock _matBlockForExampleObj;
MaterialPropertyBlock _matBlockForBatch;
void OnEnable()
{
_brg = new BatchRendererGroup(CullingCallback);
var mat = ExampleObject.GetComponent<MeshRenderer>().sharedMaterial;
var mesh = ExampleObject.GetComponent<MeshFilter>().sharedMesh;
_matBlockForExampleObj = new MaterialPropertyBlock();
_matBlockForBatch = new MaterialPropertyBlock();
ExampleObject.GetComponent<MeshRenderer>().GetPropertyBlock(_matBlockForExampleObj);
_matBlockForBatch.SetFloatArray(_shaderPropId, new float[] { 0 });
_batch = _brg.AddBatch(mesh, 0, mat, 0, castShadows: ShadowCastingMode.On, receiveShadows: true, invertCulling: false,
bounds: new Bounds(Vector3.one * 20, Vector3.one * 20), instanceCount: 1, customProps: _matBlockForBatch,
associatedSceneObject: null);
_shaderPropId = Shader.PropertyToID("_BRG_TestVal");
}
void OnDisable()
{
_brg.Dispose();
}
void Update()
{
var wobble = Mathf.Sin(Time.time * 6);
// Showing that instancing with the MaterialPropertyBlock works
_matBlockForBatch.SetFloatArray(_shaderPropId, new float[] { wobble });
_brg.SetInstancingData(_batch, 1, _matBlockForBatch);
var transforms = _brg.GetBatchMatrices(_batch);
transforms[0] = Matrix4x4.Translate(new Vector3(0, wobble, 0));
// - This didnt work
// var instVals = _brg.GetBatchScalarArray(_batch, _shaderPropId);
// instVals[0] = wobble;
// Just to prove to myself that the instance property is working when not using BatchRendererGroup
_matBlockForExampleObj.SetFloat(_shaderPropId, wobble);
ExampleObject.GetComponent<MeshRenderer>().SetPropertyBlock(_matBlockForExampleObj);
}
// Not relevent, just dummy culling
JobHandle CullingCallback(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext)
{
for (var batchIndex = 0; batchIndex < cullingContext.batchVisibility.Length; ++batchIndex)
{
var batchVisibility = cullingContext.batchVisibility[batchIndex];
for (var i = 0; i < batchVisibility.instancesCount; ++i)
{
cullingContext.visibleIndices[batchVisibility.offset + i] = i;
}
batchVisibility.visibleCount = batchVisibility.instancesCount;
cullingContext.batchVisibility[batchIndex] = batchVisibility;
}
return default;
}
}
}