Adaug proiectul Unity

This commit is contained in:
2026-11-01 23:39:55 +02:00
parent cb14d9d37d
commit 863eac8f2c
23463 changed files with 5412601 additions and 0 deletions
@@ -0,0 +1,172 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Unity.Collections;
using Unity.Mathematics;
namespace UnityEngine.Rendering.Universal.Tests
{
class BuddyAllocatorTests
{
static IEnumerable<int> levelsCounts1D = Enumerable.Range(1, 24);
[TestCaseSource(nameof(levelsCounts1D))]
public void Empty1D(int levelCount)
{
var allocator = new BuddyAllocator(levelCount, 1, Allocator.Temp);
allocator.Dispose();
}
static IEnumerable<int> levelsCounts2D = Enumerable.Range(1, 12);
[TestCaseSource(nameof(levelsCounts2D))]
public void Empty2D(int levelCount)
{
var allocator = new BuddyAllocator(levelCount, 2, Allocator.Temp);
allocator.Dispose();
}
static IEnumerable<int> levelsCounts3D = Enumerable.Range(1, 8);
[TestCaseSource(nameof(levelsCounts3D))]
public void Empty3D(int levelCount)
{
var allocator = new BuddyAllocator(levelCount, 3, Allocator.Temp);
allocator.Dispose();
}
[Test]
public void Allocate1()
{
using var allocator = new BuddyAllocator(8, 2);
Assert.IsTrue(allocator.TryAllocate(0, out var allocation));
Assert.AreEqual(0, allocation.index);
}
[Test]
public void Allocate6()
{
using var allocator = new BuddyAllocator(8, 2);
Assert.IsTrue(allocator.TryAllocate(1, out var a0));
Assert.AreEqual(math.uint2(0, 0), a0.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a1));
Assert.AreEqual(math.uint2(1, 0), a1.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a2));
Assert.AreEqual(math.uint2(0, 1), a2.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a3));
Assert.AreEqual(math.uint2(1, 1), a3.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a4));
Assert.AreEqual(math.uint2(2, 0), a4.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a5));
Assert.AreEqual(math.uint2(3, 0), a5.index2D);
}
[Test]
public void Allocate6Recycle2()
{
using var allocator = new BuddyAllocator(3, 2);
Assert.IsTrue(allocator.TryAllocate(1, out var a0));
Assert.AreEqual(math.uint2(0, 0), a0.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a1));
Assert.AreEqual(math.uint2(1, 0), a1.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a2));
Assert.AreEqual(math.uint2(0, 1), a2.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a3));
Assert.AreEqual(math.uint2(1, 1), a3.index2D);
allocator.Free(a3);
allocator.Free(a2);
Assert.IsTrue(allocator.TryAllocate(1, out a2));
Assert.AreEqual(math.uint2(0, 1), a2.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out a3));
Assert.AreEqual(math.uint2(1, 1), a3.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a4));
Assert.AreEqual(math.uint2(2, 0), a4.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a5));
Assert.AreEqual(math.uint2(3, 0), a5.index2D);
}
[Test]
public void Allocate6Recycle4()
{
using var allocator = new BuddyAllocator(3, 2);
Assert.IsTrue(allocator.TryAllocate(1, out var a0));
Assert.AreEqual(math.uint2(0, 0), a0.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a1));
Assert.AreEqual(math.uint2(1, 0), a1.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a2));
Assert.AreEqual(math.uint2(0, 1), a2.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a3));
Assert.AreEqual(math.uint2(1, 1), a3.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a4));
Assert.AreEqual(math.uint2(2, 0), a4.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a5));
Assert.AreEqual(math.uint2(3, 0), a5.index2D);
allocator.Free(a0);
allocator.Free(a1);
allocator.Free(a2);
allocator.Free(a3);
Assert.IsTrue(allocator.TryAllocate(0, out var a6));
Assert.AreEqual(math.uint2(0, 0), a6.index2D);
}
[Test]
public void CubemapScenario1()
{
using var allocator = new BuddyAllocator(3, 2);
// Allocate 6 items on level 2. This will use up (0, 0) and (1, 0) on level 1.
Assert.IsTrue(allocator.TryAllocate(2, out var a00));
Assert.IsTrue(allocator.TryAllocate(2, out var a01));
Assert.IsTrue(allocator.TryAllocate(2, out var a02));
Assert.IsTrue(allocator.TryAllocate(2, out var a03));
Assert.IsTrue(allocator.TryAllocate(2, out var a04));
Assert.IsTrue(allocator.TryAllocate(2, out var a05));
Assert.AreEqual(math.uint2(0, 0), a00.index2D);
Assert.AreEqual(math.uint2(1, 0), a01.index2D);
Assert.AreEqual(math.uint2(0, 1), a02.index2D);
Assert.AreEqual(math.uint2(1, 1), a03.index2D);
Assert.AreEqual(math.uint2(2, 0), a04.index2D);
Assert.AreEqual(math.uint2(3, 0), a05.index2D);
Assert.IsTrue(allocator.TryAllocate(1, out var a10));
Assert.IsTrue(allocator.TryAllocate(1, out var a11));
Assert.IsTrue(allocator.TryAllocate(1, out var a12));
Assert.IsTrue(allocator.TryAllocate(1, out var a13));
Assert.IsTrue(allocator.TryAllocate(1, out var a14));
Assert.IsTrue(allocator.TryAllocate(1, out var a15));
Assert.AreEqual(math.uint2(0, 1), a10.index2D);
Assert.AreEqual(math.uint2(1, 1), a11.index2D);
Assert.AreEqual(math.uint2(2, 0), a12.index2D);
Assert.AreEqual(math.uint2(3, 0), a13.index2D);
Assert.AreEqual(math.uint2(2, 1), a14.index2D);
Assert.AreEqual(math.uint2(3, 1), a15.index2D);
// This should make (0, 0) and (1, 0) available on level 1 again.
allocator.Free(a05);
allocator.Free(a04);
allocator.Free(a03);
allocator.Free(a02);
allocator.Free(a01);
allocator.Free(a00);
Assert.IsTrue(allocator.TryAllocate(1, out var a20));
Assert.IsTrue(allocator.TryAllocate(1, out var a21));
Assert.IsTrue(allocator.TryAllocate(1, out var a22));
Assert.IsTrue(allocator.TryAllocate(1, out var a23));
Assert.IsTrue(allocator.TryAllocate(1, out var a24));
Assert.IsTrue(allocator.TryAllocate(1, out var a25));
Assert.AreEqual(math.uint2(0, 0), a20.index2D);
Assert.AreEqual(math.uint2(1, 0), a21.index2D);
Assert.AreEqual(math.uint2(0, 2), a22.index2D);
Assert.AreEqual(math.uint2(1, 2), a23.index2D);
Assert.AreEqual(math.uint2(0, 3), a24.index2D);
Assert.AreEqual(math.uint2(1, 3), a25.index2D);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ebd6b9f28e27469791da648250488852
timeCreated: 1649853541
@@ -0,0 +1,61 @@
Shader "Hidden/Core/CustomDepthBlit"
{
SubShader
{
HLSLINCLUDE
#define USE_FULL_PRECISION_BLIT_TEXTURE
// For now we don't test XR in this graphics test
#undef UNITY_STEREO_INSTANCING_ENABLED
#undef UNITY_STEREO_MULTIVIEW_ENABLED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
ENDHLSL
Tags { "RenderType"="Opaque" }
LOD 100
Cull Off
ZTest Always
Pass
{
Name "Depth"
ColorMask 0
ZWrite On
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
float Frag (Varyings input) : SV_Depth
{
return SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).r;
}
ENDHLSL
}
Pass
{
Name "Depth As Color"
ZWrite Off
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
float4 Frag (Varyings input) : SV_Target
{
float depth = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord).r;
return depth;
}
ENDHLSL
}
}
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 7057bb795f794bc44a4e34ca79be6e54
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace Documentation
{
// https://jira.unity3d.com/browse/URP-1990
// class DocumentationTests
// {
// private bool TestURL(string url)
// {
// try
// {
// HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
// // Timeout set to 10 seconds
// request.Timeout = 10000;
// // Only get header information
// request.Method = "HEAD";
// using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
// {
// int statusCode = (int)response.StatusCode;
// // Successful requests
// if (statusCode >= 100 && statusCode < 400)
// return true;
// // Server Errors
// if (statusCode >= 500 && statusCode <= 510)
// return false;
// }
// }
// catch
// {
// // ignored
// }
// return false;
// }
// [Test]
// public void TestURPHelpURLAttributes()
// {
// // Start with checking a bad URL to make sure TestURL() works.
// string badURL = "https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@16.0/manual/incorrect-url";
// bool badURLResults = TestURL(badURL);
// Assert.IsFalse(badURLResults, "TestURL() failed. A broken URL should have been detected.");
// // Find everything that uses URPHelpURLAttribute
// TypeCache.TypeCollection typesWithHelpUrls = TypeCache.GetTypesWithAttribute<URPHelpURLAttribute>();
// // Check if all the URLs are valid.
// bool allURLsAreValid = true;
// StringBuilder failures = new ();
// foreach (Type type in typesWithHelpUrls)
// {
// Debug.Log("Checking \"" + type.FullName + "\"");
// object[] attributes = type.GetCustomAttributes(typeof(URPHelpURLAttribute), false);
// for (int i = 0; i < attributes.Length; i++)
// {
// URPHelpURLAttribute attribute = attributes[i] as URPHelpURLAttribute;
// Assert.IsNotNull(attribute);
// string url = attribute.URL;
// bool urlIsValid = TestURL(url);
// Debug.Log("\t" + url);
// Debug.Log(urlIsValid ? "\tSuccess!\n" : "\tFailure!\n");
// if (urlIsValid)
// continue;
// allURLsAreValid = false;
// failures.AppendLine("\t" + type.FullName);
// failures.AppendLine("\t" + url);
// failures.AppendLine();
// }
// }
// if (!allURLsAreValid)
// Assert.Fail("The following URLs failed:\n" + failures);
// }
// }
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8aa70fc832dbdae46a749f0687925875
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,287 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEditor.Rendering.Universal.Internal;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
class EditorTests
{
// Validate that resource Guids are valid
[Test]
public void ValidateBuiltinResourceFiles()
{
string templatePath = AssetDatabase.GUIDToAssetPath(ResourceGuid.rendererTemplate);
Assert.IsFalse(string.IsNullOrEmpty(templatePath));
}
// Validate that ShaderUtils.GetShaderGUID results are valid and that ShaderUtils.GetShaderPath match shader names.
[TestCase(ShaderPathID.Lit)]
[TestCase(ShaderPathID.SimpleLit)]
[TestCase(ShaderPathID.Unlit)]
[TestCase(ShaderPathID.TerrainLit)]
[TestCase(ShaderPathID.ParticlesLit)]
[TestCase(ShaderPathID.ParticlesSimpleLit)]
[TestCase(ShaderPathID.ParticlesUnlit)]
[TestCase(ShaderPathID.BakedLit)]
[TestCase(ShaderPathID.SpeedTree7)]
[TestCase(ShaderPathID.SpeedTree7Billboard)]
[TestCase(ShaderPathID.SpeedTree8)]
public void ValidateShaderResources(ShaderPathID shaderPathID)
{
string path = AssetDatabase.GUIDToAssetPath(ShaderUtils.GetShaderGUID(shaderPathID));
Assert.IsFalse(string.IsNullOrEmpty(path));
var shader = AssetDatabase.LoadAssetAtPath<Shader>(path);
Assert.AreEqual(shader.name, ShaderUtils.GetShaderPath(shaderPathID));
var propertyNames = new System.Collections.Generic.HashSet<string>();
for (int j = 0; j < shader.GetPropertyCount(); ++j)
{
string propertyName = shader.GetPropertyName(j);
Assert.IsFalse(propertyNames.Contains(propertyName), $"{shader.name} has duplicated property {propertyName}!");
propertyNames.Add(propertyName);
}
}
// When creating URP all required resources should be initialized.
[Test]
public void ValidateNewAssetResources()
{
if (GraphicsSettings.currentRenderPipeline is not UniversalRenderPipelineAsset)
{
Assert.Ignore("This test is only available when URP is the current pipeline.");
return;
}
UniversalRendererData data = ScriptableObject.CreateInstance<UniversalRendererData>();
UniversalRenderPipelineAsset asset = UniversalRenderPipelineAsset.Create(data);
UniversalRenderPipelineGlobalSettings.Ensure();
Assert.AreNotEqual(null, asset.defaultMaterial);
Assert.AreNotEqual(null, asset.defaultParticleMaterial);
Assert.AreNotEqual(null, asset.defaultLineMaterial);
Assert.AreNotEqual(null, asset.defaultTerrainMaterial);
Assert.AreNotEqual(null, asset.defaultShader);
Assert.AreNotEqual(null, asset.default2DMaterial);
// URP doesn't override the following materials
Assert.AreEqual(null, asset.defaultUIMaterial);
Assert.AreEqual(null, asset.defaultUIOverdrawMaterial);
Assert.AreEqual(null, asset.defaultUIETC1SupportedMaterial);
Assert.AreEqual(null, asset.default2DMaskMaterial);
Assert.AreNotEqual(null, asset.m_RendererDataList, "A default renderer data should be created when creating a new pipeline.");
ScriptableObject.DestroyImmediate(asset);
ScriptableObject.DestroyImmediate(data);
}
// When changing URP settings, all settings should be valid.
[Test]
public void ValidateAssetSettings()
{
// Create a new asset and validate invalid settings
UniversalRendererData data = ScriptableObject.CreateInstance<UniversalRendererData>();
UniversalRenderPipelineAsset asset = UniversalRenderPipelineAsset.Create(data);
if (asset != null)
{
asset.shadowDistance = -1.0f;
Assert.GreaterOrEqual(asset.shadowDistance, 0.0f);
asset.renderScale = -1.0f;
Assert.GreaterOrEqual(asset.renderScale, UniversalRenderPipeline.minRenderScale);
asset.renderScale = 32.0f;
Assert.LessOrEqual(asset.renderScale, UniversalRenderPipeline.maxRenderScale);
asset.shadowNormalBias = -1.0f;
Assert.GreaterOrEqual(asset.shadowNormalBias, 0.0f);
asset.shadowNormalBias = 32.0f;
Assert.LessOrEqual(asset.shadowNormalBias, UniversalRenderPipeline.maxShadowBias);
asset.shadowDepthBias = -1.0f;
Assert.GreaterOrEqual(asset.shadowDepthBias, 0.0f);
asset.shadowDepthBias = 32.0f;
Assert.LessOrEqual(asset.shadowDepthBias, UniversalRenderPipeline.maxShadowBias);
asset.maxAdditionalLightsCount = -1;
Assert.GreaterOrEqual(asset.maxAdditionalLightsCount, 0);
asset.maxAdditionalLightsCount = 32;
Assert.LessOrEqual(asset.maxAdditionalLightsCount, UniversalRenderPipeline.maxPerObjectLights);
}
ScriptableObject.DestroyImmediate(asset);
ScriptableObject.DestroyImmediate(data);
}
[Test]
public void ValidateDefaultRendererAfterReset()
{
UniversalRendererData data = ScriptableObject.CreateInstance<UniversalRendererData>();
UniversalRenderPipelineAsset asset = UniversalRenderPipelineAsset.Create(data);
const string kTempDir = "Assets/ValidateDefaultRendererAfterReset";
string assetPath = $"{kTempDir}/URPAsset.asset";
CoreUtils.EnsureFolderTreeInAssetFilePath(assetPath);
AssetDatabase.CreateAsset(asset, assetPath);
AssetDatabase.SaveAssets();
string path = AssetDatabase.GetAssetPath(asset);
Assume.That(!string.IsNullOrEmpty(path));
Assert.NotNull(asset.m_RendererDataList[asset.m_DefaultRendererIndex]);
Unsupported.SmartReset(asset);// will create a new default renderer data
Assert.NotNull(asset.m_RendererDataList[asset.m_DefaultRendererIndex]);
ScriptableObject.DestroyImmediate(data);
AssetDatabase.DeleteAsset(kTempDir);
}
// When working with SpeedTree v7 assets, UniversalSpeedTree8Upgrader should not throw exception
[Test]
public void UniversalSpeedTree8Upgrader_ShouldntThrowExceptionWhenImportingSpeedTree7Assets()
{
const string STv7AssetName = "EuropeanBeech_Desktop.spm";
const string STv7AssetPath = "Assets/CommonAssets/SpeedTree/SpeedTreeV7/EU_Beech/" + STv7AssetName;
// Ensure this is not thrown:
// NullReferenceException: Object reference not set to an instance of an object
// UnityEditor.Rendering.SpeedTree8MaterialUpgrader.GetWindQuality
// UnityEditor.Rendering.SpeedTree8MaterialUpgrader.UpgradeWindQuality
// UnityEditor.Rendering.SpeedTree8MaterialUpgrader.SpeedTree8MaterialFinalizer
// UnityEditor.Rendering.Universal.UniversalSpeedTree8Upgrader.UniversalSpeedTree8MaterialFinalizer
Assert.DoesNotThrow(() => AssetDatabase.ImportAsset(STv7AssetPath));
}
[Test]
public void UseReAllocateIfNeededWithoutTextureLeak()
{
Object[] pretestTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
RTHandle myHandle = default(RTHandle);
// URP is not initlized in test framework, init RTHandlePool here which is required for this test.
if (UniversalRenderPipeline.s_RTHandlePool == null)
{
UniversalRenderPipeline.s_RTHandlePool = new RTHandleResourcePool();
}
// Realloc RTHandle 100 times with different resolution.
for (int i = 0; i < 100; i++)
{
RenderTextureDescriptor rtd = new RenderTextureDescriptor(1, 1 + i, GraphicsFormat.R8G8B8A8_UNorm, GraphicsFormat.None);
RenderingUtils.ReAllocateHandleIfNeeded(ref myHandle, rtd, FilterMode.Point, TextureWrapMode.Clamp);
}
UniversalRenderPipeline.s_RTHandlePool.Cleanup();
RTHandles.Release(myHandle);
Object[] posttestTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
Assert.That(posttestTextures, Is.EquivalentTo(pretestTextures), "A texture leak is detected when using RenderingUtils.ReAllocateIfNeeded.");
}
[Test]
public void UseReAllocateIfNeededWithoutTextureLeakTextureDesc()
{
Object[] pretestTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
RTHandle myHandle = default(RTHandle);
// URP is not initlized in test framework, init RTHandlePool here which is required for this test.
if (UniversalRenderPipeline.s_RTHandlePool == null)
{
UniversalRenderPipeline.s_RTHandlePool = new RTHandleResourcePool();
}
// Realloc RTHandle 100 times with different resolution.
for (int i = 0; i < 100; i++)
{
var desc = new TextureDesc(1, 1 + i);
desc.format = GraphicsFormat.R8G8B8A8_UNorm;
desc.filterMode = FilterMode.Point;
desc.wrapMode = TextureWrapMode.Clamp;
RenderingUtils.ReAllocateHandleIfNeeded(ref myHandle, desc, "TestTexture");
}
UniversalRenderPipeline.s_RTHandlePool.Cleanup();
RTHandles.Release(myHandle);
Object[] posttestTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
Assert.That(posttestTextures, Is.EquivalentTo(pretestTextures), "A texture leak is detected when using RenderingUtils.ReAllocateIfNeeded.");
}
[Test]
public void UseReAllocateIfNeededCorrect()
{
Object[] pretestTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
RTHandle myHandle = default(RTHandle);
// URP is not initlized in test framework, init RTHandlePool here which is required for this test.
if (UniversalRenderPipeline.s_RTHandlePool == null)
{
UniversalRenderPipeline.s_RTHandlePool = new RTHandleResourcePool();
}
var desc = new TextureDesc(128, 128);
desc.format = GraphicsFormat.R8G8B8A8_UNorm;
desc.filterMode = FilterMode.Point;
desc.wrapMode = TextureWrapMode.Clamp;
RenderingUtils.ReAllocateHandleIfNeeded(ref myHandle, desc, "TestTexture");
Assert.That(IsEqualDesc(in desc, myHandle), "RenderingUtils.ReAllocateIfNeeded alloced RTHandle with different properties than requested.");
desc.width = desc.height = 64;
desc.format = GraphicsFormat.R32_SFloat;
desc.filterMode = FilterMode.Bilinear;
desc.wrapMode = TextureWrapMode.Repeat;
RenderingUtils.ReAllocateHandleIfNeeded(ref myHandle, desc, "TestTexture");
Assert.That(IsEqualDesc(in desc, myHandle), "RenderingUtils.ReAllocateIfNeeded alloced RTHandle with different properties than requested.");
UniversalRenderPipeline.s_RTHandlePool.Cleanup();
RTHandles.Release(myHandle);
}
bool IsEqualDesc(in TextureDesc desc, RTHandle rt)
{
return rt.rt.width == desc.width
&& rt.rt.height == desc.height
&& rt.rt.graphicsFormat == desc.format
&& rt.rt.wrapMode == desc.wrapMode
&& rt.rt.filterMode == desc.filterMode;
}
[TestCase(ShaderPathID.Lit)]
[TestCase(ShaderPathID.SimpleLit)]
[TestCase(ShaderPathID.Unlit)]
[TestCase(ShaderPathID.TerrainLit)]
[TestCase(ShaderPathID.ParticlesLit)]
[TestCase(ShaderPathID.ParticlesSimpleLit)]
[TestCase(ShaderPathID.ParticlesUnlit)]
[TestCase(ShaderPathID.BakedLit)]
[TestCase(ShaderPathID.SpeedTree7)]
[TestCase(ShaderPathID.SpeedTree7Billboard)]
[TestCase(ShaderPathID.SpeedTree8)]
public void UseDynamicBranchFogKeyword(ShaderPathID shaderPathID)
{
string path = AssetDatabase.GUIDToAssetPath(ShaderUtils.GetShaderGUID(shaderPathID));
var shader = AssetDatabase.LoadAssetAtPath<Shader>(path);
var keywordIdentifiers = new string[] { "FOG_EXP", "FOG_EXP2", "FOG_LINEAR" };
var dynamicBranchFogKeyword = UniversalRenderPipeline.UseDynamicBranchFogKeyword();
foreach (var identifier in keywordIdentifiers)
{
LocalKeyword keyword = new LocalKeyword(shader, identifier);
if (dynamicBranchFogKeyword)
{
Assert.That(keyword.isDynamic, Is.True, $"{identifier} is not dynamic branch keyword.");
}
else
{
Assert.That(keyword.isDynamic, Is.False, $"{identifier} is dynamic branch keyword.");
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 42af586c09f391941a2a8a7bd5164b31
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,68 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Profiling;
using UnityEngine.Rendering.Universal;
using UnityEditor.Rendering.Universal.Internal;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.Universal;
using UnityEngine.TestTools;
class EditorTests_URPDisabled
{
private RenderPipelineAsset m_PreviousRenderPipelineAssetGraphicsSettings;
private RenderPipelineAsset m_PreviousRenderPipelineAssetQualitySettings;
[SetUp]
public void Setup()
{
m_PreviousRenderPipelineAssetGraphicsSettings = GraphicsSettings.defaultRenderPipeline;
m_PreviousRenderPipelineAssetQualitySettings = QualitySettings.renderPipeline;
GraphicsSettings.defaultRenderPipeline = null;
QualitySettings.renderPipeline = null;
}
[TearDown]
public void TearDown()
{
GraphicsSettings.defaultRenderPipeline = m_PreviousRenderPipelineAssetGraphicsSettings;
QualitySettings.renderPipeline = m_PreviousRenderPipelineAssetQualitySettings;
}
// When creating a new render pipeline asset it should not log any errors or throw exceptions.
[Test]
public void CreatePipelineAssetWithoutErrors()
{
UniversalRendererData data = ScriptableObject.CreateInstance<UniversalRendererData>();
UniversalRenderPipelineAsset asset = UniversalRenderPipelineAsset.Create(data);
LogAssert.NoUnexpectedReceived();
ScriptableObject.DestroyImmediate(asset);
ScriptableObject.DestroyImmediate(data);
}
// When creating a new Universal Renderer asset it should not log any errors or throw exceptions.
[Test]
public void CreateUniversalRendererAssetWithoutErrors()
{
var asset = ScriptableObject.CreateInstance<UniversalRendererData>();
ResourceReloader.ReloadAllNullIn(asset, UniversalRenderPipelineAsset.packagePath);
var renderer = asset.InternalCreateRenderer();
LogAssert.NoUnexpectedReceived();
renderer.Dispose();
ScriptableObject.DestroyImmediate(asset);
}
// When creating a new renderer 2d asset it should not log any errors or throw exceptions.
[Test]
public void CreateRenderer2DAssetWithoutErrors()
{
var asset = ScriptableObject.CreateInstance<Renderer2DData>();
ResourceReloader.ReloadAllNullIn(asset, UniversalRenderPipelineAsset.packagePath);
var renderer = asset.InternalCreateRenderer();
LogAssert.NoUnexpectedReceived();
renderer.Dispose();
ScriptableObject.DestroyImmediate(asset);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2cc7528ffe326894bb487b2ead9059fa
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Test
{
class FilmGrainResourcesStripperTests
{
[Test]
public void AllRendererDataLackPostProcessData_AllNull_ReturnsTrue()
{
var rendererDataList = new List<ScriptableRendererData>
{
ScriptableObject.CreateInstance<UniversalRendererData>(),
ScriptableObject.CreateInstance<UniversalRendererData>()
};
foreach (var rd in rendererDataList)
((UniversalRendererData)rd).postProcessData = null;
Assert.IsTrue(FilmGrainResourcesStripper.PostProcessDisabledInAllRenderers(rendererDataList));
foreach (var rd in rendererDataList)
Object.DestroyImmediate(rd);
}
[Test]
public void AllRendererDataLackPostProcessData_OneHasPostProcessData_ReturnsFalse()
{
var ppData = ScriptableObject.CreateInstance<PostProcessData>();
var withPP = ScriptableObject.CreateInstance<UniversalRendererData>();
var withoutPP = ScriptableObject.CreateInstance<UniversalRendererData>();
withPP.postProcessData = ppData;
withoutPP.postProcessData = null;
var rendererDataList = new List<ScriptableRendererData> { withPP, withoutPP };
Assert.IsFalse(FilmGrainResourcesStripper.PostProcessDisabledInAllRenderers(rendererDataList));
Object.DestroyImmediate(ppData);
Object.DestroyImmediate(withPP);
Object.DestroyImmediate(withoutPP);
}
[Test]
public void AllRendererDataLackPostProcessData_EmptyList_ReturnsTrue()
{
Assert.IsTrue(FilmGrainResourcesStripper.PostProcessDisabledInAllRenderers(new List<ScriptableRendererData>()));
}
[Test]
public void AllRendererDataLackPostProcessData_Renderer2DWithNull_ReturnsTrue()
{
var renderer2D = ScriptableObject.CreateInstance<Renderer2DData>();
renderer2D.postProcessData = null;
var rendererDataList = new List<ScriptableRendererData> { renderer2D };
Assert.IsTrue(FilmGrainResourcesStripper.PostProcessDisabledInAllRenderers(rendererDataList));
Object.DestroyImmediate(renderer2D);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a71f4ac0efe4c4b952be60885c37082
timeCreated: 1773649928
@@ -0,0 +1,163 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEditor.Rendering.Universal.Internal;
using UnityEngine.Experimental.Rendering.Universal;
using UnityEngine.TestTools;
using UnityEditor.SceneManagement;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
class NoLeaksOnEnterLeavePlaymode
{
// This variable needs to be serialized, as going into play-mode will reload the domain and
// wipe the state of all objects, including the content of this variable
[SerializeField]
string materialNames = "";
[SerializeField]
string meshNames = "";
[SerializeField]
string textureNames = "";
void EnsureUniversalRPIsActivePipeline()
{
Camera.main.Render();
// Skip test if project is not configured to be SRP project
if (RenderPipelineManager.currentPipeline == null)
Assert.Ignore("Test project has no SRP configured, skipping test");
Assert.IsInstanceOf<UniversalRenderPipeline>(RenderPipelineManager.currentPipeline);
}
Dictionary<string, int> CountResources(string[] names)
{
var result = new Dictionary<string, int>();
foreach (string name in names)
{
if (result.TryGetValue(name, out int materialCount))
{
result[name] = materialCount + 1;
}
else
{
result.Add(name, 1);
}
}
return result;
}
void CompareResourceLists(Dictionary<string, int> oldList, Dictionary<string, int> newList, string [] blackList)
{
foreach (var newRes in newList)
{
// Ignore blacklisted materials
if (blackList.Contains(newRes.Key)) continue;
int oldCount = 0;
oldList.TryGetValue(newRes.Key, out oldCount);
if (newRes.Value > oldCount)
{
Debug.LogError("Leaked " + newRes.Key + "(" + (newRes.Value - oldCount) + "x)");
}
}
}
[UnityTest]
public IEnumerator NoResourceLeaks()
{
// Ignoring OpenGL as it has now been deprecated and this test is unstable on that platform.
GraphicsDeviceType gfxAPI = SystemInfo.graphicsDeviceType;
if (gfxAPI == GraphicsDeviceType.OpenGLCore)
yield break;
// give it a chance to warm-up by entering play mode once
// in theory this shouldn't be needed but I hope this avoids the worst instabilities.
yield return new EnterPlayMode();
yield return null;
yield return new ExitPlayMode();
yield return null;
// Grab the list of existing objects
var mats = Resources.FindObjectsOfTypeAll(typeof(Material));
materialNames = string.Join(";", mats.Select(m => m.name));
var meshes = Resources.FindObjectsOfTypeAll(typeof(Mesh));
meshNames = string.Join(";", meshes.Select(m => m.name));
var textures = Resources.FindObjectsOfTypeAll(typeof(Texture));
textureNames = string.Join(";", textures.Select(m => m.name));
yield return new EnterPlayMode();
yield return null;
yield return new ExitPlayMode();
yield return null;
// Grab lists of existing objects.
// Note: resources created from code often reuse the same names so we have to both check the names
// and the counts per name to ensure nothing leaked.
var newMats = Resources.FindObjectsOfTypeAll(typeof(Material));
var newMeshes = Resources.FindObjectsOfTypeAll(typeof(Mesh));
var newTextures = Resources.FindObjectsOfTypeAll(typeof(Texture));
string[] materialBlackList = {
// Debug materials
"Hidden/Universal/HDRDebugView",
"Hidden/Universal Render Pipeline/Debug/DebugReplacement",
// Fonts are intentionally preserved in the editor for performance reasons.
"Apple Color Emoji - Regular Material",
"Arial - Regular Material",
"Arial Unicode MS - Regular Material",
"Helvetica Neue - Regular Material",
"Inter - Regular Material", // UUM-28555
"Inter - Regular Material + Inter - Semi Bold Atlas", // UUM-28555
"Malgun Gothic - Regular Material",
"Microsoft Sans Serif - Regular Material",
"Microsoft YaHei - Regular Material",
"MS Gothic - Regular Material",
"Nirmala UI - Regular Material",
"Roboto Mono - Regular Material",
"Segoe UI Emoji - Regular Material"
};
var oldMaterialNames = materialNames.Split(";");
var materialsPerNameOld = CountResources(oldMaterialNames);
var newMaterialNames = newMats.Select(m => m.name).ToArray();
var materialsPerNameNew = CountResources(newMaterialNames);
CompareResourceLists(materialsPerNameOld, materialsPerNameNew, materialBlackList);
string[] meshBlackList = {
};
var oldMeshNames = meshNames.Split(";");
var meshesPerNameOld = CountResources(oldMeshNames);
var newMeshNames = newMeshes.Select(m => m.name).ToArray();
var meshesPerNameNew = CountResources(newMeshNames);
CompareResourceLists(meshesPerNameOld, meshesPerNameNew, meshBlackList);
string[] textureBlackList = {
"Apple Color Emoji - Regular Atlas",
"Arial - Regular Atlas",
"Arial Unicode MS - Regular Atlas",
"Helvetica Neue - Regular Atlas",
"Inter - Regular Atlas",
"Inter - Regular Material + Inter - Semi Bold Atlas",
"Malgun Gothic - Regular Atlas",
"Microsoft Sans Serif - Regular Atlas",
"Microsoft YaHei - Regular Atlas",
"MS Gothic - Regular Atlas",
"Nirmala UI - Regular Atlas",
"Roboto Mono - Regular Atlas",
"Segoe UI Emoji - Regular Atlas"
};
var oldTextureNames = textureNames.Split(";");
var texturesPerNameOld = CountResources(oldTextureNames);
var newTextureNames = newTextures.Select(m => m.name).ToArray();
var texturesPerNameNew = CountResources(newTextureNames);
CompareResourceLists(texturesPerNameOld, texturesPerNameNew, textureBlackList);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0209e47ee7283cd42b965a3264075610
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fb0ec4b8bb8f2d34b91204563167f685
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,53 @@
Shader "Hidden/Custom/Test Shader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a176945d0e562084691bce8e11084c6a
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,53 @@
Shader "Hidden/Custom/Test Shader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ace59f7f124432f4f923bd3bfa93e0ad
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 572910c10080c0945a0ef731ccedc739, type: 3}
m_Name: PostProcessData BloomPS Different 1
m_EditorClassIdentifier:
shaders:
stopNanPS: {fileID: 4800000, guid: 1121bb4e615ca3c48b214e79e841e823, type: 3}
subpixelMorphologicalAntialiasingPS: {fileID: 4800000, guid: 63eaba0ebfb82cc43bde059b4a8c65f6,
type: 3}
gaussianDepthOfFieldPS: {fileID: 4800000, guid: 5e7134d6e63e0bc47a1dd2669cedb379,
type: 3}
bokehDepthOfFieldPS: {fileID: 4800000, guid: 2aed67ad60045d54ba3a00c91e2d2631,
type: 3}
cameraMotionBlurPS: {fileID: 4800000, guid: 1edcd131364091c46a17cbff0b1de97a,
type: 3}
paniniProjectionPS: {fileID: 4800000, guid: a15b78cf8ca26ca4fb2090293153c62c,
type: 3}
lutBuilderLdrPS: {fileID: 4800000, guid: 65df88701913c224d95fc554db28381a, type: 3}
lutBuilderHdrPS: {fileID: 4800000, guid: ec9fec698a3456d4fb18cf8bacb7a2bc, type: 3}
bloomPS: {fileID: 4800000, guid: ace59f7f124432f4f923bd3bfa93e0ad, type: 3}
temporalAntialiasingPS: {fileID: 4800000, guid: 9c70c1a35ff15f340b38ea84842358bf,
type: 3}
LensFlareDataDrivenPS: {fileID: 4800000, guid: 6cda457ac28612740adb23da5d39ea92,
type: 3}
LensFlareScreenSpacePS: {fileID: 4800000, guid: 701880fecb344ea4c9cd0db3407ab287,
type: 3}
scalingSetupPS: {fileID: 4800000, guid: e8ee25143a34b8c4388709ea947055d1, type: 3}
easuPS: {fileID: 4800000, guid: 562b7ae4f629f144aa97780546fce7c6, type: 3}
uberPostPS: {fileID: 4800000, guid: e7857e9d0c934dc4f83f270f8447b006, type: 3}
finalPostPassPS: {fileID: 4800000, guid: c49e63ed1bbcb334780a3bd19dfed403, type: 3}
textures:
blueNoise16LTex:
- {fileID: 2800000, guid: 81200413a40918d4d8702e94db29911c, type: 3}
- {fileID: 2800000, guid: d50c5e07c9911a74982bddf7f3075e7b, type: 3}
- {fileID: 2800000, guid: 1134690bf9216164dbc75050e35b7900, type: 3}
- {fileID: 2800000, guid: 7ce2118f74614a94aa8a0cdf2e6062c3, type: 3}
- {fileID: 2800000, guid: 2ca97df9d1801e84a8a8f2c53cb744f0, type: 3}
- {fileID: 2800000, guid: e63eef8f54aa9dc4da9a5ac094b503b5, type: 3}
- {fileID: 2800000, guid: 39451254daebd6d40b52899c1f1c0c1b, type: 3}
- {fileID: 2800000, guid: c94ad916058dff743b0f1c969ddbe660, type: 3}
- {fileID: 2800000, guid: ed5ea7ce59ca8ec4f9f14bf470a30f35, type: 3}
- {fileID: 2800000, guid: 071e954febf155243a6c81e48f452644, type: 3}
- {fileID: 2800000, guid: 96aaab9cc247d0b4c98132159688c1af, type: 3}
- {fileID: 2800000, guid: fc3fa8f108657e14486697c9a84ccfc5, type: 3}
- {fileID: 2800000, guid: bfed3e498947fcb4890b7f40f54d85b9, type: 3}
- {fileID: 2800000, guid: d512512f4af60a442ab3458489412954, type: 3}
- {fileID: 2800000, guid: 47a45908f6db0cb44a0d5e961143afec, type: 3}
- {fileID: 2800000, guid: 4dcc0502f8586f941b5c4a66717205e8, type: 3}
- {fileID: 2800000, guid: 9d92991794bb5864c8085468b97aa067, type: 3}
- {fileID: 2800000, guid: 14381521ff11cb74abe3fe65401c23be, type: 3}
- {fileID: 2800000, guid: d36f0fe53425e08499a2333cf423634c, type: 3}
- {fileID: 2800000, guid: d4044ea2490d63b43aa1765f8efbf8a9, type: 3}
- {fileID: 2800000, guid: c9bd74624d8070f429e3f46d161f9204, type: 3}
- {fileID: 2800000, guid: d5c9b274310e5524ebe32a4e4da3df1f, type: 3}
- {fileID: 2800000, guid: f69770e54f2823f43badf77916acad83, type: 3}
- {fileID: 2800000, guid: 10b6c6d22e73dea46a8ab36b6eebd629, type: 3}
- {fileID: 2800000, guid: a2ec5cbf5a9b64345ad3fab0912ddf7b, type: 3}
- {fileID: 2800000, guid: 1c3c6d69a645b804fa232004b96b7ad3, type: 3}
- {fileID: 2800000, guid: d18a24d7b4ed50f4387993566d9d3ae2, type: 3}
- {fileID: 2800000, guid: c989e1ed85cf7154caa922fec53e6af6, type: 3}
- {fileID: 2800000, guid: ff47e5a0f105eb34883b973e51f4db62, type: 3}
- {fileID: 2800000, guid: fa042edbfc40fbd4bad0ab9d505b1223, type: 3}
- {fileID: 2800000, guid: 896d9004736809c4fb5973b7c12eb8b9, type: 3}
- {fileID: 2800000, guid: 179f794063d2a66478e6e726f84a65bc, type: 3}
filmGrainTex:
- {fileID: 2800000, guid: 654c582f7f8a5a14dbd7d119cbde215d, type: 3}
- {fileID: 2800000, guid: dd77ffd079630404e879388999033049, type: 3}
- {fileID: 2800000, guid: 1097e90e1306e26439701489f391a6c0, type: 3}
- {fileID: 2800000, guid: f0b67500f7fad3b4c9f2b13e8f41ba6e, type: 3}
- {fileID: 2800000, guid: 9930fb4528622b34687b00bbe6883de7, type: 3}
- {fileID: 2800000, guid: bd9e8c758250ef449a4b4bfaad7a2133, type: 3}
- {fileID: 2800000, guid: 510a2f57334933e4a8dbabe4c30204e4, type: 3}
- {fileID: 2800000, guid: b4db8180660810945bf8d55ab44352ad, type: 3}
- {fileID: 2800000, guid: fd2fd78b392986e42a12df2177d3b89c, type: 3}
- {fileID: 2800000, guid: 5cdee82a77d13994f83b8fdabed7c301, type: 3}
smaaAreaTex: {fileID: 2800000, guid: d1f1048909d55cd4fa1126ab998f617e, type: 3}
smaaSearchTex: {fileID: 2800000, guid: 51eee22c2a633ef4aada830eed57c3fd, type: 3}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 350a709cf1218764c94f752764b6ab69
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 572910c10080c0945a0ef731ccedc739, type: 3}
m_Name: PostProcessData BloomPS Different
m_EditorClassIdentifier:
shaders:
stopNanPS: {fileID: 4800000, guid: 1121bb4e615ca3c48b214e79e841e823, type: 3}
subpixelMorphologicalAntialiasingPS: {fileID: 4800000, guid: 63eaba0ebfb82cc43bde059b4a8c65f6,
type: 3}
gaussianDepthOfFieldPS: {fileID: 4800000, guid: 5e7134d6e63e0bc47a1dd2669cedb379,
type: 3}
bokehDepthOfFieldPS: {fileID: 4800000, guid: 2aed67ad60045d54ba3a00c91e2d2631,
type: 3}
cameraMotionBlurPS: {fileID: 4800000, guid: 1edcd131364091c46a17cbff0b1de97a,
type: 3}
paniniProjectionPS: {fileID: 4800000, guid: a15b78cf8ca26ca4fb2090293153c62c,
type: 3}
lutBuilderLdrPS: {fileID: 4800000, guid: 65df88701913c224d95fc554db28381a, type: 3}
lutBuilderHdrPS: {fileID: 4800000, guid: ec9fec698a3456d4fb18cf8bacb7a2bc, type: 3}
bloomPS: {fileID: 4800000, guid: a176945d0e562084691bce8e11084c6a, type: 3}
temporalAntialiasingPS: {fileID: 4800000, guid: 9c70c1a35ff15f340b38ea84842358bf,
type: 3}
LensFlareDataDrivenPS: {fileID: 4800000, guid: 6cda457ac28612740adb23da5d39ea92,
type: 3}
LensFlareScreenSpacePS: {fileID: 4800000, guid: 701880fecb344ea4c9cd0db3407ab287,
type: 3}
scalingSetupPS: {fileID: 4800000, guid: e8ee25143a34b8c4388709ea947055d1, type: 3}
easuPS: {fileID: 4800000, guid: 562b7ae4f629f144aa97780546fce7c6, type: 3}
uberPostPS: {fileID: 4800000, guid: e7857e9d0c934dc4f83f270f8447b006, type: 3}
finalPostPassPS: {fileID: 4800000, guid: c49e63ed1bbcb334780a3bd19dfed403, type: 3}
textures:
blueNoise16LTex:
- {fileID: 2800000, guid: 81200413a40918d4d8702e94db29911c, type: 3}
- {fileID: 2800000, guid: d50c5e07c9911a74982bddf7f3075e7b, type: 3}
- {fileID: 2800000, guid: 1134690bf9216164dbc75050e35b7900, type: 3}
- {fileID: 2800000, guid: 7ce2118f74614a94aa8a0cdf2e6062c3, type: 3}
- {fileID: 2800000, guid: 2ca97df9d1801e84a8a8f2c53cb744f0, type: 3}
- {fileID: 2800000, guid: e63eef8f54aa9dc4da9a5ac094b503b5, type: 3}
- {fileID: 2800000, guid: 39451254daebd6d40b52899c1f1c0c1b, type: 3}
- {fileID: 2800000, guid: c94ad916058dff743b0f1c969ddbe660, type: 3}
- {fileID: 2800000, guid: ed5ea7ce59ca8ec4f9f14bf470a30f35, type: 3}
- {fileID: 2800000, guid: 071e954febf155243a6c81e48f452644, type: 3}
- {fileID: 2800000, guid: 96aaab9cc247d0b4c98132159688c1af, type: 3}
- {fileID: 2800000, guid: fc3fa8f108657e14486697c9a84ccfc5, type: 3}
- {fileID: 2800000, guid: bfed3e498947fcb4890b7f40f54d85b9, type: 3}
- {fileID: 2800000, guid: d512512f4af60a442ab3458489412954, type: 3}
- {fileID: 2800000, guid: 47a45908f6db0cb44a0d5e961143afec, type: 3}
- {fileID: 2800000, guid: 4dcc0502f8586f941b5c4a66717205e8, type: 3}
- {fileID: 2800000, guid: 9d92991794bb5864c8085468b97aa067, type: 3}
- {fileID: 2800000, guid: 14381521ff11cb74abe3fe65401c23be, type: 3}
- {fileID: 2800000, guid: d36f0fe53425e08499a2333cf423634c, type: 3}
- {fileID: 2800000, guid: d4044ea2490d63b43aa1765f8efbf8a9, type: 3}
- {fileID: 2800000, guid: c9bd74624d8070f429e3f46d161f9204, type: 3}
- {fileID: 2800000, guid: d5c9b274310e5524ebe32a4e4da3df1f, type: 3}
- {fileID: 2800000, guid: f69770e54f2823f43badf77916acad83, type: 3}
- {fileID: 2800000, guid: 10b6c6d22e73dea46a8ab36b6eebd629, type: 3}
- {fileID: 2800000, guid: a2ec5cbf5a9b64345ad3fab0912ddf7b, type: 3}
- {fileID: 2800000, guid: 1c3c6d69a645b804fa232004b96b7ad3, type: 3}
- {fileID: 2800000, guid: d18a24d7b4ed50f4387993566d9d3ae2, type: 3}
- {fileID: 2800000, guid: c989e1ed85cf7154caa922fec53e6af6, type: 3}
- {fileID: 2800000, guid: ff47e5a0f105eb34883b973e51f4db62, type: 3}
- {fileID: 2800000, guid: fa042edbfc40fbd4bad0ab9d505b1223, type: 3}
- {fileID: 2800000, guid: 896d9004736809c4fb5973b7c12eb8b9, type: 3}
- {fileID: 2800000, guid: 179f794063d2a66478e6e726f84a65bc, type: 3}
filmGrainTex:
- {fileID: 2800000, guid: 654c582f7f8a5a14dbd7d119cbde215d, type: 3}
- {fileID: 2800000, guid: dd77ffd079630404e879388999033049, type: 3}
- {fileID: 2800000, guid: 1097e90e1306e26439701489f391a6c0, type: 3}
- {fileID: 2800000, guid: f0b67500f7fad3b4c9f2b13e8f41ba6e, type: 3}
- {fileID: 2800000, guid: 9930fb4528622b34687b00bbe6883de7, type: 3}
- {fileID: 2800000, guid: bd9e8c758250ef449a4b4bfaad7a2133, type: 3}
- {fileID: 2800000, guid: 510a2f57334933e4a8dbabe4c30204e4, type: 3}
- {fileID: 2800000, guid: b4db8180660810945bf8d55ab44352ad, type: 3}
- {fileID: 2800000, guid: fd2fd78b392986e42a12df2177d3b89c, type: 3}
- {fileID: 2800000, guid: 5cdee82a77d13994f83b8fdabed7c301, type: 3}
smaaAreaTex: {fileID: 2800000, guid: d1f1048909d55cd4fa1126ab998f617e, type: 3}
smaaSearchTex: {fileID: 2800000, guid: 51eee22c2a633ef4aada830eed57c3fd, type: 3}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e7b20d8e594294f4380ea14212e1b042
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,147 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using Assert = UnityEngine.Assertions.Assert;
namespace UnityEditor.Rendering.Universal
{
class PostProcessDataAnalyticsTests
{
private static PostProcessDataAnalytics.Analytic.PropertyToGUIDs[] s_Datas = new[]
{
new PostProcessDataAnalytics.Analytic.PropertyToGUIDs()
{
propertyName = "bloomPS",
defaultGUID = "5f1864addb451f54bae8c86d230f736e",
usedGUIDs = new List<string>()
{
"a176945d0e562084691bce8e11084c6a",
}
},
new PostProcessDataAnalytics.Analytic.PropertyToGUIDs()
{
propertyName = "bloomPS",
defaultGUID = "5f1864addb451f54bae8c86d230f736e",
usedGUIDs = new List<string>()
{
"a176945d0e562084691bce8e11084c6a",
"a176945d0e562084691bce8e11084c6a"
}
},
new PostProcessDataAnalytics.Analytic.PropertyToGUIDs()
{
propertyName = "bloomPS",
defaultGUID = "5f1864addb451f54bae8c86d230f736e",
usedGUIDs = new List<string>()
{
"ace59f7f124432f4f923bd3bfa93e0ad",
"a176945d0e562084691bce8e11084c6a"
}
}
};
private static IEnumerable<(string[], PostProcessDataAnalytics.Analytic.PropertyToGUIDs)> TestDataExtractData()
{
yield return (
new string[]
{
"Packages/com.unity.render-pipelines.universal/Tests/Editor/PostProcessDataTests/PostProcessData BloomPS Different.asset",
},
s_Datas[0]);
yield return (
new string[]
{
"Packages/com.unity.render-pipelines.universal/Tests/Editor/PostProcessDataTests/PostProcessData BloomPS Different.asset",
"Packages/com.unity.render-pipelines.universal/Tests/Editor/PostProcessDataTests/PostProcessData BloomPS Different.asset",
},
s_Datas[1]);
yield return (
new string[]
{
"Packages/com.unity.render-pipelines.universal/Tests/Editor/PostProcessDataTests/PostProcessData BloomPS Different 1.asset",
"Packages/com.unity.render-pipelines.universal/Tests/Editor/PostProcessDataTests/PostProcessData BloomPS Different.asset",
},
s_Datas[2]);
}
RenderPipelineAsset asset;
bool wasCreated = false;
[SetUp]
public void SetUp()
{
if (GraphicsSettings.currentRenderPipelineAssetType == typeof(UniversalRenderPipelineAsset))
return;
asset = QualitySettings.renderPipeline;
QualitySettings.renderPipeline = UniversalRenderPipelineAsset.Create();
wasCreated = true;
}
[TearDown]
public void TearDown()
{
if (!wasCreated)
return;
var current = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
QualitySettings.renderPipeline = asset;
foreach (var rendererData in current.rendererDataList)
Object.DestroyImmediate(rendererData);
Object.DestroyImmediate(current);
}
[Test][TestCaseSource(nameof(TestDataExtractData))]
public void DataIsExtractedCorrectly((string[] input, PostProcessDataAnalytics.Analytic.PropertyToGUIDs expected) testCase)
{
using (UnityEngine.Pool.ListPool<PostProcessData>.Get(out var tmp))
{
foreach (var i in testCase.input)
{
var asset = AssetDatabase.LoadAssetAtPath<PostProcessData>(i);
Assert.IsNotNull(asset, $"Unable to load asset at {i}");
tmp.Add(asset);
}
var data = PostProcessDataAnalytics.Analytic.ExtractData(tmp);
var bloom = data.FirstOrDefault(d =>
d.propertyName.Equals(nameof(PostProcessData.ShaderResources.bloomPS)));
Assert.IsNotNull(bloom);
Assert.AreEqual(testCase.expected.propertyName, bloom.propertyName);
Assert.AreEqual(testCase.expected.defaultGUID, bloom.defaultGUID);
CollectionAssert.AreEqual(testCase.expected.usedGUIDs, bloom.usedGUIDs);
}
}
private static IEnumerable<(PostProcessDataAnalytics.Analytic.PropertyToGUIDs, PostProcessDataAnalytics.Analytic.Usage)> TestData()
{
yield return (s_Datas[0], PostProcessDataAnalytics.Analytic.Usage.ModifiedForTheProject);
yield return (s_Datas[1], PostProcessDataAnalytics.Analytic.Usage.ModifiedForTheProject);
yield return (s_Datas[2], PostProcessDataAnalytics.Analytic.Usage.ModifiedForEachQualityLevel);
}
[Test]
[TestCaseSource(nameof(TestData))]
public void GenerateMapWithDifferencesTests((PostProcessDataAnalytics.Analytic.PropertyToGUIDs input, PostProcessDataAnalytics.Analytic.Usage expected) testCase)
{
var dataToSent =
PostProcessDataAnalytics.Analytic.GatherDataToBeSent(new [] {testCase.input });
int count = 0;
foreach (PostProcessDataAnalytics.Analytic.AnalyticsData i in dataToSent)
{
if (i.property.Equals(nameof(PostProcessData.ShaderResources.bloomPS)))
Assert.AreEqual(i.usage, testCase.expected.ToString());
++count;
}
Assert.AreEqual(1, count);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6472bf1a81592fe41a53a321e920bf6f
@@ -0,0 +1,201 @@
using NUnit.Framework;
using UnityEngine.Experimental.Rendering;
using Unity.Collections;
using UnityEditor.Rendering.Tests;
using UnityEngine.Rendering.RenderGraphModule.Util;
using UnityEngine.Rendering.Universal;
using static UnityEngine.Rendering.RenderGraphModule.Util.RenderGraphUtils;
using UnityEditor.Rendering;
namespace UnityEngine.Rendering.Tests
{
internal partial class RenderGraphTests : RenderGraphTestsCore
{
[OneTimeSetUp]
public void OneTimeSetup()
{
if (!(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset))
Assert.Ignore("Current pipeline is not URP. Skipping tests...");
}
static GraphicsFormat[] depthBlitTestFormats =
{
GraphicsFormat.D32_SFloat,
GraphicsFormat.D24_UNorm,
GraphicsFormat.D16_UNorm,
};
public enum MSAAState
{
MSAA_None,
MSAA_4X,
}
static MSAAState[] depthBlitTestMSAA = { MSAAState.MSAA_None, MSAAState.MSAA_4X, };
RTHandle CreateDepthTexture(int width, int height, float depthValue, GraphicsFormat depthFormat, bool msaa = false, bool force2D = false)
{
// Create a new RTHandle texture
var depthHandle = RTHandles.Alloc(width, height,
depthFormat,
dimension: force2D ? TextureDimension.Tex2D : TextureXR.dimension,
useMipMap: false,
autoGenerateMips: false,
msaaSamples: (msaa) ? MSAASamples.MSAA4x : MSAASamples.None,
bindTextureMS: msaa,
name: "Depth Texture 32 bit");
var cmd = new CommandBuffer();
cmd.name = "Clear Depth RT";
cmd.SetRenderTarget(depthHandle);
cmd.ClearRenderTarget(true, true, Color.black, depthValue);
Graphics.ExecuteCommandBuffer(cmd);
return depthHandle;
}
[Test]
public void UtilityPasses_CopyDepth(
[ValueSource(nameof(depthBlitTestFormats))] GraphicsFormat depthFormat,
[ValueSource(nameof(depthBlitTestMSAA))] MSAAState msaa
)
{
const int kWidth = 4;
const int kHeight = 4;
// Verify if the test is being executed in a non-URP project (e.g pipeline asset set to null)
if (!EditorGraphicsSettings.TryGetRenderPipelineSettingsForPipeline<UniversalRenderPipelineRuntimeShaders, UniversalRenderPipeline>(out var shaders))
return;
if (Blitter.GetBlitMaterial(TextureDimension.Tex2D) == null && shaders != null)
{
Blitter.Initialize(shaders.coreBlitPS, shaders.coreBlitColorAndDepthPS);
}
float expectedDepthValue = 0.20f;
float gpuDepthValue = expectedDepthValue;
if (SystemInfo.usesReversedZBuffer)
gpuDepthValue = 1 - expectedDepthValue;
var sourceDepth = CreateDepthTexture(kWidth, kHeight, gpuDepthValue, depthFormat, msaa != MSAAState.MSAA_None);
var destinationDepth = CreateDepthTexture(kWidth, kHeight, 0.0f, depthFormat);
var depthAsColor = RTHandles.Alloc(kWidth, kHeight,
GraphicsFormat.R32_SFloat,
dimension: TextureXR.dimension,
useMipMap: false,
autoGenerateMips: false,
name: "Depth As Color Texture 32 bit");
m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) =>
{
// Initialize the RTHandle system if necessary
RTHandles.Initialize(kWidth, kHeight);
var source = m_RenderGraph.ImportTexture(sourceDepth);
var intermediate = m_RenderGraph.ImportTexture(destinationDepth);
var destination = m_RenderGraph.ImportTexture(depthAsColor);
// First do a copy from depth to depth, moving the value of 0.25 depth to the intermediate buffer.
m_RenderGraph.AddBlitPass(source, intermediate, Vector2.one, Vector2.zero);
// Then we move the depth value from the intermediate buffer to a color buffer to allow reading back its data to the CPU.
m_RenderGraph.AddBlitPass(intermediate, destination, Vector2.one, Vector2.zero);
};
RenderReadbackAndAssert(depthAsColor, expectedDepthValue);
sourceDepth.Release();
destinationDepth.Release();
depthAsColor.Release();
Blitter.Cleanup();
}
[Test]
public void UtilityPasses_CopyDepthWithMaterial([ValueSource(nameof(depthBlitTestFormats))] GraphicsFormat depthFormat)
{
const int kWidth = 4;
const int kHeight = 4;
// Verify if the test is being executed in a non-URP project (e.g pipeline asset set to null)
if (!EditorGraphicsSettings.TryGetRenderPipelineSettingsForPipeline<UniversalRenderPipelineRuntimeShaders, UniversalRenderPipeline>(out var shaders))
return;
if (Blitter.GetBlitMaterial(TextureDimension.Tex2D) == null && shaders != null)
{
Blitter.Initialize(shaders.coreBlitPS, shaders.coreBlitColorAndDepthPS);
}
float expectedDepthValue = 0.20f;
float gpuDepthValue = expectedDepthValue;
if (SystemInfo.usesReversedZBuffer)
gpuDepthValue = 1 - expectedDepthValue;
var sourceDepth = CreateDepthTexture(kWidth, kHeight, gpuDepthValue, depthFormat, false, true);
var destinationDepth = CreateDepthTexture(kWidth, kHeight, 0.0f, depthFormat, false, true);
var depthAsColor = RTHandles.Alloc(kWidth, kHeight,
GraphicsFormat.R32_SFloat,
dimension: TextureXR.dimension,
useMipMap: false,
autoGenerateMips: false,
name: "Depth As Color Texture 32 bit");
var shader = Shader.Find("Hidden/Core/CustomDepthBlit");
Assert.IsNotNull(shader);
var customDepthToColorMaterial = new Material(shader);
m_RenderGraphTestPipeline.recordRenderGraphBody = (context, camera, cmd) =>
{
// Initialize the RTHandle system if necessary
RTHandles.Initialize(kWidth, kHeight);
var source = m_RenderGraph.ImportTexture(sourceDepth);
var intermediate = m_RenderGraph.ImportTexture(destinationDepth);
var destination = m_RenderGraph.ImportTexture(depthAsColor);
// First do a copy from depth to depth, moving the value of 0.25 depth to the intermediate buffer.
m_RenderGraph.AddBlitPass(new BlitMaterialParameters(source, intermediate, customDepthToColorMaterial, 0));
m_RenderGraph.AddBlitPass(new BlitMaterialParameters(intermediate, destination, customDepthToColorMaterial, 1));
};
RenderReadbackAndAssert(depthAsColor, expectedDepthValue);
CoreUtils.Destroy(customDepthToColorMaterial);
sourceDepth.Release();
depthAsColor.Release();
Blitter.Cleanup();
}
void RenderReadbackAndAssert(RTHandle colorBuffer, float expectedDepthValue)
{
ExternalGPUProfiler.BeginGPUCapture();
m_Camera.Render();
NativeArray<float> data = default;
AsyncGPUReadback.Request(colorBuffer, 0, (res) =>
{
Assert.That(!res.hasError, "GPU readback failed");
Assert.That(res.done, "GPU readback not done");
data = res.GetData<float>();
});
AsyncGPUReadback.WaitAllRequests();
ExternalGPUProfiler.EndGPUCapture();
Assert.That(data.Length, Is.EqualTo(colorBuffer.rt.width * colorBuffer.rt.height));
for (int i = 0; i < colorBuffer.rt.width * colorBuffer.rt.height; i++)
{
const float tolerance = 0.02f;
float e = Mathf.Abs(data[i] - expectedDepthValue);
Assert.True(e < tolerance, $"Depth Data does not match: actual = {data[i]}, expected = {expectedDepthValue}, error = {e}, tolerance = {tolerance}");
}
data.Dispose();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fb0540054a4845f4896120b033478868
@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine.Profiling;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
namespace UnityEngine.Rendering.Tests
{
class CullingTestRenderPass : ScriptableRenderPass
{
/// <inheritdoc/>
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var cameraData = frameData.Get<UniversalCameraData>();
var cullContextData = frameData.Get<CullContextData>();
Assert.IsTrue(cameraData != null);
Assert.IsTrue(cullContextData != null);
cameraData.camera.TryGetCullingParameters(false, out var cullingParameters);
var cullingResults = cullContextData.Cull(ref cullingParameters);
var lightsInScene = Object.FindObjectsByType<Light>();
Assert.IsTrue(cullingResults.visibleLights.Length == lightsInScene.Length);
}
}
class RenderGraphTestsCulling
{
static Recorder gcAllocRecorder = Recorder.Get("GC.Alloc");
const int kLightCount = 3;
CullingTestRenderPass m_TestRenderPass;
ScriptableRenderContext? m_RenderContext;
Camera m_Camera;
List<GameObject> m_GameObjects = new();
[SetUp]
public void Setup()
{
m_TestRenderPass = new CullingTestRenderPass();
RenderPipelineManager.beginCameraRendering += OnBeginCamera;
m_RenderContext = null;
// We need a real ScriptableRenderContext and a camera to execute the render graph
// add the default camera
var cameraGO = new GameObject("Culling_GameObject")
{
hideFlags = HideFlags.HideAndDontSave
};
cameraGO.tag = "MainCamera";
m_Camera = cameraGO.AddComponent<Camera>();
m_GameObjects.Add(cameraGO);
for (int i = 0; i < kLightCount; ++i)
{
var lightGO = new GameObject("Light_GameObject" + i);
var light = lightGO.AddComponent<Light>();
light.type = LightType.Point;
m_GameObjects.Add(lightGO);
}
}
[TearDown]
public void TearDown()
{
m_TestRenderPass = null;
m_RenderContext = null;
RenderPipelineManager.beginCameraRendering -= OnBeginCamera;
foreach (var obj in m_GameObjects)
{
GameObject.DestroyImmediate(obj);
}
}
[Test]
public void RenderPassCullingAPIWorks()
{
if (DisableTestWhenExecutedOnNonURPProject())
return;
SubmitCameraRenderRequest(m_Camera);
}
[Test]
public void RenderPassCullingAPIDoesNotAlloc()
{
if (DisableTestWhenExecutedOnNonURPProject())
return;
SubmitCameraRenderRequest(m_Camera);
Assert.IsTrue(m_RenderContext != null);
var contextContainer = new ContextContainer();
var cullData = contextContainer.Create<CullContextData>();
ValidateNoGCAllocs(() =>
{
cullData.SetRenderContext(m_RenderContext.Value);
});
}
bool DisableTestWhenExecutedOnNonURPProject()
{
return !(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset);
}
void OnBeginCamera(ScriptableRenderContext context, Camera cam)
{
m_RenderContext = context;
// Use the EnqueuePass method to inject a custom render pass
cam.GetUniversalAdditionalCameraData().scriptableRenderer.EnqueuePass(m_TestRenderPass);
}
void SubmitCameraRenderRequest(Camera camera)
{
var request = new RenderPipeline.StandardRequest();
var desc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight, RenderTextureFormat.Default, 32);
request.destination = RenderTexture.GetTemporary(desc);
// Check if the active render pipeline supports the render request
if (RenderPipeline.SupportsRenderRequest(camera, request))
{
RenderPipeline.SubmitRenderRequest(camera, request);
}
RenderTexture.ReleaseTemporary(request.destination);
}
void ValidateNoGCAllocs(Action action)
{
// Warmup - this will catch static c'tors etc.
CountGCAllocs(action);
// Actual test.
var count = CountGCAllocs(action);
if (count != 0)
throw new AssertionException($"Expected 0 GC allocations but there were {count}");
}
int CountGCAllocs(Action action)
{
gcAllocRecorder.FilterToCurrentThread();
gcAllocRecorder.enabled = true;
action();
gcAllocRecorder.enabled = false;
return gcAllocRecorder.sampleBlockCount;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: da9d116cbd3a95840aeb4f28ba5146da
@@ -0,0 +1,105 @@
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Tests
{
[TestFixture]
class RenderTextureDescriptorDimensionsTests
{
private Camera m_Camera;
private UniversalCameraData m_CameraData;
public RenderTexture m_RT;
public class RenderScaleTestCase
{
public float renderScale { get; }
public bool cameraTargetIsRenderTexture { get; }
public RenderScaleTestCase(float renderScale, bool cameraTargetIsRenderTexture)
{
this.renderScale = renderScale;
this.cameraTargetIsRenderTexture = cameraTargetIsRenderTexture;
}
public override string ToString()
{
return $"Render Scale : {renderScale}, Rendering To Texture : {cameraTargetIsRenderTexture}";
}
}
[OneTimeSetUp]
public void GlobalSetup()
{
var go = new GameObject(nameof(RenderTextureDescriptorDimensionsTests));
m_Camera = go.AddComponent<Camera>();
m_CameraData = new UniversalCameraData
{
camera = m_Camera
};
m_RT = new RenderTexture(256, 256, 16, RenderTextureFormat.ARGB32);
m_RT.Create();
}
[OneTimeTearDown]
public void GlobalCleanup()
{
Object.DestroyImmediate(m_Camera.gameObject);
m_RT.Release();
}
public RenderTextureDescriptor CreateRenderTextureDescriptor()
{
int msaaSamples = 1;
bool needsAlpha = false;
UniversalRenderPipeline.CreateBackbufferInfo(m_Camera, m_CameraData, needsAlpha);
return UniversalRenderPipeline.CreateRenderTextureDescriptor(
m_Camera,
m_CameraData,
msaaSamples);
}
public void CheckDimensions(RenderTextureDescriptor desc, RenderScaleTestCase testCase)
{
var expectedWidth = Mathf.Max(1, (int)(m_Camera.pixelWidth * testCase.renderScale));
var expectedHeight = Mathf.Max(1, (int)(m_Camera.pixelHeight * testCase.renderScale));
Assert.AreEqual(expectedWidth, desc.width);
Assert.AreEqual(expectedHeight, desc.height);
}
public static IEnumerable<RenderScaleTestCase> TestCasesTextureDimension()
{
// Texture target
yield return new RenderScaleTestCase(0f, true);
yield return new RenderScaleTestCase(0.5f, true);
yield return new RenderScaleTestCase(1f, true);
yield return new RenderScaleTestCase(2f, true);
// Backbuffer target
yield return new RenderScaleTestCase(0f, false);
yield return new RenderScaleTestCase(0.5f, false);
yield return new RenderScaleTestCase(1f, false);
yield return new RenderScaleTestCase(2f, false);
}
[TestCaseSource(nameof(TestCasesTextureDimension))]
public void TextureDescriptor_FromCameraData(RenderScaleTestCase testCase)
{
// Setup needed data for the test
m_CameraData.renderScale = testCase.renderScale;
m_Camera.targetTexture = (testCase.cameraTargetIsRenderTexture) ? m_RT : null;
// Initialize scaledWidth and scaledHeight using the helper function
UniversalRenderPipeline.InitializeScaledDimensions(m_Camera, m_CameraData);
var desc = CreateRenderTextureDescriptor();
CheckDimensions(desc, testCase);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dd26f353075a7de438d1eeb98517dc50
@@ -0,0 +1,97 @@
using System.Collections.Generic;
using NUnit.Framework;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering.Universal;
[TestFixture]
class RenderingLayersTests
{
string[] m_DefinedLayers;
int[] m_DefinedValues;
int m_LayersSize;
[OneTimeSetUp]
public void OneTimeSetup()
{
m_DefinedLayers = RenderingLayerMask.GetDefinedRenderingLayerNames();
m_DefinedValues = RenderingLayerMask.GetDefinedRenderingLayerValues();
m_LayersSize = RenderingLayerMask.GetRenderingLayerCount();
}
[OneTimeTearDown]
public void OneTimeTeardown()
{
var diff = RenderingLayerMask.GetRenderingLayerCount() - m_LayersSize;
if (diff > 0)
for (int i = 0; i < diff; i++)
RenderPipelineEditorUtility.TryRemoveLastRenderingLayerName();
else
for (int i = 0; i < -diff; i++)
RenderPipelineEditorUtility.TryAddRenderingLayerName(string.Empty);
for (int i = 1; i < RenderingLayerMask.GetRenderingLayerCount(); i++)
RenderPipelineEditorUtility.TrySetRenderingLayerName(i, string.Empty);
for (int i = 0; i < m_DefinedValues.Length; i++)
{
var value = m_DefinedValues[i];
if (RenderingLayerMask.defaultRenderingLayerMask == value)
continue;
var name = m_DefinedLayers[i];
var index = Mathf.FloorToInt(Mathf.Log(value, 2));
RenderPipelineEditorUtility.TrySetRenderingLayerName(index, name);
}
}
[SetUp]
public void Setup()
{
var layerCount = RenderingLayerMask.GetRenderingLayerCount() - 1;
for (int i = 0; i < layerCount; i++)
RenderPipelineEditorUtility.TryRemoveLastRenderingLayerName();
}
static TestCaseData[] s_MaskSizeTestCases =
{
new TestCaseData(7)
.SetName("Given a Rendering Layers size of 7, the mask size is 8 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits8),
new TestCaseData(8)
.SetName("Given a Rendering Layers size of 8, the mask size is 8 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits8),
new TestCaseData(9)
.SetName("Given a Rendering Layers size of 9, the mask size is 16 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits16),
new TestCaseData(16)
.SetName("Given a Rendering Layers size of 16, the mask size is 16 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits16),
new TestCaseData(17)
.SetName("Given a Rendering Layers size of 17, the mask size is 24 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits24),
new TestCaseData(24)
.SetName("Given a Rendering Layers size of 24, the mask size is 24 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits24),
new TestCaseData(25)
.SetName("Given a Rendering Layers size of 25, the mask size is 32 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits32),
new TestCaseData(32)
.SetName("Given a Rendering Layers size of 32, the mask size is 32 bits")
.Returns((int)RenderingLayerUtils.MaskSize.Bits32)
};
[Test, TestCaseSource(nameof(s_MaskSizeTestCases))]
public int MaskSizeTest(int tagManagerLayerCount)
{
var currentLayerCount = RenderingLayerMask.GetRenderingLayerCount();
var requiredLayers = tagManagerLayerCount - currentLayerCount;
if (requiredLayers > 0)
for (int i = 0; i < requiredLayers; i++)
RenderPipelineEditorUtility.TryAddRenderingLayerName($"Layer {currentLayerCount + i}");
var urpRenderer = ScriptableObject.CreateInstance<UniversalRendererData>().InternalCreateRenderer() as UniversalRenderer;
RenderingLayerUtils.RequireRenderingLayers(urpRenderer, new List<ScriptableRendererFeature>(), 0, out var evt, out var maskSize);
urpRenderer.Dispose();
return (int)maskSize;
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7bd051581c284375b0ba2d185aca3541
timeCreated: 1724681009
@@ -0,0 +1,26 @@
using UnityEditor;
using NUnit.Framework;
using UnityEditor.Rendering.Universal;
namespace UnityEngine.Rendering.Tests
{
class ScriptTemplatesTests
{
string[] paths = new string[]
{
$"{ScriptTemplates.ScriptTemplatePath}UnlitURP.txt",
$"{ScriptTemplates.ScriptTemplatePath}ScriptableRendererFeature.txt"
};
[Test]
public void ScriptTemplatesExist()
{
for (int i = 0; i < paths.Length; i++)
{
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(paths[i]);
Assert.NotNull(asset);
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4c477f36e726e48d986eb1c7d1281549
@@ -0,0 +1,179 @@
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
class ScriptableRendererDataEditorTests
{
const string k_TempAssetPath = "Assets/ScriptableRendererDataEditorTests";
UniversalRendererData m_RendererData;
string m_AssetPath;
Editor m_Editor;
[SetUp]
public void Setup()
{
m_RendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
CoreUtils.EnsureFolderTreeInAssetFilePath($"{k_TempAssetPath}/test.asset");
m_AssetPath = $"{k_TempAssetPath}/RendererData_{System.Guid.NewGuid():N}.asset";
AssetDatabase.CreateAsset(m_RendererData, m_AssetPath);
AssetDatabase.SaveAssets();
// Clear undo stack to ensure clean state
Undo.ClearAll();
}
[TearDown]
public void TearDown()
{
// Ensure editor is destroyed before clearing undo or deleting assets
if (m_Editor != null)
{
Object.DestroyImmediate(m_Editor);
m_Editor = null;
}
Undo.ClearAll();
if (m_RendererData != null)
{
AssetDatabase.DeleteAsset(m_AssetPath);
m_RendererData = null;
}
if (AssetDatabase.IsValidFolder(k_TempAssetPath))
AssetDatabase.DeleteAsset(k_TempAssetPath);
}
ScriptableRendererDataEditor CreateEditor()
{
m_Editor = Editor.CreateEditor(m_RendererData);
return (ScriptableRendererDataEditor)m_Editor;
}
[Test]
public void AddComponent_AddsRendererFeature()
{
var editor = CreateEditor();
Assert.AreEqual(0, m_RendererData.rendererFeatures.Count, "Renderer should start with no features");
editor.AddComponent(typeof(RenderObjects));
Assert.AreEqual(1, m_RendererData.rendererFeatures.Count, "Renderer should have one feature after adding");
Assert.IsInstanceOf<RenderObjects>(m_RendererData.rendererFeatures[0], "Added feature should be RenderObjects");
}
[Test]
public void AddComponent_SetsHideFlags()
{
var editor = CreateEditor();
editor.AddComponent(typeof(RenderObjects));
var feature = m_RendererData.rendererFeatures[0];
Assert.IsTrue((feature.hideFlags & HideFlags.HideInHierarchy) != 0,
"Added feature should have HideInHierarchy flag set");
}
[Test]
public void AddComponent_StoresFeatureInSameAsset()
{
var editor = CreateEditor();
// Verify target is persistent (required for sub-asset creation)
Assert.IsTrue(EditorUtility.IsPersistent(m_RendererData), "RendererData should be persistent");
editor.AddComponent(typeof(RenderObjects));
AssetDatabase.SaveAssets();
AssetDatabase.ImportAsset(m_AssetPath);
// Reload the asset to get fresh references
m_RendererData = AssetDatabase.LoadAssetAtPath<UniversalRendererData>(m_AssetPath);
var feature = m_RendererData.rendererFeatures[0];
// Feature should be stored at the same asset path as the renderer data
string featurePath = AssetDatabase.GetAssetPath(feature);
Assert.AreEqual(m_AssetPath, featurePath, "Feature asset path should match renderer data path");
// Feature should not be the main asset (it's embedded in the renderer data)
Assert.IsFalse(AssetDatabase.IsMainAsset(feature), "Feature should not be the main asset");
}
[Test]
public void AddComponent_CanBeUndone()
{
var editor = CreateEditor();
Assert.AreEqual(0, m_RendererData.rendererFeatures.Count);
editor.AddComponent(typeof(RenderObjects));
Assert.AreEqual(1, m_RendererData.rendererFeatures.Count);
Undo.PerformUndo();
// Reload asset to get fresh state
m_RendererData = AssetDatabase.LoadAssetAtPath<UniversalRendererData>(m_AssetPath);
Assert.AreEqual(0, m_RendererData.rendererFeatures.Count, "Feature count should be 0 after undo");
}
[Test]
public void AddComponent_CanBeRedone()
{
var editor = CreateEditor();
editor.AddComponent(typeof(RenderObjects));
Assert.AreEqual(1, m_RendererData.rendererFeatures.Count);
Undo.PerformUndo();
m_RendererData = AssetDatabase.LoadAssetAtPath<UniversalRendererData>(m_AssetPath);
Assert.AreEqual(0, m_RendererData.rendererFeatures.Count);
Undo.PerformRedo();
m_RendererData = AssetDatabase.LoadAssetAtPath<UniversalRendererData>(m_AssetPath);
Assert.AreEqual(1, m_RendererData.rendererFeatures.Count, "Feature count should be 1 after redo");
}
[Test]
public void AddMultipleComponents_MaintainsOrder()
{
var editor = CreateEditor();
editor.AddComponent(typeof(RenderObjects));
editor.AddComponent(typeof(FullScreenPassRendererFeature));
Assert.AreEqual(2, m_RendererData.rendererFeatures.Count);
Assert.IsInstanceOf<RenderObjects>(m_RendererData.rendererFeatures[0]);
Assert.IsInstanceOf<FullScreenPassRendererFeature>(m_RendererData.rendererFeatures[1]);
}
[Test]
public void NewFeatures_HaveHideInHierarchyFlag()
{
var editor = CreateEditor();
editor.AddComponent(typeof(RenderObjects));
editor.AddComponent(typeof(FullScreenPassRendererFeature));
foreach (var feature in m_RendererData.rendererFeatures)
{
Assert.IsTrue((feature.hideFlags & HideFlags.HideInHierarchy) != 0,
$"Feature {feature.name} should have HideInHierarchy flag");
}
}
[Test]
public void RendererFeatureMapCount_MatchesFeatureCount()
{
var editor = CreateEditor();
editor.AddComponent(typeof(RenderObjects));
editor.AddComponent(typeof(FullScreenPassRendererFeature));
Assert.AreEqual(m_RendererData.m_RendererFeatures.Count, m_RendererData.m_RendererFeatureMap.Count,
"Feature map count should match features count");
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cc9a0e128afcfe74d965b5c34ce187a2
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe1a138aa19e2e64d963c084b4006b0e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,579 @@
using System.Collections.Generic;
using NUnit.Framework;
using UnityEditor.Rendering.Universal;
using UnityEngine.Rendering.Universal;
using ShaderPrefilteringData = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.ShaderPrefilteringData;
using PrefilteringMode = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringMode;
using PrefilteringModeMainLightShadows = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringModeMainLightShadows;
using PrefilteringModeAdditionalLights = UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.PrefilteringModeAdditionalLights;
namespace ShaderStrippingAndPrefiltering
{
class ShaderPrefilteringTests
{
class TestHelper
{
internal bool isAssetUsingforward = true;
internal bool everyRendererHasSSAO = false;
internal bool everyRendererHasSSR = false;
internal bool stripXRKeywords = true;
internal bool stripHDRKeywords = true;
internal bool stripDebugDisplay = true;
internal bool stripBicubicLightmapSampling = true;
internal bool stripReflectionProbeRotation = true;
internal bool stripScreenSpaceIrradiance = true;
internal bool stripScreenCoordOverride = true;
internal bool stripUnusedVariants = true;
internal List<ScreenSpaceAmbientOcclusionSettings> ssaoRendererFeatures = new List<ScreenSpaceAmbientOcclusionSettings>();
internal ShaderPrefilteringData defaultPrefilteringData;
public TestHelper()
{
defaultPrefilteringData = CreatePrefilteringSettings(ShaderFeatures.None);
}
internal ShaderPrefilteringData CreatePrefilteringSettings(ShaderFeatures shaderFeatures)
{
#if SURFACE_CACHE
return ShaderBuildPreprocessor.CreatePrefilteringSettings(ref shaderFeatures, isAssetUsingforward, everyRendererHasSSAO, everyRendererHasSSR, stripXRKeywords, stripHDRKeywords, stripDebugDisplay, stripScreenCoordOverride, stripBicubicLightmapSampling, stripReflectionProbeRotation, stripScreenSpaceIrradiance, stripUnusedVariants, ref ssaoRendererFeatures);
#else
return ShaderBuildPreprocessor.CreatePrefilteringSettings(ref shaderFeatures, isAssetUsingforward, everyRendererHasSSAO, everyRendererHasSSR, stripXRKeywords, stripHDRKeywords, stripDebugDisplay, stripScreenCoordOverride, stripBicubicLightmapSampling, stripReflectionProbeRotation, stripUnusedVariants, ref ssaoRendererFeatures);
#endif
}
internal void AssertPrefilteringData(ShaderPrefilteringData expected, ShaderPrefilteringData actual)
{
Assert.AreEqual(expected.forwardPlusPrefilteringMode, actual.forwardPlusPrefilteringMode, "forwardPlusPrefilteringMode mismatch");
Assert.AreEqual(expected.deferredPrefilteringMode, actual.deferredPrefilteringMode, "deferredPrefilteringMode mismatch");
Assert.AreEqual(expected.mainLightShadowsPrefilteringMode, actual.mainLightShadowsPrefilteringMode, "mainLightShadowsPrefilteringMode mismatch");
Assert.AreEqual(expected.additionalLightsPrefilteringMode, actual.additionalLightsPrefilteringMode, "additionalLightsPrefilteringMode mismatch");
Assert.AreEqual(expected.additionalLightsShadowsPrefilteringMode, actual.additionalLightsShadowsPrefilteringMode, "additionalLightsShadowsPrefilteringMode mismatch");
Assert.AreEqual(expected.screenSpaceOcclusionPrefilteringMode, actual.screenSpaceOcclusionPrefilteringMode, "screenSpaceOcclusionPrefilteringMode mismatch");
Assert.AreEqual(expected.screenSpaceReflectionPrefilteringMode, actual.screenSpaceReflectionPrefilteringMode, "screenSpaceReflectionPrefilteringMode mismatch");
Assert.AreEqual(expected.stripXRKeywords, actual.stripXRKeywords, "stripXRKeywords mismatch");
Assert.AreEqual(expected.stripHDRKeywords, actual.stripHDRKeywords, "stripHDRKeywords mismatch");
Assert.AreEqual(expected.stripDebugDisplay, actual.stripDebugDisplay, "stripDebugDisplay mismatch");
Assert.AreEqual(expected.stripScreenCoordOverride, actual.stripScreenCoordOverride, "stripScreenCoordOverride mismatch");
Assert.AreEqual(expected.stripWriteRenderingLayers, actual.stripWriteRenderingLayers, "stripWriteRenderingLayers mismatch");
Assert.AreEqual(expected.stripDBufferMRT1, actual.stripDBufferMRT1, "stripDBufferMRT1 mismatch");
Assert.AreEqual(expected.stripDBufferMRT2, actual.stripDBufferMRT2, "stripDBufferMRT2 mismatch");
Assert.AreEqual(expected.stripDBufferMRT3, actual.stripDBufferMRT3, "stripDBufferMRT2 mismatch");
Assert.AreEqual(expected.stripNativeRenderPass, actual.stripNativeRenderPass, "stripNativeRenderPass mismatch");
Assert.AreEqual(expected.stripSSAOBlueNoise, actual.stripSSAOBlueNoise, "stripSSAOBlueNoise mismatch");
Assert.AreEqual(expected.stripSSAOInterleaved, actual.stripSSAOInterleaved, "stripSSAOInterleaved mismatch");
Assert.AreEqual(expected.stripSSAODepthNormals, actual.stripSSAODepthNormals, "stripSSAODepthNormals mismatch");
Assert.AreEqual(expected.stripSSAOSourceDepthLow, actual.stripSSAOSourceDepthLow, "stripSSAOSourceDepthLow mismatch");
Assert.AreEqual(expected.stripSSAOSourceDepthMedium, actual.stripSSAOSourceDepthMedium, "stripSSAOSourceDepthMedium mismatch");
Assert.AreEqual(expected.stripSSAOSourceDepthHigh, actual.stripSSAOSourceDepthHigh, "stripSSAOSourceDepthHigh mismatch");
Assert.AreEqual(expected.stripSSAOSampleCountLow, actual.stripSSAOSampleCountLow, "stripSSAOSampleCountLow mismatch");
Assert.AreEqual(expected.stripSSAOSampleCountMedium, actual.stripSSAOSampleCountMedium, "stripNativeRenderPass mismatch");
Assert.AreEqual(expected.stripSSAOSampleCountHigh, actual.stripSSAOSampleCountHigh, "stripNativeRenderPass mismatch");
Assert.AreEqual(expected.stripWriteSmoothness, actual.stripWriteSmoothness, "stripWriteSmoothness mismatch");
Assert.AreEqual(expected, actual, "Some mismatch between the Prefiltering Data that is not covered in the previous tests.");
}
}
[Test]
public void TestCreatePrefilteringSettings_NoFeatures()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_RenderingModes()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// Forward Plus only in use
helper.isAssetUsingforward = false;
expected = helper.defaultPrefilteringData;
expected.forwardPlusPrefilteringMode = PrefilteringMode.SelectOnly;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ForwardPlus);
helper.AssertPrefilteringData(expected, actual);
// Deferred only in use
helper.isAssetUsingforward = false;
expected = helper.defaultPrefilteringData;
expected.deferredPrefilteringMode = PrefilteringMode.SelectOnly;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DeferredShading);
helper.AssertPrefilteringData(expected, actual);
// Forward & Forward+ in use
helper.isAssetUsingforward = true;
expected = helper.defaultPrefilteringData;
expected.forwardPlusPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ForwardPlus);
helper.AssertPrefilteringData(expected, actual);
// Forward & Deferred in use
helper.isAssetUsingforward = true;
expected = helper.defaultPrefilteringData;
expected.deferredPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DeferredShading);
helper.AssertPrefilteringData(expected, actual);
// Forward+ & Deferred in use
helper.isAssetUsingforward = false;
expected = helper.defaultPrefilteringData;
expected.forwardPlusPrefilteringMode = PrefilteringMode.Select;
expected.deferredPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ForwardPlus | ShaderFeatures.DeferredShading);
helper.AssertPrefilteringData(expected, actual);
// Forward, Forward+ & Deferred in use
helper.isAssetUsingforward = true;
expected = helper.defaultPrefilteringData;
expected.forwardPlusPrefilteringMode = PrefilteringMode.Select;
expected.deferredPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ForwardPlus | ShaderFeatures.DeferredShading);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_AdditionalLights()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// Vertex with and without the OFF variant
expected = helper.defaultPrefilteringData;
expected.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectVertex;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.AdditionalLightsVertex);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectVertexAndOff;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.AdditionalLightsVertex | ShaderFeatures.AdditionalLightsKeepOffVariants);
helper.AssertPrefilteringData(expected, actual);
// Pixel with and without the OFF variant
expected = helper.defaultPrefilteringData;
expected.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectPixel;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.AdditionalLightsPixel);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.additionalLightsPrefilteringMode = PrefilteringModeAdditionalLights.SelectPixelAndOff;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.AdditionalLightsPixel | ShaderFeatures.AdditionalLightsKeepOffVariants);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_Shadows()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// Main Light Shadows
expected = helper.defaultPrefilteringData;
expected.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLight;
expected.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Remove;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.MainLightShadows);
helper.AssertPrefilteringData(expected, actual);
// Main Light Shadows & OFF
expected = helper.defaultPrefilteringData;
expected.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLightAndOff;
expected.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Remove;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.MainLightShadows | ShaderFeatures.ShadowsKeepOffVariants);
helper.AssertPrefilteringData(expected, actual);
// Main Light Shadows & Cascade
expected = helper.defaultPrefilteringData;
expected.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectMainLightAndCascades;
expected.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Remove;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.MainLightShadows | ShaderFeatures.MainLightShadowsCascade);
helper.AssertPrefilteringData(expected, actual);
// Main Light Shadows & Cascade & OFF
expected = helper.defaultPrefilteringData;
expected.mainLightShadowsPrefilteringMode = PrefilteringModeMainLightShadows.SelectAll;
expected.additionalLightsShadowsPrefilteringMode = PrefilteringMode.Remove;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.MainLightShadows | ShaderFeatures.MainLightShadowsCascade | ShaderFeatures.ShadowsKeepOffVariants);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_GlobalSettings()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// XR
helper.stripXRKeywords = false;
expected = helper.defaultPrefilteringData;
expected.stripXRKeywords = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripXRKeywords = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
// HDR
helper.stripHDRKeywords = false;
expected = helper.defaultPrefilteringData;
expected.stripHDRKeywords = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripHDRKeywords = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
Assert.AreEqual(true, actual.stripHDRKeywords);
helper.AssertPrefilteringData(expected, actual);
// Rendering Debugger
helper.stripDebugDisplay = false;
expected = helper.defaultPrefilteringData;
expected.stripDebugDisplay = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripDebugDisplay = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
// Bicubic lightmap sampling
helper.stripBicubicLightmapSampling = false;
expected = helper.defaultPrefilteringData;
expected.stripBicubicLightmapSampling = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripBicubicLightmapSampling = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
// Reflection Probe Rotation
helper.stripReflectionProbeRotation = false;
expected = helper.defaultPrefilteringData;
expected.stripReflectionProbeRotation = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripReflectionProbeRotation = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
// Screen Coord Override
helper.stripScreenCoordOverride = false;
expected = helper.defaultPrefilteringData;
expected.stripScreenCoordOverride = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripScreenCoordOverride = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
// Screen Space Irradiance
#if SURFACE_CACHE
helper.stripScreenSpaceIrradiance = false;
expected = helper.defaultPrefilteringData;
expected.stripScreenSpaceIrradiance = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
helper.stripScreenSpaceIrradiance = true;
expected = helper.defaultPrefilteringData;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
#else
helper.stripScreenSpaceIrradiance = false;
expected = helper.defaultPrefilteringData;
expected.stripScreenSpaceIrradiance = true;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
#endif
}
[Test]
public void TestCreatePrefilteringSettings_RenderingLayers()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
expected = helper.defaultPrefilteringData;
expected.stripWriteRenderingLayers = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.OpaqueWriteRenderingLayers);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripWriteRenderingLayers = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DepthNormalPassRenderingLayers);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripWriteRenderingLayers = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.GBufferWriteRenderingLayers);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_Decals()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT1 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT1);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT2 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT2);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT3 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT3);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT1 = false;
expected.stripDBufferMRT2 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT1 | ShaderFeatures.DBufferMRT2);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT1 = false;
expected.stripDBufferMRT3 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT1 | ShaderFeatures.DBufferMRT3);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT2 = false;
expected.stripDBufferMRT3 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT2 | ShaderFeatures.DBufferMRT3);
helper.AssertPrefilteringData(expected, actual);
expected = helper.defaultPrefilteringData;
expected.stripDBufferMRT1 = false;
expected.stripDBufferMRT2 = false;
expected.stripDBufferMRT3 = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.DBufferMRT1 | ShaderFeatures.DBufferMRT2 | ShaderFeatures.DBufferMRT3);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_NativeRenderPass()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// Enabled Render Pass
expected = helper.defaultPrefilteringData;
expected.stripNativeRenderPass = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.RenderPassEnabled);
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_ScreenSpaceOcclusion()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// Screen Space Occlusion Enabled
expected = helper.defaultPrefilteringData;
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion);
helper.AssertPrefilteringData(expected, actual);
// Every Renderer has SSAO with & without strip unused variants
helper.everyRendererHasSSAO = true;
helper.stripUnusedVariants = true;
expected = helper.defaultPrefilteringData;
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.SelectOnly;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion);
helper.AssertPrefilteringData(expected, actual);
helper.stripUnusedVariants = false;
expected = helper.defaultPrefilteringData;
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion);
helper.AssertPrefilteringData(expected, actual);
helper.stripUnusedVariants = true;
helper.everyRendererHasSSAO = false;
// SSAO shader
// Single SSAO feature
helper.ssaoRendererFeatures.Add(new ScreenSpaceAmbientOcclusionSettings()
{
AOMethod = ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.BlueNoise,
Downsample = false,
AfterOpaque = false,
Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.DepthNormals,
NormalSamples = ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium,
Intensity = 3.0f,
DirectLightingStrength = 0.25f,
Radius = 0.035f,
Samples = ScreenSpaceAmbientOcclusionSettings.AOSampleOption.Medium,
BlurQuality = ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.High,
Falloff = 100f,
});
expected = helper.defaultPrefilteringData;
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
#if MODERN_SSAO
expected.stripSSAODepthNormals = false;
expected.stripSSAOSourceDepthLow = false;
expected.stripSSAOSourceDepthMedium = false;
expected.stripSSAOSourceDepthHigh = false;
expected.stripSSAOBlueNoise = false;
expected.stripSSAOInterleaved = false;
expected.stripSSAOSampleCountLow = false;
expected.stripSSAOSampleCountMedium = false;
expected.stripSSAOSampleCountHigh = false;
#else
expected.stripSSAOBlueNoise = false;
expected.stripSSAODepthNormals = false;
expected.stripSSAOSampleCountMedium = false;
#endif
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion);
helper.AssertPrefilteringData(expected, actual);
// Two SSAO features
helper.ssaoRendererFeatures.Add(new ScreenSpaceAmbientOcclusionSettings()
{
AOMethod = ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient,
Downsample = false,
AfterOpaque = false,
Source = ScreenSpaceAmbientOcclusionSettings.DepthSource.Depth,
NormalSamples = ScreenSpaceAmbientOcclusionSettings.NormalQuality.Medium,
Intensity = 3.0f,
DirectLightingStrength = 0.25f,
Radius = 0.035f,
Samples = ScreenSpaceAmbientOcclusionSettings.AOSampleOption.High,
BlurQuality = ScreenSpaceAmbientOcclusionSettings.BlurQualityOptions.Medium,
Falloff = 100f,
});
expected = helper.defaultPrefilteringData;
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
#if MODERN_SSAO
expected.stripSSAODepthNormals = false;
expected.stripSSAOSourceDepthLow = false;
expected.stripSSAOSourceDepthMedium = false;
expected.stripSSAOSourceDepthHigh = false;
expected.stripSSAOBlueNoise = false;
expected.stripSSAOInterleaved = false;
expected.stripSSAOSampleCountLow = false;
expected.stripSSAOSampleCountMedium = false;
expected.stripSSAOSampleCountHigh = false;
#else
expected.stripSSAOBlueNoise = false;
expected.stripSSAOInterleaved = false;
expected.stripSSAODepthNormals = false;
expected.stripSSAOSourceDepthMedium = false;
expected.stripSSAOSampleCountMedium = false;
expected.stripSSAOSampleCountHigh = false;
#endif
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion);
helper.AssertPrefilteringData(expected, actual);
// Two SSAO features - Both set to After Opaque with Interleaved
helper.ssaoRendererFeatures[0].AfterOpaque = true;
helper.ssaoRendererFeatures[0].AOMethod = ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
helper.ssaoRendererFeatures[1].AfterOpaque = true;
helper.ssaoRendererFeatures[1].AOMethod = ScreenSpaceAmbientOcclusionSettings.AOMethodOptions.InterleavedGradient;
expected = helper.defaultPrefilteringData;
#if MODERN_SSAO
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Select;
expected.stripSSAODepthNormals = false;
expected.stripSSAOSourceDepthLow = false;
expected.stripSSAOSourceDepthMedium = false;
expected.stripSSAOSourceDepthHigh = false;
expected.stripSSAOBlueNoise = false;
expected.stripSSAOInterleaved = false;
expected.stripSSAOSampleCountLow = false;
expected.stripSSAOSampleCountMedium = false;
expected.stripSSAOSampleCountHigh = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceOcclusion | ShaderFeatures.ScreenSpaceOcclusionAfterOpaque);
#else
expected.screenSpaceOcclusionPrefilteringMode = PrefilteringMode.Remove;
expected.stripSSAOBlueNoise = true;
expected.stripSSAOInterleaved = false;
expected.stripSSAODepthNormals = false;
expected.stripSSAOSourceDepthMedium = false;
expected.stripSSAOSampleCountMedium = false;
expected.stripSSAOSampleCountHigh = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
#endif
helper.AssertPrefilteringData(expected, actual);
}
[Test]
public void TestCreatePrefilteringSettings_ScreenSpaceReflection()
{
ShaderPrefilteringData actual;
ShaderPrefilteringData expected;
TestHelper helper = new();
// SSR disabled
expected = helper.defaultPrefilteringData;
expected.screenSpaceReflectionPrefilteringMode = PrefilteringMode.Remove;
expected.stripWriteSmoothness = true;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.None);
helper.AssertPrefilteringData(expected, actual);
#if URP_SCREEN_SPACE_REFLECTION
// SSR enabled
expected = helper.defaultPrefilteringData;
expected.screenSpaceReflectionPrefilteringMode = PrefilteringMode.Select;
expected.stripWriteSmoothness = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceReflection);
helper.AssertPrefilteringData(expected, actual);
// Every Renderer has SSR with & without strip unused variants
helper.everyRendererHasSSR = true;
helper.stripUnusedVariants = true;
expected = helper.defaultPrefilteringData;
expected.screenSpaceReflectionPrefilteringMode = PrefilteringMode.SelectOnly;
expected.stripWriteSmoothness = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceReflection);
helper.AssertPrefilteringData(expected, actual);
helper.stripUnusedVariants = false;
expected = helper.defaultPrefilteringData;
expected.screenSpaceReflectionPrefilteringMode = PrefilteringMode.Select;
expected.stripWriteSmoothness = false;
actual = helper.CreatePrefilteringSettings(ShaderFeatures.ScreenSpaceReflection);
helper.AssertPrefilteringData(expected, actual);
helper.stripUnusedVariants = true;
helper.everyRendererHasSSR = false;
#endif
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d39807a20ab1bc45a1f531d4e7d99f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 573a6c03a0cb85549bc135c9832138b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 12294e4088bdd864c84d9aa37fc453b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,104 @@
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace UnityEditor.Rendering.Universal.Tests
{
// UUM-152935: undoing a ShadowCaster2D shape edit in Play mode logged
// "No script asset for ShadowCasterPath. Check that the definition is in a file of the same name."
// ShadowCasterPath is a ScriptableObject, so Unity needs a MonoScript for it, which needs a file of the same name.
// The type is looked up by name because it only exists when com.unity.2d.common is installed.
class ShadowCasterPathUndoTests
{
static readonly Type ShadowCasterPathType =
Type.GetType("UnityEditor.Rendering.Universal.ShadowCasterPath, Unity.RenderPipelines.Universal.Editor");
// Serialized so it survives the domain reload on exiting Play mode, which runs before the assert.
[SerializeField]
List<string> m_MissingScriptWarnings = new List<string>();
void OnLogMessage(string message, string stackTrace, LogType type)
{
if (message.Contains("No script asset for"))
m_MissingScriptWarnings.Add(message);
}
static void IgnoreIfShadowCasterPathMissing()
{
if (ShadowCasterPathType == null)
Assert.Ignore("ShadowCasterPath needs com.unity.2d.common.");
}
static ScriptableObject CreateShadowCasterPath()
{
IgnoreIfShadowCasterPathMissing();
var path = ScriptableObject.CreateInstance(ShadowCasterPathType);
path.hideFlags = HideFlags.HideAndDontSave;
return path;
}
[Test]
public void ShadowCasterPath_HasMonoScript()
{
var path = CreateShadowCasterPath();
try
{
var script = MonoScript.FromScriptableObject(path);
Assert.IsNotNull(script, "ShadowCasterPath has no MonoScript.");
Assert.AreEqual(ShadowCasterPathType, script.GetClass());
}
finally
{
UnityEngine.Object.DestroyImmediate(path);
}
}
[UnityTest]
public IEnumerator UndoShadowCasterPathInPlayMode_DoesNotWarnAboutMissingScript()
{
return UndoShadowCasterPathInPlayMode(false);
}
[UnityTest]
public IEnumerator UndoRedoShadowCasterPathInPlayMode_DoesNotWarnAboutMissingScript()
{
return UndoShadowCasterPathInPlayMode(true);
}
IEnumerator UndoShadowCasterPathInPlayMode(bool redo)
{
// Check before entering Play mode, so an ignored test does not leave the Editor in Play mode.
IgnoreIfShadowCasterPathMissing();
yield return new EnterPlayMode();
var path = CreateShadowCasterPath();
m_MissingScriptWarnings.Clear();
Application.logMessageReceived += OnLogMessage;
try
{
Undo.IncrementCurrentGroup();
Undo.RegisterCompleteObjectUndo(path, "Edit Shadow Caster Shape");
Undo.FlushUndoRecordObjects();
Undo.IncrementCurrentGroup();
Undo.PerformUndo();
if (redo)
Undo.PerformRedo();
}
finally
{
Application.logMessageReceived -= OnLogMessage;
Undo.ClearUndo(path);
UnityEngine.Object.DestroyImmediate(path);
}
yield return new ExitPlayMode();
Assert.IsEmpty(m_MissingScriptWarnings);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c3e1a5d9b2f4e8a6d0c4b1f3a92e57d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using System;
using System.Text.RegularExpressions;
using NUnit.Framework;
using UnityEngine.TestTools;
namespace UnityEngine.Rendering.Universal.Tests
{
[TestFixture]
sealed class SupportedOnRendererAttributeTests
{
class CustomRenderer { }
static readonly Regex k_InvalidTypeMessage = new($@"{nameof(SupportedOnRendererAttribute)} Attribute targets an invalid {nameof(ScriptableRendererData)}");
static readonly Regex k_NullParametersMessage = new($@"{nameof(SupportedOnRendererAttribute)} parameters cannot be null");
[Test]
public void NonScriptableRendererDataType_LogsErrorAndProducesEmptyTypeArray()
{
LogAssert.Expect(LogType.Error, k_InvalidTypeMessage);
var attr = new SupportedOnRendererAttribute(typeof(CustomRenderer));
Assert.That(attr.rendererTypes, Is.Not.Null);
Assert.That(attr.rendererTypes, Is.Empty);
}
[Test]
public void NullType_LogsErrorAndProducesEmptyTypeArray()
{
LogAssert.Expect(LogType.Error, k_NullParametersMessage);
var attr = new SupportedOnRendererAttribute((Type[])null);
Assert.That(attr.rendererTypes, Is.Not.Null);
Assert.That(attr.rendererTypes, Is.Empty);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3fc1d215954974240928b390996c4362
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 30adb98416985a445bf000ceb696941f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b117ddec9feb0445a5b1ff958fd1399
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8df36688c2526454a967c4ebbff74976
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,220 @@
using System.Collections;
using NUnit.Framework;
using UnityEditor.Rendering.Converter;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class AnimationClipConverterTests
{
const string k_TestsPath = "Assets/AnimationClipConverterTests/";
static AnimationClip CreateAnimationClip()
{
// Create a new animation clip
AnimationClip clip = new AnimationClip();
clip.legacy = true;
clip.frameRate = 60;
// Create keyframes for the color animation
Keyframe[] redKeys = new Keyframe[3];
Keyframe[] greenKeys = new Keyframe[3];
Keyframe[] blueKeys = new Keyframe[3];
Keyframe[] alphaKeys = new Keyframe[3];
// Start color (Red) at time 0
redKeys[0] = new Keyframe(0f, 1f);
greenKeys[0] = new Keyframe(0f, 0f);
blueKeys[0] = new Keyframe(0f, 0f);
alphaKeys[0] = new Keyframe(0f, 1f);
// Middle color (Green) at time 1
redKeys[1] = new Keyframe(1f, 0f);
greenKeys[1] = new Keyframe(1f, 1f);
blueKeys[1] = new Keyframe(1f, 0f);
alphaKeys[1] = new Keyframe(1f, 1f);
// End color (Blue) at time 2
redKeys[2] = new Keyframe(2f, 0f);
greenKeys[2] = new Keyframe(2f, 0f);
blueKeys[2] = new Keyframe(2f, 1f);
alphaKeys[2] = new Keyframe(2f, 1f);
// Create animation curves
AnimationCurve redCurve = new AnimationCurve(redKeys);
AnimationCurve greenCurve = new AnimationCurve(greenKeys);
AnimationCurve blueCurve = new AnimationCurve(blueKeys);
AnimationCurve alphaCurve = new AnimationCurve(alphaKeys);
// Set curves to the clip with correct binding format
// Empty string "" means the animated object itself
clip.SetCurve("", typeof(MeshRenderer), "material._Color.r", redCurve);
clip.SetCurve("", typeof(MeshRenderer), "material._Color.g", greenCurve);
clip.SetCurve("", typeof(MeshRenderer), "material._Color.b", blueCurve);
clip.SetCurve("", typeof(MeshRenderer), "material._Color.a", alphaCurve);
// Set the clip to loop
AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
settings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, settings);
// Save the animation clip as an asset
string path = k_TestsPath + "ColorAnimation.anim";
CoreUtils.EnsureFolderTreeInAssetFilePath(path);
AssetDatabase.CreateAsset(clip, path);
AssetDatabase.SaveAssets();
return clip;
}
public static GameObject CreatePrefabForTest(Material[] materials, AnimationClip clip, string assetPath)
{
// Create a temporary GameObject
var go = new GameObject("TestingPrefabGO");
try
{
// Add components
var mf = go.AddComponent<MeshFilter>();
var mr = go.AddComponent<MeshRenderer>();
mr.sharedMaterials = materials;
var anim = go.AddComponent<Animation>();
anim.enabled = true;
anim.clip = clip;
string localPath = assetPath + go.name + ".prefab";
CoreUtils.EnsureFolderTreeInAssetFilePath(localPath);
// Save as prefab
var prefab = PrefabUtility.SaveAsPrefabAsset(go, localPath, out bool success);
if (!success || prefab == null)
{
Debug.LogError("Failed to save prefab at: " + assetPath);
return null;
}
AssetDatabase.ImportAsset(localPath);
AssetDatabase.SaveAssets();
return prefab;
}
finally
{
// Cleanup temporary instance
UnityEngine.Object.DestroyImmediate(go);
}
}
private static Material GetDefaultDiffuse()
{
if (GraphicsSettings.currentRenderPipeline is not UniversalRenderPipelineAsset)
return null;
return AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat");
}
private static Material GetURPDefaultMaterial()
{
if (GraphicsSettings.currentRenderPipeline is not UniversalRenderPipelineAsset)
return null;
// Get URP default material from graphics settings
return GraphicsSettings.GetRenderPipelineSettings<UniversalRenderPipelineEditorMaterials>().defaultMaterial;
}
AnimationClipConverter m_Converter;
[OneTimeSetUp]
public void OneTimeSetup()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset == null)
Assert.Ignore("Project without URP. Skipping test");
var universalRenderer = urpAsset.scriptableRenderer as UniversalRenderer;
if (universalRenderer == null)
Assert.Ignore("Project without URP - Universal Renderer. Skipping test");
m_Converter = new AnimationClipConverter();
Assume.That(m_Converter.m_UpgradePathsToNewShaders == null, "Upgraders is not null, when it should be null");
m_Converter.BeforeConvert();
Assume.That(m_Converter.m_UpgradePathsToNewShaders != null, "Upgraders was not initialized");
}
[OneTimeTearDown]
public void OneTimeTeardown()
{
if (m_Converter != null)
{
m_Converter.AfterConvert();
Assume.That(m_Converter.m_UpgradePathsToNewShaders == null, "Upgraders was not disposed");
AssetDatabase.DeleteAsset(k_TestsPath);
}
}
AnimationClip m_AnimationClip;
[SetUp]
public void Setup()
{
m_AnimationClip = CreateAnimationClip();
Assume.That(m_AnimationClip != null, "Unable to create animation clip");
}
[TearDown]
public void TearDown()
{
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(m_AnimationClip));
}
private static IEnumerable MaterialTestCases()
{
yield return new TestCaseData(
new Material[] { GetDefaultDiffuse() },
Status.Warning,
"material._Color"
).SetName("GivenBuiltInMaterial_WhenConverting_ThenNoUpgradeNeeded");
yield return new TestCaseData(
new Material[] { GetURPDefaultMaterial() },
Status.Success,
"material._BaseColor"
).SetName("GivenURPMaterial_WhenConverting_ThenUpgradeSucceeds");
yield return new TestCaseData(
new Material[] { GetDefaultDiffuse(), GetURPDefaultMaterial() },
Status.Error,
"material._Color"
).SetName("GivenMixedMaterials_WhenConverting_ThenReturnsError");
}
[Test, TestCaseSource(nameof(MaterialTestCases))]
public void PerformAnimationClipConversion(Material[] materials, Status expectedStatus, string expectedBindingPropertyName)
{
AnimationClipConverterItem animationClipConverterItem = new(GlobalObjectId.GetGlobalObjectIdSlow(m_AnimationClip), AssetDatabase.GetAssetPath(m_AnimationClip));
var go = CreatePrefabForTest(materials, m_AnimationClip, k_TestsPath + $"{TestContext.CurrentContext.Test.Name}/");
animationClipConverterItem.dependencies.Add(
new RenderPipelineConverterAssetItem(
GlobalObjectId.GetGlobalObjectIdSlow(go),
AssetDatabase.GetAssetPath(go))
);
var status = m_Converter.Convert(animationClipConverterItem, out var message);
Assert.AreEqual(expectedStatus, status, $"Expected status {expectedStatus} but got {status} with {message}");
foreach (var b in AnimationUtility.GetCurveBindings(m_AnimationClip))
{
Assert.IsTrue(b.propertyName.Contains(expectedBindingPropertyName));
}
}
}
}
@@ -0,0 +1,378 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class AnimationClipUpgradePathsCacheTests
{
public class DefaultBuiltInToURP : MaterialUpgrader
{
public DefaultBuiltInToURP(string oldShaderName, string newShaderName)
{
if (oldShaderName == null)
throw new ArgumentNullException(nameof(oldShaderName));
RenameShader(oldShaderName, newShaderName, null);
RenameFloat("builtIn01", "urp01");
RenameFloat("builtIn03", "urp02");
RenameColor("builtIn01", "urp01");
RenameColor("builtIn03", "urp02");
RenameTexture("builtIn01", "urp01");
RenameTexture("builtIn03", "urp02");
}
}
public class ConflictingUpgrader : MaterialUpgrader
{
public ConflictingUpgrader(string oldShaderName, string newShaderName)
{
RenameShader(oldShaderName, newShaderName, null);
// Creates conflict - same source maps to different targets
RenameFloat("conflictProp", "target01");
}
}
public class ConflictingUpgrader01 : MaterialUpgrader
{
public ConflictingUpgrader01(string oldShaderName, string newShaderName)
{
RenameShader(oldShaderName, newShaderName, null);
// Creates conflict - same source maps to different targets
RenameFloat("conflictProp", "target02");
}
}
public class AlternativeBuiltInToURP : MaterialUpgrader
{
public AlternativeBuiltInToURP(string oldShaderName, string newShaderName)
{
RenameShader(oldShaderName, newShaderName, null);
RenameFloat("builtIn01", "urpAlternative01");
RenameColor("colorProp", "urpColor");
RenameTexture("textureProp", "urpTexture");
}
}
private static IEnumerable s_ValidUpgradeTestCases()
{
// Test valid float property upgrade
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urp01"))
.SetName("ValidUpgrade_Float_BuiltIn01ToUrp01");
// Test valid float property upgrade (second mapping)
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn03"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urp02"))
.SetName("ValidUpgrade_Float_BuiltIn03ToUrp02");
// Test valid color property upgrade
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Color,
"builtIn01"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urp01"))
.SetName("ValidUpgrade_Color_BuiltIn01ToUrp01");
// Test valid texture property upgrade
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Texture,
"builtIn01"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urp01"))
.SetName("ValidUpgrade_Texture_BuiltIn01ToUrp01");
}
private static IEnumerable s_NoMappingTestCases()
{
// Test property with no mapping
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"nonExistentProperty"
).Returns((ShaderPropertyUsage.NoMapping, "nonExistentProperty"))
.SetName("NoMapping_Float_NonExistentProperty");
// Test color property with no mapping
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Color,
"unmappedColorProp"
).Returns((ShaderPropertyUsage.NoMapping, "unmappedColorProp"))
.SetName("NoMapping_Color_UnmappedProperty");
}
private static IEnumerable s_AlreadyUpgradedTestCases()
{
// Test property that's already upgraded (target property name)
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"urp01"
).Returns((ShaderPropertyUsage.AlreadyUpgraded, "urp01"))
.SetName("AlreadyUpgraded_Float_Urp01");
// Test texture property that's already upgraded
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Texture,
"urp02"
).Returns((ShaderPropertyUsage.AlreadyUpgraded, "urp02"))
.SetName("AlreadyUpgraded_Texture_Urp02");
}
private static IEnumerable s_InvalidShaderTestCases()
{
// Test with non-existent shader
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"NonExistentShader",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01"
).Returns((ShaderPropertyUsage.InvalidShader, "builtIn01"))
.SetName("InvalidShader_NonExistentShader");
// Test with null shader name
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
null,
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01"
).Returns((ShaderPropertyUsage.InvalidShader, "builtIn01"))
.SetName("InvalidShader_NullShaderName");
// Test with empty shader name
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
},
"",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01"
).Returns((ShaderPropertyUsage.InvalidShader, "builtIn01"))
.SetName("InvalidShader_EmptyShaderName");
}
private static IEnumerable s_MultipleUpgradePathsTestCases()
{
// Test conflicting upgrade paths
yield return new TestCaseData(
new MaterialUpgrader[]
{
new ConflictingUpgrader("OldShader", "NewShader"),
new ConflictingUpgrader01("OldShader", "NewShader"),
},
"NewShader",
MaterialUpgrader.MaterialPropertyType.Float,
"conflictProp"
).Returns((ShaderPropertyUsage.MultipleUpgradePaths, "target02"))
.SetName("MultipleUpgradePaths_ConflictingProperty");
// Test multiple upgraders with conflicting mappings
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
new AlternativeBuiltInToURP("AlternativeBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01"
).Returns((ShaderPropertyUsage.MultipleUpgradePaths, "urpAlternative01"))
.SetName("MultipleUpgradePaths_MultipleUpgradersConflict");
}
private static IEnumerable s_MultipleUpgradersTestCases()
{
// Test non-conflicting properties from different upgraders
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
new AlternativeBuiltInToURP("AlternativeBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Color,
"colorProp"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urpColor"))
.SetName("MultipleUpgraders_NonConflictingColorProperty");
// Test property from first upgrader when multiple upgraders exist
yield return new TestCaseData(
new MaterialUpgrader[]
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
new AlternativeBuiltInToURP("AlternativeBuiltIn", "DefaultURP"),
},
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn03"
).Returns((ShaderPropertyUsage.ValidForUpgrade, "urp02"))
.SetName("MultipleUpgraders_PropertyFromFirstUpgrader");
}
[Test, TestCaseSource(nameof(s_ValidUpgradeTestCases))]
[TestCaseSource(nameof(s_NoMappingTestCases))]
[TestCaseSource(nameof(s_AlreadyUpgradedTestCases))]
[TestCaseSource(nameof(s_InvalidShaderTestCases))]
[TestCaseSource(nameof(s_MultipleUpgradePathsTestCases))]
[TestCaseSource(nameof(s_MultipleUpgradersTestCases))]
public (ShaderPropertyUsage, string) DoTest(
MaterialUpgrader[] upgraders,
string shaderName,
MaterialUpgrader.MaterialPropertyType propertyType,
string property)
{
using var cache = new AnimationClipUpgradePathsCache(upgraders.ToList());
ShaderPropertyUsage usage = cache.GetShaderPropertyUsage(
shaderName,
propertyType,
property,
out string newPropertyName);
return (usage, newPropertyName);
}
[Test]
public void EmptyUpgraderList_ReturnsInvalidShader()
{
using var cache = new AnimationClipUpgradePathsCache(new List<MaterialUpgrader>());
var usage = cache.GetShaderPropertyUsage(
"AnyShader",
MaterialUpgrader.MaterialPropertyType.Float,
"anyProperty",
out string newPropertyName);
Assert.AreEqual(ShaderPropertyUsage.InvalidShader, usage);
Assert.AreEqual("anyProperty", newPropertyName);
}
[Test]
public void Dispose_CanBeCalledMultipleTimes()
{
var cache = new AnimationClipUpgradePathsCache(
new List<MaterialUpgrader>
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP")
});
cache.Dispose();
Assert.DoesNotThrow(() => cache.Dispose());
}
[Test]
public void DifferentPropertyTypes_HaveIndependentMappings()
{
using var cache = new AnimationClipUpgradePathsCache(
new List<MaterialUpgrader>
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP")
});
// Same property name, different types should have independent mappings
var floatUsage = cache.GetShaderPropertyUsage(
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Float,
"builtIn01",
out string floatNewName);
var colorUsage = cache.GetShaderPropertyUsage(
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Color,
"builtIn01",
out string colorNewName);
var textureUsage = cache.GetShaderPropertyUsage(
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Texture,
"builtIn01",
out string textureNewName);
Assert.AreEqual(ShaderPropertyUsage.ValidForUpgrade, floatUsage);
Assert.AreEqual(ShaderPropertyUsage.ValidForUpgrade, colorUsage);
Assert.AreEqual(ShaderPropertyUsage.ValidForUpgrade, textureUsage);
Assert.AreEqual("urp01", floatNewName);
Assert.AreEqual("urp01", colorNewName);
Assert.AreEqual("urp01", textureNewName);
}
[Test]
public void MultipleShaders_AreHandledIndependently()
{
using var cache = new AnimationClipUpgradePathsCache(
new List<MaterialUpgrader>
{
new DefaultBuiltInToURP("DefaultBuiltIn", "DefaultURP"),
new AlternativeBuiltInToURP("AlternativeBuiltIn", "AlternativeURP")
});
var usage1 = cache.GetShaderPropertyUsage(
"DefaultURP",
MaterialUpgrader.MaterialPropertyType.Color,
"builtIn01",
out string newName1);
var usage2 = cache.GetShaderPropertyUsage(
"AlternativeURP",
MaterialUpgrader.MaterialPropertyType.Color,
"colorProp",
out string newName2);
Assert.AreEqual(ShaderPropertyUsage.ValidForUpgrade, usage1);
Assert.AreEqual(ShaderPropertyUsage.ValidForUpgrade, usage2);
Assert.AreEqual("urp01", newName1);
Assert.AreEqual("urpColor", newName2);
}
}
}
@@ -0,0 +1,294 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine.Rendering;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class EditorCurveBindingsTests
{
private static IEnumerable BindingsTestCases()
{
// Default -> float
yield return new TestCaseData(
"nonMatchingProperty"
).Returns((ShaderPropertyType.Float, "nonMatchingProperty"));
// Floats
yield return new TestCaseData(
"material._Metallic"
).Returns((ShaderPropertyType.Float, "_Metallic"));
yield return new TestCaseData(
"material._Smoothness"
).Returns((ShaderPropertyType.Float, "_Smoothness"));
yield return new TestCaseData(
"material._BumpScale"
).Returns((ShaderPropertyType.Float, "_BumpScale"));
yield return new TestCaseData(
"material._OcclusionStrength"
).Returns((ShaderPropertyType.Float, "_OcclusionStrength"));
yield return new TestCaseData(
"material._Metallic.x"
).Returns((ShaderPropertyType.Float, "_Metallic"));
yield return new TestCaseData(
"material._Metallic.y"
).Returns((ShaderPropertyType.Float, "_Metallic"));
yield return new TestCaseData(
"material._Metallic.z"
).Returns((ShaderPropertyType.Float, "_Metallic"));
yield return new TestCaseData(
"material._Metallic.w"
).Returns((ShaderPropertyType.Float, "_Metallic"));
// Colors
yield return new TestCaseData(
"material._Color.r"
).Returns((ShaderPropertyType.Color, "_Color"));
yield return new TestCaseData(
"material._Color.g"
).Returns((ShaderPropertyType.Color, "_Color"));
yield return new TestCaseData(
"material._Color.b"
).Returns((ShaderPropertyType.Color, "_Color"));
yield return new TestCaseData(
"material._Color.a"
).Returns((ShaderPropertyType.Color, "_Color"));
yield return new TestCaseData(
"material._EmissionColor.r"
).Returns((ShaderPropertyType.Color, "_EmissionColor"));
yield return new TestCaseData(
"material._EmissionColor.g"
).Returns((ShaderPropertyType.Color, "_EmissionColor"));
yield return new TestCaseData(
"material._EmissionColor.b"
).Returns((ShaderPropertyType.Color, "_EmissionColor"));
yield return new TestCaseData(
"material._EmissionColor.a"
).Returns((ShaderPropertyType.Color, "_EmissionColor"));
yield return new TestCaseData(
"material._SpecColor.r"
).Returns((ShaderPropertyType.Color, "_SpecColor"));
// Textures - _ST (Scale and Tiling)
yield return new TestCaseData(
"material._MainTex_ST"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_ST.x"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_ST.y"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_ST.z"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_ST.w"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._BumpMap_ST"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
yield return new TestCaseData(
"material._BumpMap_ST.x"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
yield return new TestCaseData(
"material._MetallicGlossMap_ST.z"
).Returns((ShaderPropertyType.Texture, "_MetallicGlossMap"));
yield return new TestCaseData(
"material._OcclusionMap_ST.w"
).Returns((ShaderPropertyType.Texture, "_OcclusionMap"));
yield return new TestCaseData(
"material._EmissionMap_ST"
).Returns((ShaderPropertyType.Texture, "_EmissionMap"));
yield return new TestCaseData(
"material._DetailAlbedoMap_ST.x"
).Returns((ShaderPropertyType.Texture, "_DetailAlbedoMap"));
// Textures - _TexelSize
yield return new TestCaseData(
"material._MainTex_TexelSize"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_TexelSize.x"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_TexelSize.y"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_TexelSize.z"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_TexelSize.w"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._BumpMap_TexelSize"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
yield return new TestCaseData(
"material._BumpMap_TexelSize.x"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
// Textures - _HDR
yield return new TestCaseData(
"material._MainTex_HDR"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_HDR.x"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_HDR.y"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_HDR.z"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._MainTex_HDR.w"
).Returns((ShaderPropertyType.Texture, "_MainTex"));
yield return new TestCaseData(
"material._EmissionMap_HDR"
).Returns((ShaderPropertyType.Texture, "_EmissionMap"));
yield return new TestCaseData(
"material._EmissionMap_HDR.x"
).Returns((ShaderPropertyType.Texture, "_EmissionMap"));
// Textures - _Bump (less common, but valid)
yield return new TestCaseData(
"material._BumpMap_Bump"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
yield return new TestCaseData(
"material._BumpMap_Bump.x"
).Returns((ShaderPropertyType.Texture, "_BumpMap"));
yield return new TestCaseData(
"material._DetailNormalMap_Bump"
).Returns((ShaderPropertyType.Texture, "_DetailNormalMap"));
// Edge cases - properties with underscores
yield return new TestCaseData(
"material._My_Custom_Property"
).Returns((ShaderPropertyType.Float, "_My_Custom_Property"));
yield return new TestCaseData(
"material._My_Custom_Property.x"
).Returns((ShaderPropertyType.Float, "_My_Custom_Property"));
yield return new TestCaseData(
"material._My_Custom_Color.r"
).Returns((ShaderPropertyType.Color, "_My_Custom_Color"));
yield return new TestCaseData(
"material._My_Custom_Texture_ST"
).Returns((ShaderPropertyType.Texture, "_My_Custom_Texture"));
yield return new TestCaseData(
"material._My_Custom_Texture_ST.x"
).Returns((ShaderPropertyType.Texture, "_My_Custom_Texture"));
// Common URP properties
yield return new TestCaseData(
"material._BaseMap_ST"
).Returns((ShaderPropertyType.Texture, "_BaseMap"));
yield return new TestCaseData(
"material._BaseColor.r"
).Returns((ShaderPropertyType.Color, "_BaseColor"));
yield return new TestCaseData(
"material._SpecularColor.g"
).Returns((ShaderPropertyType.Color, "_SpecularColor"));
// Common HDRP properties
yield return new TestCaseData(
"material._BaseColorMap_ST"
).Returns((ShaderPropertyType.Texture, "_BaseColorMap"));
yield return new TestCaseData(
"material._NormalMap_ST.x"
).Returns((ShaderPropertyType.Texture, "_NormalMap"));
yield return new TestCaseData(
"material._MaskMap_ST"
).Returns((ShaderPropertyType.Texture, "_MaskMap"));
yield return new TestCaseData(
"material._DetailMap_ST.y"
).Returns((ShaderPropertyType.Texture, "_DetailMap"));
// Properties with numbers
yield return new TestCaseData(
"material._Texture2D_ST"
).Returns((ShaderPropertyType.Texture, "_Texture2D"));
yield return new TestCaseData(
"material._Texture2D_ST.x"
).Returns((ShaderPropertyType.Texture, "_Texture2D"));
yield return new TestCaseData(
"material._Layer0_BaseColor.r"
).Returns((ShaderPropertyType.Color, "_Layer0_BaseColor"));
yield return new TestCaseData(
"material._Layer1_BaseMap_ST"
).Returns((ShaderPropertyType.Texture, "_Layer1_BaseMap"));
// Vector properties (not color, not texture sub-property)
yield return new TestCaseData(
"material._CustomVector.x"
).Returns((ShaderPropertyType.Float, "_CustomVector"));
yield return new TestCaseData(
"material._CustomVector.y"
).Returns((ShaderPropertyType.Float, "_CustomVector"));
}
[Test, TestCaseSource(nameof(BindingsTestCases))]
public (ShaderPropertyType, string) DoTest(string property)
{
var binding = new EditorCurveBinding
{
propertyName = property
};
var (name, type) = EditorCurveBindingUtils.InferShaderProperty(binding);
return (type, name);
}
}
}
@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine.TestTools;
using UnityEngine;
namespace UnityEditor.Rendering.Universal.Tools
{
[Category("Graphics Tools")]
class ConverterTests
{
class NotAConverterType
{
}
[Test]
public void BatchModeFails()
{
bool ok = Converters.RunInBatchMode(new List<Type>() { typeof(NotAConverterType) });
Assert.IsFalse(ok);
}
[Test]
public void RunInBatchMode_LogsUsageWarning()
{
LogAssert.Expect(
LogType.Warning,
"Using this API can lead to incomplete or unpredictable conversion outcomes. " +
"For reliable results, please perform the conversion via the dedicated window: " +
"Window > Rendering > Render Pipeline Converter."
);
bool _ = Converters.RunInBatchMode(new List<Type>() {});
}
public static IEnumerable<TestCaseData> TestCases()
{
yield return new TestCaseData(
"BuiltInToURP",
new List<string> { "Material" },
true,
new List<Type> { typeof(BuiltInToURP3DMaterialUpgrader) }
).SetName("When Using Inclusive filter with Material in the correct category. The Filter only returns that converter");
yield return new TestCaseData(
"BuiltInToURP",
new List<string> { "ParametricToFreeformLight" },
true,
new List<Type>()
).SetName("When Using Inclusive filter with Light in the wrong category. The Filter returns nothing");
yield return new TestCaseData(
"BuiltInToURP",
new List<string>
{
"RenderSettings",
"PPv2"
},
false,
new List<Type>
{
typeof(AnimationClipConverter),
typeof(BuiltInToURP3DMaterialUpgrader),
typeof(BuiltInToURP3DReadonlyMaterialConverter),
}
).SetName("When Using Exclusive filter. The filter returns everything except the given ids");
yield return new TestCaseData(
"BuiltInToURP",
new List<string>(),
true,
new List<Type>() // No converters match
).SetName("When Using Inclusive filter with no converters. The filter returns nothing");
yield return new TestCaseData(
"BuiltInToURP",
new List<string>(),
false,
new List<Type>
{
typeof(PPv2Converter),
typeof(BuiltInToURP3DRenderSettingsConverter),
typeof(AnimationClipConverter),
typeof(BuiltInToURP3DMaterialUpgrader),
typeof(BuiltInToURP3DReadonlyMaterialConverter),
}
).SetName("BuiltInToURP - When Using Exclusive filter with no converters. The filter returns everything");
yield return new TestCaseData(
"BuiltInToURP2D",
new List<string>(),
false,
new List<Type>
{
typeof(BuiltInToURP2DRenderSettingsConverter),
typeof(BuiltInToURP2DReadonlyMaterialConverter),
}
).SetName("BuiltInToURP2D - When Using Exclusive filter with no converters. The filter returns everything");
yield return new TestCaseData(
"UpgradeURP2DAssets",
new List<string>(),
false,
new List<Type>
{
typeof(ParametricToFreeformLightUpgrader)
}
).SetName("UpgradeURP2DAssets - When Using Exclusive filter with no converters. The filter returns everything");
}
[TestCaseSource(nameof(TestCases))]
public void FilterConverters_ShouldReturnExpectedConverters(
string containerName,
List<string> filterList,
bool filterModeIsInclusive,
List<Type> expectedTypes)
{
var actualTypes = Converters.FilterConverters(containerName, filterList, filterModeIsInclusive);
CollectionAssert.AreEquivalent(expectedTypes, actualTypes);
}
[Test]
public void CommandLine_ArgumentsParsedProperly()
{
// case 1 - working command
var dummyArgs = "-batchmode -executeMethod UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine --flagA -paramA 1 2 3 --flagB --flagC -paramB --flagD";
var actualArgs = Converters.ParseArgs(dummyArgs.Split(' '));
Dictionary<string, List<string>> expectedArgs = new()
{
{ "-executeMethod", new List<string> {"UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine"} },
{ "-paramA", new List<string> {"1", "2", "3"} },
{ "-paramB", new List<string> {} },
{ "Flags", new List<string> {"--flagA", "--flagB", "--flagC", "--flagD"} }
};
CollectionAssert.AreEquivalent(expectedArgs, actualArgs);
// case 2 - Error: No -batchmode flag
dummyArgs = "-executeMethod UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine --flagA -paramA 1 2 3";
var exception = Assert.Throws<ArgumentException>(() => Converters.ParseArgs(dummyArgs.Split(' ')));
Assert.That(exception.Message, Is.EqualTo("No -batchmode argument found. Exiting."));
// case 3 - Error: Adding values without a key
dummyArgs = "-batchmode -executeMethod UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine --flagA wrongArgument";
exception = Assert.Throws<ArgumentException>(() => Converters.ParseArgs(dummyArgs.Split(' ')));
Assert.That(exception.Message, Is.EqualTo("Unrecognized argument: wrongArgument"));
}
#pragma warning disable CS0618 // Type or member is obsolete
public static IEnumerable<TestCaseData> TestCasesDeprecated()
{
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP,
new List<ConverterId> { ConverterId.Material },
ConverterFilter.Inclusive,
new List<Type> { typeof(BuiltInToURP3DMaterialUpgrader) }
).SetName("When Using Inclusive filter with Material in the correct category. The Filter only returns that converter");
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP,
new List<ConverterId> { ConverterId.ParametricToFreeformLight },
ConverterFilter.Inclusive,
new List<Type>()
).SetName("When Using Inclusive filter with Light in the wrong category. The Filter returns nothing");
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP,
new List<ConverterId>
{
ConverterId.RenderSettings,
#if PPV2_EXISTS
ConverterId.PPv2
#endif
},
ConverterFilter.Exclusive,
new List<Type>
{
typeof(AnimationClipConverter),
typeof(BuiltInToURP3DMaterialUpgrader),
typeof(BuiltInToURP3DReadonlyMaterialConverter),
}
).SetName("When Using Exclusive filter. The filter returns everything except the given ids");
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP,
new List<ConverterId>(),
ConverterFilter.Inclusive,
new List<Type>() // No converters match
).SetName("When Using Inclusive filter with no converters. The filter returns nothing");
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP,
new List<ConverterId>(),
ConverterFilter.Exclusive,
new List<Type>
{
#if PPV2_EXISTS
typeof(PPv2Converter),
#endif
typeof(BuiltInToURP3DRenderSettingsConverter),
typeof(AnimationClipConverter),
typeof(BuiltInToURP3DMaterialUpgrader),
typeof(BuiltInToURP3DReadonlyMaterialConverter),
}
).SetName("BuiltInToURP - When Using Exclusive filter with no converters. The filter returns everything");
yield return new TestCaseData(
ConverterContainerId.BuiltInToURP2D,
new List<ConverterId>(),
ConverterFilter.Exclusive,
new List<Type>
{
typeof(BuiltInToURP2DRenderSettingsConverter),
typeof(BuiltInToURP2DReadonlyMaterialConverter),
}
).SetName("BuiltInToURP2D - When Using Exclusive filter with no converters. The filter returns everything");
yield return new TestCaseData(
ConverterContainerId.UpgradeURP2DAssets,
new List<ConverterId>(),
ConverterFilter.Exclusive,
new List<Type>
{
typeof(URP3DToURP2DReadonlyMaterialConverter),
typeof(ParametricToFreeformLightUpgrader)
}
).SetName("UpgradeURP2DAssets - When Using Exclusive filter with no converters. The filter returns everything");
}
[TestCaseSource(nameof(TestCasesDeprecated))]
public void FilterConverters_ShouldReturnExpectedConverters_DeprecatedAPI(
ConverterContainerId containerId,
List<ConverterId> filterList,
ConverterFilter filterMode,
List<Type> expectedTypes)
{
var actualTypes = Converters.FilterConverters(containerId, filterList, filterMode);
CollectionAssert.AreEquivalent(expectedTypes, actualTypes);
}
[Test]
public void CommandLine_SuggestCorrectCommands()
{
var expectedOutputTemplate = "The method you're trying to use is deprecated. Try running the following command in the command line:\n{0}";
// case 1
var containerID = ConverterContainerId.BuiltInToURP;
var filterList = new List<ConverterId> { ConverterId.Material, ConverterId.RenderSettings };
Converters.SuggestUpdatedCommand(containerID.ToString(), filterList.ConvertAll(id => id.ToString()), true);
var suggestedCommand = "<path to Unity> -projectPath <path to project> -batchmode -executeMethod UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine --inclusive -container BuiltInToURP -typesFilter Material RenderSettings";
LogAssert.Expect(LogType.Log, String.Format(expectedOutputTemplate, suggestedCommand));
// case 2
containerID = ConverterContainerId.BuiltInToURP2D;
filterList = new List<ConverterId> { };
Converters.SuggestUpdatedCommand(containerID.ToString(), filterList.ConvertAll(id => id.ToString()), false);
suggestedCommand = "<path to Unity> -projectPath <path to project> -batchmode -executeMethod UnityEditor.Rendering.Universal.Converters.RunInBatchModeCmdLine --exclusive -container BuiltInToURP2D";
LogAssert.Expect(LogType.Log, String.Format(expectedOutputTemplate, suggestedCommand));
}
#pragma warning restore CS0618 // Type or member is obsolete
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f857058956905cc46809c39c05d64706
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: df85683b3cef14f6393316a2df3225eb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,153 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class AutodeskInteractiveCutoutMaterialUpgraderTest : MaterialUpgraderTestBase<AutodeskInteractiveUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new AutodeskInteractiveUpgrader("Autodesk Interactive");
}
public AutodeskInteractiveCutoutMaterialUpgraderTest() : base("Autodesk Interactive",
"Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveMasked")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeAutodeskInteractiveMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterial_When_Upgrading_Then_TheShaderUpgradedToAutodeskInteractiveMasked",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveMasked", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAlbedoColorRedAutodeskInteractiveMaterial_When_Upgrading_Then_TheAlbedoColorRemainsRed",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.SetColor("_Color", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialAlphaClipValue_When_Upgrading_Then_TheAlphaClipValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.SetFloat("_Cutoff", 0.3f);
},
verify = material =>
{
Assert.AreEqual(0.3f, material.GetFloat("_OpacityThreshold"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialMetallicValue_When_Upgrading_Then_TheMetallicValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.SetFloat("_Metallic", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialRoughnessValue_When_Upgrading_Then_TheRoughnessValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.SetFloat("_Glossiness", 0.3f);
},
verify = material =>
{
Assert.AreEqual(0.3f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialEmissionColorGreen_When_Upgrading_Then_TheEmissionColorRemainsGreen",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.SetColor("_EmissionColor", Color.green);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
Assert.AreEqual(Color.green, material.GetColor("_EmissionColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialEnableGPUInstancingEnabled_When_Upgrading_Then_TheGPUInstancingRemainsEnabled",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAutodeskInteractiveMaterialEnableGPUInstancingDisabled_When_Upgrading_Then_TheGPUInstancingRemainsDisabled",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // cutout
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,138 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class AutodeskInteractiveFadeMaterialUpgraderTest : MaterialUpgraderTestBase<AutodeskInteractiveUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new AutodeskInteractiveUpgrader("Autodesk Interactive");
}
public AutodeskInteractiveFadeMaterialUpgraderTest() : base("Autodesk Interactive",
"Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveTransparent")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeAutodeskInteractiveMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterial_When_Upgrading_Then_TheShaderUpgradedToAutodeskInteractiveMasked",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveTransparent", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAlbedoColorRedAutodeskInteractiveMaterial_When_Upgrading_Then_TheAlbedoColorRemainsRed",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.SetColor("_Color", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterialMetallicValue_When_Upgrading_Then_TheMetallicValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.SetFloat("_Metallic", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterialRoughnessValue_When_Upgrading_Then_TheRoughnessValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.SetFloat("_Glossiness", 0.3f);
},
verify = material =>
{
Assert.AreEqual(0.3f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterialEmissionColorGreen_When_Upgrading_Then_TheEmissionColorRemainsGreen",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.SetColor("_EmissionColor", Color.green);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
Assert.AreEqual(Color.green, material.GetColor("_EmissionColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterialEnableGPUInstancingEnabled_When_Upgrading_Then_TheGPUInstancingRemainsEnabled",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeAutodeskInteractiveMaterialEnableGPUInstancingDisabled_When_Upgrading_Then_TheGPUInstancingRemainsDisabled",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,138 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class AutodeskInteractiveOpaqueMaterialUpgraderTest : MaterialUpgraderTestBase<AutodeskInteractiveUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new AutodeskInteractiveUpgrader("Autodesk Interactive");
}
public AutodeskInteractiveOpaqueMaterialUpgraderTest() : base("Autodesk Interactive",
"Universal Render Pipeline/Autodesk Interactive/AutodeskInteractive")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeAutodeskInteractiveMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueAutodeskInteractiveMaterial_When_Upgrading_Then_TheShaderUpgradedToAutodeskInteractive",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Autodesk Interactive/AutodeskInteractive", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueAlbedoColorRedAutodeskInteractiveMaterial_When_Upgrading_Then_TheAlbedoColorRemainsRed",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.SetColor("_Color", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueMetallicValue_When_Upgrading_Then_TheMetallicValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.SetFloat("_Metallic", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueRoughnessValue_When_Upgrading_Then_TheRoughnessValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.SetFloat("_Glossiness", 0.3f);
},
verify = material =>
{
Assert.AreEqual(0.3f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionColorGreen_When_Upgrading_Then_TheEmissionColorRemainsGreen",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.SetColor("_EmissionColor", Color.green);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
Assert.AreEqual(Color.green, material.GetColor("_EmissionColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEnableGPUInstancingEnabled_When_Upgrading_Then_TheGPUInstancingRemainsEnabled",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEnableGPUInstancingDisabled_When_Upgrading_Then_TheGPUInstancingRemainsDisabled",
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // opaque
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,138 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class AutodeskInteractiveTransparentMaterialUpgraderTest : MaterialUpgraderTestBase<AutodeskInteractiveUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new AutodeskInteractiveUpgrader("Autodesk Interactive");
}
public AutodeskInteractiveTransparentMaterialUpgraderTest() : base("Autodesk Interactive",
"Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveTransparent")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeAutodeskInteractiveMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterial_When_Upgrading_Then_TheShaderUpgradedToAutodeskInteractiveMasked",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Autodesk Interactive/AutodeskInteractiveTransparent", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAlbedoColorRedAutodeskInteractiveMaterial_When_Upgrading_Then_TheAlbedoColorRemainsRed",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.SetColor("_Color", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterialMetallicValue_When_Upgrading_Then_TheMetallicValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.SetFloat("_Metallic", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterialRoughnessValue_When_Upgrading_Then_TheRoughnessValueRemainsTheSame",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.SetFloat("_Glossiness", 0.3f);
},
verify = material =>
{
Assert.AreEqual(0.3f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterialEmissionColorGreen_When_Upgrading_Then_TheEmissionColorRemainsGreen",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.SetColor("_EmissionColor", Color.green);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
Assert.AreEqual(Color.green, material.GetColor("_EmissionColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterialEnableGPUInstancingEnabled_When_Upgrading_Then_TheGPUInstancingRemainsEnabled",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentAutodeskInteractiveMaterialEnableGPUInstancingDisabled_When_Upgrading_Then_TheGPUInstancingRemainsDisabled",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); // transparent
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,93 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
abstract class MaterialUpgraderTestBase<T> where T : MaterialUpgrader
{
protected T m_Upgrader;
protected Material m_Material;
protected string m_OldShaderPath;
protected string m_NewShaderPath;
protected MaterialUpgraderTestBase(string oldShaderPath, string newShaderPath)
{
m_OldShaderPath = oldShaderPath;
m_NewShaderPath = newShaderPath;
}
[OneTimeSetUp]
public abstract void OneTimeSetUp();
[SetUp]
public void Setup()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset == null)
Assert.Ignore("Project without URP. Skipping test");
var shader = Shader.Find(m_OldShaderPath);
Assume.That(shader, Is.Not.Null, $"Shader '{m_OldShaderPath}' not found.");
m_Material = new Material(shader);
}
[TearDown]
public void TearDown()
{
if (m_Material != null)
{
UnityEngine.Object.DestroyImmediate(m_Material);
m_Material = null;
}
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
m_Upgrader = null;
}
public class MaterialUpgradeTestCase
{
public string name;
public Action<Material> setup;
public Action<Material> verify;
public bool ignore;
public string ignoreReason;
public override string ToString() => name;
}
protected void UpgradeMaterial(MaterialUpgradeTestCase testCase)
{
if (testCase.ignore)
{
Assert.Ignore(testCase.ignoreReason ?? "Test case ignored.");
}
Assume.That(testCase.setup, Is.Not.Null, $"Test case '{testCase.name}' has a null setup Action.");
Assume.That(testCase.verify, Is.Not.Null, $"Test case '{testCase.name}' has a null verify Action.");
// Arrange
var material = m_Material;
testCase.setup(material);
// Act
m_Upgrader.Upgrade(material, MaterialUpgrader.UpgradeFlags.None);
//Assert common
Assert.AreEqual(m_NewShaderPath, material.shader.name, $"Shader mismatch in case: {testCase.name}");
//Assert specific
testCase.verify(material);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1b477d4c93a074c40bf5c83b3d7962a4
@@ -0,0 +1,557 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class ParticleMaterialUpgraderTestUnlit : MaterialUpgraderTestBase<ParticleUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new ParticleUpgrader("Particles/Standard Unlit");
}
public ParticleMaterialUpgraderTestUnlit() : base("Particles/Standard Unlit", "Universal Render Pipeline/Particles/Unlit")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeParticleStandardUnlitMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_AlphaCutOffParticleStandardUnlit_When_Upgrading_Then_TheMaterialURPTransparentWithAlphaCutOffPreserve",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // Cutout to enable Alpha Cutoff slider
},
verify = material =>
{
Assert.AreEqual(1.0f, material.GetFloat("_AlphaClip"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AlphaCutOffValueParticleStandardUnlit_When_Upgrading_Then_TheMaterialURPTransparentWithAlphaCutOffValuePreserve",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // Cutout to enable Alpha Cutoff slider
material.SetFloat("_Cutoff", 0.25f); // Alpha Cutoff enabled
},
verify = material =>
{
Assert.AreEqual(0.25f, material.GetFloat("_Cutoff")); // Alpha Cutoff
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueFlipBookFrameBlendingParticleStandardUnlit_When_Upgrading_Then_OpaqueTheMaterialURPFlipBookBlendingEnabled",
setup = material =>
{
//enable flipbook frame blending
material.SetFloat("_FlipbookMode", 1.0f);
},
verify = material =>
{
//check flipbook blending is enabled
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OldParticleShaderNameStandardUnlit_WhenUpgrading_Then_TheShaderURPKeepParticleUnlitName",
setup = material =>
{
//check old shader name
Assert.AreEqual("Particles/Standard Unlit", material.shader.name);
},
verify = material =>
{
//check new shader name
Assert.AreEqual("Universal Render Pipeline/Particles/Unlit", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueTwoSidedParticleStandardUnlit_WhenUpgrading_Then_OpaqueTheMaterialURPTwoSidedEnabled",
setup = material =>
{
//enable two sided
material.SetFloat("_Cull", 0.0f); // Two Sided enabled//
},
verify = material =>
{
//check two sided is enabled
Assert.AreEqual(0.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueTwoSidedParticleStandardUnlit_WhenUpgrading_Then_OpaqueTheMaterialURPTwoSidedDisabled",
setup = material =>
{
//enable two sided
material.SetFloat("_Cull", 1.0f); // Two Sided disabled//
},
verify = material =>
{
//check two sided is disabled
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_MaterialNameParticleStandardUnlit_WhenUpgrading_Then_TheMaterialURPParticleUnlitPreserve",
setup = material =>
{
//set material name
material.name = "MaterialParticleUnlit";
},
verify = material =>
{
//check material name is preserved
Assert.AreEqual("MaterialParticleUnlit", material.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_EmissionEnabledParticleStandardUnlit_WhenUpgrading_Then_TheEmissionParticleURPUnlitPreserve",
setup = material =>
{
//enable emission keyword
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check emission is enabled
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_EmissionDisabledParticleStandardUnlit_WhenUpgrading_Then_TheEmissionParticleURPUnlitPreserve",
setup = material =>
{
//disable emission keyword
CoreUtils.SetKeyword(material, "_EMISSION", false);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.None;
},
verify = material =>
{
//check emission is disabled
Assert.IsFalse(material.IsKeywordEnabled("_EMISSION"));
// Should be set to EmissiveIsBlack to match BiRP behavior when emission unchecked
Assert.AreEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_EmissionRedColorParticleStandardUnlit_WhenUpgrading_Then_TheEmissionRedColorParticleURPUnlitPreserve",
setup = material =>
{
//enable emission keyword
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.SetColor("_EmissionColor", Color.red);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check emission is enabled
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
//check emission color is red
Assert.AreEqual(Color.red, material.GetColor("_EmissionColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueParticleStandardUnlit_WhenUpgrading_Then_TheOpaqueURPParticleUnlit",
setup = material =>
{
//set material to opaque
material.SetFloat("_Mode", 0.0f); // Opaque
},
verify = material =>
{
//check material is opaque
Assert.AreEqual(0.0f, material.GetFloat("_Surface")); // Surface type
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_TilingSetToStandardParticleUnlitMaterial_When_Upgrading_Then_TheMaterialURPTilingParticleUnlitPreserved",
setup = material =>
{
material.SetTextureScale("_MainTex", new Vector2(2.0f, 2.0f)); // Set tiling
},
verify = material =>
{
Assert.AreEqual(new Vector2(2.0f, 2.0f), material.GetTextureScale("_BaseMap")); // Check that tiling is preserved after upgrade
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_BaseMapColorSetToRedStandardParticleUnlitMaterial_When_Upgradin_Then_TheMaterialURPBaseMapColorRedPreserve",
setup = material =>
{
//set base map color to red
material.SetColor("_Color", Color.red);
},
verify = material =>
{
//check base map color is red
Assert.AreEqual(Color.red, material.GetColor("_BaseColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_RenderQueueFromBackgroundStandardParticleUnlitMaterial_When_Upgrading_Then_TheMaterialURPRenderQueueFromBackgroundParticleUnlitPreserve",
ignore = true,
ignoreReason = "Fails, does not preserve set render queue",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set custom render queue from shader, should be 1000
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Background;
//material.renderQueue = 2555;
},
verify = material =>
{
//check render queue from shader is preserved
//Assert.AreEqual(2555, material.renderQueue);
Assert.AreEqual((int)UnityEngine.Rendering.RenderQueue.Background, material.renderQueue);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeMultiplyStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueMultiplyPreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to multiply
material.SetFloat("_ColorMode", 0.0f); // Multiply
},
verify = material =>
{
//check color mode is multiply
Assert.AreEqual(0.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeAdditiveStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueAdditivePreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to additive
material.SetFloat("_ColorMode", 1.0f); // Additive
},
verify = material =>
{
//check color mode is additive
Assert.AreEqual(1.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeSubtractiveStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueSubtractivePreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to subtractive
material.SetFloat("_ColorMode", 2.0f); // Subtractive
},
verify = material =>
{
//check color mode is subtractive
Assert.AreEqual(2.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeOverlayStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueOverlayPreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to overlay
material.SetFloat("_ColorMode", 3.0f); // Overlay
},
verify = material =>
{
//check color mode is overlay
Assert.AreEqual(3.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeColorStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueColorPreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to color
material.SetFloat("_ColorMode", 4.0f); // Color
},
verify = material =>
{
//check color mode is color
Assert.AreEqual(4.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueColorModeDifferenceStandardParticleUnlitMaterial_When_Upgrading_Then_TheURPParticleUnlitOpaqueDifferencePreserve",
setup = material =>
{
//set the material to opaque first
material.SetFloat("_Mode", 0.0f); // Opaque
//set color mode to difference
material.SetFloat("_ColorMode", 5.0f); // Difference
},
verify = material =>
{
//check color mode is difference
Assert.AreEqual(5.0f, material.GetFloat("_ColorMode"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeSoftParticleStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_TheFadeSoftParticleURPParticleUnlitMaterialPreserve",
setup = material =>
{
//set the material to fade
material.SetFloat("_Mode", 2.0f); // Fade
//enable soft particles checkbox
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles enabled
},
verify = material =>
{
//check soft particles is enabled
Assert.AreEqual(1.0f, material.GetFloat("_SoftParticlesEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CameraFadingTransarentStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_CameraFadingTransparentURPParticleUnlitMaterialPreserve",
setup = material =>
{
//set the material to Transparent
material.SetFloat("_Mode", 3.0f); // Transparent
//enable camera fading checkbox
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading enabled
},
verify = material =>
{
//check camera fading is enabled
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_DistortionTransarentStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_DistortionTransparentURPParticleUnlitMaterialPreserve",
setup = material =>
{
//set the material to Transparent
material.SetFloat("_Mode", 3.0f); // Transparent
//enable distortion checkbox
material.SetFloat("_DistortionEnabled", 1.0f); // Distortion enabled
},
verify = material =>
{
//check distortion is enabled
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentModeStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_TransparentModeURPParticleUnlitMaterialPreserve",
setup = material =>
{
//set the material to Transparent
material.SetFloat("_Mode", 3.0f); // Transparent
},
verify = material =>
{
//check material is Transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeModeStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_TransparentModeURPParticleUnlitMaterialConverted",
setup = material =>
{
//set the material to Fade
material.SetFloat("_Mode", 2.0f); // Fade
},
verify = material =>
{
//check material is Transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveRenderingModeStandardParticleUnlitMaterialEnabled_When_Upgrading_Then_AdditiveModeURPParticleUnlitMaterialPreserve",
setup = material =>
{
//set the material to Additive
material.SetFloat("_Mode", 4.0f); // Additive
},
verify = material =>
{
//check material is Additive
Assert.AreEqual(2.0f, material.GetFloat("_Blend"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_RenderingModeSubtractiveStandardParticleUnlitMaterial_When_Upgrading_Then_SurfaceTypeURPParticleUnlitMaterialDropdownNotBlank",
setup = material =>
{
//set the material to Subtractive
material.SetFloat("_Mode", 5.0f); // Subtractive
},
verify = material =>
{
//check material surface type is transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
//check color mode is subtractive
Assert.AreEqual(2.0f, material.GetFloat("_ColorMode"));
//check blend mode is alpha
Assert.AreEqual(0.0f, material.GetFloat("_Blend"));
//check that the _COLORADDSUBDIFF_ON keyword is enabled
Assert.IsTrue(material.IsKeywordEnabled("_COLORADDSUBDIFF_ON"));
//check that _BaseColorAddSubDiff is set correctly for subtractive mode
Assert.AreEqual(new Vector4(-1.0f, 0.0f, 0.0f, 0.0f), material.GetVector("_BaseColorAddSubDiff"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionKeywordEnabledStandardUnlit_WhenUpgrading_Then_TheOpaqueURPParticleUnlitPreserveEmissionKeyword",
setup = material =>
{
//set the material to opaque with emission keyword enabled
material.SetFloat("_Mode", 0.0f); // Opaque
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission keyword is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.None, material.globalIlluminationFlags);
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionDisabledStandardUnlit_WhenUpgrading_Then_TheOpaqueURPParticleUnlitEmissionRemainsDisabled",
setup = material =>
{
//set the material to opaque without emission enabled (no keyword, None flags)
material.SetFloat("_Mode", 0.0f); // Opaque
CoreUtils.SetKeyword(material, "_EMISSION", false);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.None;
},
verify = material =>
{
//check the material emission remains disabled
Assert.IsFalse(material.IsKeywordEnabled("_EMISSION"));
// Should be set to EmissiveIsBlack to match BiRP behavior when emission unchecked
Assert.AreEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentEmissionKeywordEnabledStandardUnlit_WhenUpgrading_Then_TheTransparentURPParticleUnlitPreserveEmissionKeyword",
setup = material =>
{
//set the material to transparent with emission keyword enabled
material.SetFloat("_Mode", 3.0f); // Transparent
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission keyword is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.None, material.globalIlluminationFlags);
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
}
}
@@ -0,0 +1,847 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class ParticleSurfaceMaterialUpgraderTest : MaterialUpgraderTestBase<ParticleUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new ParticleUpgrader("Particles/Standard Surface");
}
public ParticleSurfaceMaterialUpgraderTest() : base("Particles/Standard Surface", "Universal Render Pipeline/Particles/Lit")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeParticleStandardUnlitMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueParticleStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserve",
setup = material =>
{
//set the material to opaque
material.SetFloat("_Mode", 0.0f); // Opaque
},
verify = material =>
{
//check the material is still opaque
Assert.AreEqual(0.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutParticleStandardSurface_WhenUpgrading_Then_TheCutoutURPParticleLitGoesOpaque",
setup = material =>
{
//set the material to cutout mode
material.SetFloat("_Mode", 1.0f); // Cutout
},
verify = material =>
{
//check the material is opaque
Assert.AreEqual(0.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeParticleStandardSurface_WhenUpgrading_Then_TheFadeURPParticleLitGoesTransparent",
setup = material =>
{
//set the material to fade mode
material.SetFloat("_Mode", 2.0f); // Fade
},
verify = material =>
{
//check the material is transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentParticleStandardSurface_WhenUpgrading_Then_TheTransparentURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent mode
material.SetFloat("_Mode", 3.0f); // Transparent
},
verify = material =>
{
//check the material is still transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveParticleStandardSurface_WhenUpgrading_Then_TheAdditiveURPParticleLitGoesTransparent",
setup = material =>
{
//set the material to additive mode
material.SetFloat("_Mode", 4.0f); // Additive
},
verify = material =>
{
//check the material is transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveParticleStandardSurface_WhenUpgrading_Then_TheSubtractiveURPParticleLitSurfaceIsNotEmpty",
setup = material =>
{
//set the material to subtractive mode
material.SetFloat("_Mode", 5.0f); // Subtractive
},
verify = material =>
{
//check material surface type is transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
//check color mode is subtractive
Assert.AreEqual(2.0f, material.GetFloat("_ColorMode"));
//check blend mode is alpha
Assert.AreEqual(0.0f, material.GetFloat("_Blend"));
//check that the _COLORADDSUBDIFF_ON keyword is enabled
Assert.IsTrue(material.IsKeywordEnabled("_COLORADDSUBDIFF_ON"));
//check that _BaseColorAddSubDiff is set correctly for subtractive mode
Assert.AreEqual(new Vector4(-1.0f, 0.0f, 0.0f, 0.0f), material.GetVector("_BaseColorAddSubDiff"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateParticleStandardSurface_WhenUpgrading_Then_TheModulateURPParticleLitSurfaceGoesTransparent",
setup = material =>
{
//set the material to modulate mode
material.SetFloat("_Mode", 6.0f); // Modulate
},
verify = material =>
{
//check the material is transparent
Assert.AreEqual(1.0f, material.GetFloat("_Surface"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheOpaqueFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to opaque with flipbook frame blending
material.SetFloat("_Mode", 0.0f); // Opaque
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueTwoSidedStandardSurface_WhenUpgrading_Then_TheOpaqueTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to opaque and two sided
material.SetFloat("_Mode", 0.0f); // Opaque
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueMetallicValueStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserveMetallicValue",
setup = material =>
{
//set the material to opaque with metallic value
material.SetFloat("_Mode", 0.0f); // Opaque
material.SetFloat("_Metallic", 0.7f); // Metallic Value
},
verify = material =>
{
//check the material metallic value is preserved
Assert.AreEqual(0.7f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueSmoothnessValueStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserveSmoothnessValue",
setup = material =>
{
//set the material to opaque with smoothness value
material.SetFloat("_Mode", 0.0f); // Opaque
material.SetFloat("_Glossiness", 0.3f); // Smoothness Value
},
verify = material =>
{
//check the material smoothness value is preserved
Assert.AreEqual(0.3f, material.GetFloat("_Smoothness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionCheckboxEnabledStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserveEmissionCheckbox",
setup = material =>
{
//set the material to opaque with emission enabled
material.SetFloat("_Mode", 0.0f); // Opaque
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission checkbox is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueAlbedoColorRedStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserveAlbedoColorRed",
setup = material =>
{
//set the material to opaque with albedo color red
material.SetFloat("_Mode", 0.0f); // Opaque
material.SetColor("_Color", Color.red);
},
verify = material =>
{
//check the material albedo color is preserved as red
Assert.AreEqual(Color.red, material.GetColor("_BaseColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutAlphaCutoffValueStandardSurface_WhenUpgrading_Then_TheCutoutAlphaCutoffValueURPParticleLitPreserve",
setup = material =>
{
//set the material to cutout with alpha cutoff value
material.SetFloat("_Mode", 1.0f); // Cutout
material.SetFloat("_Cutoff", 0.2f); // Alpha Cutoff Value
},
verify = material =>
{
//check the material alpha cutoff value is preserved
Assert.AreEqual(0.2f, material.GetFloat("_Cutoff"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_CutoutStandardSurface_WhenUpgrading_Then_TheCutoutAlphaClippingCheckboxURPParticleLitEnabled",
setup = material =>
{
//set the material to cutout mode
material.SetFloat("_Mode", 1.0f); // Cutout
},
verify = material =>
{
//check the material alpha Clipping checkbox is enabled
Assert.AreEqual(1f, material.GetFloat("_AlphaClip"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheFadeFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with flipbook frame blending
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeTwoSidedStandardSurface_WhenUpgrading_Then_TheFadeTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to fade and two sided
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeSoftParticlesStandardSurface_WhenUpgrading_Then_TheFadeSoftParticlesURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with soft particles
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
},
verify = material =>
{
//check the material soft particles is preserved
Assert.AreEqual(1.0f, material.GetFloat("_SoftParticlesEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeSoftParticleNearValueStandardSurface_WhenUpgrading_Then_TheFadeSoftParticleNearValueURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with soft particles and set near value
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
material.SetFloat("_SoftParticlesNearFadeDistance", 0.1f); // Soft Particle Near
},
verify = material =>
{
//check the material soft particle near value is preserved
Assert.AreEqual(0.1f, material.GetFloat("_SoftParticlesNearFadeDistance"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeSoftParticleFarValueStandardSurface_WhenUpgrading_Then_TheFadeSoftParticleFarValueURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with soft particles and set far value
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
material.SetFloat("_SoftParticlesFarFadeDistance", 0.7f); // Soft Particle Far
},
verify = material =>
{
//check the material soft particle far value is preserved
Assert.AreEqual(0.7f, material.GetFloat("_SoftParticlesFarFadeDistance"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeCameraFadingStandardSurface_WhenUpgrading_Then_TheFadeCameraFadingURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with camera fading
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading
},
verify = material =>
{
//check the material camera fading is preserved
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeCameraDistortionStandardSurface_WhenUpgrading_Then_TheFadeCameraDistortionURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with camera distortion
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
},
verify = material =>
{
//check the material camera distortion is preserved
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeDistortionStrengthValueStandardSurface_WhenUpgrading_Then_TheFadeDistortionStrengthValueURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with camera distortion and set distortion strength value
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
material.SetFloat("_DistortionStrength", 2f); // Distortion Strength
},
verify = material =>
{
//check the material distortion strength value is preserved
Assert.AreEqual(2f, material.GetFloat("_DistortionStrength"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_FadeDistortionBlendValueStandardSurface_WhenUpgrading_Then_TheFadeDistortionBlendValueURPParticleLitPreserve",
setup = material =>
{
//set the material to fade with camera distortion and set distortion blend value
material.SetFloat("_Mode", 2.0f); // Fade
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
material.SetFloat("_DistortionBlend", 0.1f); // Distortion Blend
},
verify = material =>
{
//check the material distortion blend value is preserved
Assert.AreEqual(0.1f, material.GetFloat("_DistortionBlend"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheTransparentFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent with flipbook frame blending
material.SetFloat("_Mode", 3.0f); // Transparent
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentTwoSidedStandardSurface_WhenUpgrading_Then_TheTransparentTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent and two sided
material.SetFloat("_Mode", 3.0f); // Transparent
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentCameraFadingStandardSurface_WhenUpgrading_Then_TheTransparentCameraFadingURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent with camera fading
material.SetFloat("_Mode", 3.0f); // Transparent
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading
},
verify = material =>
{
//check the material camera fading is preserved
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentCameraDistortionStandardSurface_WhenUpgrading_Then_TheTransparentCameraDistortionURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent with camera distortion
material.SetFloat("_Mode", 3.0f); // Transparent
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
},
verify = material =>
{
//check the material camera distortion is preserved
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentEmissionEnabledStandardSurface_WhenUpgrading_Then_TheTransparentEmissionEnabledURPParticleLitPreserve",
setup = material =>
{
//set the material to transparent with emission enabled
material.SetFloat("_Mode", 3.0f); // Transparent
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission enabled is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheAdditiveFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to additive with flipbook frame blending
material.SetFloat("_Mode", 4.0f); // Additive
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveTwoSidedStandardSurface_WhenUpgrading_Then_TheAdditiveTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to additive and two sided
material.SetFloat("_Mode", 4.0f); // Additive
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveSoftParticlesStandardSurface_WhenUpgrading_Then_TheAdditiveSoftParticlesURPParticleLitPreserve",
setup = material =>
{
//set the material to additive with soft particles
material.SetFloat("_Mode", 4.0f); // Additive
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
},
verify = material =>
{
//check the material soft particles is preserved
Assert.AreEqual(1.0f, material.GetFloat("_SoftParticlesEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveCameraFadingStandardSurface_WhenUpgrading_Then_TheAdditiveCameraFadingURPParticleLitPreserve",
setup = material =>
{
//set the material to additive with camera fading
material.SetFloat("_Mode", 4.0f); // Additive
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading
},
verify = material =>
{
//check the material camera fading is preserved
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_AdditiveDistortionEnabledStandardSurface_WhenUpgrading_Then_TheAdditiveDistortionEnabledURPParticleLitPreserve",
setup = material =>
{
//set the material to additive with camera distortion
material.SetFloat("_Mode", 4.0f); // Additive
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
},
verify = material =>
{
//check the material camera distortion is preserved
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheSubtractiveFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to subtractive with flipbook frame blending
material.SetFloat("_Mode", 5.0f); // Subtractive
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveTwoSidedStandardSurface_WhenUpgrading_Then_TheSubtractiveTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to subtractive and two sided
material.SetFloat("_Mode", 5.0f); // Subtractive
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveSoftParticlesStandardSurface_WhenUpgrading_Then_TheSubtractiveSoftParticlesURPParticleLitPreserve",
setup = material =>
{
//set the material to subtractive with soft particles
material.SetFloat("_Mode", 5.0f); // Subtractive
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
},
verify = material =>
{
//check the material soft particles is preserved
Assert.AreEqual(1.0f, material.GetFloat("_SoftParticlesEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveCameraFadingStandardSurface_WhenUpgrading_Then_TheSubtractiveCameraFadingURPParticleLitPreserve",
setup = material =>
{
//set the material to subtractive with camera fading
material.SetFloat("_Mode", 5.0f); // Subtractive
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading
},
verify = material =>
{
//check the material camera fading is preserved
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SubtractiveDistortionEnabledStandardSurface_WhenUpgrading_Then_TheSubtractiveDistortionEnabledURPParticleLitPreserve",
setup = material =>
{
//set the material to subtractive with camera distortion
material.SetFloat("_Mode", 5.0f); // Subtractive
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
},
verify = material =>
{
//check the material camera distortion is preserved
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateFlipBookFrameBlendingStandardSurface_WhenUpgrading_Then_TheModulateFlipBookFrameBlendingURPParticleLitPreserve",
setup = material =>
{
//set the material to modulate with flipbook frame blending
material.SetFloat("_Mode", 6.0f); // Modulate
material.SetFloat("_FlipbookMode", 1.0f); // Frame Blending
},
verify = material =>
{
//check the material flipbook mode is still frame blending
Assert.AreEqual(1.0f, material.GetFloat("_FlipbookBlending"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateTwoSidedStandardSurface_WhenUpgrading_Then_TheModulateTwoSidedURPParticleLitPreserve",
setup = material =>
{
//set the material to modulate and two sided
material.SetFloat("_Mode", 6.0f); // Modulate
material.SetFloat("_Cull", 1.0f); // Two Sided
},
verify = material =>
{
//check the material is still two sided
Assert.AreEqual(1.0f, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateSoftParticlesStandardSurface_WhenUpgrading_Then_TheModulateSoftParticlesURPParticleLitPreserve",
setup = material =>
{
//set the material to modulate with soft particles
material.SetFloat("_Mode", 6.0f); // Modulate
material.SetFloat("_SoftParticlesEnabled", 1.0f); // Soft Particles
},
verify = material =>
{
//check the material soft particles is preserved
Assert.AreEqual(1.0f, material.GetFloat("_SoftParticlesEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateCameraFadingStandardSurface_WhenUpgrading_Then_TheModulateCameraFadingURPParticleLitPreserve",
setup = material =>
{
//set the material to modulate with camera fading
material.SetFloat("_Mode", 6.0f); // Modulate
material.SetFloat("_CameraFadingEnabled", 1.0f); // Camera Fading
},
verify = material =>
{
//check the material camera fading is preserved
Assert.AreEqual(1.0f, material.GetFloat("_CameraFadingEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_ModulateDistortionEnabledStandardSurface_WhenUpgrading_Then_TheModulateDistortionEnabledURPParticleLitPreserve",
setup = material =>
{
//set the material to modulate with camera distortion
material.SetFloat("_Mode", 6.0f); // Modulate
material.SetFloat("_DistortionEnabled", 1.0f); // Camera Distortion
},
verify = material =>
{
//check the material camera distortion is preserved
Assert.AreEqual(1.0f, material.GetFloat("_DistortionEnabled"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionKeywordEnabledStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitPreserveEmissionKeyword",
setup = material =>
{
//set the material to opaque with emission keyword enabled
material.SetFloat("_Mode", 0.0f); // Opaque
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission keyword is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.None, material.globalIlluminationFlags);
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_OpaqueEmissionDisabledStandardSurface_WhenUpgrading_Then_TheOpaqueURPParticleLitEmissionRemainsDisabled",
setup = material =>
{
//set the material to opaque without emission enabled (no keyword, None flags)
material.SetFloat("_Mode", 0.0f); // Opaque
CoreUtils.SetKeyword(material, "_EMISSION", false);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.None;
},
verify = material =>
{
//check the material emission remains disabled
Assert.IsFalse(material.IsKeywordEnabled("_EMISSION"));
// Should be set to EmissiveIsBlack to match BiRP behavior when emission unchecked
Assert.AreEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TransparentEmissionKeywordEnabledStandardSurface_WhenUpgrading_Then_TheTransparentURPParticleLitPreserveEmissionKeyword",
setup = material =>
{
//set the material to transparent with emission keyword enabled
material.SetFloat("_Mode", 3.0f); // Transparent
CoreUtils.SetKeyword(material, "_EMISSION", true);
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
},
verify = material =>
{
//check the material emission keyword is preserved
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.None, material.globalIlluminationFlags);
Assert.AreNotEqual(MaterialGlobalIlluminationFlags.EmissiveIsBlack, material.globalIlluminationFlags);
}
};
}
}
@@ -0,0 +1,245 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class SpeedTree7MaterialUpgraderTest : MaterialUpgraderTestBase<SpeedTreeUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new SpeedTreeUpgrader("Nature/SpeedTree");
}
public SpeedTree7MaterialUpgraderTest() : base("Nature/SpeedTree",
"Universal Render Pipeline/Nature/SpeedTree7")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeSpeedTree7Material(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree7Material_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7",
setup = material =>
{
// No specific setup is needed for this test case, as we are only verifying that the shader is upgraded correctly.
},
verify = material =>
{
// Verify that the shader has been upgraded to the expected SpeedTree7 shader.
Assert.AreEqual("Universal Render Pipeline/Nature/SpeedTree7", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialHueVariationColorGreen_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7HueVariationColorGreenStay",
setup = material =>
{
// Set the HueVariationColor property to Green before upgrading.
material.SetColor("_HueVariation", Color.green);
},
verify = material =>
{
// Verify that the HueVariationColor property is still set to Green after upgrading.
Assert.AreEqual(Color.green, material.GetColor("_HueVariation"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialColorRed_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7ColorRedStay",
setup = material =>
{
// Set the Color property to Red before upgrading.
material.SetColor("_Color", Color.red);
},
verify = material =>
{
// Verify that the Color property is still set to Red after upgrading.
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialCullBack_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7CullBackStay",
setup = material =>
{
// Set the Cull property to Back before upgrading.
material.SetFloat("_Cull", 2);
},
verify = material =>
{
// Verify that the Cull property is still set to Back after upgrading.
Assert.AreEqual(2, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialCullOff_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7CullOffStay",
setup = material =>
{
// Set the Cull property to Off before upgrading.
material.SetFloat("_Cull", 0);
},
verify = material =>
{
// Verify that the Cull property is still set to Off after upgrading.
Assert.AreEqual(0, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialCullFront_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7CullFrontStay",
setup = material =>
{
// Set the Cull property to Front before upgrading.
material.SetFloat("_Cull", 1);
},
verify = material =>
{
// Verify that the Cull property is still set to Front after upgrading.
Assert.AreEqual(1, material.GetFloat("_Cull"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityNone_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityNoneStay",
setup = material =>
{
// Set the WindQuality property to None before upgrading.
material.SetFloat("_WindQuality", 0);
},
verify = material =>
{
// Verify that the WindQuality property is still set to None after upgrading.
Assert.AreEqual(0, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityFastest_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityFastestStay",
setup = material =>
{
// Set the WindQuality property to Fastest before upgrading.
material.SetFloat("_WindQuality", 1);
},
verify = material =>
{
// Verify that the WindQuality property is still set to Fastest after upgrading.
Assert.AreEqual(1, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityFast_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityFastStay",
setup = material =>
{
// Set the WindQuality property to Fast before upgrading.
material.SetFloat("_WindQuality", 2);
},
verify = material =>
{
// Verify that the WindQuality property is still set to Fast after upgrading.
Assert.AreEqual(2, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityBetter_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityBetterStay",
setup = material =>
{
// Set the WindQuality property to Better before upgrading.
material.SetFloat("_WindQuality", 3);
},
verify = material =>
{
// Verify that the WindQuality property is still set to Better after upgrading.
Assert.AreEqual(3, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityBest_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityBestStay",
setup = material =>
{
// Set the WindQuality property to Best before upgrading.
material.SetFloat("_WindQuality", 4);
},
verify = material =>
{
// Verify that the WindQuality property is still set to Best after upgrading.
Assert.AreEqual(4, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialWindQualityPalm_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7WindQualityPalmStay",
setup = material =>
{
// Set the WindQuality property to Palm before upgrading.
material.SetFloat("_WindQuality", 5);
},
verify = material =>
{
// Verify that the WindQuality property is still set to Palm after upgrading.
Assert.AreEqual(5, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialGPUInstancingOn_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7GPUInstancingOnStay",
setup = material =>
{
// Enable GPU Instancing before upgrading.
material.enableInstancing = true;
},
verify = material =>
{
// Verify that GPU Instancing is still enabled after upgrading.
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree7MaterialGPUInstancingOff_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree7GPUInstancingOffStay",
setup = material =>
{
// Disable GPU Instancing before upgrading.
material.enableInstancing = false;
},
verify = material =>
{
// Verify that GPU Instancing is still disabled after upgrading.
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,320 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class SpeedTree8MaterialUpgraderTest : MaterialUpgraderTestBase<UniversalSpeedTree8Upgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new UniversalSpeedTree8Upgrader("Nature/SpeedTree8");
}
public SpeedTree8MaterialUpgraderTest() : base("Nature/SpeedTree8",
"Universal Render Pipeline/Nature/SpeedTree8_PBRLit")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeSpeedTree8Material(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8Material_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLit",
setup = material =>
{
// No specific setup is needed for this test case, as we are only verifying that the shader is upgraded correctly.
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Nature/SpeedTree8_PBRLit", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialColorRed_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitColorRedRemains",
setup = material =>
{
// Set the Color property to Red before upgrading.
material.SetColor("_Color", Color.red);
},
verify = material =>
{
// Verify that the Color property is still set to Red after upgrading.
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialSmoothness01f_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitSmoothness01fRemains",
setup = material =>
{
material.SetFloat("_Glossiness", 0.1f);
},
verify = material =>
{
Assert.AreEqual(0.1f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialMetallic01_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitMetallic01Remains",
setup = material =>
{
material.SetFloat("_Metallic", 0.1f);
},
verify = material =>
{
Assert.AreEqual(0.1f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialSubsurfaceColorBlue_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitSubsurfaceColorBlueRemains",
setup = material =>
{
//set the subsurface color to blue
material.SetColor("_SubsurfaceColor", Color.blue);
},
verify = material =>
{
//verify that the subsurface color is still set to blue after upgrading
Assert.AreEqual(Color.blue, material.GetColor("_SubsurfaceColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityNone_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityNoneRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityFastest_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityFastestRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityFast_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityFastRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 2f);
},
verify = material =>
{
Assert.AreEqual(2f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityBetter_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityBetterRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 3f);
},
verify = material =>
{
Assert.AreEqual(3f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityBest_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityBestRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 4f);
},
verify = material =>
{
Assert.AreEqual(4f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialWindQualityPalm_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitWindQualityPalmRemains",
setup = material =>
{
material.SetFloat("_WindQuality", 5f);
},
verify = material =>
{
Assert.AreEqual(5f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialHueVariationEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitHueVariationEnabledRemains",
setup = material =>
{
material.EnableKeyword("EFFECT_HUE_VARIATION");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_HueVariationKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialHueVariationDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitHueVariationDisabledRemains",
setup = material =>
{
material.DisableKeyword("EFFECT_HUE_VARIATION");
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_HueVariationKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialHueVariationColorRed_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitHueVariationColorRedRemains",
setup = material =>
{
//set the hue variation color to red
material.SetColor("_HueVariationColor", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_HueVariationColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialSubsurfaceEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitSubsurfaceEnabledRemains",
setup = material =>
{
material.EnableKeyword("EFFECT_SUBSURFACE");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_SubsurfaceKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialSubsurfaceDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitSubsurfaceDisabledRemains",
setup = material =>
{
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_SubsurfaceKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialBillboardEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitBillboardEnabledRemains",
setup = material =>
{
material.SetFloat("_BillboardKwToggle", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("EFFECT_BILLBOARD"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree8MaterialBillboardDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitBillboardDisabledRemains",
setup = material =>
{
material.SetFloat("_BillboardKwToggle", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("EFFECT_BILLBOARD"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree8MaterialGPUInstancingOn_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitGPUInstancingOnRemains",
setup = material =>
{
// Enable GPU Instancing before upgrading.
material.enableInstancing = true;
},
verify = material =>
{
// Verify that GPU Instancing is still enabled after upgrading.
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTree8MaterialGPUInstancingOff_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree8_PBRLitGPUInstancingOffRemains",
setup = material =>
{
// Disable GPU Instancing before upgrading.
material.enableInstancing = false;
},
verify = material =>
{
// Verify that GPU Instancing is still disabled after upgrading.
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,374 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class SpeedTree9MaterialUpgraderTest : MaterialUpgraderTestBase<UniversalSpeedTree9Upgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new UniversalSpeedTree9Upgrader("Nature/SpeedTree9");
}
public SpeedTree9MaterialUpgraderTest() : base("Nature/SpeedTree9",
"Universal Render Pipeline/Nature/SpeedTree9_URP")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeSpeedTree9Material(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9Material_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URP",
setup = material =>
{
// No specific setup is needed for this test case, as we are only verifying that the shader is upgraded correctly.
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Nature/SpeedTree9_URP", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialColorRed_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPColorRed",
setup = material =>
{
// set _ColorTint to red
material.SetColor("_ColorTint", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSmoothness02f_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPSmoothness02f",
setup = material =>
{
material.SetFloat("_Glossiness", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialMetallic02f_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPMetallic02f",
setup = material =>
{
material.SetFloat("_Metallic", 0.2f);
},
verify = material =>
{
Assert.AreEqual(0.2f, material.GetFloat("_Metallic"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSubsurfaceColorRed_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPSurfaceColorRed",
setup = material =>
{
material.SetColor("_SubsurfaceColor", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_SubsurfaceColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialHueVariationEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_HueVariationEnabled",
setup = material =>
{
material.EnableKeyword("EFFECT_HUE_VARIATION");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_HueVariationKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialHueVariationDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_HueVariationDisabled",
setup = material =>
{
//no need because this is off by default
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_HueVariationKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialHueVariationColorRed_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_HueVariationColorRed",
setup = material =>
{
//enable hue variation checkbox
material.EnableKeyword("EFFECT_HUE_VARIATION");
//set the hue variation color to red
material.SetColor("_HueVariationColor", Color.red);
},
verify = material =>
{
Assert.AreEqual(Color.red, material.GetColor("_HueVariationColor"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_Speedtree9MaterialNormalMapEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_NormalMapEnabled",
setup = material =>
{
material.EnableKeyword("EFFECT_BUMP");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_NormalMapKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialNormalMapDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_NormalMapDisabled",
setup = material =>
{
material.DisableKeyword("EFFECT_BUMP");
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_NormalMapKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSubsurfaceEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPSubsurfaceEnabled",
setup = material =>
{
material.EnableKeyword("EFFECT_SUBSURFACE");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_SubsurfaceKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSubsurfaceDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_URPSubsurfaceDisabled",
setup = material =>
{
//no need to check, because it is off by default
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_SubsurfaceKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBillboardEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_BillboardEnabled",
setup = material =>
{
material.EnableKeyword("EFFECT_BILLBOARD");
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_BillboardKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBillboardDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_BillboardDisabled",
setup = material =>
{
material.DisableKeyword("EFFECT_BILLBOARD");
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_BillboardKwToggle"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSharedMotionEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_MotionEnabled",
setup = material =>
{
material.SetFloat("_WIND_SHARED", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_WIND_SHARED"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialSharedMotionDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_MotionDisabled",
setup = material =>
{
material.SetFloat("_WIND_SHARED", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_WIND_SHARED"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBranch1MotionEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_Branch1MotionEnabled",
setup = material =>
{
material.SetFloat("_WIND_BRANCH1", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_WIND_BRANCH1"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBranch1MotionDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_Branch1MotionDisabled",
setup = material =>
{
material.SetFloat("_WIND_BRANCH1", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_WIND_BRANCH1"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBranch2MotionEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_Branch2MotionEnabled",
setup = material =>
{
material.SetFloat("_WIND_BRANCH2", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_WIND_BRANCH2"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialBranch2MotionDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_Branch2MotionDisabled",
setup = material =>
{
material.SetFloat("_WIND_BRANCH2", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_WIND_BRANCH2"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialRippleMotionEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_RippleMotionEnabled",
setup = material =>
{
material.SetFloat("_WIND_RIPPLE", 1f);
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_WIND_RIPPLE"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialRippleMotionDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_RippleMotionDisabled",
setup = material =>
{
material.SetFloat("_WIND_RIPPLE", 0f);
},
verify = material =>
{
Assert.AreEqual(0f, material.GetFloat("_WIND_RIPPLE"));
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialGPUInstancingEnabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_GPUInstancingEnabled",
setup = material =>
{
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTree9MaterialGPUInstancingDisabled_WhenUpgrading_Then_TheShaderUpgradedToUniversalRenderPipelineSpeedTree9_GPUInstancingDisabled",
setup = material =>
{
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,154 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class SpeedTreeBillboardMaterialUpgraderTest : MaterialUpgraderTestBase<SpeedTreeBillboardUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new SpeedTreeBillboardUpgrader("Nature/SpeedTree Billboard");
}
public SpeedTreeBillboardMaterialUpgraderTest() : base("Nature/SpeedTree Billboard",
"Universal Render Pipeline/Nature/SpeedTree7 Billboard")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeSpeedTree7BillboardMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_SpeedTreeBillboardMaterial_When_Upgrading_Then_ShaderIsUpgradedToSpeedTree7Billboard",
setup = material =>
{
// No specific setup is needed for this test case, as we are only verifying that the shader is upgraded correctly.
},
verify = material =>
{
// Verify that the shader has been upgraded to the expected shader.
Assert.AreEqual("Universal Render Pipeline/Nature/SpeedTree7 Billboard", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialMainColorRed_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardMainColorIsRed",
setup = material =>
{
// Set the main color to red before upgrading.
material.SetColor("_Color", Color.red);
},
verify = material =>
{
// Verify that the main color is still red after upgrading.
Assert.AreEqual(Color.red, material.GetColor("_Color"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialHueVariationGreen_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardHueVariationIsGreen",
setup = material =>
{
// Set the hue variation to green before upgrading.
material.SetColor("_HueVariation", Color.green);
},
verify = material =>
{
// Verify that the hue variation is still green after upgrading.
Assert.AreEqual(Color.green, material.GetColor("_HueVariation"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialAlphaCutoff02_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardAlphaCutoffIs02",
setup = material =>
{
// Set the alpha cutoff to 0.2 before upgrading.
material.SetFloat("_Cutoff", 0.2f);
},
verify = material =>
{
// Verify that the alpha cutoff is still 0.2 after upgrading.
Assert.AreEqual(0.2f, material.GetFloat("_Cutoff"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialWindQualityNone_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardWindQualityIsNone",
setup = material =>
{
// Set the wind quality to none before upgrading.
material.SetFloat("_WindQuality", 0.0f);
},
verify = material =>
{
// Verify that the wind quality is still none after upgrading.
Assert.AreEqual(0.0f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialWindQualityFastest_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardWindQualityIsFastest",
setup = material =>
{
// Set the wind quality to fastest before upgrading.
material.SetFloat("_WindQuality", 1.0f);
},
verify = material =>
{
// Verify that the wind quality is still fastest after upgrading.
Assert.AreEqual(1.0f, material.GetFloat("_WindQuality"));
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialGPUInstancingEnabled_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardGPUInstancingIsEnabled",
setup = material =>
{
// Enable GPU instancing before upgrading.
material.enableInstancing = true;
},
verify = material =>
{
// Verify that GPU instancing is still enabled after upgrading.
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_SpeedTreeBillboardMaterialGPUInstancingDisabled_When_Upgrading_Then_TheShaderUniversalRenderPipelineSpeedTree7BillboardGPUInstancingIsDisabled",
setup = material =>
{
// Disable GPU instancing before upgrading.
material.enableInstancing = false;
},
verify = material =>
{
// Verify that GPU instancing is still disabled after upgrading.
Assert.IsFalse(material.enableInstancing);
}
};
}
}
@@ -0,0 +1,294 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class StandardMaterialUpgraderTest : MaterialUpgraderTestBase<StandardUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new StandardUpgrader("Standard");
}
public StandardMaterialUpgraderTest() : base("Standard", "Universal Render Pipeline/Lit")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeParticleStandardUnlitMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name = "Given_OpaqueBuiltInMaterial_When_Upgrading_Then_TheMaterialSurfaceOpaqueAndAlphaTestOff", // change the test name here
setup = material =>
{
material.SetFloat("_Mode", 0.0f); // Opaque
},
verify = material =>
{
Assert.AreEqual(0.0f, material.GetFloat("_Surface")); // Surface type Opaque
Assert.IsFalse(material.IsKeywordEnabled("_ALPHATEST_ON")); // No alpha test
}
};
yield return new MaterialUpgradeTestCase
{
name = "Given_CutoutBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSurfaceOpaqueAndAlphaTestOn",
setup = material =>
{
material.SetFloat("_Mode", 1.0f); // Cutout
},
verify = material =>
{
Assert.IsTrue(material.IsKeywordEnabled("_ALPHATEST_ON")); // Alpha clipping enabled
Assert.AreEqual(0.0f, material.GetFloat("_Surface")); // Surface type Opaque
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_FadeBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSurfaceTransparentAndAlphaBlend",
setup = material =>
{
material.SetFloat("_Mode", 2.0f); // fade mode
},
verify = material =>
{
Assert.IsTrue(material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")); // Surface type Transparent
Assert.AreEqual((float)BaseShaderGUI.SurfaceType.Transparent, material.GetFloat("_Surface"));
Assert.AreEqual((float)BaseShaderGUI.BlendMode.Alpha, material.GetFloat("_Blend")); // Blend mode Alpha
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_TransparentBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSurfaceTransparentAndPremultiply",
setup = material =>
{
material.SetFloat("_Mode", 3.0f); //transparent mode
},
verify = material =>
{
Assert.IsTrue(material.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT")); // Surface type Transparent
Assert.AreEqual((float)BaseShaderGUI.SurfaceType.Transparent, material.GetFloat("_Surface"));
Assert.AreEqual((float)BaseShaderGUI.BlendMode.Premultiply, material.GetFloat("_Blend")); // Blend mode Premultiply
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_GPUInstancingEnabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPGPUInstancingEnabled",
setup = material =>
{
material.enableInstancing = true; // enable GPU Instancing
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing); // GPU Instancing enabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_GPUInstancingDisabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPGPUInstancingDisabled",
setup = material =>
{
material.enableInstancing = false; // disable GPU Instancing
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing); // GPU Instancing disabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_EnvironmentReflectionsEnabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPEnvironmentReflectionsEnabled",
setup = material =>
{
material.SetFloat("_GlossyReflections", 1.0f); // Enable environment reflections
},
verify = material =>
{
Assert.AreEqual(1.0f, material.GetFloat("_GlossyReflections")); // Environment reflections enabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_EnvironmentReflectionsDisabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPEnvironmentReflectionsDisabled",
setup = material =>
{
material.SetFloat("_GlossyReflections", 0.0f); // Disable environment reflections
},
verify = material =>
{
Assert.AreEqual(0.0f, material.GetFloat("_GlossyReflections")); // Environment reflections disabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_SpecularHighlightsEnabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSpecularHighlightsEnabled",
setup = material =>
{
material.SetFloat("_SpecularHighlights", 1.0f); // Enable specular highlights
},
verify = material =>
{
Assert.AreEqual(1.0f, material.GetFloat("_SpecularHighlights")); // Specular highlights enabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_SpecularHighlightsDisabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSpecularHighlightsDisabled",
setup = material =>
{
material.SetFloat("_SpecularHighlights", 0.0f); // Disable specular highlights
},
verify = material =>
{
Assert.AreEqual(0.0f, material.GetFloat("_SpecularHighlights")); // Specular highlights disabled
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_RenderQueueSetoToBuiltInMaterial_When_Upgrading_Then_TheMaterialURPRenderQueuePreserved",
ignore = true,
ignoreReason = "Fails, needs investigation",
setup = material =>
{
material.renderQueue = 2500; // queue
},
verify = material =>
{
Assert.AreEqual(2500, material.renderQueue); // Check that render queue is preserved after upgrade
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_TilingSetToBuiltInMaterial_When_Upgrading_Then_TheMaterialURPTilingPreserved",
setup = material =>
{
material.SetTextureScale("_MainTex", new Vector2(2.0f, 2.0f)); // Set tiling
},
verify = material =>
{
Assert.AreEqual(new Vector2(2.0f, 2.0f), material.GetTextureScale("_BaseMap")); // Check that tiling is preserved after upgrade
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_TilingSecondaryMapSetToBuiltInMaterial_When_Upgrading_Then_TheMaterialURPTilingSecondaryMapPreserved",
ignore = true,
ignoreReason = "Fails, needs investigation",
setup = material =>
{
material.SetTextureScale("_MainTex", new Vector2(3.0f, 3.0f)); // Tiling
material.SetTextureOffset("_MainTex", new Vector2(9.0f, 9.0f));
},
verify = material =>
{
Assert.AreEqual(new Vector2(3.0f, 3.0f), material.GetTextureOffset("_BaseMap")); // Check that tiling is preserved after upgrade
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_MetallicValueSetToBuiltInMaterial_When_Upgrading_Then_TheMaterialURPMetallicValuePreserved",
setup = material =>
{
material.SetFloat("_Metallic", 1f); // Metallic
},
verify = material =>
{
Assert.AreEqual(1f, material.GetFloat("_Metallic")); // Check that metallic value is preserved after upgrade
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_SmoothnessValueSetToBuiltInMaterial_When_Upgrading_Then_TheMaterialURPSmoothnessValuePreserved",
setup = material =>
{
material.SetFloat("_Glossiness", 0.0f); // Smoothness
},
verify = material =>
{
Assert.AreEqual(0.0f, material.GetFloat("_Glossiness"));
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_MetallicSourceAlphaBuiltInMaterial_When_Upgrading_Then_TheMaterialURPMetallicSourceAlphaPreserved",
setup = material =>
{
material.SetFloat("_SmoothnessTextureChannel", 0.0f); // Metallic source alpha
},
verify = material =>
{
Assert.AreEqual(0.0f, material.GetFloat("_SmoothnessTextureChannel"));
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_AlbedoSourceAlphaBuiltInMaterial_When_Upgrading_Then_TheMaterialURPAlbedoSourceAlphaPreserved",
setup = material =>
{
material.SetFloat("_SmoothnessTextureChannel", 1.0f);
},
verify = material =>
{
Assert.AreEqual(1.0f, material.GetFloat("_SmoothnessTextureChannel"));
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_EmissionEnabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPEmissionEnabled",
ignore = true,
ignoreReason = "Fails, needs investigation",
setup = material =>
{
material.EnableKeyword("_EMISSION");
},
verify = material =>
{
Assert.IsTrue(material.IsKeywordEnabled("_EMISSION"));
}
};
yield return new MaterialUpgradeTestCase()
{
name = "Given_EmissionDisabledBuiltInMaterial_When_Upgrading_Then_TheMaterialURPEmissionDisabled",
ignore = true,
ignoreReason = "Fails, needs investigation",
setup = material =>
{
material.DisableKeyword("_EMISSION");
},
verify = material =>
{
Assert.IsFalse(material.IsKeywordEnabled("_EMISSION"));
}
};
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0722f9616ea0a48e280b552e67e783a5
@@ -0,0 +1,90 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using UnityEngine;
using UnityEngine.TestTools;
[Category("Graphics Tools")]
class TerrainStandardMaterialUpgraderTest : MaterialUpgraderTestBase<TerrainUpgrader>
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
m_Upgrader = new TerrainUpgrader("Nature/Terrain/Standard");
}
public TerrainStandardMaterialUpgraderTest() : base("Nature/Terrain/Standard",
"Universal Render Pipeline/Terrain/Lit")
{
}
[Test]
[TestCaseSource(nameof(MaterialUpgradeCases))]
public void UpgradeTerrainStandardMaterial(MaterialUpgradeTestCase testCase)
{
base.UpgradeMaterial(testCase);
}
private static IEnumerable MaterialUpgradeCases()
{
yield return new MaterialUpgradeTestCase
{
name =
"Given_TerrainStandardMaterial_When_Upgrading_Then_TheShaderUpgradedToUniversalRenderPipelineTerrainLit",
setup = material =>
{
// No specific setup is needed for this test case, as we are only verifying that the shader is upgraded correctly.
},
verify = material =>
{
Assert.AreEqual("Universal Render Pipeline/Terrain/Lit", material.shader.name);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TerrainStandardMaterialEnabledInstancing_When_Upgrading_Then_TheInstancingEnabled",
setup = material =>
{
material.enableInstancing = true;
},
verify = material =>
{
Assert.IsTrue(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TerrainStandardMaterialDisabledInstancing_When_Upgrading_Then_TheInstancingDisabled",
setup = material =>
{
material.enableInstancing = false;
},
verify = material =>
{
Assert.IsFalse(material.enableInstancing);
}
};
yield return new MaterialUpgradeTestCase
{
name =
"Given_TerrainStandardMaterialLodFadeCrossFadeEnabled_When_Upgrading_Then_TheLodFadeCrossFadeDisabled",
setup = material =>
{
material.EnableKeyword("LOD_FADE_CROSSFADE");
},
verify = material =>
{
Assert.IsFalse(material.IsKeywordEnabled("LOD_FADE_CROSSFADE"));
}
};
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 942a5a86e2bef824ea90af68b65e11d5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using System;
using NUnit.Framework;
using UnityEditor.Rendering.Converter;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class ReadonlyMaterialConverterTests_MaterialReferenceBuilder
{
[OneTimeSetUp]
public void OneTimeSetup()
{
if (!(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset))
Assert.Ignore("Current pipeline is not URP. Skipping tests");
}
public class TestClass_PublicPropertySharedProperty
{
public Material Single { get; set; }
public Material[] Array { get; set; }
public Material SharedSingle { get; set; }
public Material[] SharedArray { get; set; }
}
[Test]
public void TypeWithSharedAndNonSharedProperties_OnlySharedOnesAreReturnedOnMaterialAccessor()
{
var obj = Activator.CreateInstance(typeof(TestClass_PublicPropertySharedProperty));
Assert.IsTrue(MaterialReferenceBuilder.TryGetReferenceInfoFromType(obj.GetType(), out var entry));
Assert.AreEqual(2, entry.materialAccessors.Count);
Assert.AreEqual("SharedSingle", entry.materialAccessors[0].member.Name);
Assert.AreEqual("SharedArray", entry.materialAccessors[1].member.Name);
}
}
}
@@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using UnityEditor.Rendering.Converter;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using static UnityEditor.Rendering.Converter.MaterialReferenceBuilder;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class ReadonlyMaterialConverterTests_MaterialReferenceChanger
{
#region Types Definition
public class TestClass_PublicNonSerializedField
{
[NonSerialized] public Material Single;
[NonSerialized] public Material[] Array;
}
public class TestClass_PrivateField
{
Material Single;
Material[] Array;
}
public class TestClass_NoGetProperties
{
private Material m_Single;
private Material[] m_Array;
public Material Single { set => m_Single = value; }
public Material[] Array { set => m_Array = value; }
}
public class TestClass_PublicField
{
public Material Single;
public Material[] Array;
}
public class TestClass_PrivateSerializedField
{
[SerializeField] Material Single;
[SerializeField] Material[] Array;
}
public class TestClass_PrivateProperties
{
Material Single { get; set; }
Material[] Array { get; set; }
}
public class TestClass_PublicProperty
{
public Material Single { get; set; }
public Material[] Array { get; set; }
}
public class TestClass_PublicPropertyWithBackingField
{
Material m_Single;
Material[] m_Array;
public Material Single { get => m_Single; set => m_Single = value; }
public Material[] Array { get => m_Array; set => m_Array = value; }
}
#endregion
Material[] m_Materials;
Material[] m_ExpectedMaterials;
BuiltInToURP3DReadonlyMaterialConverter m_Converter;
[OneTimeSetUp]
public void OneTimeSetup()
{
if (!(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset))
Assert.Ignore("Current pipeline is not URP. Skipping tests");
m_Converter = new BuiltInToURP3DReadonlyMaterialConverter();
m_Materials = m_Converter.mappings.GetBuiltInMaterials();
Assume.That(m_Materials.Length > 0, "There are no mapping materials");
m_ExpectedMaterials = new Material[m_Materials.Length];
for(int i = 0; i < m_Materials.Length; ++i)
{
Assert.IsTrue(m_Converter.mappings.TryGetMappingMaterial(m_Materials[i], out var expectedMaterial));
m_ExpectedMaterials[i] = expectedMaterial;
}
}
public static IEnumerable<TestCaseData> Success_TestCases()
{
yield return new TestCaseData(typeof(TestClass_PublicField)).SetName("Public Fields are migrated");
yield return new TestCaseData(typeof(TestClass_PrivateSerializedField)).SetName("Private Serialized Fields are migrated");
yield return new TestCaseData(typeof(TestClass_PublicProperty)).SetName("Public Properties are migrated");
yield return new TestCaseData(typeof(TestClass_PrivateProperties)).SetName("Private Properties are migrated");
yield return new TestCaseData(typeof(TestClass_PublicPropertyWithBackingField)).SetName("Public Property With Serialized Field are migrated");
}
public static IEnumerable<TestCaseData> Failing_TestCases()
{
yield return new TestCaseData(typeof(TestClass_PublicNonSerializedField)).SetName("Public Non Fields");
yield return new TestCaseData(typeof(TestClass_PrivateField)).SetName("Private Fields");
yield return new TestCaseData(typeof(TestClass_NoGetProperties)).SetName("Setter only Properties ");
}
[TestCaseSource(nameof(Failing_TestCases))]
public void ReassignMaterial_Failing_Tests(Type classType)
{
var obj = Activator.CreateInstance(classType);
Assert.IsFalse(MaterialReferenceBuilder.TryGetReferenceInfoFromType(obj.GetType(), out var entry));
}
private bool TryGetMembers(object obj, MaterialReferenceInfo entry, out Func<object> getterArray, out Action<object> setterArray, out Func<object> getterSingle, out Action<object> setterSingle)
{
getterArray = null;
setterArray = null;
getterSingle = null;
setterSingle = null;
bool ok = true;
foreach (var materialAccessor in entry.materialAccessors)
{
ok &= materialAccessor.isArray ?
MaterialReferenceBuilder.TryGetFromMemberInfoAccessors(obj, materialAccessor.member, out getterArray, out setterArray) :
MaterialReferenceBuilder.TryGetFromMemberInfoAccessors(obj, materialAccessor.member, out getterSingle, out setterSingle);
}
return getterArray != null && setterArray != null && getterSingle != null && setterSingle != null;
}
private object CreateInstanceWithAllMaterials(Type classType, MaterialReferenceInfo entry, out Func<object> getterArray, out Action<object> setterArray, out Func<object> getterSingle, out Action<object> setterSingle)
{
var obj = Activator.CreateInstance(classType);
Assert.IsTrue(TryGetMembers(obj, entry, out getterArray, out setterArray, out getterSingle, out setterSingle), "Failed to get material accessors");
var copy = (Material[])m_Materials.Clone();
// Set initial materials
setterSingle(copy[0]);
setterArray(copy);
return obj;
}
[TestCaseSource(nameof(Success_TestCases))]
public void ReassignMaterial_Success_Tests(Type classType)
{
Assert.IsTrue(MaterialReferenceBuilder.TryGetReferenceInfoFromType(classType, out var entry));
var obj = CreateInstanceWithAllMaterials(classType, entry, out var getterArray, out var setterArray, out var getterSingle, out var setterSingle);
// Perform the reassignment
using (var materialReferenceChanger = new MaterialReferenceChanger(m_Converter.mappings))
{
var sb = new StringBuilder();
bool ok = materialReferenceChanger.ReassignMaterials(obj, null, entry, sb);
Assert.IsTrue(ok, "Reassing Materials Failed");
}
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(m_ExpectedMaterials, getterArray() as Material[]), "Materials Arrays NOT changed");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(m_ExpectedMaterials[0], getterSingle() as Material), "Material Single NOT changed");
}
[TestCaseSource(nameof(Success_TestCases))]
public void ReassignMaterial_OnPrefabWhenNoOverride(Type classType)
{
Assert.IsTrue(MaterialReferenceBuilder.TryGetReferenceInfoFromType(classType, out var entry));
var obj = CreateInstanceWithAllMaterials(classType, entry, out var getterArray, out var setterArray, out var getterSingle, out var setterSingle);
var objPrefab = CreateInstanceWithAllMaterials(classType, entry, out var getterPrefabArray, out var setterPrefabArray, out var getterPrefabSingle, out var setterPrefabSingle);
// Perform the reassignment
using (var materialReferenceChanger = new MaterialReferenceChanger(m_Converter.mappings))
{
var sb = new StringBuilder();
bool ok = materialReferenceChanger.ReassignMaterials(obj, objPrefab, entry, sb);
Assert.IsTrue(ok, "Reassing Materials Failed");
}
// Nothing is changed, as the instance should not change prefab materials.
var expectedBuiltIn = (Material[])m_Materials.Clone();
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn, getterArray() as Material[]), "Materials from the instance have been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn, getterPrefabArray() as Material[]), "Materials from the prefab have NOT been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn[0], getterSingle() as Material), "Materials from the instance have been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn[0], getterPrefabSingle() as Material), "Materials from the prefab have NOT been modified");
}
[TestCaseSource(nameof(Success_TestCases))]
public void ReassignMaterial_OnInstanceWhenOverridingPrefab(Type classType)
{
Assert.IsTrue(MaterialReferenceBuilder.TryGetReferenceInfoFromType(classType, out var entry));
var obj = CreateInstanceWithAllMaterials(classType, entry, out var getterArray, out var setterArray, out var getterSingle, out var setterSingle);
var objPrefab = CreateInstanceWithAllMaterials(classType, entry, out var getterPrefabArray, out var setterPrefabArray, out var getterPrefabSingle, out var setterPrefabSingle);
// Prefab will point to 0, and instance to last, changing instance to fake an override from the prefab
setterSingle(m_Materials[m_Materials.Length - 1]);
// Change the instance materials to reverse order
var builtInReversed = (Material[])m_Materials.Clone();
Array.Reverse(builtInReversed);
setterArray(builtInReversed);
// Perform the reassignment
using (var materialReferenceChanger = new MaterialReferenceChanger(m_Converter.mappings))
{
var sb = new StringBuilder();
bool ok = materialReferenceChanger.ReassignMaterials(obj, objPrefab, entry, sb);
Assert.IsTrue(ok, "Reassing Materials Failed");
}
var expectedBuiltIn = (Material[])m_Materials.Clone();
var reversedExpected = (Material[])m_ExpectedMaterials.Clone();
Array.Reverse(reversedExpected);
// As the instance is overriding materials, those must me changed, but not the prefab
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(reversedExpected, getterArray() as Material[]), "Materials from the instance have NOT been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn, getterPrefabArray() as Material[]), "Materials from the prefab have been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(reversedExpected[0], getterSingle() as Material), "Materials from the instance have NOT been modified");
Assert.IsTrue(MaterialReferenceChanger.AreMaterialsEqual(expectedBuiltIn[0], getterPrefabSingle() as Material), "Materials from the prefab have been modified");
}
}
}
@@ -0,0 +1,184 @@
using NUnit.Framework;
using UnityEditor.Rendering.Converter;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class ReadonlyMaterialConverterTests
{
const string k_BasePrefabPath = "Assets/ReadonlyMaterialConverterTests/";
GameObject m_GO;
MeshRenderer m_MeshRenderer;
string m_CurrentTestAssetPath;
public static GameObject CreatePrefabWithMeshRenderer(Material[] materials, string assetPath)
{
var go = new GameObject("TestPrefab");
try
{
var mf = go.AddComponent<MeshFilter>();
var mr = go.AddComponent<MeshRenderer>();
mr.sharedMaterials = materials;
CoreUtils.EnsureFolderTreeInAssetFilePath(assetPath);
var prefab = PrefabUtility.SaveAsPrefabAsset(go, assetPath, out bool success);
if (!success || prefab == null)
{
Debug.LogError("Failed to save prefab at: " + assetPath);
return null;
}
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.SaveAssets();
return prefab;
}
catch (System.Exception ex)
{
Debug.LogException(ex);
}
finally
{
UnityEngine.Object.DestroyImmediate(go);
}
return null;
}
[OneTimeSetUp]
public void OneTimeSetup()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset == null)
Assert.Ignore("Project without URP. Skipping test");
}
[TearDown]
public void Teardown()
{
if (!string.IsNullOrEmpty(m_CurrentTestAssetPath))
{
// Delete the specific prefab file
if (AssetDatabase.LoadAssetAtPath<GameObject>(m_CurrentTestAssetPath) != null)
{
AssetDatabase.DeleteAsset(m_CurrentTestAssetPath);
}
}
m_CurrentTestAssetPath = null;
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
// Clean up the entire test folder
if (AssetDatabase.IsValidFolder(k_BasePrefabPath.TrimEnd('/')))
{
AssetDatabase.DeleteAsset(k_BasePrefabPath.TrimEnd('/'));
}
}
private void SetupTestForConverter(ReadonlyMaterialConverter converter, string testName)
{
var materials = converter.mappings.GetBuiltInMaterials();
Assume.That(materials.Length > 0, "There are no mapping materials");
// Create unique asset path for this specific test
m_CurrentTestAssetPath = k_BasePrefabPath + testName + ".prefab";
m_GO = CreatePrefabWithMeshRenderer(materials, m_CurrentTestAssetPath);
m_MeshRenderer = m_GO.GetComponent<MeshRenderer>();
Assert.AreEqual(converter.mappings.count, m_MeshRenderer.sharedMaterials.Length,
"ReadonlyMaterialMap - Lengths are different");
int i = 0;
foreach (var key in converter.mappings.Keys)
{
Assert.AreEqual(key, m_MeshRenderer.sharedMaterials[i].name,
"ReadonlyMaterialMap - Order has changed");
++i;
}
}
private void CheckMaterialsAfterConversion(ReadonlyMaterialConverter converter, Material[] actual)
{
int i = 0;
var materials = converter.mappings.GetBuiltInMaterials();
foreach (var key in converter.mappings.Keys)
{
Assert.IsTrue(converter.mappings.TryGetMappingMaterial(materials[i], out var expected));
Assert.AreEqual(expected, actual[i], "The material was not changed");
++i;
}
}
private void RunConverterTest(ReadonlyMaterialConverter converter, string testName)
{
SetupTestForConverter(converter, testName);
var gid = GlobalObjectId.GetGlobalObjectIdSlow(m_GO);
var assetItem = new RenderPipelineConverterAssetItem(gid, AssetDatabase.GetAssetPath(m_GO));
converter.assets.Add(assetItem);
Assert.IsNull(converter.m_MaterialReferenceChanger,
"MaterialReferenceChanger should be null before BeforeConvert");
converter.BeforeConvert();
Assert.IsNotNull(converter.m_MaterialReferenceChanger,
"MaterialReferenceChanger should NOT be null after BeforeConvert");
var status = converter.Convert(assetItem, out var message);
converter.AfterConvert();
Assert.IsNull(converter.m_MaterialReferenceChanger,
"MaterialReferenceChanger should be null after AfterConvert");
Assert.AreEqual(Status.Success, status);
Assert.IsTrue(string.IsNullOrEmpty(message), $"Message should be empty. Message: {message}");
CheckMaterialsAfterConversion(converter, m_MeshRenderer.sharedMaterials);
}
[Test]
public void BuiltInToURP3D_ReassignMaterials_Succeeds()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset.scriptableRenderer is not UniversalRenderer)
Assert.Ignore("Requires UniversalRenderer. Skipping test");
var converter = new BuiltInToURP3DReadonlyMaterialConverter();
RunConverterTest(converter, nameof(BuiltInToURP3D_ReassignMaterials_Succeeds));
}
[Test]
public void URP3DToURP2D_ReassignMaterials_Succeeds()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset.scriptableRenderer is not Renderer2D)
Assert.Ignore("Requires Renderer2D. Skipping test");
var converter = new URP3DToURP2DReadonlyMaterialConverter();
RunConverterTest(converter, nameof(URP3DToURP2D_ReassignMaterials_Succeeds));
}
[Test]
public void BuiltInToURP2D_ReassignMaterials_Succeeds()
{
var urpAsset = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
if (urpAsset.scriptableRenderer is not Renderer2D)
Assert.Ignore("Requires Renderer2D. Skipping test");
var converter = new BuiltInToURP2DReadonlyMaterialConverter();
RunConverterTest(converter, nameof(BuiltInToURP2D_ReassignMaterials_Succeeds));
}
}
}
@@ -0,0 +1,179 @@
using System.Collections.Generic;
using NUnit.Framework;
using UnityEditor.Rendering.Converter;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace UnityEditor.Rendering.Universal.Tools
{
[TestFixture]
[Category("Graphics Tools")]
class RenderSettingsConverterTests
{
[OneTimeSetUp]
public void OneTimeSetup()
{
if (QualitySettings.names.Length == 0)
Assert.Ignore("Project without quality settings. Skipping test");
}
RenderPipelineAsset m_RenderPipelineAsset;
int m_QualityLevel = -1;
string m_DefaultFolder = string.Empty;
string m_QualityLevelName = string.Empty;
[SetUp]
public void Setup()
{
m_RenderPipelineAsset = QualitySettings.renderPipeline;
QualitySettings.renderPipeline = null;
m_QualityLevel = QualitySettings.GetQualityLevel();
m_QualityLevelName = QualitySettings.names[m_QualityLevel];
m_DefaultFolder = UniversalProjectSettings.projectSettingsFolderPath;
UniversalProjectSettings.projectSettingsFolderPath = nameof(RenderSettingsConverterTests);
}
[TearDown]
public void TearDown()
{
var path = $"Assets/{UniversalProjectSettings.projectSettingsFolderPath}";
if (AssetDatabase.AssetPathExists(path))
{
AssetDatabase.DeleteAsset(path);
AssetDatabase.Refresh();
}
QualitySettings.renderPipeline = m_RenderPipelineAsset;
UniversalProjectSettings.projectSettingsFolderPath = m_DefaultFolder;
}
[Test]
public void WhenRunningBuiltInToURP3DRenderSettingsConverter_TheCurrent_QualityLevel_IsNowURP_AndHasEverythingProperlyAssigned()
{
var renderSettingsConverter = new BuiltInToURP3DRenderSettingsConverter();
var expectedEntry = $"[{m_QualityLevel}] {m_QualityLevelName}";
void OnScanFinished(List<IRenderPipelineConverterItem> scanItems)
{
Assert.IsTrue(scanItems.Count > 0, "Initialization did not found the item to convert");
// Find the Quality folder (RenderSettingsConverter returns Graphics and Quality folders)
IFolderRenderPipelineConverterItem qualityFolder = null;
foreach (var item in scanItems)
{
if (item is IFolderRenderPipelineConverterItem folder && folder.name == "Quality")
{
qualityFolder = folder;
break;
}
}
Assert.IsNotNull(qualityFolder, "Quality folder not found in scan results");
Assert.IsTrue(qualityFolder.children.Count > m_QualityLevel, $"Quality level {m_QualityLevel} out of range for {qualityFolder.children.Count} quality levels");
Assert.AreEqual(m_QualityLevel, QualitySettings.GetQualityLevel(), "Initialization did not rollback quality level");
var status = renderSettingsConverter.Convert(qualityFolder.children[m_QualityLevel], out string msg);
Assert.IsTrue(status != Status.Error, msg);
Assert.AreEqual(m_QualityLevel, QualitySettings.GetQualityLevel(), "Run did not rollback quality level");
// ---------- ASSET REFERENCE CHECK ----------
var urpAsset = QualitySettings.renderPipeline as UniversalRenderPipelineAsset;
Assert.IsNotNull(urpAsset, "URP asset is not assigned");
Assert.AreEqual($"Assets/{UniversalProjectSettings.projectSettingsFolderPath}/{m_QualityLevelName}.asset", AssetDatabase.GetAssetPath(urpAsset));
// ---------- RENDERER REFERENCE CHECK ----------
Assert.IsNotNull(urpAsset.m_RendererDataList);
Assert.AreEqual(1, urpAsset.m_RendererDataList.Length);
Assert.AreEqual($"Assets/{UniversalProjectSettings.projectSettingsFolderPath}/Default_Forward_Renderer.asset", AssetDatabase.GetAssetPath(urpAsset.m_RendererDataList[0]));
// ---------- SETTINGS FORWARDING CHECK ----------
var targetGrp = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
var tier = EditorGraphicsSettings.GetTierSettings(targetGrp, GraphicsTier.Tier3);
Assert.AreEqual(QualitySettings.softParticles, urpAsset.supportsCameraDepthTexture, "supportsCameraDepthTexture mismatch");
Assert.AreEqual(tier.hdr, urpAsset.supportsHDR, "supportsHDR mismatch");
Assert.AreEqual(QualitySettings.antiAliasing == 0 ? 1 : QualitySettings.antiAliasing, urpAsset.msaaSampleCount, "msaaSampleCount mismatch");
var expectedMainLightMode = QualitySettings.pixelLightCount == 0 ? LightRenderingMode.Disabled : LightRenderingMode.PerPixel;
Assert.AreEqual(expectedMainLightMode, urpAsset.mainLightRenderingMode, "mainLightRenderingMode mismatch");
Assert.AreEqual(QualitySettings.shadows != UnityEngine.ShadowQuality.Disable, urpAsset.supportsMainLightShadows, "supportsMainLightShadows mismatch");
Assert.AreEqual(BuiltInToURP3DRenderSettingsConverter.GetEquivalentMainlightShadowResolution((int)QualitySettings.shadowResolution), urpAsset.mainLightShadowmapResolution, "mainLightShadowmapResolution mismatch");
var expectedAdditionalLightsMode = QualitySettings.pixelLightCount == 0 ? LightRenderingMode.PerVertex : LightRenderingMode.PerPixel;
Assert.AreEqual(expectedAdditionalLightsMode, urpAsset.additionalLightsRenderingMode, "additionalLightsRenderingMode mismatch");
Assert.AreEqual(QualitySettings.pixelLightCount != 0 ? Mathf.Max(0, QualitySettings.pixelLightCount) : 4, urpAsset.maxAdditionalLightsCount, "maxAdditionalLightsCount mismatch");
Assert.AreEqual(QualitySettings.shadows != UnityEngine.ShadowQuality.Disable, urpAsset.supportsAdditionalLightShadows, "supportsAdditionalLightShadows mismatch");
Assert.AreEqual(BuiltInToURP3DRenderSettingsConverter.GetEquivalentAdditionalLightAtlasShadowResolution((int)QualitySettings.shadowResolution), urpAsset.additionalLightsShadowmapResolution, "additionalLightsShadowmapResolution mismatch");
Assert.AreEqual(tier.reflectionProbeBlending, urpAsset.reflectionProbeBlending, "reflectionProbeBlending mismatch");
Assert.AreEqual(tier.reflectionProbeBoxProjection, urpAsset.reflectionProbeBoxProjection, "reflectionProbeBoxProjection mismatch");
Assert.AreEqual(QualitySettings.shadowDistance, urpAsset.shadowDistance, "shadowDistance mismatch");
var expectedCascadeCount = tier.cascadedShadowMaps ? QualitySettings.shadowCascades : 1;
Assert.AreEqual(expectedCascadeCount, urpAsset.shadowCascadeCount, "shadowCascadeCount mismatch");
Assert.AreEqual(QualitySettings.shadowCascade2Split, urpAsset.cascade2Split, "cascade2Split mismatch");
Assert.AreEqual(QualitySettings.shadowCascade4Split, urpAsset.cascade4Split, "cascade4Split mismatch");
Assert.AreEqual(QualitySettings.shadows == UnityEngine.ShadowQuality.All, urpAsset.supportsSoftShadows, "supportsSoftShadows mismatch");
// ---------- RENDERER FORWARDING CHECK ----------
Assert.AreEqual(1, urpAsset.m_RendererDataList.Length);
Assert.IsNotNull(urpAsset.m_RendererDataList[0]);
}
renderSettingsConverter.Scan(OnScanFinished);
}
[Test]
public void WhenRunningBuiltInToURP2DRenderSettingsConverter_TheCurrent_QualityLevel_IsNowURP_AndHasEverythingProperlyAssigned()
{
var renderSettingsConverter = new BuiltInToURP2DRenderSettingsConverter();
var expectedEntry = $"[{m_QualityLevel}] {m_QualityLevelName}";
void OnScanFinished(List<IRenderPipelineConverterItem> scanItems)
{
Assert.IsTrue(scanItems.Count > 0, "Initialization did not found the item to convert");
// Find the Quality folder (RenderSettingsConverter returns Graphics and Quality folders)
IFolderRenderPipelineConverterItem qualityFolder = null;
foreach (var item in scanItems)
{
if (item is IFolderRenderPipelineConverterItem folder && folder.name == "Quality")
{
qualityFolder = folder;
break;
}
}
Assert.IsNotNull(qualityFolder, "Quality folder not found in scan results");
Assert.IsTrue(qualityFolder.children.Count > m_QualityLevel, $"Quality level {m_QualityLevel} out of range for {qualityFolder.children.Count} quality levels");
Assert.AreEqual(m_QualityLevel, QualitySettings.GetQualityLevel(), "Initialization did not rollback quality level");
var status = renderSettingsConverter.Convert(qualityFolder.children[m_QualityLevel], out string msg);
Assert.IsTrue(status != Status.Error, msg);
Assert.AreEqual(m_QualityLevel, QualitySettings.GetQualityLevel(), "Run did not rollback quality level");
// ---------- ASSET REFERENCE CHECK ----------
var urpAsset = QualitySettings.renderPipeline as UniversalRenderPipelineAsset;
Assert.IsNotNull(urpAsset, "URP asset is not assigned");
Assert.AreEqual($"Assets/{UniversalProjectSettings.projectSettingsFolderPath}/{m_QualityLevelName}.asset", AssetDatabase.GetAssetPath(urpAsset));
// ---------- RENDERER REFERENCE CHECK ----------
Assert.IsNotNull(urpAsset.m_RendererDataList);
Assert.AreEqual(1, urpAsset.m_RendererDataList.Length);
Assert.AreEqual($"Assets/{UniversalProjectSettings.projectSettingsFolderPath}/Default_2D_Renderer.asset", AssetDatabase.GetAssetPath(urpAsset.m_RendererDataList[0]));
}
renderSettingsConverter.Scan(OnScanFinished);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 63521e524f5ad0e4c96e22187d781a46
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f75203f9fbded7345a3ea0799dba11d0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,933 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using NUnit.Framework;
using Unity.ProjectAuditor.Editor;
using Unity.ProjectAuditor.Editor.Core;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.TestTools;
namespace UnityEditor.Rendering.Universal.ProjectAuditor.Tests
{
[NUnit.Framework.Category("Graphics Tools")]
[TestFixture]
class URPSettingsAnalyzerTests
{
private UniversalRenderPipelineAsset m_PreviousDefaultRenderPipeline;
private RenderPipelineAsset[] m_PreviousQualitySettings;
private int m_PreviousQualityLevel;
private ColorSpace m_PreviousColorSpace;
private bool m_PreviousStaticBatching;
[SetUp]
public void SetUp()
{
// Save previous settings
m_PreviousDefaultRenderPipeline = GraphicsSettings.defaultRenderPipeline as UniversalRenderPipelineAsset;
m_PreviousColorSpace = PlayerSettings.colorSpace;
m_PreviousStaticBatching = PlayerSettings.GetStaticBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget);
// Save quality settings
m_PreviousQualitySettings = new RenderPipelineAsset[QualitySettings.names.Length];
m_PreviousQualityLevel = QualitySettings.GetQualityLevel();
for (int i = 0; i < QualitySettings.names.Length; i++)
{
QualitySettings.SetQualityLevel(i);
m_PreviousQualitySettings[i] = QualitySettings.renderPipeline;
}
QualitySettings.SetQualityLevel(m_PreviousQualityLevel);
}
[TearDown]
public void TearDown()
{
// Restore previous settings
GraphicsSettings.defaultRenderPipeline = m_PreviousDefaultRenderPipeline;
PlayerSettings.colorSpace = m_PreviousColorSpace;
PlayerSettings.SetStaticBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, m_PreviousStaticBatching);
// Restore quality settings
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = m_PreviousQualitySettings[i];
}
QualitySettings.SetQualityLevel(m_PreviousQualityLevel);
}
#region URP Assets Tests (0001-0100)
[Test]
public void URP0001_MissingURPAsset_DetectsIssue()
{
// Arrange
GraphicsSettings.defaultRenderPipeline = null;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = null;
}
var analyzer = new MissingAssignedRenderPipeline();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect missing URP asset from default");
Assert.AreEqual("URP0001", analyzer.Descriptor.Id);
}
[Test]
public void URP0001_URPAssetPresent_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
GraphicsSettings.defaultRenderPipeline = urpAsset;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
var analyzer = new MissingAssignedRenderPipeline();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue when URP asset is assigned");
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0002_NoRendererAssigned_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
// Set renderer list to null
urpAsset.m_RendererDataList = null;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new NoRendererAssignedAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1, issues.Count, "Should detect missing renderer");
Assert.AreEqual("URP0002", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0003_URPAssetNotAtLastVersion_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
urpAsset.k_AssetVersion--;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new URPAssetLastVersionValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1, issues.Count, "Should detect not at last version asset");
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0003", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0004_HDREnabled_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
urpAsset.supportsHDR = true;
GraphicsSettings.defaultRenderPipeline = urpAsset;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
var analyzer = new HDREnabledValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect not at last version asset");
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0004", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("HDR"));
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0004_HDRDisabled_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
urpAsset.supportsHDR = false;
GraphicsSettings.defaultRenderPipeline = urpAsset;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
var analyzer = new HDREnabledValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect not at last version asset");
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0004", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("HDR"));
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0005_MSAA4x_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
// Set MSAA to 4x
urpAsset.msaaSampleCount = 4;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
var analyzer = new MSAAValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect MSAA 4x");
Assert.AreEqual("URP0005", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0005_MSAA8x_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Set MSAA to 8x
urpAsset.msaaSampleCount = 8;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new MSAAValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect MSAA 8x");
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0005_MSAA2x_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Set MSAA to 2x
urpAsset.msaaSampleCount = 2;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new MSAAValidation();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue when MSAA is 2x or lower");
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
#endregion
#region Renderer Tests (0101-0200)
[Test]
public void URP0101_InvalidRendererIndex_DetectsOutOfBounds()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Set invalid renderer index (out of bounds)
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 99; // Out of bounds
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new InvalidRendererIndexAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect invalid renderer index");
Assert.AreEqual("URP0101", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0101_InvalidRendererIndex_DetectsNullRenderer()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Set renderer at index to null
urpAsset.m_RendererDataList = new ScriptableRendererData[] { null };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new InvalidRendererIndexAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect null renderer at valid index");
// Cleanup
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0101_ValidRendererIndex_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Set valid renderer index
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new InvalidRendererIndexAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue with valid renderer index");
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0102_MissingRendererFeatures_HasCorrectDescriptor()
{
var analyzer = new MissingRendererFeaturesAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0102", analyzer.Descriptor.Id);
}
[Test]
public void URP0103_DuplicateRendererFeatures_HasCorrectDescriptor()
{
var analyzer = new DuplicateRendererFeaturesAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0103", analyzer.Descriptor.Id);
}
[Test]
public void URP0104_InactiveRendererFeatures_HasCorrectDescriptor()
{
var analyzer = new InactiveRendererFeaturesAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0104", analyzer.Descriptor.Id);
}
#endregion
#region Global Settings Tests (0201-0300)
[Test]
public void URP0201_GlobalSettingsAsset_HasCorrectDescriptor()
{
var analyzer = new GlobalSettingsAssetAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0201", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("Global Settings"));
}
[Test]
public void URP0202_DefaultVolumeProfile_HasCorrectDescriptor()
{
var analyzer = new DefaultVolumeProfileAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0202", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("Volume Profile"));
}
#endregion
#region SRP and Static Batching Tests (0301-0400)
[Test]
public void URP0301_SRPBatcherDisabled_HasCorrectDescriptor()
{
var analyzer = new SRPBatcherAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0301", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("SRP Batcher"));
}
[Test]
public void URP0301_SRPBatcherDisabled_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Disable SRP Batcher
urpAsset.useSRPBatcher = false;
// Assign renderer to URP asset
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new SRPBatcherAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect disabled SRP Batcher");
Assert.AreEqual("URP0301", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0301_SRPBatcherEnabled_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Enable SRP Batcher
urpAsset.useSRPBatcher = true;
// Assign renderer to URP asset
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
var analyzer = new SRPBatcherAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue when SRP Batcher is enabled");
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0302_StaticBatchingConflict_HasCorrectDescriptor()
{
var analyzer = new StaticBatchingWithSRPBatcherAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0302", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("Static Batching"));
}
[Test]
public void URP0302_StaticBatchingDisabled_NoIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
urpAsset.useSRPBatcher = true;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
PlayerSettings.SetStaticBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, false);
var analyzer = new StaticBatchingWithSRPBatcherAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue when static batching is disabled");
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0302_StaticBatchingEnabledWithSRPBatcher_DetectsIssue()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Enable both SRP Batcher and Static Batching
urpAsset.useSRPBatcher = true;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
GraphicsSettings.defaultRenderPipeline = urpAsset;
PlayerSettings.SetStaticBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, true);
var analyzer = new StaticBatchingWithSRPBatcherAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect conflict when both SRP Batcher and Static Batching are enabled");
Assert.AreEqual("URP0302", analyzer.Descriptor.Id);
// Cleanup
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
#endregion
#region Other Tests (0401+)
[Test]
public void URP0401_LinearColorSpace_DetectsGammaSpace()
{
// Arrange
PlayerSettings.colorSpace = ColorSpace.Gamma;
var analyzer = new LinearColorSpaceAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1, issues.Count, "Should detect Gamma color space");
Assert.AreEqual("URP0401", analyzer.Descriptor.Id);
}
[Test]
public void URP0401_LinearColorSpace_NoIssueWhenLinear()
{
// Arrange
PlayerSettings.colorSpace = ColorSpace.Linear;
var analyzer = new LinearColorSpaceAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(0, issues.Count, "Should not detect issue when Linear color space is used");
}
[Test]
public void URP0402_UnmigratedMaterials_HasCorrectDescriptor()
{
var analyzer = new UnmigratedMaterialsAnalyzer();
Assert.IsNotNull(analyzer.Descriptor);
Assert.AreEqual("URP0402", analyzer.Descriptor.Id);
Assert.IsTrue(analyzer.Descriptor.Title.Contains("Materials"));
}
#endregion
#region Quality Settings Tests
[Test]
public void URP0301_SRPBatcherDisabled_DetectsIssues()
{
// Arrange
var urpAsset = ScriptableObject.CreateInstance<UniversalRenderPipelineAsset>();
var rendererData = ScriptableObject.CreateInstance<UniversalRendererData>();
GraphicsSettings.defaultRenderPipeline = urpAsset;
for (int i = 0; i < QualitySettings.names.Length && i < m_PreviousQualitySettings.Length; i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = urpAsset;
}
// Disable SRP Batcher
urpAsset.useSRPBatcher = false;
urpAsset.m_RendererDataList = new ScriptableRendererData[] { rendererData };
urpAsset.m_DefaultRendererIndex = 0;
// Set in quality settings instead of default
int currentQualityLevel = QualitySettings.GetQualityLevel();
QualitySettings.renderPipeline = urpAsset;
var analyzer = new SRPBatcherAnalyzer();
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.AreEqual(1 + QualitySettings.count, issues.Count, "Should detect disabled SRP Batcher in quality settings");
// Cleanup
QualitySettings.renderPipeline = m_PreviousQualitySettings[currentQualityLevel];
UnityEngine.Object.DestroyImmediate(rendererData);
UnityEngine.Object.DestroyImmediate(urpAsset);
}
[Test]
public void URP0001_MissingURPAsset_DetectsInMultipleQualityLevels()
{
// Arrange
var analyzer = new MissingAssignedRenderPipeline();
int currentQualityLevel = QualitySettings.GetQualityLevel();
// Clear render pipeline in multiple quality levels
List<int> clearedLevels = new List<int>();
for (int i = 0; i < Mathf.Min(2, QualitySettings.names.Length); i++)
{
QualitySettings.SetQualityLevel(i);
QualitySettings.renderPipeline = null;
clearedLevels.Add(i);
}
QualitySettings.SetQualityLevel(currentQualityLevel);
// Act
var issues = analyzer.EnumerateIssues().ToList();
// Assert
Assert.IsTrue(issues.Count >= clearedLevels.Count,
$"Should detect missing URP asset in at least {clearedLevels.Count} quality level(s)");
// Cleanup happens in TearDown
}
#endregion
#region Integration Tests
private IEnumerable<IRenderingSettingsAnalyzer> GetAllAnalyzers()
{
var analyzerTypes = TypeCache.GetTypesDerivedFrom<IRenderingSettingsAnalyzer>();
foreach (var type in analyzerTypes)
{
if (!type.IsAbstract && !type.IsInterface)
{
yield return Activator.CreateInstance(type) as IRenderingSettingsAnalyzer;
}
}
}
[Test]
public void AllAnalyzers_HaveUniqueDescriptorIds()
{
// Arrange
var analyzers = GetAllAnalyzers().ToList();
// Act
var descriptorIds = analyzers.Select(a => a.Descriptor.Id).ToList();
var uniqueIds = descriptorIds.Distinct().ToList();
// Assert
Assert.AreEqual(descriptorIds.Count, uniqueIds.Count,
"All descriptor IDs should be unique. Duplicates found.");
}
[Test]
public void AllAnalyzers_FollowNamingConvention()
{
// Arrange
var analyzers = GetAllAnalyzers();
var idPattern = new Regex(@"^URP\d{4}$");
// Act & Assert
foreach (var analyzer in analyzers)
{
string id = analyzer.Descriptor.Id;
Assert.IsTrue(idPattern.IsMatch(id),
$"Descriptor ID '{id}' should match pattern 'URP####' where #### is a 4-digit number");
}
}
[Test]
public void AllAnalyzers_HaveValidDescriptors()
{
// Arrange
var analyzers = GetAllAnalyzers();
// Act & Assert
foreach (var analyzer in analyzers)
{
var descriptor = analyzer.Descriptor;
var typeName = analyzer.GetType().Name;
Assert.IsNotNull(descriptor, $"{typeName}: Descriptor should not be null");
Assert.IsFalse(string.IsNullOrEmpty(descriptor.Id), $"{typeName}: Descriptor ID should not be empty");
Assert.IsFalse(string.IsNullOrEmpty(descriptor.Title), $"{typeName}: Descriptor Title should not be empty");
Assert.IsFalse(string.IsNullOrEmpty(descriptor.Description), $"{typeName}: Descriptor Description should not be empty");
Assert.IsFalse(string.IsNullOrEmpty(descriptor.Recommendation), $"{typeName}: Descriptor Recommendation should not be empty");
}
}
[Test]
public void AllAnalyzers_DescriptorIdsAreInValidRanges()
{
// Arrange
var analyzers = GetAllAnalyzers();
var idPattern = new Regex(@"^URP(\d{4})$");
// Define valid ranges
var validRanges = new[]
{
(start: 1, end: 100, name: "URP Assets"),
(start: 101, end: 200, name: "Renderer"),
(start: 201, end: 300, name: "Global Settings"),
(start: 301, end: 400, name: "SRP and Static Batching"),
(start: 401, end: 9999, name: "Other")
};
// Act & Assert
foreach (var analyzer in analyzers)
{
string id = analyzer.Descriptor.Id;
var typeName = analyzer.GetType().Name;
var match = idPattern.Match(id);
Assert.IsTrue(match.Success, $"{typeName}: Descriptor ID '{id}' should match pattern 'URP####'");
int numericId = int.Parse(match.Groups[1].Value);
bool isInValidRange = validRanges.Any(range => numericId >= range.start && numericId <= range.end);
Assert.IsTrue(isInValidRange,
$"{typeName}: Descriptor ID '{id}' (numeric value: {numericId}) is not in any valid range. " +
$"Valid ranges are: {string.Join(", ", validRanges.Select(r => $"{r.name} ({r.start:D4}-{r.end:D4})"))}");
}
}
[Test]
public void AllAnalyzers_HaveCategoryAttribute()
{
// Arrange
var analyzerTypes = TypeCache.GetTypesDerivedFrom<IRenderingSettingsAnalyzer>();
// Act & Assert
foreach (var type in analyzerTypes)
{
if (type.IsAbstract || type.IsInterface)
continue;
var categoryAttr = type.GetCustomAttribute<System.ComponentModel.CategoryAttribute>();
Assert.IsNotNull(categoryAttr, $"{type.Name}: Should have [Category] attribute");
var validCategories = new[] { "URP Assets", "Renderer", "Global Settings", "SRP and Static Batching", "Other" };
Assert.Contains(categoryAttr.Category, validCategories,
$"{type.Name}: Category '{categoryAttr.Category}' should be one of the valid categories");
}
}
[Test]
public void AllAnalyzers_DescriptorIdsMatchCategoryAttribute()
{
// Arrange
var analyzerTypes = TypeCache.GetTypesDerivedFrom<IRenderingSettingsAnalyzer>();
var idPattern = new Regex(@"^URP(\d{4})$");
// Act & Assert
foreach (var type in analyzerTypes)
{
if (type.IsAbstract || type.IsInterface)
continue;
var analyzer = Activator.CreateInstance(type) as IRenderingSettingsAnalyzer;
string id = analyzer.Descriptor.Id;
var typeName = type.Name;
// Get the Category attribute
var categoryAttr = type.GetCustomAttribute<System.ComponentModel.CategoryAttribute>();
Assert.IsNotNull(categoryAttr, $"{typeName}: Should have [Category] attribute");
string category = categoryAttr.Category;
var match = idPattern.Match(id);
Assert.IsTrue(match.Success, $"{typeName}: Descriptor ID '{id}' should match pattern 'URP####'");
int numericId = int.Parse(match.Groups[1].Value);
var expectedRange = GetRangeForCategory(category);
Assert.IsTrue(numericId >= expectedRange.start && numericId <= expectedRange.end,
$"{typeName}: ID {id} (numeric: {numericId}) should be in range {expectedRange.start:D4}-{expectedRange.end:D4} for category '{category}'");
}
}
[Test]
public void AllCategories_HaveAnalyzersInCorrectRanges()
{
// Arrange
var analyzerTypes = TypeCache.GetTypesDerivedFrom<IRenderingSettingsAnalyzer>();
var idPattern = new Regex(@"^URP(\d{4})$");
var categoriesFound = new Dictionary<string, List<(string typeName, int id)>>();
// Act
foreach (var type in analyzerTypes)
{
if (type.IsAbstract || type.IsInterface)
continue;
var analyzer = Activator.CreateInstance(type) as IRenderingSettingsAnalyzer;
var categoryAttr = type.GetCustomAttribute<System.ComponentModel.CategoryAttribute>();
if (categoryAttr != null)
{
var match = idPattern.Match(analyzer.Descriptor.Id);
if (match.Success)
{
int numericId = int.Parse(match.Groups[1].Value);
if (!categoriesFound.ContainsKey(categoryAttr.Category))
categoriesFound[categoryAttr.Category] = new List<(string, int)>();
categoriesFound[categoryAttr.Category].Add((type.Name, numericId));
}
}
}
// Assert
foreach (var kvp in categoriesFound)
{
var category = kvp.Key;
var analyzers = kvp.Value;
var expectedRange = GetRangeForCategory(category);
foreach (var (typeName, numericId) in analyzers)
{
Assert.IsTrue(numericId >= expectedRange.start && numericId <= expectedRange.end,
$"Category '{category}': {typeName} has ID {numericId:D4} which is outside expected range {expectedRange.start:D4}-{expectedRange.end:D4}");
}
}
}
private (int start, int end) GetRangeForCategory(string category)
{
return category switch
{
"URP Assets" => (1, 100),
"Renderer" => (101, 200),
"Global Settings" => (201, 300),
"SRP and Static Batching" => (301, 400),
"Other" => (401, 9999),
_ => throw new ArgumentException($"Unknown category: {category}")
};
}
#endregion
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 729807ff59ce7944f978ddc8d3c09c8f
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2d428e2ad3bcf4344a7b4d4c8a2daa1a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More