您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
423 行
17 KiB
423 行
17 KiB
using System;
|
|
using System.IO;
|
|
using System.Linq.Expressions;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering.HDPipeline;
|
|
|
|
namespace UnityEditor.Experimental.Rendering.HDPipeline
|
|
{
|
|
using GradingType = PostProcessing.ColorGradingSettings.GradingType;
|
|
using EyeAdaptationType = PostProcessing.EyeAdaptationSettings.EyeAdaptationType;
|
|
|
|
[CustomEditor(typeof(PostProcessing))]
|
|
public class PostProcessingEditor : Editor
|
|
{
|
|
#region Serialized settings
|
|
public class ColorGradingSettings
|
|
{
|
|
public SerializedProperty type;
|
|
public SerializedProperty exposure;
|
|
|
|
public SerializedProperty logLut;
|
|
|
|
public SerializedProperty neutralBlackIn;
|
|
public SerializedProperty neutralWhiteIn;
|
|
public SerializedProperty neutralBlackOut;
|
|
public SerializedProperty neutralWhiteOut;
|
|
public SerializedProperty neutralWhiteLevel;
|
|
public SerializedProperty neutralWhiteClip;
|
|
}
|
|
|
|
public class EyeAdaptationSettings
|
|
{
|
|
public SerializedProperty enabled;
|
|
public SerializedProperty showDebugHistogramInGameView;
|
|
|
|
public SerializedProperty lowPercent;
|
|
public SerializedProperty highPercent;
|
|
|
|
public SerializedProperty minLuminance;
|
|
public SerializedProperty maxLuminance;
|
|
public SerializedProperty exposureCompensation;
|
|
|
|
public SerializedProperty adaptationType;
|
|
|
|
public SerializedProperty speedUp;
|
|
public SerializedProperty speedDown;
|
|
|
|
public SerializedProperty logMin;
|
|
public SerializedProperty logMax;
|
|
}
|
|
|
|
public class ChromaticAberrationSettings
|
|
{
|
|
public SerializedProperty enabled;
|
|
public SerializedProperty spectralTexture;
|
|
public SerializedProperty intensity;
|
|
}
|
|
|
|
public class VignetteSettings
|
|
{
|
|
public SerializedProperty enabled;
|
|
public SerializedProperty color;
|
|
public SerializedProperty center;
|
|
public SerializedProperty intensity;
|
|
public SerializedProperty smoothness;
|
|
}
|
|
|
|
public class BloomSettings
|
|
{
|
|
public SerializedProperty enabled;
|
|
public SerializedProperty intensity;
|
|
public SerializedProperty threshold;
|
|
public SerializedProperty softKnee;
|
|
public SerializedProperty radius;
|
|
public SerializedProperty lensTexture;
|
|
public SerializedProperty lensIntensity;
|
|
}
|
|
#endregion
|
|
|
|
public ColorGradingSettings colorGrading;
|
|
public EyeAdaptationSettings eyeAdaptation;
|
|
public ChromaticAberrationSettings chromaSettings;
|
|
public VignetteSettings vignetteSettings;
|
|
public BloomSettings bloomSettings;
|
|
public SerializedProperty globalDithering;
|
|
|
|
SerializedProperty FindProperty<TValue>(Expression<Func<PostProcessing, TValue>> expr)
|
|
{
|
|
var path = Utilities.GetFieldPath(expr);
|
|
return serializedObject.FindProperty(path);
|
|
}
|
|
|
|
void OnEnable()
|
|
{
|
|
colorGrading = new ColorGradingSettings
|
|
{
|
|
type = FindProperty(x => x.colorGrading.type),
|
|
exposure = FindProperty(x => x.colorGrading.exposure),
|
|
|
|
logLut = FindProperty(x => x.colorGrading.logLut),
|
|
|
|
neutralBlackIn = FindProperty(x => x.colorGrading.neutralBlackIn),
|
|
neutralWhiteIn = FindProperty(x => x.colorGrading.neutralWhiteIn),
|
|
neutralBlackOut = FindProperty(x => x.colorGrading.neutralBlackOut),
|
|
neutralWhiteOut = FindProperty(x => x.colorGrading.neutralWhiteOut),
|
|
neutralWhiteLevel = FindProperty(x => x.colorGrading.neutralWhiteLevel),
|
|
neutralWhiteClip = FindProperty(x => x.colorGrading.neutralWhiteClip)
|
|
};
|
|
|
|
eyeAdaptation = new EyeAdaptationSettings
|
|
{
|
|
enabled = FindProperty(x => x.eyeAdaptation.enabled),
|
|
showDebugHistogramInGameView = FindProperty(x => x.eyeAdaptation.showDebugHistogramInGameView),
|
|
|
|
lowPercent = FindProperty(x => x.eyeAdaptation.lowPercent),
|
|
highPercent = FindProperty(x => x.eyeAdaptation.highPercent),
|
|
|
|
minLuminance = FindProperty(x => x.eyeAdaptation.minLuminance),
|
|
maxLuminance = FindProperty(x => x.eyeAdaptation.maxLuminance),
|
|
exposureCompensation = FindProperty(x => x.eyeAdaptation.exposureCompensation),
|
|
|
|
adaptationType = FindProperty(x => x.eyeAdaptation.adaptationType),
|
|
|
|
speedUp = FindProperty(x => x.eyeAdaptation.speedUp),
|
|
speedDown = FindProperty(x => x.eyeAdaptation.speedDown),
|
|
|
|
logMin = FindProperty(x => x.eyeAdaptation.logMin),
|
|
logMax = FindProperty(x => x.eyeAdaptation.logMax)
|
|
};
|
|
|
|
chromaSettings = new ChromaticAberrationSettings
|
|
{
|
|
enabled = FindProperty(x => x.chromaSettings.enabled),
|
|
spectralTexture = FindProperty(x => x.chromaSettings.spectralTexture),
|
|
intensity = FindProperty(x => x.chromaSettings.intensity)
|
|
};
|
|
|
|
vignetteSettings = new VignetteSettings
|
|
{
|
|
enabled = FindProperty(x => x.vignetteSettings.enabled),
|
|
color = FindProperty(x => x.vignetteSettings.color),
|
|
center = FindProperty(x => x.vignetteSettings.center),
|
|
intensity = FindProperty(x => x.vignetteSettings.intensity),
|
|
smoothness = FindProperty(x => x.vignetteSettings.smoothness)
|
|
};
|
|
|
|
bloomSettings = new BloomSettings
|
|
{
|
|
enabled = FindProperty(x => x.bloomSettings.enabled),
|
|
|
|
intensity = FindProperty(x => x.bloomSettings.intensity),
|
|
threshold = FindProperty(x => x.bloomSettings.threshold),
|
|
|
|
softKnee = FindProperty(x => x.bloomSettings.softKnee),
|
|
radius = FindProperty(x => x.bloomSettings.radius),
|
|
|
|
lensTexture = FindProperty(x => x.bloomSettings.lensTexture),
|
|
lensIntensity = FindProperty(x => x.bloomSettings.lensIntensity)
|
|
};
|
|
|
|
globalDithering = FindProperty(x => x.globalDithering);
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
serializedObject.Update();
|
|
|
|
Do("Color Grading", ColorGradingUI);
|
|
Do("Eye Adaptation", EyeAdaptationUI);
|
|
Do("Bloom", BloomUI);
|
|
Do("Chromatic Aberration", ChromaticAberrationUI);
|
|
Do("Vignette", VignetteUI);
|
|
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.PropertyField(globalDithering);
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void Do(string header, Action func)
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField(header, EditorStyles.boldLabel);
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
if (func != null)
|
|
func();
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
void ColorGradingUI()
|
|
{
|
|
var camera = (target as PostProcessing).GetComponent<Camera>();
|
|
if (camera != null)
|
|
{
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.Space(EditorGUI.indentLevel * 15f);
|
|
if (GUILayout.Button("Export frame to EXR", EditorStyles.miniButton))
|
|
{
|
|
string path = EditorUtility.SaveFilePanelInProject("Export frame as EXR...", "Frame.exr", "exr", "");
|
|
|
|
if (!string.IsNullOrEmpty(path))
|
|
SaveFrameToEXR(camera, path);
|
|
}
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.PropertyField(colorGrading.exposure);
|
|
EditorGUILayout.PropertyField(colorGrading.type);
|
|
|
|
EditorGUI.indentLevel++;
|
|
|
|
var gradingType = (GradingType)colorGrading.type.intValue;
|
|
|
|
if (gradingType == GradingType.Custom)
|
|
{
|
|
EditorGUILayout.PropertyField(colorGrading.logLut);
|
|
|
|
if (!ValidateLutImportSettings())
|
|
{
|
|
EditorGUILayout.HelpBox("Invalid LUT import settings.", MessageType.Warning);
|
|
|
|
GUILayout.Space(-32);
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("Fix", GUILayout.Width(60)))
|
|
{
|
|
SetLUTImportSettings();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
GUILayout.Space(8);
|
|
}
|
|
GUILayout.Space(11);
|
|
}
|
|
}
|
|
else if (gradingType == GradingType.Neutral)
|
|
{
|
|
EditorGUILayout.PropertyField(colorGrading.neutralBlackIn);
|
|
EditorGUILayout.PropertyField(colorGrading.neutralWhiteIn);
|
|
EditorGUILayout.PropertyField(colorGrading.neutralBlackOut);
|
|
EditorGUILayout.PropertyField(colorGrading.neutralWhiteOut);
|
|
EditorGUILayout.PropertyField(colorGrading.neutralWhiteLevel);
|
|
EditorGUILayout.PropertyField(colorGrading.neutralWhiteClip);
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
void EyeAdaptationUI()
|
|
{
|
|
EditorGUILayout.PropertyField(eyeAdaptation.enabled);
|
|
|
|
if (eyeAdaptation.enabled.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(eyeAdaptation.showDebugHistogramInGameView);
|
|
|
|
EditorGUILayout.PropertyField(eyeAdaptation.logMin, new GUIContent("Histogram Log Min"));
|
|
EditorGUILayout.PropertyField(eyeAdaptation.logMax, new GUIContent("Histogram Log Max"));
|
|
EditorGUILayout.Space();
|
|
|
|
float low = eyeAdaptation.lowPercent.floatValue;
|
|
float high = eyeAdaptation.highPercent.floatValue;
|
|
|
|
EditorGUILayout.MinMaxSlider(new GUIContent("Filter"), ref low, ref high, 1f, 99f);
|
|
|
|
eyeAdaptation.lowPercent.floatValue = low;
|
|
eyeAdaptation.highPercent.floatValue = high;
|
|
|
|
EditorGUILayout.PropertyField(eyeAdaptation.minLuminance);
|
|
EditorGUILayout.PropertyField(eyeAdaptation.maxLuminance);
|
|
EditorGUILayout.PropertyField(eyeAdaptation.exposureCompensation);
|
|
|
|
EditorGUILayout.PropertyField(eyeAdaptation.adaptationType);
|
|
|
|
if (eyeAdaptation.adaptationType.intValue == (int)EyeAdaptationType.Progressive)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUILayout.PropertyField(eyeAdaptation.speedUp);
|
|
EditorGUILayout.PropertyField(eyeAdaptation.speedDown);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BloomUI()
|
|
{
|
|
EditorGUILayout.PropertyField(bloomSettings.enabled);
|
|
|
|
if (bloomSettings.enabled.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(bloomSettings.intensity);
|
|
EditorGUILayout.PropertyField(bloomSettings.threshold);
|
|
|
|
EditorGUILayout.PropertyField(bloomSettings.softKnee);
|
|
EditorGUILayout.PropertyField(bloomSettings.radius);
|
|
|
|
EditorGUILayout.PropertyField(bloomSettings.lensTexture);
|
|
EditorGUILayout.PropertyField(bloomSettings.lensIntensity);
|
|
|
|
bloomSettings.intensity.floatValue = Mathf.Max(0f, bloomSettings.intensity.floatValue);
|
|
bloomSettings.threshold.floatValue = Mathf.Max(0f, bloomSettings.threshold.floatValue);
|
|
bloomSettings.lensIntensity.floatValue = Mathf.Max(0f, bloomSettings.lensIntensity.floatValue);
|
|
}
|
|
}
|
|
|
|
void ChromaticAberrationUI()
|
|
{
|
|
EditorGUILayout.PropertyField(chromaSettings.enabled);
|
|
|
|
if (chromaSettings.enabled.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(chromaSettings.spectralTexture);
|
|
EditorGUILayout.PropertyField(chromaSettings.intensity);
|
|
}
|
|
}
|
|
|
|
void VignetteUI()
|
|
{
|
|
EditorGUILayout.PropertyField(vignetteSettings.enabled);
|
|
|
|
if (vignetteSettings.enabled.boolValue)
|
|
{
|
|
EditorGUILayout.PropertyField(vignetteSettings.color);
|
|
EditorGUILayout.PropertyField(vignetteSettings.center);
|
|
EditorGUILayout.PropertyField(vignetteSettings.intensity);
|
|
EditorGUILayout.PropertyField(vignetteSettings.smoothness);
|
|
}
|
|
}
|
|
|
|
#region Color grading stuff
|
|
void SetLUTImportSettings()
|
|
{
|
|
var lut = (target as PostProcessing).colorGrading.logLut;
|
|
var importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(lut));
|
|
importer.textureType = TextureImporterType.Default;
|
|
importer.filterMode = FilterMode.Bilinear;
|
|
importer.mipmapEnabled = false;
|
|
importer.anisoLevel = 0;
|
|
importer.sRGBTexture = false;
|
|
importer.npotScale = TextureImporterNPOTScale.None;
|
|
importer.textureCompression = TextureImporterCompression.Uncompressed;
|
|
importer.SaveAndReimport();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
bool ValidateLutImportSettings()
|
|
{
|
|
var lut = (target as PostProcessing).colorGrading.logLut;
|
|
|
|
if (lut == null)
|
|
return true;
|
|
|
|
var importer = (TextureImporter)AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(lut));
|
|
return importer.anisoLevel == 0
|
|
&& importer.mipmapEnabled == false
|
|
&& importer.sRGBTexture == false
|
|
&& (importer.textureCompression == TextureImporterCompression.Uncompressed)
|
|
&& importer.filterMode == FilterMode.Bilinear;
|
|
}
|
|
|
|
void SaveFrameToEXR(Camera camera, string path)
|
|
{
|
|
// We want a 1024x32 sized render at a minimum so that we have enough space to stamp the lut
|
|
var aspect = (float)camera.pixelHeight / (float)camera.pixelWidth;
|
|
var width = camera.pixelWidth >= 1024
|
|
? camera.pixelWidth
|
|
: 1024;
|
|
var height = Mathf.RoundToInt(width * aspect);
|
|
|
|
var texture = new Texture2D(width, height, TextureFormat.RGBAHalf, false, true);
|
|
var targetRt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
|
|
|
|
// Render the current frame without post processing
|
|
var oldPPState = (target as PostProcessing).enabled;
|
|
(target as PostProcessing).enabled = false;
|
|
var oldTarget = camera.targetTexture;
|
|
var oldActive = RenderTexture.active;
|
|
camera.targetTexture = targetRt;
|
|
camera.Render();
|
|
|
|
// Stamp the log lut in the top left corner
|
|
const int k_InternalLogLutSize = 32;
|
|
var stampMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/LutGen");
|
|
stampMaterial.SetVector("_LutParams", new Vector4(
|
|
k_InternalLogLutSize,
|
|
0.5f / (k_InternalLogLutSize * k_InternalLogLutSize),
|
|
0.5f / k_InternalLogLutSize,
|
|
k_InternalLogLutSize / (k_InternalLogLutSize - 1f))
|
|
);
|
|
|
|
var stampRt = RenderTexture.GetTemporary(1024, 32, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
|
|
Graphics.Blit(null, stampRt, stampMaterial, 0);
|
|
|
|
RenderTexture.active = targetRt;
|
|
GL.PushMatrix();
|
|
{
|
|
GL.LoadPixelMatrix(0, width, height, 0);
|
|
Graphics.DrawTexture(new Rect(0, 0, stampRt.width, stampRt.height), stampRt);
|
|
}
|
|
GL.PopMatrix();
|
|
|
|
// Read back
|
|
texture.ReadPixels(new Rect(0, 0, targetRt.width, targetRt.height), 0, 0);
|
|
camera.targetTexture = oldTarget;
|
|
RenderTexture.active = oldActive;
|
|
(target as PostProcessing).enabled = oldPPState;
|
|
|
|
// Cleanup
|
|
RenderTexture.ReleaseTemporary(stampRt);
|
|
RenderTexture.ReleaseTemporary(targetRt);
|
|
Utilities.Destroy(stampMaterial);
|
|
|
|
// Save
|
|
File.WriteAllBytes(path, texture.EncodeToEXR(Texture2D.EXRFlags.CompressPIZ));
|
|
AssetDatabase.Refresh();
|
|
}
|
|
#endregion
|
|
}
|
|
}
|