[HLSL CODE] APPLYGAMECOLORCORRECTION & DNI-khajiit
Posted: 03 Jul 2015, 07:44
Just to get a better understanding on what happened in APPLYGAMECOLORCORRECTION in Skyrim enbeffect.fx
for DNI-K, looks final part.
First, here is the original code
and with the help in Shader_ORIGINALPOSTPROCESS, here are separate parts with notations
*I've combined and rearrange some lines to get a better view.
*thanks to JawZ for additional info on imagespace & imagespace modifier
external registers:
the first part would be r0 initialization
and preparing to blend bloom
blends bloom and color
then is the part for Skyrim post process
one can observed with Enhanced ENB Diagnostics by number6/scegielski that c2 ~ c4 are controlled by game and often changes from cell to cell, which also altered by lighting mods.
c5 can be used as D-N-I-khajiit separation without whole set of identical color correction process just for khajiit.
*update:
c5 is NOT night eye specific, it is Fade in imagespace modifier and used in different events including night eye.
here are DNIK examples
and for the EKhajiitFactor, there are 3 options
option1:
may introduce unwanted color change on other event that uses Fade in imagespace modifier.
option2:
suggested by jawZ for unmoded night eye, will not affecting other game vfx , no transition time( probably doesn't matters, transition time is rather fast when switching night eye)
option3:
use enhanced night eye esp by number6.
also not affecting other game vfx, conserved night eye transition time.
anyway, hopes these are not too boring.
feel free to comment below.
update: April.3.16
As supplement,
here is the complete rephrase of game color correction.
for DNI-K, looks final part.
First, here is the original code
Code: Select all
#ifdef APPLYGAMECOLORCORRECTION
//apply original
r0.x=1.0/_c2.y;
r1=tex2D(_s2, _v0);
r0.yz=r1.xy * _c1.y;
r0.w=1.0/r0.y;
r0.z=r0.w * r0.z;
r1=tex2D(_s0, _v0);
r1.xyz=r1 * _c1.y;
r0.w=dot(_c7.xyz, r1.xyz);
r1.w=r0.w * r0.z;
r0.z=r0.z * r0.w + _c7.w;
r0.z=1.0/r0.z;
r0.x=r1.w * r0.x + _c7.w;
r0.x=r0.x * r1.w;
r0.x=r0.z * r0.x;
if (r0.w<0) r0.x=_c6.x;
r0.z=1.0/r0.w;
r0.z=r0.z * r0.x;
r0.x=saturate(-r0.x + _c2.x);
// r2=tex2D(_s3, _v0);//enb bloom
r2=tex2D(_s1, _v0);//skyrim bloom
r2.xyz=r2 * _c1.y;
r2.xyz=r0.x * r2;
r1.xyz=r1 * r0.z + r2;
r0.x=dot(r1.xyz, _c7.xyz);
r1.w=_c7.w;
r2=lerp(r0.x, r1, _c3.x);
r1=r0.x * _c4 - r2;
r1=_c4.w * r1 + r2;
r1=_c3.w * r1 - r0.y; //khajiit night vision _c3.w
r0=_c3.z * r1 + r0.y;
r1=-r0 + _c5;
_oC0=_c5.w * r1 + r0;
#endif //APPLYGAMECOLORCORRECTION
*I've combined and rearrange some lines to get a better view.
*thanks to JawZ for additional info on imagespace & imagespace modifier
external registers:
Code: Select all
// ColorRange c1 float4( null, color range constant, null, null)
// Param c2 float4( bloom coeff(level related), brightness Level constant, null, null)
//Post-Process
// Cinematic c3 float4( saturation, null, brightness, contrast)
// Tint c4 float4( Tint RGB, Tint alpha)
// Fade c5 float4( fade RGB, fade alpha) //vfx includes night eye and other visual effects
Code: Select all
r1 = tex2D(_s2, _v0) * _c1.y; // float4(L2 hysteresis average, L1 hysteresis average, instant average, null), multiplied with color range multiplier.
r0.x = 1.0/_c2.y;
r0.yz = r1.xy;
r0.w = 1.0/r0.y;
r0.z = r0.w * r0.z;
r1 = tex2D(_s0, _v0) * _c1.y; //color, multiplied with color range multiplier
r0.w = dot(_c7.xyz, r1.xyz); //lum(orig)
// r0 = float4( 1/ Brightness Level, L2 average, adaptation ratio, lum(orig))
// L2 hysteresis average
r1.w=r0.w * r0.z; //r1.w = L(orig) * ---------------------- = L(adp)
r0.z=r0.z * r0.w + _c7.w; // L1 hysteresis average
r0.z=1.0/r0.z; //
r0.x=r1.w * r0.x + _c7.w; //
r0.x=r0.x * r1.w; // 1 + L(adp) / Level
r0.x=r0.z * r0.x; //r0.x = L(adp) * -------------------- = L'
// 1 + L(adp)
Code: Select all
if (r0.w<0) r0.x=_c6.x; // if Lum(orig) < 0, set L' == 0
r0.z=1.0/r0.w; // invert Lum(orig)
r0.z=r0.z * r0.x; // == L' / Lum(orig)
r0.x=saturate(-r0.x + _c2.x); // saturate( bloom level - L'), 0 when L' > bloom level
r2=tex2D(_s1, _v0) * _c1.y; // Skyrim bloom, multiplied with color range multiplier
//r0 = float4( bloom brightpass, null, Lum old-new ratio, null)
Code: Select all
r2.xyz = r0.x * r2; // bloom * saturate( _c2.x - L') == bloom * brightpass
r1.xyz = r0.z * r1; // color * L'/ Lum(orig), maps original brightness to new brightness
/*
L'
color' = color * ---------
L(orig)
*/
r1.xyz = r1 + r2; // blending color and bloom
r1.w = _c7.w; // = 1
Code: Select all
r0.x = dot(r1.xyz, _c7.xyz); // gray scale
r2 = lerp(r0.x, r1, _c3.x); // saturation: lerp( gray, color, saturation weight)
r1 = lerp(r2, r0.x * _c4, _c4.w); // tint: lerp( color(saturation), gray * tint, tint weight)
r0 = lerp(r0.y, _c3.w * r1, _c3.z); // intensity, contrast: lerp( average, intensity * color(tint), contrast weight)
_oC0 = lerp(r0, _c5 , _c5.w); // Fade: additional color correction for sfx, only > 0 when triggers imagespace modifier
c5 can be used as D-N-I-khajiit separation without whole set of identical color correction process just for khajiit.
*update:
c5 is NOT night eye specific, it is Fade in imagespace modifier and used in different events including night eye.
here are DNIK examples
Code: Select all
//for DNI-KDNI
float parm = lerp( lerp( parm_D, parm_N, ENightDayFactor), parm_I, EInteriorFactor);
float parm_k = lerp( lerp( parm_k_D, parm_k_N, ENightDayFactor), parm_k_I, EInteriorFactor);
parm = lerp(parm, parm_k, EKhajiitFactor);
//or DNIK
float parm = lerp( lerp( parm_D, parm_N, ENightDayFactor), parm_I, EInteriorFactor);
parm = lerp(parm, parm_k, EKhajiitFactor);
option1:
may introduce unwanted color change on other event that uses Fade in imagespace modifier.
Code: Select all
float EKhajiitFactor = _c5.w * KhajiitFactorMultiplier;
suggested by jawZ for unmoded night eye, will not affecting other game vfx , no transition time( probably doesn't matters, transition time is rather fast when switching night eye)
Code: Select all
float EKhajiitFactor = (_c2.y >= 0.562498 && _c2.y <= 0.5625 && _c5.z >= 0.745096 && _c5.z <= 0.745099)? 1:0;
use enhanced night eye esp by number6.
also not affecting other game vfx, conserved night eye transition time.
Code: Select all
float EKhajiitFactor = (_c5.r < 0.01 && _c5.g < 0.01)? _c5.b: 0;
feel free to comment below.
update: April.3.16
As supplement,
here is the complete rephrase of game color correction.
Code: Select all
////////////////////////////////////////////////////
// AGCC Inputs
////////////////////////////////////////////////////
float AGCC_ColorRange = _c1.y; //Linear scaler, requires confirm on Imagespace Parm in CK.
float AGCC_Average = tex2D(_s2, coord).x * _c1.y; // scene average (log average if following Reinhard's defines)
float3 AGCC_LumCoeff = _c7.rgb;
float AGCC_AdaptAvg = tex2D(_s2, coord).y * _c1.y / AGCC_Average;
float AGCC_SqWhight = _c2.y; //Square of minimum white, requires confirm on Imagespace Parm in CK.
float AGCC_BloomCoeff = _c2.x; //Bloom scaler, requires confirm on Imagespace Parm in CK.
float AGCC_Saturation = _c3.x;
float3 AGCC_Tint = _c4.rgb;
float AGCC_TintWeight = _c4.a;
float AGCC_Brightness = _c3.w;
float AGCC_Contrast = _c3.z;
float3 AGCC_Fade = _c5.rgb;
float AGCC_FadeWeight = _c5.w;
color = tex2D(_s0, _v0) * AGCC_ColorRange; // color
bloom = tex2D(_s1, _v0) * AGCC_ColorRange; // Skyrim bloom
////////////////////////////////////////////////////
// AGCC Tonemapper with adaptation (auto exposure).
////////////////////////////////////////////////////
float lum_orig = dot(color.rgb, AGCC_LumCoeff);
float lum_scaled = lum_orig * AGCC_AdaptAvg;
float lum_mapped = lum_scaled * ( lum_scaled / AGCC_SqWhight + 1) / ( lum_scaled + 1); //Reinhard
lum_mapped = (lum_orig < 0)? 0: lum_mapped;
color = color * lum_mapped / lum_orig;
////////////////////////////////////////////////////
// AGCC Bloom Blending
////////////////////////////////////////////////////
bloom = bloom * saturate(AGCC_BloomCoeff - lum_mapped);
color = color + bloom;
/*
bloom behavior:
if bloom_coeff < lum
color = color; <-- no bloom
if bloom_coeff > lum + 1
color = color + bloom; <-- add
if lum + 1 > bloom_coeff > lum
color = color + bloom * (difference);
*/
////////////////////////////////////////////////////
// AGCC PostProcess/Cinematic settings
////////////////////////////////////////////////////
float lum = dot(color.rgb, AGCC_LumCoeff);
color = lerp(lum, color, AGCC_Saturation);
color = lerp(color, lum * AGCC_Tint, AGCC_TintWeight);
color = color * AGCC_Brightness;
color = lerp(AGCC_Average, color, AGCC_Contrast);
color = lerp(color, AGCC_Fade, AGCC_FadeWeight);
color.a = 1;