diff --git a/Shaders/bloom_pass/bloom_pass.frag.glsl b/Shaders/bloom_pass/bloom_pass.frag.glsl index e4862975..5674dc8b 100755 --- a/Shaders/bloom_pass/bloom_pass.frag.glsl +++ b/Shaders/bloom_pass/bloom_pass.frag.glsl @@ -4,16 +4,27 @@ uniform sampler2D tex; +uniform vec3 PPComp10; + in vec2 texCoord; out vec4 fragColor; void main() { vec3 col = textureLod(tex, texCoord, 0.0).rgb; float brightness = dot(col, vec3(0.2126, 0.7152, 0.0722)); - if (brightness > bloomThreshold) { - fragColor.rgb = col; - } - else { - fragColor.rgb = vec3(0.0); - } + #ifdef _CPostprocess + if (brightness > PPComp10.z) { + fragColor.rgb = col; + } + else { + fragColor.rgb = vec3(0.0); + } + #else + if (brightness > bloomThreshold) { + fragColor.rgb = col; + } + else { + fragColor.rgb = vec3(0.0); + } + #endif } diff --git a/Shaders/bloom_pass/bloom_pass.json b/Shaders/bloom_pass/bloom_pass.json index 4988978e..6e6541e2 100755 --- a/Shaders/bloom_pass/bloom_pass.json +++ b/Shaders/bloom_pass/bloom_pass.json @@ -5,7 +5,12 @@ "depth_write": false, "compare_mode": "always", "cull_mode": "none", - "links": [], + "links": [ + { + "name": "PPComp10", + "link": "_PPComp10" + } + ], "texture_params": [], "vertex_shader": "../include/pass.vert.glsl", "fragment_shader": "bloom_pass.frag.glsl" diff --git a/Shaders/blur_gaus_pass/blur_gaus_pass.frag.glsl b/Shaders/blur_gaus_pass/blur_gaus_pass.frag.glsl index dc77e839..6df818c5 100644 --- a/Shaders/blur_gaus_pass/blur_gaus_pass.frag.glsl +++ b/Shaders/blur_gaus_pass/blur_gaus_pass.frag.glsl @@ -7,13 +7,19 @@ uniform sampler2D tex; uniform vec2 dir; uniform vec2 screenSize; +uniform vec3 PPComp11; + in vec2 texCoord; out vec4 fragColor; const float weight[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535); void main() { - vec2 step = (dir / screenSize.xy) * bloomRadius; + #ifdef _CPostprocess + vec2 step = (dir / screenSize.xy) * PPComp11.y; + #else + vec2 step = (dir / screenSize.xy) * bloomRadius; + #endif fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb * weight[0]; for (int i = 1; i < 10; i++) { vec2 s = step * (float(i) + 0.5); @@ -21,6 +27,10 @@ void main() { fragColor.rgb += textureLod(tex, texCoord - s, 0.0).rgb * weight[i]; } - fragColor.rgb *= bloomStrength / 5; + #ifdef _CPostprocess + fragColor.rgb *= PPComp11.x / 5; + #else + fragColor.rgb *= bloomStrength / 5; + #endif fragColor.rgb = min(fragColor.rgb, 64.0); } diff --git a/Shaders/blur_gaus_pass/blur_gaus_pass.json b/Shaders/blur_gaus_pass/blur_gaus_pass.json index 229f67d6..d1a9749d 100755 --- a/Shaders/blur_gaus_pass/blur_gaus_pass.json +++ b/Shaders/blur_gaus_pass/blur_gaus_pass.json @@ -13,6 +13,10 @@ { "name": "screenSize", "link": "_windowSize" + }, + { + "name": "PPComp11", + "link": "_PPComp11" } ], "texture_params": [], @@ -32,6 +36,10 @@ { "name": "screenSize", "link": "_windowSize" + }, + { + "name": "PPComp11", + "link": "_PPComp11" } ], "texture_params": [], @@ -54,6 +62,10 @@ { "name": "screenSize", "link": "_windowSize" + }, + { + "name": "PPComp11", + "link": "_PPComp11" } ], "texture_params": [], diff --git a/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.frag.glsl b/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.frag.glsl index ba466a77..5988645a 100644 --- a/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.frag.glsl +++ b/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.frag.glsl @@ -3,6 +3,7 @@ #include "compiled.inc" uniform sampler2D tex; +uniform vec3 PPComp13; in vec2 texCoord; out vec4 fragColor; @@ -36,8 +37,13 @@ vec4 spectrum_offset(float t) { void main() { - float max_distort = compoChromaticStrength; - int num_iter = compoChromaticSamples; + #ifdef _CPostprocess + float max_distort = PPComp13.x; + int num_iter = int(PPComp13.y); + #else + float max_distort = compoChromaticStrength; + int num_iter = compoChromaticSamples; + #endif float reci_num_iter_f = 1.0 / float(num_iter); diff --git a/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.json b/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.json index bdc52964..4af5587a 100644 --- a/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.json +++ b/Shaders/chromatic_aberration_pass/chromatic_aberration_pass.json @@ -6,7 +6,12 @@ "color_write_alpha": false, "compare_mode": "always", "cull_mode": "none", - "links": [], + "links": [ + { + "name": "PPComp13", + "link": "_PPComp13" + } + ], "texture_params": [], "vertex_shader": "../include/pass.vert.glsl", "fragment_shader": "chromatic_aberration_pass.frag.glsl" diff --git a/Shaders/compositor_pass/compositor_pass.frag.glsl b/Shaders/compositor_pass/compositor_pass.frag.glsl index 216aeff0..26e8a2f5 100755 --- a/Shaders/compositor_pass/compositor_pass.frag.glsl +++ b/Shaders/compositor_pass/compositor_pass.frag.glsl @@ -6,6 +6,9 @@ #ifdef _CDOF #include "std/dof.glsl" #endif +#ifdef _CPostprocess +#include "std/colorgrading.glsl" +#endif uniform sampler2D tex; #ifdef _CDepth @@ -24,6 +27,43 @@ uniform sampler2D lutTexture; uniform sampler2D histogram; #endif +#ifdef _CPostprocess +uniform vec3 globalWeight; +uniform vec3 globalTint; +uniform vec3 globalSaturation; +uniform vec3 globalContrast; +uniform vec3 globalGamma; +uniform vec3 globalGain; +uniform vec3 globalOffset; + +uniform vec3 shadowSaturation; +uniform vec3 shadowContrast; +uniform vec3 shadowGamma; +uniform vec3 shadowGain; +uniform vec3 shadowOffset; + +uniform vec3 midtoneSaturation; +uniform vec3 midtoneContrast; +uniform vec3 midtoneGamma; +uniform vec3 midtoneGain; +uniform vec3 midtoneOffset; + +uniform vec3 highlightSaturation; +uniform vec3 highlightContrast; +uniform vec3 highlightGamma; +uniform vec3 highlightGain; +uniform vec3 highlightOffset; + +uniform vec3 PPComp1; +uniform vec3 PPComp2; +uniform vec3 PPComp3; +uniform vec3 PPComp4; +uniform vec3 PPComp5; +uniform vec3 PPComp6; +uniform vec3 PPComp7; +uniform vec3 PPComp8; +#endif + // #ifdef _CPos // uniform vec3 eye; // uniform vec3 eyeLook; @@ -77,6 +117,25 @@ vec3 applyFog(vec3 rgb, float distance) { } #endif +#ifdef _CPostprocess +float ComputeEV100(const float aperture2, const float shutterTime, const float ISO) { + return log2(aperture2 / shutterTime * 100.0 / ISO); +} +float ConvertEV100ToExposure(float EV100) { + return 1/0.8 * exp2(-EV100); +} +float ComputeEV(float avgLuminance) { + const float sqAperture = PPComp1[0].x * PPComp1.x; + const float shutterTime = 1.0 / PPComp1.y; + const float ISO = PPComp1.z; + const float EC = PPComp2.x; + + float EV100 = ComputeEV100(sqAperture, shutterTime, ISO); + + return ConvertEV100ToExposure(EV100 - EC) * PI; +} +#endif + vec4 LUTlookup(in vec4 textureColor, in sampler2D lookupTable) { //Clamp to prevent weird results @@ -154,7 +213,11 @@ void main() { #endif #ifdef _CFishEye - const float fishEyeStrength = -0.01; + #ifdef _CPostprocess + const float fishEyeStrength = -(PPComp2.y); + #else + const float fishEyeStrength = -0.01; + #endif const vec2 m = vec2(0.5, 0.5); vec2 d = texCo - m; float r = sqrt(dot(d, d)); @@ -225,7 +288,23 @@ void main() { #else #ifdef _CDOF - fragColor = vec4(dof(texCo, depth, tex, gbufferD, texStep, cameraProj), 1.0); + #ifdef _CPostprocess + + bool compoAutoFocus = false; + float compoDistance = PPComp3.x; + float compoLength = PPComp3.y; + float compoStop = PPComp3.z; + + if (PPComp2.z == 1){ + compoAutoFocus = true; + } else { + compoAutoFocus = false; + } + + fragColor.rgb = dof(texCo, depth, tex, gbufferD, texStep, cameraProj, compoAutoFocus, compoDistance, compoLength, compoStop); + #else + fragColor.rgb = dof(texCo, depth, tex, gbufferD, texStep, cameraProj, true, compoDOFDistance, compoDOFLength, compoDOFFstop); + #endif #else fragColor = textureLod(tex, texCo, 0.0); #endif @@ -271,7 +350,11 @@ void main() { #ifdef _CGrain // const float compoGrainStrength = 4.0; float x = (texCo.x + 4.0) * (texCo.y + 4.0) * (time * 10.0); - fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * compoGrainStrength; + #ifdef _CPostprocess + fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * PPComp4.y; + #else + fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * compoGrainStrength; + #endif #endif #ifdef _CGrainStatic @@ -287,28 +370,96 @@ void main() { fragColor.rgb += fragColor.rgb * compoExposureStrength; #endif +#ifdef _CPostprocess + fragColor.rgb *= ComputeEV(0.0); +#endif + #ifdef _AutoExposure float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0); fragColor.rgb *= pow(expo, autoExposureStrength * 2.0); #endif -#ifdef _CToneFilmic - fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma -#endif -#ifdef _CToneFilmic2 - fragColor.rgb = acesFilm(fragColor.rgb); - fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); -#endif -#ifdef _CToneReinhard - fragColor.rgb = tonemapReinhard(fragColor.rgb); - fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); -#endif -#ifdef _CToneUncharted - fragColor.rgb = tonemapUncharted2(fragColor.rgb); - fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma -#endif -#ifdef _CToneNone - fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma +#ifdef _CPostprocess + + #ifdef _CToneCustom + fragColor.rgb = clamp((fragColor.rgb * (PPComp4.z * fragColor.rgb + PPComp5.x)) / (fragColor.rgb * (PPComp5.y * fragColor.rgb + PPComp5.z) + PPComp6.x), 0.0, 1.0); + #else + if(PPComp4.x == 0){ //Filmic 1 + fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma + } else if (PPComp4.x == 1){ //Filmic 2 + fragColor.rgb = acesFilm(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); + } else if (PPComp4.x == 2){ //Reinhard + fragColor.rgb = tonemapReinhard(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); + } else if (PPComp4.x == 3){ //Uncharted2 + fragColor.rgb = tonemapUncharted2(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma + fragColor.rgb = clamp(fragColor.rgb, 0.0, 1.0); + } else if (PPComp4.x == 4){ //None + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma + } else if (PPComp4.x == 5){ //Non-Gamma / Linear + fragColor.rgb = fragColor.rgb; + } else if (PPComp4.x == 6){ //HDP + vec3 x = fragColor.rgb - 0.004; + //vec3 x = max(0, fragColor.rgb - 0.004); + fragColor.rgb = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06); + } else if (PPComp4.x == 7){ //Raw + vec4 vh = vec4(fragColor.rgb, 1); + vec4 va = (1.425 * vh) + 0.05; + vec4 vf = ((vh * va + 0.004) / ((vh * (va + 0.55) + 0.0491))) - 0.0821; + fragColor.rgb = vf.rgb / vf.www; + } else if (PPComp4.x == 8){ //False Colors for luminance control + + vec4 c = vec4(fragColor.r,fragColor.g,fragColor.b,0); //Linear without gamma + + vec3 luminanceVector = vec3(0.2125, 0.7154, 0.0721); //Relative Luminance Vector + float luminance = dot(luminanceVector, c.xyz); + + vec3 maxLumColor = vec3(1,0,0); //High values (> 1.0) + //float maxLum = 2.0; Needs to read the highest pixel, but I don't know how to yet + //Probably easier with a histogram too, once it's it in place? + + vec3 midLumColor = vec3(0,1,0); //Mid values (< 1.0) + float midLum = 1.0; + + vec3 minLumColor = vec3(0,0,1); //Low values (< 1.0) + float minLum = 0.0; + + if(luminance < midLum){ + fragColor.rgb = mix(minLumColor, midLumColor, luminance); + } else { + fragColor.rgb = mix(midLumColor, maxLumColor, luminance); + } + + } else { + fragColor.rgb = vec3(0,1,0); //ERROR + } + #endif + +#else + #ifdef _CToneFilmic + fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma + #endif + #ifdef _CToneFilmic2 + fragColor.rgb = acesFilm(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); + #endif + #ifdef _CToneReinhard + fragColor.rgb = tonemapReinhard(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); + #endif + #ifdef _CToneUncharted + fragColor.rgb = tonemapUncharted2(fragColor.rgb); + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma + fragColor.rgb = clamp(fragColor.rgb, 0.0, 2.2); + #endif + #ifdef _CToneNone + fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma + #endif + #ifdef _CToneCustom + fragColor.rgb = clamp((fragColor.rgb * (1 * fragColor.rgb + 1)) / (fragColor.rgb * (1 * fragColor.rgb + 1 ) + 1), 0.0, 1.0); + #endif #endif #ifdef _CBW @@ -326,16 +477,83 @@ void main() { // fragColor.rgb += compoBrightness; // #endif +#ifdef _CPostprocess + //Global Values + + float factor = 1; + float colorTempK = globalWeight.x; + vec3 ColorTempRGB = ColorTemperatureToRGB(colorTempK); + + float originalLuminance = Luminance(fragColor.rgb); + vec3 blended = mix(fragColor.rgb, fragColor.rgb * ColorTempRGB, factor); + vec3 resultHSL = RGBtoHSL(blended); + vec3 luminancePreservedRGB = HSLtoRGB(vec3(resultHSL.x, resultHSL.y, originalLuminance)); + fragColor = vec4(mix(blended, luminancePreservedRGB, LUMINANCE_PRESERVATION), 1.0); + + mat3 CCSaturation = mat3 ( //Saturation + globalSaturation.r * shadowSaturation.r, globalSaturation.g * shadowSaturation.g, globalSaturation.b * shadowSaturation.b, //Shadows + Global + globalSaturation.r * midtoneSaturation.r, globalSaturation.g * midtoneSaturation.g, globalSaturation.b * midtoneSaturation.b, //Midtones + Global + globalSaturation.r * highlightSaturation.r, globalSaturation.g * highlightSaturation.g, globalSaturation.b * highlightSaturation.b //Highlights + Global + ); + + mat3 CCContrast = mat3 ( + globalContrast.r * shadowContrast.r, globalContrast.g * shadowContrast.g, globalContrast.b * shadowContrast.b, //Shadows + Global + globalContrast.r * midtoneContrast.r, globalContrast.g * midtoneContrast.g, globalContrast.b * midtoneContrast.b, //Midtones + Global + globalContrast.r * highlightContrast.r, globalContrast.g * highlightContrast.g, globalContrast.b * highlightContrast.b //Highlights + Global + ); + + mat3 CCGamma = mat3 ( + globalGamma.r * shadowGamma.r, globalGamma.g * shadowGamma.g, globalGamma.b * shadowGamma.b, //Shadows + Global + globalGamma.r * midtoneGamma.r, globalGamma.g * midtoneGamma.g, globalGamma.b * midtoneGamma.b, //Midtones + Global + globalGamma.r * highlightGamma.r, globalGamma.g * highlightGamma.g, globalGamma.b * highlightGamma.b //Highlights + Global + ); + + mat3 CCGain = mat3 ( + globalGain.r * shadowGain.r, globalGain.g * shadowGain.g, globalGain.b * shadowGain.b, //Shadows + Global + globalGain.r * midtoneGain.r, globalGain.g * midtoneGain.g, globalGain.b * midtoneGain.b, //Midtones + Global + globalGain.r * highlightGain.r, globalGain.g * highlightGain.g, globalGain.b * highlightGain.b //Highlights + Global + ); + + mat3 CCOffset = mat3 ( + globalOffset.r * shadowOffset.r, globalOffset.g * shadowOffset.g, globalOffset.b * shadowOffset.b, //Shadows + Global + globalOffset.r * midtoneOffset.r, globalOffset.g * midtoneOffset.g, globalOffset.b * midtoneOffset.b, //Midtones + Global + globalOffset.r * highlightOffset.r, globalOffset.g * highlightOffset.g, globalOffset.b * highlightOffset.b //Highlights + Global + ); + + vec2 ToneWeights = vec2(globalWeight.y, globalWeight.z); + + fragColor.rgb = FinalizeColorCorrection( + fragColor.rgb, + CCSaturation, + CCContrast, + CCGamma, + CCGain, + CCOffset, + ToneWeights + ); + + //Tint + fragColor.rgb *= vec3(globalTint.r,globalTint.g,globalTint.b); +#endif + #ifdef _CLensTex #ifdef _CLensTexMasking vec4 scratches = texture(lensTexture, texCo); vec3 scratchBlend = fragColor.rgb + scratches.rgb; - float centerMaxClip = compoCenterMaxClip; - float centerMinClip = compoCenterMinClip; - float luminanceMax = compoLuminanceMax; - float luminanceMin = compoLuminanceMin; - float brightnessExp = compoBrightnessExponent; + #ifdef _CPostprocess + float centerMaxClip = PPComp6.y; + float centerMinClip = PPComp6.z; + float luminanceMax = PPComp7.x; + float luminanceMin = PPComp7.y; + float brightnessExp = PPComp7.z; + #else + float centerMaxClip = compoCenterMaxClip; + float centerMinClip = compoCenterMinClip; + float luminanceMax = compoLuminanceMax; + float luminanceMin = compoLuminanceMin; + float brightnessExp = compoBrightnessExponent; + #endif float center = smoothstep(centerMaxClip, centerMinClip, length(texCo - 0.5)); float luminance = dot(fragColor.rgb, vec3(0.299, 0.587, 0.114)); diff --git a/Shaders/compositor_pass/compositor_pass.json b/Shaders/compositor_pass/compositor_pass.json index 6874932a..1b79a33c 100755 --- a/Shaders/compositor_pass/compositor_pass.json +++ b/Shaders/compositor_pass/compositor_pass.json @@ -75,6 +75,156 @@ "name": "lutTexture", "link": "$luttexture.jpg", "ifdef": ["_CLUT"] + }, + { + "name": "globalWeight", + "link": "_globalWeight", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalTint", + "link": "_globalTint", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalSaturation", + "link": "_globalSaturation", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalContrast", + "link": "_globalContrast", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalGamma", + "link": "_globalGamma", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalGain", + "link": "_globalGain", + "ifdef": ["_CPostprocess"] + }, + { + "name": "globalOffset", + "link": "_globalOffset", + "ifdef": ["_CPostprocess"] + }, + { + "name": "shadowSaturation", + "link": "_shadowSaturation", + "ifdef": ["_CPostprocess"] + }, + { + "name": "shadowContrast", + "link": "_shadowContrast", + "ifdef": ["_CPostprocess"] + }, + { + "name": "shadowGamma", + "link": "_shadowGamma", + "ifdef": ["_CPostprocess"] + }, + { + "name": "shadowGain", + "link": "_shadowGain", + "ifdef": ["_CPostprocess"] + }, + { + "name": "shadowOffset", + "link": "_shadowOffset", + "ifdef": ["_CPostprocess"] + }, + { + "name": "midtoneSaturation", + "link": "_midtoneSaturation", + "ifdef": ["_CPostprocess"] + }, + { + "name": "midtoneContrast", + "link": "_midtoneContrast", + "ifdef": ["_CPostprocess"] + }, + { + "name": "midtoneGamma", + "link": "_midtoneGamma", + "ifdef": ["_CPostprocess"] + }, + { + "name": "midtoneGain", + "link": "_midtoneGain", + "ifdef": ["_CPostprocess"] + }, + { + "name": "midtoneOffset", + "link": "_midtoneOffset", + "ifdef": ["_CPostprocess"] + }, + { + "name": "highlightSaturation", + "link": "_highlightSaturation", + "ifdef": ["_CPostprocess"] + }, + { + "name": "highlightContrast", + "link": "_highlightContrast", + "ifdef": ["_CPostprocess"] + }, + { + "name": "highlightGamma", + "link": "_highlightGamma", + "ifdef": ["_CPostprocess"] + }, + { + "name": "highlightGain", + "link": "_highlightGain", + "ifdef": ["_CPostprocess"] + }, + { + "name": "highlightOffset", + "link": "_highlightOffset", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp1", + "link": "_PPComp1", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp2", + "link": "_PPComp2", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp3", + "link": "_PPComp3", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp4", + "link": "_PPComp4", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp5", + "link": "_PPComp5", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp6", + "link": "_PPComp6", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp7", + "link": "_PPComp7", + "ifdef": ["_CPostprocess"] + }, + { + "name": "PPComp8", + "link": "_PPComp8", + "ifdef": ["_CPostprocess"] } ], "texture_params": [], diff --git a/Shaders/ssao_pass/ssao_pass.frag.glsl b/Shaders/ssao_pass/ssao_pass.frag.glsl index ffcc0d20..c14f6bba 100755 --- a/Shaders/ssao_pass/ssao_pass.frag.glsl +++ b/Shaders/ssao_pass/ssao_pass.frag.glsl @@ -12,6 +12,9 @@ uniform vec3 eyeLook; uniform vec2 screenSize; uniform mat4 invVP; +uniform vec3 PPComp11; +uniform vec3 PPComp12; + in vec2 texCoord; in vec3 viewRay; out float fragColor; @@ -30,7 +33,11 @@ void main() { vec3 currentPos = getPosNoEye(eyeLook, vray, depth, cameraProj); // vec3 currentPos = getPos2NoEye(eye, invVP, depth, texCoord); float currentDistance = length(currentPos); - float currentDistanceA = currentDistance * ssaoScale * (1.0 / ssaoRadius); + #ifdef _CPostprocess + float currentDistanceA = currentDistance * PPComp12.y * (1.0 / PPComp11.z); + #else + float currentDistanceA = currentDistance * ssaoScale * (1.0 / ssaoRadius); + #endif float currentDistanceB = currentDistance * 0.0005; ivec2 px = ivec2(texCoord * screenSize); float phi = (3 * px.x ^ px.y + px.x * px.y) * 10; @@ -47,6 +54,10 @@ void main() { fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015); } - fragColor *= (ssaoStrength * 0.3) / samples; + #ifdef _CPostprocess + fragColor *= (PPComp12.x * 0.3) / samples; + #else + fragColor *= (ssaoStrength * 0.3) / samples; + #endif fragColor = 1.0 - fragColor; } diff --git a/Shaders/ssao_pass/ssao_pass.json b/Shaders/ssao_pass/ssao_pass.json index 8f951f6b..4d4bc23a 100755 --- a/Shaders/ssao_pass/ssao_pass.json +++ b/Shaders/ssao_pass/ssao_pass.json @@ -25,6 +25,14 @@ { "name": "screenSize", "link": "_screenSize" + }, + { + "name": "PPComp11", + "link": "_PPComp11" + }, + { + "name": "PPComp12", + "link": "_PPComp12" } ], "texture_params": [], diff --git a/Shaders/ssr_pass/ssr_pass.frag.glsl b/Shaders/ssr_pass/ssr_pass.frag.glsl index 93c369a4..0fc1ea0a 100755 --- a/Shaders/ssr_pass/ssr_pass.frag.glsl +++ b/Shaders/ssr_pass/ssr_pass.frag.glsl @@ -12,6 +12,9 @@ uniform mat4 P; uniform mat3 V3; uniform vec2 cameraProj; +uniform vec3 PPComp9; +uniform vec3 PPComp10; + in vec3 viewRay; in vec2 texCoord; out vec4 fragColor; @@ -48,12 +51,20 @@ vec4 binarySearch(vec3 dir) { if (ddepth < 0.0) hitCoord += dir; } // Ugly discard of hits too far away - if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0); + #ifdef _CPostprocess + if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0); + #else + if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0); + #endif return vec4(getProjectedCoord(hitCoord), 0.0, 1.0); } vec4 rayCast(vec3 dir) { - dir *= ssrRayStep; + #ifdef _CPostprocess + dir *= PPComp9.x; + #else + dir *= ssrRayStep; + #endif for (int i = 0; i < maxSteps; i++) { hitCoord += dir; if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); @@ -63,7 +74,7 @@ vec4 rayCast(vec3 dir) { void main() { vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); - float roughness = g0.b; + float roughness = unpackFloat(g0.b).y; if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; } float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a); @@ -83,7 +94,12 @@ void main() { vec3 reflected = normalize(reflect(viewPos, viewNormal)); hitCoord = viewPos; - vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0; + #ifdef _CPostprocess + vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0; + #else + vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0; + #endif + // * max(ssrMinRayStep, -viewPos.z) vec4 coords = rayCast(dir); @@ -91,12 +107,11 @@ void main() { float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0); float reflectivity = 1.0 - roughness; - float intensity = pow(reflectivity, ssrFalloffExp) * - screenEdgeFactor * - clamp(-reflected.z, 0.0, 1.0) * - clamp((ssrSearchDist - length(viewPos - hitCoord)) * - (1.0 / ssrSearchDist), 0.0, 1.0) * - coords.w; + #ifdef _CPostprocess + float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w; + #else + float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0) * coords.w; + #endif intensity = clamp(intensity, 0.0, 1.0); vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb; diff --git a/Shaders/ssr_pass/ssr_pass.json b/Shaders/ssr_pass/ssr_pass.json index 675520bf..496ac5a0 100755 --- a/Shaders/ssr_pass/ssr_pass.json +++ b/Shaders/ssr_pass/ssr_pass.json @@ -21,6 +21,14 @@ { "name": "cameraProj", "link": "_cameraPlaneProj" + }, + { + "name": "PPComp9", + "link": "_PPComp9" + }, + { + "name": "PPComp10", + "link": "_PPComp10" } ], "texture_params": [], diff --git a/Shaders/std/colorgrading.glsl b/Shaders/std/colorgrading.glsl new file mode 100644 index 00000000..3fcc8720 --- /dev/null +++ b/Shaders/std/colorgrading.glsl @@ -0,0 +1,144 @@ +// Colorgrading library functions - Inspired by UE4 +//No specific license (maybe zlib), but just do whatever + +#define LUMINANCE_PRESERVATION 0.75 +#define EPSILON 1e-10 +#define LUMA1 0.2722287168 +#define LUMA2 0.6740817658 +#define LUMA3 0.0536895174 + +float saturate(float v) { return clamp(v, 0.0, 1.0); } +vec2 saturate(vec2 v) { return clamp(v, vec2(0.0), vec2(1.0)); } +vec3 saturate(vec3 v) { return clamp(v, vec3(0.0), vec3(1.0)); } +vec4 saturate(vec4 v) { return clamp(v, vec4(0.0), vec4(1.0)); } + +float LumaKey (vec3 color) { + return dot(color, vec3(LUMA1, LUMA2, LUMA3)); +} + +vec3 ColorTemperatureToRGB(float temperatureInKelvins) +{ + vec3 retColor; + + temperatureInKelvins = clamp(temperatureInKelvins, 1000.0, 40000.0) / 100.0; + + if (temperatureInKelvins <= 66.0) + { + retColor.r = 1.0; + retColor.g = saturate(0.39008157876901960784 * log(temperatureInKelvins) - 0.63184144378862745098); + } + else + { + float t = temperatureInKelvins - 60.0; + retColor.r = saturate(1.29293618606274509804 * pow(t, -0.1332047592)); + retColor.g = saturate(1.12989086089529411765 * pow(t, -0.0755148492)); + } + + if (temperatureInKelvins >= 66.0) + retColor.b = 1.0; + else if(temperatureInKelvins <= 19.0) + retColor.b = 0.0; + else + retColor.b = saturate(0.54320678911019607843 * log(temperatureInKelvins - 10.0) - 1.19625408914); + + return retColor; +} + +float Luminance(vec3 color) +{ + float fmin = min(min(color.r, color.g), color.b); + float fmax = max(max(color.r, color.g), color.b); + return (fmax + fmin) / 2.0; +} + +vec3 HUEtoRGB(float H) +{ + float R = abs(H * 6.0 - 3.0) - 1.0; + float G = 2.0 - abs(H * 6.0 - 2.0); + float B = 2.0 - abs(H * 6.0 - 4.0); + return saturate(vec3(R,G,B)); +} + +vec3 HSLtoRGB(in vec3 HSL) +{ + vec3 RGB = HUEtoRGB(HSL.x); + float C = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y; + return (RGB - 0.5) * C + vec3(HSL.z); +} + +vec3 RGBtoHCV(vec3 RGB) +{ + vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0); + vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx); + float C = Q.x - min(Q.w, Q.y); + float H = abs((Q.w - Q.y) / (6.0 * C + EPSILON) + Q.z); + return vec3(H, C, Q.x); +} + +vec3 RGBtoHSL(vec3 RGB) +{ + vec3 HCV = RGBtoHCV(RGB); + float L = HCV.z - HCV.y * 0.5; + float S = HCV.y / (1.0 - abs(L * 2.0 - 1.0) + EPSILON); + return vec3(HCV.x, S, L); +} + + +vec3 ToneColorCorrection(vec3 Color, vec3 ColorSaturation, vec3 ColorContrast, vec3 ColorGamma, vec3 ColorGain, vec3 ColorOffset) { + //First initialize the colorluma key + float ColorLuma = LumaKey(Color); + //Add the saturation with the above key + Color = max(vec3(0,0,0), mix(ColorLuma.xxx, Color, ColorSaturation)); + //Contrast with slight color correction (0.18 coefficient) + float ContrastCorrectionCoefficient = 0.18; + Color = pow(Color * (1.0 / ContrastCorrectionCoefficient), ColorContrast) * ContrastCorrectionCoefficient; + //Gamma + Color = pow(Color, 1.0 / ColorGamma); + //Gain and Offset + Color = Color.rgb * ColorGain + (ColorOffset - 1); + //Return the color corrected profile + return Color; +} + +vec3 FinalizeColorCorrection(vec3 Color, mat3 ColorSaturation, mat3 ColorContrast, mat3 ColorGamma, mat3 ColorGain, mat3 ColorOffset, vec2 Toneweights) { + + float CCShadowsMax = Toneweights.x; + float CCHighlightsMin = Toneweights.y; + + //First initialize the colorluma key and set color correction weights + float ColorLuma = LumaKey(Color); + float CCWeightShadows = 1 - smoothstep(0, CCShadowsMax, ColorLuma); + float CCWeightHighlights = smoothstep(CCHighlightsMin, 1, ColorLuma); + float CCWeightMidtones = 1 - CCWeightShadows - CCWeightHighlights; + + vec3 CCColorShadows = ToneColorCorrection ( + Color, + ColorSaturation[0], + ColorContrast[0], + ColorGamma[0], + ColorGain[0], + ColorOffset[0] + ); + + vec3 CCColorMidtones = ToneColorCorrection ( + Color, + ColorSaturation[1], + ColorContrast[1], + ColorGamma[1], + ColorGain[1], + ColorOffset[1] + ); + + vec3 CCColorHighlights = ToneColorCorrection ( + Color, + ColorSaturation[2], + ColorContrast[2], + ColorGamma[2], + ColorGain[2], + ColorOffset[2] + ); + + vec3 CombinedCCProfile = CCColorShadows * CCWeightShadows + CCColorMidtones * CCWeightMidtones + CCColorHighlights * CCWeightHighlights; + + return vec3(CombinedCCProfile); +} \ No newline at end of file diff --git a/Shaders/std/dof.glsl b/Shaders/std/dof.glsl index f1416207..68cec1a1 100644 --- a/Shaders/std/dof.glsl +++ b/Shaders/std/dof.glsl @@ -31,17 +31,33 @@ vec3 color(vec2 coords, const float blur, const sampler2D tex, const vec2 texSte return col + mix(vec3(0.0), col, thresh * blur); } -vec3 dof(const vec2 texCoord, const float gdepth, const sampler2D tex, const sampler2D gbufferD, const vec2 texStep, const vec2 cameraProj) { +vec3 dof( + const vec2 texCoord, + const float gdepth, + const sampler2D tex, + const sampler2D gbufferD, + const vec2 texStep, + const vec2 cameraProj, + const bool autoFocus, + const float DOFDistance, + const float DOFLength, + const float DOFFStop) { + float depth = linearize(gdepth, cameraProj); - // const float fDepth = compoDOFDistance; - float fDepth = linearize(textureLod(gbufferD, focus, 0.0).r * 2.0 - 1.0, cameraProj); // Autofocus - - const float f = compoDOFLength; // Focal length in mm - const float d = fDepth * 1000.0; // Focal plane in mm + float fDepth = 0.0; + + if(autoFocus) { + fDepth = linearize(textureLod(gbufferD, focus, 0.0).r * 2.0 - 1.0, cameraProj); + } else { + fDepth = DOFDistance; + } + + float f = DOFLength; // Focal length in mm + float d = fDepth * 1000.0; // Focal plane in mm float o = depth * 1000.0; // Depth in mm float a = (o * f) / (o - f); float b = (d * f) / (d - f); - float c = (d - f) / (d * compoDOFFstop * coc); + float c = (d - f) / (d * DOFFStop * coc); float blur = abs(a - b) * c; blur = clamp(blur, 0.0, 1.0); diff --git a/Sources/armory/logicnode/BloomGetNode.hx b/Sources/armory/logicnode/BloomGetNode.hx new file mode 100644 index 00000000..8a2722b9 --- /dev/null +++ b/Sources/armory/logicnode/BloomGetNode.hx @@ -0,0 +1,20 @@ +package armory.logicnode; + +class BloomGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.bloom_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.bloom_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.bloom_uniforms[2]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/BloomSetNode.hx b/Sources/armory/logicnode/BloomSetNode.hx new file mode 100644 index 00000000..e5a4fdb7 --- /dev/null +++ b/Sources/armory/logicnode/BloomSetNode.hx @@ -0,0 +1,17 @@ +package armory.logicnode; + +class BloomSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.bloom_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.bloom_uniforms[1] = inputs[2].get(); + armory.renderpath.Postprocess.bloom_uniforms[2] = inputs[3].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/CameraGetNode.hx b/Sources/armory/logicnode/CameraGetNode.hx new file mode 100644 index 00000000..8a9a478a --- /dev/null +++ b/Sources/armory/logicnode/CameraGetNode.hx @@ -0,0 +1,32 @@ +package armory.logicnode; + +class CameraGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.camera_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.camera_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.camera_uniforms[2]; + } else if (from == 3) { + return armory.renderpath.Postprocess.camera_uniforms[3]; + } else if (from == 4) { + return armory.renderpath.Postprocess.camera_uniforms[4]; + } else if (from == 5) { + return armory.renderpath.Postprocess.camera_uniforms[5]; + } else if (from == 6) { + return armory.renderpath.Postprocess.camera_uniforms[6]; + } else if (from == 7) { + return armory.renderpath.Postprocess.camera_uniforms[7]; + } else if (from == 8) { + return armory.renderpath.Postprocess.camera_uniforms[8]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/CameraSetNode.hx b/Sources/armory/logicnode/CameraSetNode.hx new file mode 100644 index 00000000..8a93dd5f --- /dev/null +++ b/Sources/armory/logicnode/CameraSetNode.hx @@ -0,0 +1,25 @@ +package armory.logicnode; + +class CameraSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.camera_uniforms[1] = inputs[2].get(); + armory.renderpath.Postprocess.camera_uniforms[2] = inputs[3].get(); + armory.renderpath.Postprocess.camera_uniforms[3] = inputs[4].get(); + armory.renderpath.Postprocess.camera_uniforms[4] = inputs[5].get(); + armory.renderpath.Postprocess.camera_uniforms[5] = inputs[6].get(); + armory.renderpath.Postprocess.camera_uniforms[6] = inputs[7].get(); + armory.renderpath.Postprocess.camera_uniforms[7] = inputs[8].get(); + armory.renderpath.Postprocess.camera_uniforms[8] = inputs[9].get(); + armory.renderpath.Postprocess.camera_uniforms[9] = inputs[10].get(); + armory.renderpath.Postprocess.camera_uniforms[10] = inputs[11].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ChromaticAberrationGetNode.hx b/Sources/armory/logicnode/ChromaticAberrationGetNode.hx new file mode 100644 index 00000000..0dd119ba --- /dev/null +++ b/Sources/armory/logicnode/ChromaticAberrationGetNode.hx @@ -0,0 +1,18 @@ +package armory.logicnode; + +class ChromaticAberrationGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.chromatic_aberration_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.chromatic_aberration_uniforms[1]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/ChromaticAberrationSetNode.hx b/Sources/armory/logicnode/ChromaticAberrationSetNode.hx new file mode 100644 index 00000000..224dd9e1 --- /dev/null +++ b/Sources/armory/logicnode/ChromaticAberrationSetNode.hx @@ -0,0 +1,16 @@ +package armory.logicnode; + +class ChromaticAberrationSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.chromatic_aberration_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.chromatic_aberration_uniforms[1] = inputs[2].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ColorgradingGetGlobalNode.hx b/Sources/armory/logicnode/ColorgradingGetGlobalNode.hx new file mode 100644 index 00000000..2fb45d76 --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingGetGlobalNode.hx @@ -0,0 +1,29 @@ +package armory.logicnode; + +class ColorgradingGetGlobalNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[0][0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[2]; + } else if (from == 3) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[3]; + } else if (from == 4) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[4]; + } else if (from == 5) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[5]; + } else if (from == 6) { + return armory.renderpath.Postprocess.colorgrading_global_uniforms[6]; + } else { + return 0.0; + } + } + +} diff --git a/Sources/armory/logicnode/ColorgradingGetHighlightNode.hx b/Sources/armory/logicnode/ColorgradingGetHighlightNode.hx new file mode 100644 index 00000000..7395674f --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingGetHighlightNode.hx @@ -0,0 +1,29 @@ +package armory.logicnode; + +class ColorgradingGetHighlightNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[0][2]; + } else if (from == 1) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[0]; + } else if (from == 2) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[1]; + } else if (from == 3) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[2]; + } else if (from == 4) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[3]; + } else if (from == 5) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[4]; + } else if (from == 6) { + return armory.renderpath.Postprocess.colorgrading_highlight_uniforms[5]; + } else { + return 0.0; + } + } + +} diff --git a/Sources/armory/logicnode/ColorgradingGetMidtoneNode.hx b/Sources/armory/logicnode/ColorgradingGetMidtoneNode.hx new file mode 100644 index 00000000..2ce5b01c --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingGetMidtoneNode.hx @@ -0,0 +1,27 @@ +package armory.logicnode; + +class ColorgradingGetMidtoneNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[2]; + } else if (from == 3) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[3]; + } else if (from == 4) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[4]; + } else if (from == 5) { + return armory.renderpath.Postprocess.colorgrading_midtone_uniforms[5]; + } else { + return 0.0; + } + } + +} diff --git a/Sources/armory/logicnode/ColorgradingGetShadowNode.hx b/Sources/armory/logicnode/ColorgradingGetShadowNode.hx new file mode 100644 index 00000000..f995a416 --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingGetShadowNode.hx @@ -0,0 +1,29 @@ +package armory.logicnode; + +class ColorgradingGetShadowNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[0][1]; + } else if (from == 1) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[0]; + } else if (from == 2) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[1]; + } else if (from == 3) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[2]; + } else if (from == 4) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[3]; + } else if (from == 5) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[4]; + } else if (from == 6) { + return armory.renderpath.Postprocess.colorgrading_shadow_uniforms[5]; + } else { + return 0.0; + } + } + +} diff --git a/Sources/armory/logicnode/ColorgradingSetGlobalNode.hx b/Sources/armory/logicnode/ColorgradingSetGlobalNode.hx new file mode 100644 index 00000000..9325285c --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingSetGlobalNode.hx @@ -0,0 +1,65 @@ +package armory.logicnode; + +class ColorgradingSetGlobalNode extends LogicNode { + + public var property0:Dynamic; + public var property1:Dynamic; + public var property2:Dynamic; + public var property3:Dynamic; + + var value:Dynamic; + var whitebalance:Dynamic; + var tint:Dynamic; + var saturation:Dynamic; + var contrast:Dynamic; + var gamma:Dynamic; + var gain:Dynamic; + var offset:Dynamic; + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + if(property0 == "Uniform"){ + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][0] = inputs[1].get(); + armory.renderpath.Postprocess.colorgrading_global_uniforms[1][0] = inputs[2].get().x; + armory.renderpath.Postprocess.colorgrading_global_uniforms[1][1] = inputs[2].get().y; + armory.renderpath.Postprocess.colorgrading_global_uniforms[1][2] = inputs[2].get().z; + + for (i in 2...7){ + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][0] = inputs[i+1].get(); + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][1] = inputs[i+1].get(); + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][2] = inputs[i+1].get(); + } + + } else if (property0 == "RGB") { + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][0] = inputs[1].get(); + + for (i in 1...7){ + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][0] = inputs[i+1].get().x; + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][1] = inputs[i+1].get().y; + armory.renderpath.Postprocess.colorgrading_global_uniforms[i][2] = inputs[i+1].get().z; + } + + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + + } else if (property0 == "Preset File") { + return; + } else { + return; + } + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ColorgradingSetHighlightNode.hx b/Sources/armory/logicnode/ColorgradingSetHighlightNode.hx new file mode 100644 index 00000000..5bb67f28 --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingSetHighlightNode.hx @@ -0,0 +1,71 @@ +package armory.logicnode; + +class ColorgradingSetHighlightNode extends LogicNode { + + public var property0:Dynamic; + public var property1:Dynamic; + public var property2:Dynamic; + public var property3:Dynamic; + + var value:Dynamic; + var whitebalance:Dynamic; + var tint:Dynamic; + var saturation:Dynamic; + var contrast:Dynamic; + var gamma:Dynamic; + var gain:Dynamic; + var offset:Dynamic; + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + if(property0 == "Uniform"){ + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][2] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][0] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][1] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][2] = inputs[i+2].get(); + } + + //trace(inputs[6].get()); + + } else if (property0 == "RGB") { + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][2] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][0] = inputs[i+2].get().x; + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][1] = inputs[i+2].get().y; + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[i][2] = inputs[i+2].get().z; + } + + } else if (property0 == "Preset File") { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } else { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } + + //trace(tint.x); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ColorgradingSetMidtoneNode.hx b/Sources/armory/logicnode/ColorgradingSetMidtoneNode.hx new file mode 100644 index 00000000..56d4585d --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingSetMidtoneNode.hx @@ -0,0 +1,67 @@ +package armory.logicnode; + +class ColorgradingSetMidtoneNode extends LogicNode { + + public var property0:Dynamic; + public var property1:Dynamic; + public var property2:Dynamic; + public var property3:Dynamic; + + var value:Dynamic; + var whitebalance:Dynamic; + var tint:Dynamic; + var saturation:Dynamic; + var contrast:Dynamic; + var gamma:Dynamic; + var gain:Dynamic; + var offset:Dynamic; + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + if(property0 == "Uniform"){ + + for (i in 0...4){ + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][0] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][1] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][2] = inputs[i+2].get(); + } + + } else if (property0 == "RGB") { + + armory.renderpath.Postprocess.colorgrading_highlight_uniforms[0][0] = inputs[1].get(); + + for (i in 0...4){ + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][0] = inputs[i+1].get().x; + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][1] = inputs[i+1].get().y; + armory.renderpath.Postprocess.colorgrading_midtone_uniforms[i][2] = inputs[i+1].get().z; + } + + } else if (property0 == "Preset File") { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } else { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } + + //trace(tint.x); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ColorgradingSetShadowNode.hx b/Sources/armory/logicnode/ColorgradingSetShadowNode.hx new file mode 100644 index 00000000..075fa2b1 --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingSetShadowNode.hx @@ -0,0 +1,71 @@ +package armory.logicnode; + +class ColorgradingSetShadowNode extends LogicNode { + + public var property0:Dynamic; + public var property1:Dynamic; + public var property2:Dynamic; + public var property3:Dynamic; + + var value:Dynamic; + var whitebalance:Dynamic; + var tint:Dynamic; + var saturation:Dynamic; + var contrast:Dynamic; + var gamma:Dynamic; + var gain:Dynamic; + var offset:Dynamic; + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + if(property0 == "Uniform"){ + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][1] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][0] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][1] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][2] = inputs[i+2].get(); + } + + //trace(inputs[6].get()); + + } else if (property0 == "RGB") { + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][2] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][0] = inputs[i+2].get().x; + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][1] = inputs[i+2].get().y; + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][2] = inputs[i+2].get().z; + } + + } else if (property0 == "Preset File") { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } else { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } + + //trace(tint.x); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/ColorgradingShadowNode.hx b/Sources/armory/logicnode/ColorgradingShadowNode.hx new file mode 100644 index 00000000..e1dddb67 --- /dev/null +++ b/Sources/armory/logicnode/ColorgradingShadowNode.hx @@ -0,0 +1,71 @@ +package armory.logicnode; + +class ColorgradingShadowNode extends LogicNode { + + public var property0:Dynamic; + public var property1:Dynamic; + public var property2:Dynamic; + public var property3:Dynamic; + + var value:Dynamic; + var whitebalance:Dynamic; + var tint:Dynamic; + var saturation:Dynamic; + var contrast:Dynamic; + var gamma:Dynamic; + var gain:Dynamic; + var offset:Dynamic; + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + if(property0 == "Uniform"){ + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][1] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][0] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][1] = inputs[i+2].get(); + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][2] = inputs[i+2].get(); + } + + //trace(inputs[6].get()); + + } else if (property0 == "RGB") { + + armory.renderpath.Postprocess.colorgrading_global_uniforms[0][2] = inputs[1].get(); + + for (i in 0...5){ + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][0] = inputs[i+2].get().x; + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][1] = inputs[i+2].get().y; + armory.renderpath.Postprocess.colorgrading_shadow_uniforms[i][2] = inputs[i+2].get().z; + } + + } else if (property0 == "Preset File") { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } else { + var value:Dynamic = inputs[0].get(); + var whitebalance:Float = inputs[1].get(); + var tint:iron.math.Vec4 = inputs[2].get(); + var saturation:Float = inputs[3].get(); + var contrast:Float = inputs[4].get(); + var gamma:Float = inputs[5].get(); + var gain:Float = inputs[6].get(); + var offset:Float = inputs[7].get(); + } + + //trace(tint.x); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/LenstextureGetNode.hx b/Sources/armory/logicnode/LenstextureGetNode.hx new file mode 100644 index 00000000..fc2efd6c --- /dev/null +++ b/Sources/armory/logicnode/LenstextureGetNode.hx @@ -0,0 +1,24 @@ +package armory.logicnode; + +class LenstextureGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.lenstexture_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.lenstexture_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.lenstexture_uniforms[2]; + } else if (from == 3) { + return armory.renderpath.Postprocess.lenstexture_uniforms[3]; + } else if (from == 4) { + return armory.renderpath.Postprocess.lenstexture_uniforms[4]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/LenstextureSetNode.hx b/Sources/armory/logicnode/LenstextureSetNode.hx new file mode 100644 index 00000000..94d1bac1 --- /dev/null +++ b/Sources/armory/logicnode/LenstextureSetNode.hx @@ -0,0 +1,19 @@ +package armory.logicnode; + +class LenstextureSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.lenstexture_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.lenstexture_uniforms[1] = inputs[2].get(); + armory.renderpath.Postprocess.lenstexture_uniforms[2] = inputs[3].get(); + armory.renderpath.Postprocess.lenstexture_uniforms[3] = inputs[4].get(); + armory.renderpath.Postprocess.lenstexture_uniforms[4] = inputs[5].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/SSAOGetNode.hx b/Sources/armory/logicnode/SSAOGetNode.hx new file mode 100644 index 00000000..2e6d7113 --- /dev/null +++ b/Sources/armory/logicnode/SSAOGetNode.hx @@ -0,0 +1,20 @@ +package armory.logicnode; + +class SSAOGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.ssao_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.ssao_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.ssao_uniforms[2]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/SSAOSetNode.hx b/Sources/armory/logicnode/SSAOSetNode.hx new file mode 100644 index 00000000..373e2e65 --- /dev/null +++ b/Sources/armory/logicnode/SSAOSetNode.hx @@ -0,0 +1,17 @@ +package armory.logicnode; + +class SSAOSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.ssao_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.ssao_uniforms[1] = inputs[2].get(); + armory.renderpath.Postprocess.ssao_uniforms[2] = inputs[3].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/logicnode/SSRGetNode.hx b/Sources/armory/logicnode/SSRGetNode.hx new file mode 100644 index 00000000..b35d9fb9 --- /dev/null +++ b/Sources/armory/logicnode/SSRGetNode.hx @@ -0,0 +1,24 @@ +package armory.logicnode; + +class SSRGetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function get(from:Int):Dynamic { + if(from == 0) { + return armory.renderpath.Postprocess.ssr_uniforms[0]; + } else if (from == 1) { + return armory.renderpath.Postprocess.ssr_uniforms[1]; + } else if (from == 2) { + return armory.renderpath.Postprocess.ssr_uniforms[2]; + } else if (from == 3) { + return armory.renderpath.Postprocess.ssr_uniforms[3]; + } else if (from == 4) { + return armory.renderpath.Postprocess.ssr_uniforms[4]; + } else { + return 0.0; + } + } +} diff --git a/Sources/armory/logicnode/SSRSetNode.hx b/Sources/armory/logicnode/SSRSetNode.hx new file mode 100644 index 00000000..800942a2 --- /dev/null +++ b/Sources/armory/logicnode/SSRSetNode.hx @@ -0,0 +1,19 @@ +package armory.logicnode; + +class SSRSetNode extends LogicNode { + + public function new(tree:LogicTree) { + super(tree); + } + + override function run(from:Int) { + + armory.renderpath.Postprocess.ssr_uniforms[0] = inputs[1].get(); + armory.renderpath.Postprocess.ssr_uniforms[1] = inputs[2].get(); + armory.renderpath.Postprocess.ssr_uniforms[2] = inputs[3].get(); + armory.renderpath.Postprocess.ssr_uniforms[3] = inputs[4].get(); + armory.renderpath.Postprocess.ssr_uniforms[4] = inputs[5].get(); + + runOutput(0); + } +} diff --git a/Sources/armory/renderpath/Postprocess.hx b/Sources/armory/renderpath/Postprocess.hx new file mode 100644 index 00000000..d21f2b61 --- /dev/null +++ b/Sources/armory/renderpath/Postprocess.hx @@ -0,0 +1,362 @@ +package armory.renderpath; + +import iron.Scene; +import iron.object.Object; +import iron.data.MaterialData; +import iron.math.Vec4; + +class Postprocess { + + public static var colorgrading_global_uniforms = [ + [6500.0, 1.0, 0.0], //0: Whitebalance, Shadow Max, Highlight Min + [1.0, 1.0, 1.0], //1: Tint + [1.0, 1.0, 1.0], //2: Saturation + [1.0, 1.0, 1.0], //3: Contrast + [1.0, 1.0, 1.0], //4: Gamma + [1.0, 1.0, 1.0], //5: Gain + [1.0, 1.0, 1.0], //6: Offset + [1.0, 1.0, 1.0] //7: LUT Strength + ]; + + public static var colorgrading_shadow_uniforms = [ + [1.0, 1.0, 1.0], //0: Saturation + [1.0, 1.0, 1.0], //1: Contrast + [1.0, 1.0, 1.0], //2: Gamma + [1.0, 1.0, 1.0], //3: Gain + [1.0, 1.0, 1.0] //4: Offset + ]; + + public static var colorgrading_midtone_uniforms = [ + [1.0, 1.0, 1.0], //0: Saturation + [1.0, 1.0, 1.0], //1: Contrast + [1.0, 1.0, 1.0], //2: Gamma + [1.0, 1.0, 1.0], //3: Gain + [1.0, 1.0, 1.0] //4: Offset + ]; + + public static var colorgrading_highlight_uniforms = [ + [1.0, 1.0, 1.0], //0: Saturation + [1.0, 1.0, 1.0], //1: Contrast + [1.0, 1.0, 1.0], //2: Gamma + [1.0, 1.0, 1.0], //3: Gain + [1.0, 1.0, 1.0] //4: Offset + ]; + + public static var camera_uniforms = [ + 1.0, //0: Camera: F-Number + 2.8333, //1: Camera: Shutter time + 100.0, //2: Camera: ISO + 0.0, //3: Camera: Exposure Compensation + 0.01, //4: Fisheye Distortion + 1, //5: DoF AutoFocus ยงยง If true, it ignores the DoF Distance setting + 10.0, //6: DoF Distance + 160.0, //7: DoF Focal Length mm + 128, //8: DoF F-Stop + 0, //9: Tonemapping Method + 2.0 //10: Film Grain + ]; + + public static var tonemapper_uniforms = [ + 1.0, //0: Slope + 1.0, //1: Toe + 1.0, //2: Shoulder + 1.0, //3: Black Clip + 1.0 //4: White Clip + ]; + + public static var ssr_uniforms = [ + 0.04, //0: Step + 0.05, //1: StepMin + 5.0, //2: Search + 5.0, //3: Falloff + 0.6 //4: Jitter + ]; + + public static var bloom_uniforms = [ + 1.0, //0: Threshold + 3.5, //1: Strength + 3.0 //2: Radius + ]; + + public static var ssao_uniforms = [ + 1.0, + 1.0, + 8 + ]; + + public static var lenstexture_uniforms = [ + 0.1, //0: Center Min Clip + 0.5, //1: Center Max Clip + 0.1, //2: Luminance Min + 2.5, //3: Luminance Max + 2.0 //4: Brightness Exponent + ]; + + public static var chromatic_aberration_uniforms = [ + 2.0, //0: Strength + 32 //1: Samples + ]; + + public static function vec3Link(object:Object, mat:MaterialData, link:String):iron.math.Vec4 { + var v:Vec4 = null; + + if (link == "_globalWeight") { + var ppm_index = 0; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalTint") { + var ppm_index = 1; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalSaturation") { + var ppm_index = 2; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalContrast") { + var ppm_index = 3; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalGamma") { + var ppm_index = 4; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalGain") { + var ppm_index = 5; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + if (link == "_globalOffset") { + var ppm_index = 6; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[ppm_index][0]; + v.y = colorgrading_global_uniforms[ppm_index][1]; + v.z = colorgrading_global_uniforms[ppm_index][2]; + } + + //Shadow ppm + if (link == "_shadowSaturation") { + var ppm_index = 0; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_shadow_uniforms[ppm_index][0]; + v.y = colorgrading_shadow_uniforms[ppm_index][1]; + v.z = colorgrading_shadow_uniforms[ppm_index][2]; + } + if (link == "_shadowContrast") { + var ppm_index = 1; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_shadow_uniforms[ppm_index][0]; + v.y = colorgrading_shadow_uniforms[ppm_index][1]; + v.z = colorgrading_shadow_uniforms[ppm_index][2]; + } + if (link == "_shadowGamma") { + var ppm_index = 2; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_shadow_uniforms[ppm_index][0]; + v.y = colorgrading_shadow_uniforms[ppm_index][1]; + v.z = colorgrading_shadow_uniforms[ppm_index][2]; + } + if (link == "_shadowGain") { + var ppm_index = 3; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_shadow_uniforms[ppm_index][0]; + v.y = colorgrading_shadow_uniforms[ppm_index][1]; + v.z = colorgrading_shadow_uniforms[ppm_index][2]; + } + if (link == "_shadowOffset") { + var ppm_index = 4; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_shadow_uniforms[ppm_index][0]; + v.y = colorgrading_shadow_uniforms[ppm_index][1]; + v.z = colorgrading_shadow_uniforms[ppm_index][2]; + } + + //Midtone ppm + if (link == "_midtoneSaturation") { + var ppm_index = 0; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_midtone_uniforms[ppm_index][0]; + v.y = colorgrading_midtone_uniforms[ppm_index][1]; + v.z = colorgrading_midtone_uniforms[ppm_index][2]; + } + if (link == "_midtoneContrast") { + var ppm_index = 1; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_midtone_uniforms[ppm_index][0]; + v.y = colorgrading_midtone_uniforms[ppm_index][1]; + v.z = colorgrading_midtone_uniforms[ppm_index][2]; + } + if (link == "_midtoneGamma") { + var ppm_index = 2; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_midtone_uniforms[ppm_index][0]; + v.y = colorgrading_midtone_uniforms[ppm_index][1]; + v.z = colorgrading_midtone_uniforms[ppm_index][2]; + } + if (link == "_midtoneGain") { + var ppm_index = 3; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_midtone_uniforms[ppm_index][0]; + v.y = colorgrading_midtone_uniforms[ppm_index][1]; + v.z = colorgrading_midtone_uniforms[ppm_index][2]; + } + if (link == "_midtoneOffset") { + var ppm_index = 4; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_midtone_uniforms[ppm_index][0]; + v.y = colorgrading_midtone_uniforms[ppm_index][1]; + v.z = colorgrading_midtone_uniforms[ppm_index][2]; + } + + //Highlight ppm + if (link == "_highlightSaturation") { + var ppm_index = 0; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_highlight_uniforms[ppm_index][0]; + v.y = colorgrading_highlight_uniforms[ppm_index][1]; + v.z = colorgrading_highlight_uniforms[ppm_index][2]; + } + if (link == "_highlightContrast") { + var ppm_index = 1; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_highlight_uniforms[ppm_index][0]; + v.y = colorgrading_highlight_uniforms[ppm_index][1]; + v.z = colorgrading_highlight_uniforms[ppm_index][2]; + } + if (link == "_highlightGamma") { + var ppm_index = 2; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_highlight_uniforms[ppm_index][0]; + v.y = colorgrading_highlight_uniforms[ppm_index][1]; + v.z = colorgrading_highlight_uniforms[ppm_index][2]; + } + if (link == "_highlightGain") { + var ppm_index = 3; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_highlight_uniforms[ppm_index][0]; + v.y = colorgrading_highlight_uniforms[ppm_index][1]; + v.z = colorgrading_highlight_uniforms[ppm_index][2]; + } + if (link == "_highlightOffset") { + var ppm_index = 4; + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_highlight_uniforms[ppm_index][0]; + v.y = colorgrading_highlight_uniforms[ppm_index][1]; + v.z = colorgrading_highlight_uniforms[ppm_index][2]; + } + + //Postprocess Components + if (link == "_PPComp1") { + v = iron.object.Uniforms.helpVec; + v.x = camera_uniforms[0]; //F-Number + v.y = camera_uniforms[1]; //Shutter + v.z = camera_uniforms[2]; //ISO + } + + if (link == "_PPComp2") { + v = iron.object.Uniforms.helpVec; + v.x = camera_uniforms[3]; //EC + v.y = camera_uniforms[4]; //Lens Distortion + v.z = camera_uniforms[5]; //DOF Autofocus + } + + if (link == "_PPComp3") { + v = iron.object.Uniforms.helpVec; + v.x = camera_uniforms[6]; //Distance + v.y = camera_uniforms[7]; //Focal Length + v.z = camera_uniforms[8]; //F-Stop + } + + if (link == "_PPComp4") { + v = iron.object.Uniforms.helpVec; + v.x = Std.int(camera_uniforms[9]); //Tonemapping + v.y = camera_uniforms[10]; //Film Grain + v.z = tonemapper_uniforms[0]; //Slope + } + + if (link == "_PPComp5") { + v = iron.object.Uniforms.helpVec; + v.x = tonemapper_uniforms[1]; //Toe + v.y = tonemapper_uniforms[2]; //Shoulder + v.z = tonemapper_uniforms[3]; //Black Clip + } + + if (link == "_PPComp6") { + v = iron.object.Uniforms.helpVec; + v.x = tonemapper_uniforms[4]; //White Clip + v.y = lenstexture_uniforms[0]; //Center Min + v.z = lenstexture_uniforms[1]; //Center Max + } + + if (link == "_PPComp7") { + v = iron.object.Uniforms.helpVec; + v.x = lenstexture_uniforms[2]; //Lum min + v.y = lenstexture_uniforms[3]; //Lum max + v.z = lenstexture_uniforms[4]; //Expo + } + + if (link == "_PPComp8") { + v = iron.object.Uniforms.helpVec; + v.x = colorgrading_global_uniforms[7][0]; //LUT R + v.y = colorgrading_global_uniforms[7][1]; //LUT G + v.z = colorgrading_global_uniforms[7][2]; //LUT B + } + + if (link == "_PPComp9") { + v = iron.object.Uniforms.helpVec; + v.x = ssr_uniforms[0]; //Step + v.y = ssr_uniforms[1]; //StepMin + v.z = ssr_uniforms[2]; //Search + } + + if (link == "_PPComp10") { + v = iron.object.Uniforms.helpVec; + v.x = ssr_uniforms[3]; //Falloff + v.y = ssr_uniforms[4]; //Jitter + v.z = bloom_uniforms[0]; //Bloom Threshold + } + + if (link == "_PPComp11") { + v = iron.object.Uniforms.helpVec; + v.x = bloom_uniforms[1]; //Bloom Strength + v.y = bloom_uniforms[2]; //Bloom Radius + v.z = ssao_uniforms[0]; //SSAO Strength + } + + if (link == "_PPComp12") { + v = iron.object.Uniforms.helpVec; + v.x = ssao_uniforms[1]; //SSAO Radius + v.y = ssao_uniforms[2]; //SSAO Max Steps + v.z = 0; + } + + if(link == "_PPComp13") { + v = iron.object.Uniforms.helpVec; + v.x = chromatic_aberration_uniforms[0]; //CA Strength + v.y = chromatic_aberration_uniforms[1]; //CA Samples + v.z = 0; + } + + public static function init() { + + iron.object.Uniforms.externalVec3Links.push(vec3Link); + + } + +} \ No newline at end of file diff --git a/Sources/armory/renderpath/RenderPathCreator.hx b/Sources/armory/renderpath/RenderPathCreator.hx index 021445c1..cc676369 100644 --- a/Sources/armory/renderpath/RenderPathCreator.hx +++ b/Sources/armory/renderpath/RenderPathCreator.hx @@ -24,6 +24,13 @@ class RenderPathCreator { public static function get(): RenderPath { path = new RenderPath(); Inc.init(path); + + #if rp_pp + iron.App.notifyOnInit(function() { + Postprocess.init(); + }); + #end + #if (rp_renderer == "Forward") RenderPathForward.init(path); path.commands = RenderPathForward.commands; diff --git a/blender/arm/logicnode/postprocess_colorgrading_get_global_node.py b/blender/arm/logicnode/postprocess_colorgrading_get_global_node.py new file mode 100644 index 00000000..81368bf3 --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_get_global_node.py @@ -0,0 +1,21 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ColorgradingGetGlobalNode(Node, ArmLogicTreeNode): + '''Colorgrading Get Global node''' + bl_idname = 'LNColorgradingGetGlobalNode' + bl_label = 'Colorgrading Get Global' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'Whitebalance') + self.outputs.new('NodeSocketVector', 'Tint') + self.outputs.new('NodeSocketVector', 'Saturation') + self.outputs.new('NodeSocketVector', 'Contrast') + self.outputs.new('NodeSocketVector', 'Gamma') + self.outputs.new('NodeSocketVector', 'Gain') + self.outputs.new('NodeSocketVector', 'Offset') + +add_node(ColorgradingGetGlobalNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_get_highlight_node.py b/blender/arm/logicnode/postprocess_colorgrading_get_highlight_node.py new file mode 100644 index 00000000..c300604e --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_get_highlight_node.py @@ -0,0 +1,20 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ColorgradingGetHighlightNode(Node, ArmLogicTreeNode): + '''Colorgrading Get Highlight node''' + bl_idname = 'LNColorgradingGetHighlightNode' + bl_label = 'Colorgrading Get Highlight' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'HightlightMin') + self.outputs.new('NodeSocketVector', 'Saturation') + self.outputs.new('NodeSocketVector', 'Contrast') + self.outputs.new('NodeSocketVector', 'Gamma') + self.outputs.new('NodeSocketVector', 'Gain') + self.outputs.new('NodeSocketVector', 'Offset') + +add_node(ColorgradingGetHighlightNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_get_midtone_node.py b/blender/arm/logicnode/postprocess_colorgrading_get_midtone_node.py new file mode 100644 index 00000000..7a6c0d78 --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_get_midtone_node.py @@ -0,0 +1,19 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ColorgradingGetMidtoneNode(Node, ArmLogicTreeNode): + '''Colorgrading Get Midtone node''' + bl_idname = 'LNColorgradingGetMidtoneNode' + bl_label = 'Colorgrading Get Midtone' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketVector', 'Saturation') + self.outputs.new('NodeSocketVector', 'Contrast') + self.outputs.new('NodeSocketVector', 'Gamma') + self.outputs.new('NodeSocketVector', 'Gain') + self.outputs.new('NodeSocketVector', 'Offset') + +add_node(ColorgradingGetMidtoneNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_get_shadow_node.py b/blender/arm/logicnode/postprocess_colorgrading_get_shadow_node.py new file mode 100644 index 00000000..1c410cf9 --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_get_shadow_node.py @@ -0,0 +1,20 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ColorgradingGetShadowNode(Node, ArmLogicTreeNode): + '''Colorgrading Get Shadow node''' + bl_idname = 'LNColorgradingGetShadowNode' + bl_label = 'Colorgrading Get Shadow' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'ShadowMax') + self.outputs.new('NodeSocketVector', 'Saturation') + self.outputs.new('NodeSocketVector', 'Contrast') + self.outputs.new('NodeSocketVector', 'Gamma') + self.outputs.new('NodeSocketVector', 'Gain') + self.outputs.new('NodeSocketVector', 'Offset') + +add_node(ColorgradingGetShadowNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_set_global_node.py b/blender/arm/logicnode/postprocess_colorgrading_set_global_node.py new file mode 100644 index 00000000..6aa6607b --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_set_global_node.py @@ -0,0 +1,89 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +def update_node(self, context): + #Clean all nodes + + while len(self.inputs) > 1: + self.inputs.remove(self.inputs[-1]) + + if (self.property0 == 'Uniform'): + self.draw_nodes_uniform(context) + elif (self.property0 == 'RGB'): + self.draw_nodes_rgb(context) + else: + self.draw_nodes_colorwheel(context) + +def set_data(self, context): + + abspath = bpy.path.abspath(self.filepath) + abspath = abspath.replace("\\","\\\\") + with open(abspath, 'r') as myfile: + data = myfile.read().replace('\n', '').replace('"','') + self.property1 = data + +class ColorgradingSetGlobalNode(Node, ArmLogicTreeNode): + '''Colorgrading Set Global node''' + bl_idname = 'LNColorgradingSetGlobalNode' + bl_label = 'Colorgrading Set Global' + bl_icon = 'QUESTION' + + # TODO: RRESET FILE OPTION FOR THE BELOW + property0 : EnumProperty( + items = [('RGB', 'RGB', 'RGB'), + ('Uniform', 'Uniform', 'Uniform')], + name='Mode', default='Uniform', update=update_node) + property1 : StringProperty(name="Loaded Data", description="Loaded data - Just ignore", default="") + filepath : StringProperty(name="Preset File", description="Postprocess colorgrading preset file", default="", subtype="FILE_PATH", update=set_data) + + + def draw_nodes_uniform(self, context): + self.inputs.new('NodeSocketFloat', 'Whitebalance') + self.inputs[-1].default_value = 6500.0 + self.inputs.new('NodeSocketColor', 'Tint') + self.inputs[-1].default_value = [1.0, 1.0, 1.0, 1.0] + self.inputs.new('NodeSocketFloat', 'Saturation') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Contrast') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gamma') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gain') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Offset') + self.inputs[-1].default_value = 1 + + def draw_nodes_rgb(self, context): + self.inputs.new('NodeSocketFloat', 'Whitebalance') + self.inputs[-1].default_value = 6500.0 + self.inputs.new('NodeSocketVector', 'Tint') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Saturation') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Contrast') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gamma') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gain') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Offset') + self.inputs[-1].default_value = [1,1,1] + + def draw_nodes_colorwheel(self, context): + pass + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.outputs.new('ArmNodeSocketAction', 'Out') + self.draw_nodes_uniform(context) + + def draw_buttons(self, context, layout): + layout.label(text="Select value mode") + layout.prop(self, 'property0') + if (self.property0 == 'Preset File'): + layout.prop(self, 'filepath') + layout.prop(self, 'property1') + +add_node(ColorgradingSetGlobalNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_set_highlight_node.py b/blender/arm/logicnode/postprocess_colorgrading_set_highlight_node.py new file mode 100644 index 00000000..55d67d63 --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_set_highlight_node.py @@ -0,0 +1,85 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +def update_node(self, context): + #Clean all nodes + + while len(self.inputs) > 1: + self.inputs.remove(self.inputs[-1]) + + if (self.property0 == 'Uniform'): + self.draw_nodes_uniform(context) + elif (self.property0 == 'RGB'): + self.draw_nodes_rgb(context) + else: + self.draw_nodes_colorwheel(context) + +def set_data(self, context): + + abspath = bpy.path.abspath(self.filepath) + abspath = abspath.replace("\\","\\\\") + with open(abspath, 'r') as myfile: + data = myfile.read().replace('\n', '').replace('"','') + self.property1 = data + +class ColorgradingSetHighlightNode(Node, ArmLogicTreeNode): + '''Colorgrading Set Highlight node''' + bl_idname = 'LNColorgradingSetHighlightNode' + bl_label = 'Colorgrading Set Highlight' + bl_icon = 'QUESTION' + + # TODO: RRESET FILE OPTION FOR THE BELOW + property0 : EnumProperty( + items = [('RGB', 'RGB', 'RGB'), + ('Uniform', 'Uniform', 'Uniform')], + name='Mode', default='Uniform', update=update_node) + property1 : StringProperty(name="Loaded Data", description="Loaded data - Just ignore", default="") + filepath : StringProperty(name="Preset File", description="Postprocess colorgrading preset file", default="", subtype="FILE_PATH", update=set_data) + + + def draw_nodes_uniform(self, context): + self.inputs.new('NodeSocketFloat', 'HighlightMin') + self.inputs[-1].default_value = 0 + self.inputs.new('NodeSocketFloat', 'Saturation') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Contrast') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gamma') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gain') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Offset') + self.inputs[-1].default_value = 1 + + def draw_nodes_rgb(self, context): + self.inputs.new('NodeSocketFloat', 'HighlightMin') + self.inputs[-1].default_value = 0 + self.inputs.new('NodeSocketVector', 'Saturation') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Contrast') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gamma') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gain') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Offset') + self.inputs[-1].default_value = [1,1,1] + + def draw_nodes_colorwheel(self, context): + pass + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.outputs.new('ArmNodeSocketAction', 'Out') + self.draw_nodes_uniform(context) + + def draw_buttons(self, context, layout): + layout.label(text="Select value mode") + layout.prop(self, 'property0') + if (self.property0 == 'Preset File'): + layout.prop(self, 'filepath') + layout.prop(self, 'property1') + +add_node(ColorgradingSetHighlightNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_set_midtone_node.py b/blender/arm/logicnode/postprocess_colorgrading_set_midtone_node.py new file mode 100644 index 00000000..f947c2af --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_set_midtone_node.py @@ -0,0 +1,83 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +def update_node(self, context): + #Clean all nodes + + while len(self.inputs) > 1: + self.inputs.remove(self.inputs[-1]) + + if (self.property0 == 'Uniform'): + self.draw_nodes_uniform(context) + elif (self.property0 == 'RGB'): + self.draw_nodes_rgb(context) + else: + self.draw_nodes_colorwheel(context) + +def set_data(self, context): + + abspath = bpy.path.abspath(self.filepath) + abspath = abspath.replace("\\","\\\\") + with open(abspath, 'r') as myfile: + data = myfile.read().replace('\n', '').replace('"','') + self.property1 = data + +class ColorgradingSetMidtoneNode(Node, ArmLogicTreeNode): + '''Colorgrading Set Midtone node''' + bl_idname = 'LNColorgradingSetMidtoneNode' + bl_label = 'Colorgrading Set Midtone' + bl_icon = 'QUESTION' + + # TODO: RRESET FILE OPTION FOR THE BELOW + property0 : EnumProperty( + items = [('RGB', 'RGB', 'RGB'), + ('Uniform', 'Uniform', 'Uniform')], + name='Mode', default='Uniform', update=update_node) + property1 : StringProperty(name="Loaded Data", description="Loaded data - Just ignore", default="") + filepath : StringProperty(name="Preset File", description="Postprocess colorgrading preset file", default="", subtype="FILE_PATH", update=set_data) + + + def draw_nodes_uniform(self, context): + self.inputs.new('NodeSocketFloat', 'Saturation') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Contrast') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gamma') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gain') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Offset') + self.inputs[-1].default_value = 1 + + def draw_nodes_rgb(self, context): + self.inputs.new('NodeSocketVector', 'Tint') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Saturation') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Contrast') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gamma') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gain') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Offset') + self.inputs[-1].default_value = [1,1,1] + + def draw_nodes_colorwheel(self, context): + pass + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.outputs.new('ArmNodeSocketAction', 'Out') + self.draw_nodes_uniform(context) + + def draw_buttons(self, context, layout): + layout.label(text="Select value mode") + layout.prop(self, 'property0') + if (self.property0 == 'Preset File'): + layout.prop(self, 'filepath') + layout.prop(self, 'property1') + +add_node(ColorgradingSetMidtoneNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_colorgrading_set_shadow_node.py b/blender/arm/logicnode/postprocess_colorgrading_set_shadow_node.py new file mode 100644 index 00000000..42c1b96c --- /dev/null +++ b/blender/arm/logicnode/postprocess_colorgrading_set_shadow_node.py @@ -0,0 +1,85 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +def update_node(self, context): + #Clean all nodes + + while len(self.inputs) > 1: + self.inputs.remove(self.inputs[-1]) + + if (self.property0 == 'Uniform'): + self.draw_nodes_uniform(context) + elif (self.property0 == 'RGB'): + self.draw_nodes_rgb(context) + else: + self.draw_nodes_colorwheel(context) + +def set_data(self, context): + + abspath = bpy.path.abspath(self.filepath) + abspath = abspath.replace("\\","\\\\") + with open(abspath, 'r') as myfile: + data = myfile.read().replace('\n', '').replace('"','') + self.property1 = data + +class ColorgradingSetShadowNode(Node, ArmLogicTreeNode): + '''Colorgrading Set Shadow node''' + bl_idname = 'LNColorgradingSetShadowNode' + bl_label = 'Colorgrading Set Shadow' + bl_icon = 'QUESTION' + + # TODO: RRESET FILE OPTION FOR THE BELOW + property0 : EnumProperty( + items = [('RGB', 'RGB', 'RGB'), + ('Uniform', 'Uniform', 'Uniform')], + name='Mode', default='Uniform', update=update_node) + property1 : StringProperty(name="Loaded Data", description="Loaded data - Just ignore", default="") + filepath : StringProperty(name="Preset File", description="Postprocess colorgrading preset file", default="", subtype="FILE_PATH", update=set_data) + + + def draw_nodes_uniform(self, context): + self.inputs.new('NodeSocketFloat', 'ShadowMax') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Saturation') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Contrast') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gamma') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Gain') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketFloat', 'Offset') + self.inputs[-1].default_value = 1 + + def draw_nodes_rgb(self, context): + self.inputs.new('NodeSocketFloat', 'ShadowMax') + self.inputs[-1].default_value = 1 + self.inputs.new('NodeSocketVector', 'Saturation') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Contrast') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gamma') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Gain') + self.inputs[-1].default_value = [1,1,1] + self.inputs.new('NodeSocketVector', 'Offset') + self.inputs[-1].default_value = [1,1,1] + + def draw_nodes_colorwheel(self, context): + pass + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.outputs.new('ArmNodeSocketAction', 'Out') + self.draw_nodes_uniform(context) + + def draw_buttons(self, context, layout): + layout.label(text="Select value mode") + layout.prop(self, 'property0') + if (self.property0 == 'Preset File'): + layout.prop(self, 'filepath') + layout.prop(self, 'property1') + +add_node(ColorgradingSetShadowNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_get_bloom.py b/blender/arm/logicnode/postprocess_get_bloom.py new file mode 100644 index 00000000..ade76128 --- /dev/null +++ b/blender/arm/logicnode/postprocess_get_bloom.py @@ -0,0 +1,17 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class BloomGetNode(Node, ArmLogicTreeNode): + '''Get Bloom Effect''' + bl_idname = 'LNBloomGetNode' + bl_label = 'Get Bloom' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'Threshold') + self.outputs.new('NodeSocketFloat', 'Strength') + self.outputs.new('NodeSocketFloat', 'Radius') + +add_node(BloomGetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_get_camera.py b/blender/arm/logicnode/postprocess_get_camera.py new file mode 100644 index 00000000..122db265 --- /dev/null +++ b/blender/arm/logicnode/postprocess_get_camera.py @@ -0,0 +1,24 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class CameraGetNode(Node, ArmLogicTreeNode): + '''Get Camera Effect''' + bl_idname = 'LNCameraGetNode' + bl_label = 'Get Camera' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'F-Stop') + self.outputs.new('NodeSocketFloat', 'Shutter Time') + self.outputs.new('NodeSocketFloat', 'ISO') + self.outputs.new('NodeSocketFloat', 'Exposure Compensation') + self.outputs.new('NodeSocketFloat', 'Fisheye Distortion') + self.outputs.new('NodeSocketBool', 'Auto Focus') + self.outputs.new('NodeSocketFloat', 'DOF Distance') + self.outputs.new('NodeSocketFloat', 'DOF Length') + self.outputs.new('NodeSocketFloat', 'DOF F-Stop') + self.outputs.new('NodeSocketFloat', 'Film Grain') + +add_node(CameraGetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_get_chromatic_aberration.py b/blender/arm/logicnode/postprocess_get_chromatic_aberration.py new file mode 100644 index 00000000..24cd2392 --- /dev/null +++ b/blender/arm/logicnode/postprocess_get_chromatic_aberration.py @@ -0,0 +1,16 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ChromaticAberrationGetNode(Node, ArmLogicTreeNode): + '''Get Chromatic Aberration Effect''' + bl_idname = 'LNChromaticAberrationGetNode' + bl_label = 'Get ChromaticAberration' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'Strength') + self.outputs.new('NodeSocketFloat', 'Samples') + +add_node(ChromaticAberrationGetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_get_ssao.py b/blender/arm/logicnode/postprocess_get_ssao.py new file mode 100644 index 00000000..acea65af --- /dev/null +++ b/blender/arm/logicnode/postprocess_get_ssao.py @@ -0,0 +1,17 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class SSAOGetNode(Node, ArmLogicTreeNode): + '''Get SSAO Effect''' + bl_idname = 'LNSSAOGetNode' + bl_label = 'Get SSAO' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'Radius') + self.outputs.new('NodeSocketFloat', 'Strength') + self.outputs.new('NodeSocketFloat', 'Max Steps') + +add_node(SSAOGetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_get_ssr.py b/blender/arm/logicnode/postprocess_get_ssr.py new file mode 100644 index 00000000..10432134 --- /dev/null +++ b/blender/arm/logicnode/postprocess_get_ssr.py @@ -0,0 +1,19 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class SSRGetNode(Node, ArmLogicTreeNode): + '''Get SSR Effect''' + bl_idname = 'LNSSRGetNode' + bl_label = 'Get SSR' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'SSR Step') + self.outputs.new('NodeSocketFloat', 'SSR Step Min') + self.outputs.new('NodeSocketFloat', 'SSR Search') + self.outputs.new('NodeSocketFloat', 'SSR Falloff') + self.outputs.new('NodeSocketFloat', 'SSR Jitter') + +add_node(SSRGetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_lenstexture_get.py b/blender/arm/logicnode/postprocess_lenstexture_get.py new file mode 100644 index 00000000..d09bbaa9 --- /dev/null +++ b/blender/arm/logicnode/postprocess_lenstexture_get.py @@ -0,0 +1,19 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class LenstextureGetNode(Node, ArmLogicTreeNode): + '''Get Tonemapper Effect''' + bl_idname = 'LNLenstextureGetNode' + bl_label = 'Get Lenstexture' + bl_icon = 'QUESTION' + + def init(self, context): + self.outputs.new('NodeSocketFloat', 'Center Min Clip') + self.outputs.new('NodeSocketFloat', 'Center Max Clip') + self.outputs.new('NodeSocketFloat', 'Luminance Min') + self.outputs.new('NodeSocketFloat', 'Luminance Max') + self.outputs.new('NodeSocketFloat', 'Brightness Exponent') + +add_node(LenstextureGetNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_lenstexture_set.py b/blender/arm/logicnode/postprocess_lenstexture_set.py new file mode 100644 index 00000000..6c200cea --- /dev/null +++ b/blender/arm/logicnode/postprocess_lenstexture_set.py @@ -0,0 +1,27 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class LenstextureSetNode(Node, ArmLogicTreeNode): + '''Set Lenstexture Effect''' + bl_idname = 'LNLenstextureSetNode' + bl_label = 'Set Lenstexture' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'Center Min Clip') + self.inputs[-1].default_value = 0.1 + self.inputs.new('NodeSocketFloat', 'Center Max Clip') + self.inputs[-1].default_value = 0.5 + self.inputs.new('NodeSocketFloat', 'Luminance Min') + self.inputs[-1].default_value = 0.10 + self.inputs.new('NodeSocketFloat', 'Luminance Max') + self.inputs[-1].default_value = 2.50 + self.inputs.new('NodeSocketFloat', 'Brightness Exponent') + self.inputs[-1].default_value = 2.0 + + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(LenstextureSetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_set_bloom.py b/blender/arm/logicnode/postprocess_set_bloom.py new file mode 100644 index 00000000..87146864 --- /dev/null +++ b/blender/arm/logicnode/postprocess_set_bloom.py @@ -0,0 +1,22 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class BloomSetNode(Node, ArmLogicTreeNode): + '''Set Bloom Effect''' + bl_idname = 'LNBloomSetNode' + bl_label = 'Set Bloom' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'Threshold') + self.inputs[-1].default_value = 1.00 + self.inputs.new('NodeSocketFloat', 'Strength') + self.inputs[-1].default_value = 3.50 + self.inputs.new('NodeSocketFloat', 'Radius') + self.inputs[-1].default_value = 3.0 + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(BloomSetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_set_camera.py b/blender/arm/logicnode/postprocess_set_camera.py new file mode 100644 index 00000000..2503ea53 --- /dev/null +++ b/blender/arm/logicnode/postprocess_set_camera.py @@ -0,0 +1,38 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class CameraSetNode(Node, ArmLogicTreeNode): + '''Set Camera Effect''' + bl_idname = 'LNCameraSetNode' + bl_label = 'Set Camera' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'F-stop') + self.inputs[-1].default_value = 2.0 + self.inputs.new('NodeSocketFloat', 'Shutter Time') + self.inputs[-1].default_value = 1.0 + self.inputs.new('NodeSocketFloat', 'ISO') + self.inputs[-1].default_value = 100.0 + self.inputs.new('NodeSocketFloat', 'Exposure Compensation') + self.inputs[-1].default_value = 0.0 + self.inputs.new('NodeSocketFloat', 'Fisheye Distortion') + self.inputs[-1].default_value = 0.01 + self.inputs.new('NodeSocketBool', 'Auto Focus') + self.inputs[-1].default_value = True + self.inputs.new('NodeSocketFloat', 'DoF Distance') + self.inputs[-1].default_value = 10.0 + self.inputs.new('NodeSocketFloat', 'DoF Length') + self.inputs[-1].default_value = 160.0 + self.inputs.new('NodeSocketFloat', 'DoF F-Stop') + self.inputs[-1].default_value = 128.0 + self.inputs.new('NodeSocketInt', 'Tonemapper') + self.inputs[-1].default_value = 0.0 + self.inputs.new('NodeSocketFloat', 'Film Grain') + self.inputs[-1].default_value = 2.0 + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(CameraSetNode, category='Postprocess') diff --git a/blender/arm/logicnode/postprocess_set_chromatic_aberration.py b/blender/arm/logicnode/postprocess_set_chromatic_aberration.py new file mode 100644 index 00000000..03bf0d41 --- /dev/null +++ b/blender/arm/logicnode/postprocess_set_chromatic_aberration.py @@ -0,0 +1,20 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class ChromaticAberrationSetNode(Node, ArmLogicTreeNode): + '''Set Chromatic Aberration Effect''' + bl_idname = 'LNChromaticAberrationSetNode' + bl_label = 'Set ChromaticAberration' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'Strength') + self.inputs[-1].default_value = 2.0 + self.inputs.new('NodeSocketInt', 'Samples') + self.inputs[-1].default_value = 32 + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(ChromaticAberrationSetNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_set_ssao.py b/blender/arm/logicnode/postprocess_set_ssao.py new file mode 100644 index 00000000..880cd2a7 --- /dev/null +++ b/blender/arm/logicnode/postprocess_set_ssao.py @@ -0,0 +1,22 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class SSAOSetNode(Node, ArmLogicTreeNode): + '''Set SSAO Effect''' + bl_idname = 'LNSSAOSetNode' + bl_label = 'Set SSAO' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'Radius') + self.inputs[-1].default_value = 1.0 + self.inputs.new('NodeSocketFloat', 'Strength') + self.inputs[-1].default_value = 5.0 + self.inputs.new('NodeSocketInt', 'Max Steps') + self.inputs[-1].default_value = 8 + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(SSAOSetNode, category='Postprocess') \ No newline at end of file diff --git a/blender/arm/logicnode/postprocess_set_ssr.py b/blender/arm/logicnode/postprocess_set_ssr.py new file mode 100644 index 00000000..8ede1ed2 --- /dev/null +++ b/blender/arm/logicnode/postprocess_set_ssr.py @@ -0,0 +1,26 @@ +import bpy +from bpy.props import * +from bpy.types import Node, NodeSocket +from arm.logicnode.arm_nodes import * + +class SSRSetNode(Node, ArmLogicTreeNode): + '''Set SSR Effect''' + bl_idname = 'LNSSRSetNode' + bl_label = 'Set SSR' + bl_icon = 'QUESTION' + + def init(self, context): + self.inputs.new('ArmNodeSocketAction', 'In') + self.inputs.new('NodeSocketFloat', 'SSR Step') + self.inputs[-1].default_value = 0.04 + self.inputs.new('NodeSocketFloat', 'SSR Step Min') + self.inputs[-1].default_value = 0.05 + self.inputs.new('NodeSocketFloat', 'SSR Search') + self.inputs[-1].default_value = 5.0 + self.inputs.new('NodeSocketFloat', 'SSR Falloff') + self.inputs[-1].default_value = 5.0 + self.inputs.new('NodeSocketFloat', 'SSR Jitter') + self.inputs[-1].default_value = 0.6 + self.outputs.new('ArmNodeSocketAction', 'Out') + +add_node(SSRSetNode, category='Postprocess') diff --git a/blender/arm/make_renderpath.py b/blender/arm/make_renderpath.py index c22b3649..ca0e829b 100755 --- a/blender/arm/make_renderpath.py +++ b/blender/arm/make_renderpath.py @@ -195,6 +195,9 @@ def build(): if compo_depth: wrd.compo_defs += '_CDepth' assets.add_khafile_def('rp_compositordepth') + if rpdat.rp_pp: + wrd.compo_defs += '_CPostprocess' + assets.add_shader_pass('compositor_pass') assets.add_khafile_def('rp_antialiasing={0}'.format(rpdat.rp_antialiasing)) @@ -329,6 +332,9 @@ def build(): if rpdat.rp_dynres: assets.add_khafile_def('rp_dynres') + if rpdat.rp_pp: + assets.add_khafile_def('rp_pp') + if rpdat.rp_chromatic_aberration: assets.add_shader_pass('copy_pass') assets.add_khafile_def('rp_chromatic_aberration') diff --git a/blender/arm/props_renderpath.py b/blender/arm/props_renderpath.py index 552ba91c..62e281df 100644 --- a/blender/arm/props_renderpath.py +++ b/blender/arm/props_renderpath.py @@ -41,6 +41,7 @@ def update_preset(self, context): rpdat.arm_texture_filter = 'Anisotropic' rpdat.arm_irradiance = True rpdat.arm_radiance = True + rpdat.rp_pp = False elif self.rp_preset == 'Mobile': rpdat.rp_renderer = 'Forward' rpdat.rp_depthprepass = False @@ -75,6 +76,7 @@ def update_preset(self, context): rpdat.arm_texture_filter = 'Linear' rpdat.arm_irradiance = True rpdat.arm_radiance = False + rpdat.rp_pp = False elif self.rp_preset == 'Max': rpdat.rp_renderer = 'Deferred' rpdat.rp_shadows = True @@ -112,6 +114,7 @@ def update_preset(self, context): rpdat.arm_texture_filter = 'Anisotropic' rpdat.arm_irradiance = True rpdat.arm_radiance = True + rpdat.rp_pp = False elif self.rp_preset == '2D/Baked': rpdat.rp_renderer = 'Forward' rpdat.rp_depthprepass = False @@ -146,6 +149,7 @@ def update_preset(self, context): rpdat.arm_texture_filter = 'Linear' rpdat.arm_irradiance = False rpdat.arm_radiance = False + rpdat.rp_pp = False update_renderpath(self, context) def update_renderpath(self, context): @@ -326,6 +330,7 @@ class ArmRPListItem(bpy.types.PropertyGroup): name='Draw Order', description='Sort objects', default='Auto', update=assets.invalidate_compiled_data) rp_stereo: BoolProperty(name="VR", description="Stereo rendering", default=False, update=update_renderpath) rp_water: BoolProperty(name="Water", description="Water surface pass", default=False, update=update_renderpath) + rp_pp: BoolProperty(name="Realtime postprocess", description="Realtime postprocess", default=False, update=update_renderpath) rp_gi: EnumProperty( # TODO: remove in 0.8 items=[('Off', 'Off', 'Off'), ('Voxel GI', 'Voxel GI', 'Voxel GI', 'ERROR', 1), diff --git a/blender/arm/props_ui.py b/blender/arm/props_ui.py index df37de3f..c690d0d7 100644 --- a/blender/arm/props_ui.py +++ b/blender/arm/props_ui.py @@ -712,6 +712,7 @@ class ARM_PT_RenderPathRendererPanel(bpy.types.Panel): layout.prop(rpdat, "rp_hdr") layout.prop(rpdat, "rp_stereo") layout.prop(rpdat, 'arm_culling') + layout.prop(rpdat, 'rp_pp') class ARM_PT_RenderPathShadowsPanel(bpy.types.Panel): bl_label = "Shadows"