├── UserLUT ├── LUTs │ ├── TestLUT1.png │ ├── TestLUT2.png │ ├── TestLUT3.png │ ├── TestLUT4.png │ ├── TestLUT5.png │ ├── TestLUT2BG.png │ ├── NeutralLUT_32.png │ ├── NeutralLUT_32.png.meta │ ├── TestLUT1.png.meta │ ├── TestLUT2.png.meta │ ├── TestLUT2BG.png.meta │ ├── TestLUT3.png.meta │ ├── TestLUT4.png.meta │ └── TestLUT5.png.meta ├── Shaders │ └── UserLUT.shader └── Scripts │ └── UserLUT.cs ├── LICENSE.md └── README.md /UserLUT/LUTs/TestLUT1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT1.png -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT2.png -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT3.png -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT4.png -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT5.png -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT2BG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/TestLUT2BG.png -------------------------------------------------------------------------------- /UserLUT/LUTs/NeutralLUT_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Seifried/Unity-PostProV2-User-LUT-And-Z-Grading/HEAD/UserLUT/LUTs/NeutralLUT_32.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Philipp Seifried, http://www.philippseifried.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /UserLUT/LUTs/NeutralLUT_32.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 924360f31661bda41a37823c6d47ffc5 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 5 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 1 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | grayScaleToAlpha: 0 25 | generateCubemap: 6 26 | cubemapConvolution: 0 27 | seamlessCubemap: 0 28 | textureFormat: 3 29 | maxTextureSize: 2048 30 | textureSettings: 31 | serializedVersion: 2 32 | filterMode: -1 33 | aniso: 0 34 | mipBias: -1 35 | wrapU: -1 36 | wrapV: -1 37 | wrapW: -1 38 | nPOTScale: 1 39 | lightmap: 0 40 | compressionQuality: 50 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spritePixelsToUnits: 100 47 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 48 | spriteGenerateFallbackPhysicsShape: 1 49 | alphaUsage: 0 50 | alphaIsTransparency: 0 51 | spriteTessellationDetail: -1 52 | textureType: 0 53 | textureShape: 1 54 | singleChannelComponent: 0 55 | maxTextureSizeSet: 0 56 | compressionQualitySet: 0 57 | textureFormatSet: 0 58 | platformSettings: 59 | - serializedVersion: 2 60 | buildTarget: DefaultTexturePlatform 61 | maxTextureSize: 2048 62 | resizeAlgorithm: 0 63 | textureFormat: -1 64 | textureCompression: 0 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | androidETC2FallbackOverride: 0 70 | spriteSheet: 71 | serializedVersion: 2 72 | sprites: [] 73 | outline: [] 74 | physicsShape: [] 75 | bones: [] 76 | spriteID: 77 | vertices: [] 78 | indices: 79 | edges: [] 80 | weights: [] 81 | spritePackingTag: 82 | userData: 83 | assetBundleName: 84 | assetBundleVariant: 85 | -------------------------------------------------------------------------------- /UserLUT/Shaders/UserLUT.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/Custom/UserLUT" 2 | { 3 | HLSLINCLUDE 4 | 5 | #pragma multi_compile __ USE_BG_LUT 6 | #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl" 7 | #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/Colors.hlsl" 8 | 9 | TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex); 10 | TEXTURE2D_SAMPLER2D(_UserLut, sampler_UserLut); 11 | float4 _UserLut_Params; 12 | #if USE_BG_LUT 13 | TEXTURE2D_SAMPLER2D(_BGLut, sampler_BGLut); 14 | float4 _BGLut_Params; 15 | float2 _BGLut_Blend; 16 | TEXTURE2D_SAMPLER2D(_CameraDepthTexture, sampler_CameraDepthTexture); 17 | #endif 18 | 19 | float4 Frag(VaryingsDefault i) : SV_Target 20 | { 21 | float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord); 22 | color.rgb = saturate(color.rgb); 23 | half3 colorGraded; 24 | 25 | #if USE_BG_LUT 26 | half3 colorGradedBG; 27 | float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, i.texcoordStereo)); 28 | float bgBlend = saturate((depth - _BGLut_Blend.x) / _BGLut_Blend.y); 29 | #endif 30 | 31 | #if !UNITY_COLORSPACE_GAMMA 32 | half3 colorSRGB = LinearToSRGB(color.rgb); 33 | colorGraded = ApplyLut2D(TEXTURE2D_PARAM(_UserLut, sampler_UserLut), colorSRGB, _UserLut_Params.xyz); 34 | #if USE_BG_LUT 35 | colorGraded = lerp(colorGraded, ApplyLut2D(TEXTURE2D_PARAM(_BGLut, sampler_BGLut), colorSRGB, _BGLut_Params.xyz), bgBlend); 36 | #endif 37 | colorGraded = SRGBToLinear(colorGraded); 38 | #else 39 | colorGraded = ApplyLut2D(TEXTURE2D_PARAM(_UserLut, sampler_UserLut), color.rgb, _UserLut_Params.xyz); 40 | #if USE_BG_LUT 41 | colorGraded = lerp(colorGraded, ApplyLut2D(TEXTURE2D_PARAM(_BGLut, sampler_BGLut), color.rgb, _BGLut_Params.xyz), bgBlend); 42 | #endif 43 | #endif 44 | 45 | color.rgb = lerp(color.rgb, colorGraded, _UserLut_Params.w); 46 | return color; 47 | } 48 | 49 | ENDHLSL 50 | 51 | SubShader 52 | { 53 | Cull Off ZWrite Off ZTest Always 54 | Pass 55 | { 56 | HLSLPROGRAM 57 | #pragma vertex VertDefault 58 | #pragma fragment Frag 59 | ENDHLSL 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT1.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5731b4d5306fa1c409089f0a9f3c8a83 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT2.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bfcc84ff16dd0ad4499143f12b0b2857 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT2BG.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ab74bc6d2b2dd644b120ae633282512 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT3.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f074c2b5f515a0640a1676c60bae99fc 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT4.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d4ae31341e42ca24fbe95346b6ef44d5 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/LUTs/TestLUT5.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ef35bd5c49623647a9f4c4acb502471 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 9 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 0 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 0 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | - serializedVersion: 2 73 | buildTarget: Standalone 74 | maxTextureSize: 2048 75 | resizeAlgorithm: 0 76 | textureFormat: -1 77 | textureCompression: 0 78 | compressionQuality: 50 79 | crunchedCompression: 0 80 | allowsAlphaSplitting: 0 81 | overridden: 0 82 | androidETC2FallbackOverride: 0 83 | spriteSheet: 84 | serializedVersion: 2 85 | sprites: [] 86 | outline: [] 87 | physicsShape: [] 88 | bones: [] 89 | spriteID: 90 | vertices: [] 91 | indices: 92 | edges: [] 93 | weights: [] 94 | spritePackingTag: 95 | pSDRemoveMatte: 0 96 | pSDShowRemoveMatteOption: 0 97 | userData: 98 | assetBundleName: 99 | assetBundleVariant: 100 | -------------------------------------------------------------------------------- /UserLUT/Scripts/UserLUT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using UnityEngine.Rendering.PostProcessing; 4 | 5 | [Serializable] 6 | [PostProcess(typeof(UserLUTRenderer), PostProcessEvent.AfterStack, "Custom/UserLUT")] 7 | public sealed class UserLUT : PostProcessEffectSettings 8 | { 9 | [DisplayName("LUT"), Tooltip("LDR Lookup Texture, 1024x32")] 10 | public TextureParameter lut = new TextureParameter { value = null, defaultState = TextureParameterDefault.Lut2D }; 11 | [Range(0f, 1f), Tooltip("LUT blend")] 12 | public FloatParameter blend = new FloatParameter { value = 1.0f }; 13 | [DisplayName("Use Background LUT"), Tooltip("Activate background LUT")] 14 | public BoolParameter useBackgroundLut = new BoolParameter{ value = false }; 15 | [DisplayName("Background LUT"), Tooltip("Background Lookup Texture, 1024x32")] 16 | public TextureParameter backgroundLut = new TextureParameter { value = null, defaultState = TextureParameterDefault.Lut2D }; 17 | [Tooltip("Distance at which blend to background starts")] 18 | public FloatParameter backgroundBlendStart = new FloatParameter { value = 50.0f }; 19 | [Tooltip("Range of blending default LUT to background LUT (from start of blend)")] 20 | public FloatParameter backgroundBlendRange = new FloatParameter { value = 10.0f }; 21 | 22 | public override bool IsEnabledAndSupported(PostProcessRenderContext context) 23 | { 24 | if (lut.value == null || blend.value == 0) 25 | { 26 | return false; 27 | } 28 | return enabled.value; 29 | } 30 | } 31 | 32 | public sealed class UserLUTRenderer : PostProcessEffectRenderer 33 | { 34 | static class Uniforms { 35 | internal static readonly int _UserLut = Shader.PropertyToID("_UserLut"); 36 | internal static readonly int _UserLut_Params = Shader.PropertyToID("_UserLut_Params"); 37 | internal static readonly int _BGLut = Shader.PropertyToID("_BGLut"); 38 | internal static readonly int _BGLut_Params = Shader.PropertyToID("_BGLut_Params"); 39 | internal static readonly int _BGLut_Blend = Shader.PropertyToID("_BGLut_Blend"); 40 | } 41 | 42 | public override DepthTextureMode GetCameraFlags() 43 | { 44 | if (settings.useBackgroundLut.value) 45 | return DepthTextureMode.Depth; 46 | return DepthTextureMode.None; 47 | } 48 | 49 | public override void Render(PostProcessRenderContext context) 50 | { 51 | var sheet = context.propertySheets.Get(Shader.Find("Hidden/Custom/UserLUT")); 52 | sheet.ClearKeywords(); 53 | Texture lut = settings.lut.value; 54 | 55 | Vector4 lutParams = new Vector4(1f / lut.width, 1f / lut.height, lut.height - 1f, settings.blend.value); 56 | sheet.properties.SetTexture(Uniforms._UserLut, lut); 57 | sheet.properties.SetVector(Uniforms._UserLut_Params, lutParams); 58 | if (settings.useBackgroundLut) 59 | { 60 | sheet.EnableKeyword("USE_BG_LUT"); 61 | if (settings.backgroundLut.value != null) 62 | { 63 | lut = settings.backgroundLut.value; 64 | } 65 | lutParams = new Vector4(1f / lut.width, 1f / lut.height, lut.height - 1f, 0); 66 | sheet.properties.SetTexture(Uniforms._BGLut, lut); 67 | sheet.properties.SetVector(Uniforms._BGLut_Params, lutParams); 68 | sheet.properties.SetVector(Uniforms._BGLut_Blend, new Vector4(settings.backgroundBlendStart.value, settings.backgroundBlendRange.value, 0, 0)); 69 | } 70 | 71 | context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0); 72 | } 73 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Z-Based Color Grading and Separate User LUT for Unity's "Post-Processing Stack V2" 2 | 3 | ![Screenshot](http://www.philippseifried.com/github/UserLUT.jpg) 4 | 5 | Unity's Post-Processing Stack V2 comes with three modes for color grading: LDR, HDR and External LUTs. Unfortunately, HDR mode lacks the option to add a user-defined LUT, and the External LUT mode requires you to color grade in HDR, which Photoshop is not very good at. If you want to grade in Photoshop and use image filters such as curves (or do something funky like posterizing the image), you're left with the LDR color grading mode in Unity, which doesn't apply tonemapping and simply clips color values higher than 1.0 6 | 7 | This package works around this limitation by implementing a separate color grading filter, similar to the V1 post-processing stack's "User LUT" effect. Simply add a regular Post-Processing V2 Color Grading effect, set it to HDR and use it to do tonemapping, then add the "User LUT" effect from this package and supply it with an LDR LUT that will be applied after the tone-mapping stage. 8 | 9 | The "User LUT" effect in this package also allows you to specify a separate LUT for grading the background (based on the camera's depth texture), so you can apply different color grading for distant objects. 10 | 11 | The downside of doing all this in a separate effect is that it comes at a slightly higher cost, since the effect isn't part of the Post-Processing Stack's uber shader, which handles many of Unity's post-processing effects in one pass. 12 | 13 | ## Getting Started 14 | ![Screenshot](http://www.philippseifried.com/github/UserLUTGettingStarted.jpg) 15 | 16 | Drop the code from the "UserLUT" folder into your project. 17 | 18 | *IMPORTANT*: For the effect to work in a build, make sure that the supplied UserLUT shader is included in the build. 19 | 20 | Add a Post Process Volume and Layer to your camera, if you haven't already. Add a Color Grading effect to the Post Processing Stack, select "High Definition Range" for mode and select the tonemapping of your choice. Leave any other checkboxes/parameters of the Color Grading effect unchecked/default. 21 | 22 | Add the effect from this package to the stack ("Custom/UserLUT"). 23 | 24 | ## Parameters 25 | 26 | * *LUT* - a 1024x32 RGB24 texture (256x16 LUTs should also be compatible). Some sample LUTs for testing are provided in the LUTs folder. To author your own, take a screenshot of your game after tonemapping, without any additional color grading applied. Open the image in Photoshop (or your image processing software of choice) and add the NeutralLUT_32 Texture in the image's corner. Apply any image filters that operate on single pixels (e.g. color balance, but not blur), then crop and export the resulting LUT into your project (settings: no sRGB, no mipmaps, no compression). Once you set your LUT in the "User LUT" effect, your game should look like the processed screenshot in Photoshop. 27 | * *Blend* - lets you blend between your selected LUT and neutral color grading (1 = full effect of your LUT). 28 | * *Use Background LUT* - if this is checked, the image is graded based on each pixel's depth in the camera's depth texture, and all background-related parameters take effect. 29 | * *Background LUT* - color grading lookup table for distant parts of the image. 30 | * *Background Blend Start* - at this distance (in world units), the color grading starts blending between foreground and background 31 | * *Background Blend Range* - distance after "Background Blend Start" at which the Background LUT has full effect. 32 | 33 | ## Compatibility 34 | 35 | Has been tested with Unity 2018.3 and 2019.1 on PC only, but should work on any platform that supports the Post-Processing Stack V2. 36 | 37 | Compatible with the Standard rendering pipeline, LWRP and HDRP (HDRP currently only in 2018.3). 38 | 39 | Compatible with Gamma and linear lighting. 40 | 41 | Orthographic cameras have trouble with the *Background Blend Start* and *Background Blend Range* parameters. Z-Blending works in principle, but the units are off and for now you need to experiment to set the right blending distance parameters. 42 | 43 | Not tested in VR. 44 | 45 | ## License 46 | 47 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 48 | 49 | ## Authors 50 | 51 | [Philipp Seifried](https://twitter.com/PhilippSeifried) - Much of the code was adapted from the Post-Processing Stack V1 and V2 versions of Color Grading / User LUT. 52 | 53 | --------------------------------------------------------------------------------