浏览代码

Merge pull request #211 from Unity-Technologies/Branch_ExportSky

Added a way to export the current sky and to override the sky lighting with a cubemap.
/fptl_cleanup
GitHub 7 年前
当前提交
fea6ad98
共有 15 个文件被更改,包括 298 次插入70 次删除
  1. 30
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  2. 5
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs
  4. 84
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs
  5. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/SkySettings.cs
  6. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Utilities.cs
  7. 110
      Assets/TestScenes/HDTest/GlobalIlluminationTest.unity
  8. 9
      Assets/ScriptableRenderPipeline/common/Resources.meta
  9. 20
      Assets/TestScenes/HDTest/GlobalIlluminationTest/CommonSettings_GlobalIllumination.asset
  10. 9
      Assets/TestScenes/HDTest/GlobalIlluminationTest/CommonSettings_GlobalIllumination.asset.meta
  11. 20
      Assets/TestScenes/HDTest/GlobalIlluminationTest/HDRISkySettings_GlobalIllumination.asset
  12. 9
      Assets/TestScenes/HDTest/GlobalIlluminationTest/HDRISkySettings_GlobalIllumination.asset.meta
  13. 9
      Assets/ScriptableRenderPipeline/common/Resources/BlitCubemap.shader.meta
  14. 56
      Assets/ScriptableRenderPipeline/common/Resources/BlitCubemap.shader

30
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEngine.Experimental.Rendering.HDPipeline;
using System.IO;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{

LayeredLitGUI.SetupMaterialKeywordsAndPass(mat);
EditorUtility.SetDirty(mat);
}
}
}
[MenuItem("HDRenderPipeline/Export Sky to Image")]
static void ExportSkyToImage()
{
HDRenderPipelineInstance renderpipelineInstance = UnityEngine.Experimental.Rendering.RenderPipelineManager.currentPipeline as HDRenderPipelineInstance;
if(renderpipelineInstance == null)
{
Debug.LogError("HDRenderPipeline is not instantiated.");
return;
}
Texture2D result = renderpipelineInstance.ExportSkyToTexture();
if(result == null)
{
return;
}
// Encode texture into PNG
byte[] bytes = null;
bytes = result.EncodeToEXR(Texture2D.EXRFlags.CompressZIP);
Object.DestroyImmediate(result);
string assetPath = EditorUtility.SaveFilePanel("Export Sky", "Assets", "SkyExport", "exr");
if (!string.IsNullOrEmpty(assetPath))
{
File.WriteAllBytes(assetPath, bytes);
AssetDatabase.Refresh();
}
}
}

5
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


m_SkyManager.RenderSky(hdCamera, m_LightLoop == null ? null : m_LightLoop.GetCurrentSunLight(), m_CameraColorBufferRT, m_CameraDepthStencilBufferRT, renderContext);
}
public Texture2D ExportSkyToTexture()
{
return m_SkyManager.ExportSkyToTexture();
}
void RenderForward(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext, bool renderOpaque)
{
// TODO: Currently we can't render opaque object forward when deferred is enabled

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs


public readonly GUIContent skyMultiplier = new GUIContent("Multiplier", "Intensity multiplier for the sky.");
public readonly GUIContent environmentUpdateMode = new GUIContent("Environment Update Mode", "Specify how the environment lighting should be updated.");
public readonly GUIContent environmentUpdatePeriod = new GUIContent("Environment Update Period", "If environment update is set to realtime, period in seconds at which it is updated (0.0 means every frame).");
public readonly GUIContent lightingOverride = new GUIContent("Lighting Override", "If a lighting override cubemap is provided, this cubemap will be used to compute lighting instead of the result from the visible sky.");
}
private static Styles s_Styles = null;

private SerializedProperty m_SkyRotation;
private SerializedProperty m_EnvUpdateMode;
private SerializedProperty m_EnvUpdatePeriod;
private SerializedProperty m_LightingOverride;
void OnEnable()
{

m_SkyRotation = serializedObject.FindProperty("rotation");
m_EnvUpdateMode = serializedObject.FindProperty("updateMode");
m_EnvUpdatePeriod = serializedObject.FindProperty("updatePeriod");
m_LightingOverride = serializedObject.FindProperty("lightingOverride");
}
public override void OnInspectorGUI()

{
EditorGUILayout.PropertyField(m_EnvUpdatePeriod, styles.environmentUpdatePeriod);
}
EditorGUILayout.PropertyField(m_LightingOverride, styles.lightingOverride);
serializedObject.ApplyModifiedProperties();
}

84
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs


RenderTexture m_SkyboxConditionalCdfRT = null;
Material m_StandardSkyboxMaterial = null; // This is the Unity standard skybox material. Used to pass the correct cubemap to Enlighten.
Material m_BlitCubemapMaterial = null;
IBLFilterGGX m_iblFilterGgx = null;

m_iblFilterGgx = new IBLFilterGGX();
// TODO: We need to have an API to send our sky information to Enlighten. For now use a workaround through skybox/cubemap material...
m_StandardSkyboxMaterial = Utilities.CreateEngineMaterial("Skybox/Cubemap");
m_StandardSkyboxMaterial = Utilities.CreateEngineMaterial("Skybox/Cubemap");
m_BlitCubemapMaterial = Utilities.CreateEngineMaterial("Hidden/BlitCubemap");
m_CurrentUpdateTime = 0.0f;
}

}
}
private void BlitCubemap(ScriptableRenderContext renderContext, Cubemap source, RenderTexture dest)
{
MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();
for (int i = 0; i < 6; ++i)
{
Utilities.SetRenderTarget(renderContext, dest, ClearFlag.ClearNone, 0, (CubemapFace)i);
var cmd = new CommandBuffer { name = "" };
propertyBlock.SetTexture("_MainTex", source);
propertyBlock.SetFloat("_faceIndex", (float)i);
cmd.DrawProcedural(Matrix4x4.identity, m_BlitCubemapMaterial, 0, MeshTopology.Triangles, 3, 1, propertyBlock);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
private void RenderCubemapGGXConvolution(ScriptableRenderContext renderContext, BuiltinSkyParameters builtinParams, SkySettings skyParams, Texture input, RenderTexture target)
{
using (new Utilities.ProfilingSample("Sky Pass: GGX Convolution", renderContext))

)
{
// Render sky into a cubemap - doesn't happen every frame, can be controlled
RenderSkyToCubemap(m_BuiltinParameters, skySettings, m_SkyboxCubemapRT);
if(m_SkySettings.lightingOverride == null)
RenderSkyToCubemap(m_BuiltinParameters, skySettings, m_SkyboxCubemapRT);
// In case the user overrides the lighting, we already have a cubemap ready but we need to blit it anyway for potential resize and so that we can generate proper mipmaps for enlighten.
else
BlitCubemap(renderContext, m_SkySettings.lightingOverride, m_SkyboxCubemapRT);
// Convolve downsampled cubemap
RenderCubemapGGXConvolution(renderContext, m_BuiltinParameters, skySettings, m_SkyboxCubemapRT, m_SkyboxGGXCubemapRT);

m_Renderer.RenderSky(m_BuiltinParameters, skySettings, false);
}
}
}
public Texture2D ExportSkyToTexture()
{
if(m_Renderer == null)
{
Debug.LogError("Cannot export sky to a texture, no SkyRenderer is setup.");
return null;
}
if(m_SkySettings == null)
{
Debug.LogError("Cannot export sky to a texture, no Sky settings are setup.");
return null;
}
int resolution = (int)m_SkySettings.resolution;
RenderTexture tempRT = new RenderTexture(resolution * 6, resolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
tempRT.dimension = TextureDimension.Tex2D;
tempRT.useMipMap = false;
tempRT.autoGenerateMips = false;
tempRT.filterMode = FilterMode.Trilinear;
tempRT.Create();
Texture2D temp = new Texture2D(resolution * 6, resolution, TextureFormat.RGBAFloat, false);
Texture2D result = new Texture2D(resolution * 6, resolution, TextureFormat.RGBAFloat, false);
// Note: We need to invert in Y the cubemap faces because the current sky cubemap is inverted (because it's a RT)
// So to invert it again so that it's a proper cubemap image we need to do it in several steps because ReadPixels does not have scale parameters:
// - Convert the cubemap into a 2D texture
// - Blit and invert it to a temporary target.
// - Read this target again into the result texture.
int offset = 0;
for (int i = 0; i < 6; ++i)
{
Graphics.SetRenderTarget(m_SkyboxCubemapRT, 0, (CubemapFace)i);
temp.ReadPixels(new Rect(0, 0, resolution, resolution), offset, 0);
temp.Apply();
offset += resolution;
}
// Flip texture.
// Temporarily disabled until proper API reaches trunk
//Graphics.Blit(temp, tempRT, new Vector2(1.0f, -1.0f), new Vector2(0.0f, 0.0f));
Graphics.Blit(temp, tempRT);
result.ReadPixels(new Rect(0, 0, resolution * 6, resolution), 0, 0);
result.Apply();
Graphics.SetRenderTarget(null);
Object.DestroyImmediate(temp);
Object.DestroyImmediate(tempRT);
return result;
}
}
}

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/Sky/SkySettings.cs


public SkyResolution resolution = SkyResolution.SkyResolution256;
public EnvironementUpdateMode updateMode = EnvironementUpdateMode.OnChanged;
public float updatePeriod = 0.0f;
public Cubemap lightingOverride = null;
private FieldInfo[] m_Properties;

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Utilities.cs


HDRenderPipeline renderContext = GraphicsSettings.renderPipelineAsset as HDRenderPipeline;
if (renderContext == null)
{
Debug.LogWarning("SkyParameters component can only be used with HDRenderPipeline custom RenderPipeline.");
Debug.LogWarning("HDRenderPipeline is not instantiated.");
return null;
}

110
Assets/TestScenes/HDTest/GlobalIlluminationTest.unity


m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_IndirectSpecularColor: {r: 0.3199536, g: 0.2875398, b: 0.2644253, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0

m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 20738779}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &29795110
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 29795112}
- component: {fileID: 29795111}
m_Layer: 0
m_Name: Scene Settings
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &29795111
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 29795110}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0e34c98127e05d340ba44a1d4a734454, type: 3}
m_Name:
m_EditorClassIdentifier:
m_CommonSettings: {fileID: 11400000, guid: 99a5b1b4f3634864da02f42919203da9, type: 2}
m_SkySettings: {fileID: 11400000, guid: 6708eedd5f11b464aa0e50eb2f100ae4, type: 2}
--- !u!4 &29795112
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 29795110}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &32562342
GameObject:
m_ObjectHideFlags: 0

- {x: -1, y: 1, z: -1}
- {x: -1, y: -1, z: 1}
- {x: -1, y: -1, z: -1}
--- !u!1 &1944423445
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 1944423448}
- component: {fileID: 1944423447}
- component: {fileID: 1944423446}
m_Layer: 0
m_Name: SceneSettings
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1944423446
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1944423445}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59b6606ef2548734bb6d11b9d160bc7e, type: 3}
m_Name:
m_EditorClassIdentifier:
rotation: 0
exposure: 0
multiplier: 1
resolution: 256
updateMode: 0
updatePeriod: 0
skyHDRI: {fileID: 8900000, guid: de78f930088fc194290da7400c89bfb5, type: 3}
--- !u!114 &1944423447
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1944423445}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bc357c46587fc9d4cb8f311794d7d2f3, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Settings:
m_ShadowMaxDistance: 1000
m_ShadowCascadeCount: 4
m_ShadowCascadeSplit0: 0.05
m_ShadowCascadeSplit1: 0.2
m_ShadowCascadeSplit2: 0.3
m_ShadowNearPlaneOffset: 5
--- !u!4 &1944423448
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1944423445}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

9
Assets/ScriptableRenderPipeline/common/Resources.meta


fileFormatVersion: 2
guid: 1e02c245110074e4aa88a9b408060d4f
folderAsset: yes
timeCreated: 1491318329
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

20
Assets/TestScenes/HDTest/GlobalIlluminationTest/CommonSettings_GlobalIllumination.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bc357c46587fc9d4cb8f311794d7d2f3, type: 3}
m_Name: CommonSettings_GlobalIllumination
m_EditorClassIdentifier:
m_Settings:
m_ShadowMaxDistance: 400
m_ShadowCascadeCount: 4
m_ShadowCascadeSplit0: 0.05
m_ShadowCascadeSplit1: 0.2
m_ShadowCascadeSplit2: 0.3
m_ShadowNearPlaneOffset: 5

9
Assets/TestScenes/HDTest/GlobalIlluminationTest/CommonSettings_GlobalIllumination.asset.meta


fileFormatVersion: 2
guid: 99a5b1b4f3634864da02f42919203da9
timeCreated: 1491228144
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

20
Assets/TestScenes/HDTest/GlobalIlluminationTest/HDRISkySettings_GlobalIllumination.asset


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59b6606ef2548734bb6d11b9d160bc7e, type: 3}
m_Name: HDRISkySettings_GlobalIllumination
m_EditorClassIdentifier:
rotation: 0
exposure: 0
multiplier: 1
resolution: 256
updateMode: 0
updatePeriod: 0
skyHDRI: {fileID: 8900000, guid: de78f930088fc194290da7400c89bfb5, type: 3}

9
Assets/TestScenes/HDTest/GlobalIlluminationTest/HDRISkySettings_GlobalIllumination.asset.meta


fileFormatVersion: 2
guid: 6708eedd5f11b464aa0e50eb2f100ae4
timeCreated: 1488464830
licenseType: Pro
NativeFormatImporter:
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderPipeline/common/Resources/BlitCubemap.shader.meta


fileFormatVersion: 2
guid: d05913e251bed7a4992c921c62e1b647
timeCreated: 1491318357
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

56
Assets/ScriptableRenderPipeline/common/Resources/BlitCubemap.shader


// Note: This shader is supposed to be removed at some point when Graphics.ConvertTexture can take a RenderTexture as a destination (it's only used by sky manager for now).
Shader "Hidden/BlitCubemap" {
SubShader {
// Cubemap blit. Takes a face index.
Pass {
ZTest Always Cull Off ZWrite Off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 4.5
#include "../../ShaderLibrary/Common.hlsl"
TEXTURECUBE(_MainTex);
SAMPLERCUBE(sampler_MainTex);
float _faceIndex;
struct appdata_t {
uint vertexID : SV_VertexID;
};
struct v2f {
float4 vertex : SV_POSITION;
float3 texcoord : TEXCOORD0;
};
static const float3 faceU[6] = { float3(0, 0, -1), float3(0, 0, 1), float3(1, 0, 0), float3(1, 0, 0), float3(1, 0, 0), float3(-1, 0, 0) };
static const float3 faceV[6] = { float3(0, -1, 0), float3(0, -1, 0), float3(0, 0, 1), float3(0, 0, -1), float3(0, -1, 0), float3(0, -1, 0) };
v2f vert (appdata_t v)
{
v2f o;
o.vertex = GetFullScreenTriangleVertexPosition(v.vertexID);
float2 uv = GetFullScreenTriangleTexcoord(v.vertexID) * 2.0 - 1.0;
int idx = (int)_faceIndex;
float3 transformU = faceU[idx];
float3 transformV = faceV[idx];
float3 n = cross(transformV, transformU);
o.texcoord = n + uv.x * transformU + uv.y * transformV;
return o;
}
float4 frag (v2f i) : SV_Target
{
return SAMPLE_TEXTURECUBE(_MainTex, sampler_MainTex, i.texcoord);
}
ENDHLSL
}
}
Fallback Off
}
正在加载...
取消
保存