Unity HDRPでは、VolumeのVirtual Environmentから背景(環境)を設定できます。現状、選べるSky TypeはGradient Sky、HDRI Sky、Physically Based Skyの3つですが、自分でカスタムSkyを作成することも可能です。この記事では単色のSkyを描画するカスタムSkyを作成してみます。
使用しているバージョンは以下のようになっています。
- Unity: 2021.2.9f1
- High Definition RP: 12.14
この記事はUnity HDRP公式ドキュメントおよびHDRPのビルトインSky実装を参考にしています。
- 公式ドキュメント
- ビルトインSky実装の場所
/Packages/High Definition RP/Runtime/Sky
/Packages/High Definition RP/Editor/Sky
カスタムSkyを実装するには、以下の三種類のスクリプト(と必要であればSky Settingsのインスペクター拡張)を作成する必要があります。
-
Sky Settings:
- Volumeコンポーネントに表示され、カスタムSkyのプロパティを管理する
-
Sky Renderer:
- Sky Settingsのプロパティをもとに、Sky Rendering ShaderでカスタムSkyの描画を行う
-
Sky Rendering Shader:
- カスタムSkyの描画を行うシェーダー
-
(Sky Settings Editor):
- Sky Settingsのインスペクター拡張
まず、SkySettingsです。
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
[VolumeComponentMenu("Sky/Uniform Sky")]
[SkyUniqueID(UNIFORM_SKY_UNIQUE_ID)]
public class UniformSky : SkySettings
{
const int UNIFORM_SKY_UNIQUE_ID = 782151;
[Tooltip("Specifies the color of the sky.")]
public ColorParameter color = new ColorParameter(Color.white, true, false, true);
public override Type GetSkyRendererType()
{
return typeof(UniformSkyRenderer);
}
public override int GetHashCode()
{
int hash = base.GetHashCode();
unchecked
{
# if UNITY_2019_3
hash = hash * 23 + color.value.GetHashCode();
# else
hash = hash * 23 + color.GetHashCode();
# endif
}
return hash;
}
}
次に、Sky Rendererです。
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
public class UniformSkyRenderer : SkyRenderer
{
public static readonly int _Color = Shader.PropertyToID("_Color");
public static readonly int _SkyIntensity = Shader.PropertyToID("_SkyIntensity");
Material m_UniformSkyMaterial;
public override void Build()
{
m_UniformSkyMaterial = CoreUtils.CreateEngineMaterial(GetUniformSkyShader());
}
Shader GetUniformSkyShader()
{
return Shader.Find("Hidden/HDRP/Sky/Custom/UniformSky");
}
public override void Cleanup()
{
CoreUtils.Destroy(m_UniformSkyMaterial);
}
protected override bool Update(BuiltinSkyParameters builtinParams)
{
return false;
}
public override void RenderSky(BuiltinSkyParameters builtinParams, bool renderForCubemap, bool renderSunDisk)
{
var uniformSky = builtinParams.skySettings as UniformSky;
float intensity = GetSkyIntensity(uniformSky, builtinParams.debugSettings);
m_UniformSkyMaterial.SetColor(_Color, uniformSky.color.value);
m_UniformSkyMaterial.SetFloat(_SkyIntensity, GetSkyIntensity(uniformSky, builtinParams.debugSettings));
CoreUtils.DrawFullScreen(builtinParams.commandBuffer, m_UniformSkyMaterial, null, renderForCubemap ? 0 : 1);
}
}
最後にSky Rendering Shaderです。UniformSkyRenderer.cs
でShader.Find
を使用しているので、このシェーダーをビルドに含めるにはResources
ディレクトリに置くか、Always-included Shaders
に含める必要があります。
Shader "Hidden/HDRP/Sky/Custom/UniformSky"
{
HLSLINCLUDE
#pragma vertex Vert
#pragma editor_sync_compilation
#pragma target 4.5
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonLighting.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/SkyUtils.hlsl"
float3 _Color;
float _SkyIntensity;
struct Attributes
{
uint vertexID : SV_VertexID;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID, UNITY_RAW_FAR_CLIP_VALUE);
return output;
}
float4 RenderSky(Varyings input)
{
return float4(_Color * _SkyIntensity, 1.0);
}
float4 FragBaking(Varyings input) : SV_Target
{
return RenderSky(input);
}
float4 FragRender(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 color = RenderSky(input);
color.rgb *= GetCurrentExposureMultiplier();
return color;
}
ENDHLSL
SubShader
{
Tags{ "RenderPipeline" = "HDRenderPipeline" }
Pass
{
ZWrite Off
ZTest Always
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment FragBaking
ENDHLSL
}
Pass
{
ZWrite Off
ZTest LEqual
Blend Off
Cull Off
HLSLPROGRAM
#pragma fragment FragRender
ENDHLSL
}
}
Fallback Off
}
ここまで作成すると、Virtual EnvironmentのSky TypeでUniform Skyが選択できるようになり、かつVolumeコンポーネントのAdd OverrideでUniform Skyを追加できます。Uniform Skyを適用するとColorプロパティで選択した色でSkyが描画されます。
Uniform Sky自体はここまでのスクリプトで機能しますが、余分なプロパティが表示されているのでインスペクター拡張を作成して必要なプロパティのみ表示します。
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.HighDefinition;
[CanEditMultipleObjects]
[VolumeComponentEditor(typeof(UniformSky))]
public class UniformSkyEditor : SkySettingsEditor
{
SerializedDataParameter m_Color;
public override void OnEnable()
{
base.OnEnable();
m_CommonUIElementsMask = (uint)SkySettingsUIElement.UpdateMode
| (uint)SkySettingsUIElement.SkyIntensity;
var o = new PropertyFetcher<UniformSky>(serializedObject);
m_Color = Unpack(o.Find(x => x.color));
}
public override void OnInspectorGUI()
{
PropertyField(m_Color);
base.CommonSkySettingsGUI();
}
}