Guest User

Bugged/troubleshooting version of AutoBrightness.fx

a guest
Jun 26th, 2019
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 30.92 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  TakenFrame.fx ver0.0.1  コマ撮りエフェクト
  4. //  作成: 針金P( 舞力介入P氏のGaussian.fx改変 )
  5. //
  6. //  上記の改変: わたり
  7. //
  8. //  Modified from LimitedFrame.fx
  9. //  AutoBrightness.fx
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////////////////////
  12.  
  13. /******************
  14. Camera position and velocity
  15. Current position
  16. Current time
  17. Old position
  18. Old velocity
  19. Old time (elapsed time?)
  20.  
  21. Pre-pass:
  22. Compute current velocity from current and old position, and old or elapsed time
  23. Compute current acceleration from current and old velocity
  24. Write current velocity, acceleration, position, and maybe time. Maybe a second pass if you can't sample from the texture you're writing to.
  25.  
  26. Main pass: sample acceleration. No need to check time if only one effect updates the texture.
  27.  
  28. ******************/
  29.  
  30. /****************
  31. Color adjustment steps
  32. Create mipmaps for original texture? Probably not
  33. Smaller texture: sample from original, use very high gamma (but also limit the input, because some input values could be 100+). Output with miplevels if this works; probably needs to.
  34.  
  35. Option for a single value or grid of values? Just in the form of texture size? Size defined as integer instead of relative to full size. Final tiny texture at this size that takes multiple samples from the intermediate, smaller texture; samples probably biased towards center.
  36.  
  37. This creates 'average brightness weighted toward peak'. Compare to previous, stored frame and access current acceleration. (Could access previous acceleration to measure 'jolt' or whatever, and use like (current acceleration - previous acceleration * 0.8), but acceleration is probably fine.)
  38.  
  39. Move values stored in previous brightness frame towards current frame based on acceleration; high acceleration = larger move. Store the result, which is updated average brightness after camera shift. *'Un-gamma' it after the adjustment, important for flickering.
  40.  
  41. Brightness is aimed at a value (could check notes here). For all pixels, adjust pixel value towards the goal. Around goal there is a zone of 'no change'. But supposed to retain blacks or something. Maybe do slight hue adjustment by adjusting each channel separately, and also adjust the average of all channels.
  42.  
  43. For 'gamma', instead of val^x, maybe val*min(val,0.9)^x (and still limit val to something like 2). Try to find objects in the scene that are pure white, but aren't lights, so a saturated backdrop doesn't have too much influence.
  44.  
  45. Configurable variables:
  46. - Highest color before adjust starts. 90~95% would be good, 100% for minimum change.
  47. - The 'gamma' which biases average towards bright pixels; changing this likely requires changing target brightness.
  48. - How much to adjust color channels separately, causing hue change.
  49. - Target brightness and acceptable range etc.
  50. - Desaturation strength to keep maximum channel below 1 by bringing all values in a pixel towards their average (gamma matters here~).
  51. - A matrix or something so red and blue correlate more strongly with green than each other when desaturating?
  52.  
  53. Could attempt to avoid highest value (1) or not. Probably not, based on video example:
  54. Sanny, 法法, 開場舞 Pentax 097 台北資訊月 2012.12.07 Taiwan dancer
  55. youtube.com/watch?v=Neaob9PGxQc
  56.  
  57. Consider 'reencode with color adjustment notes.txt'
  58.  
  59. RGB can have different acceptable zones than the average. Could use alpha channel for average, to avoid having to compute it for every pixel?
  60.  
  61. Storing 'target adjustment' instead of 'current brightness' makes the auto-adjust more responsive when going from too dark to too bright.
  62.  
  63. As a post-effect with an .x accessory, can just have control to change target brightness and maybe other settings.
  64.  
  65.  
  66. ACCESSORY CONTROLS:
  67. Tr: fades effect linearly. 0 is equivalent to off (but still uses CPU)
  68. Si: Adjusts target brightness.
  69. X position: How quickly brightness adjusts to screen contents. Increment of 10 = adjust speed doubles or halves.
  70.  
  71.  
  72. Acceleration-based adjustment starts at around 2g (~20 m/s^2) but varies based on fps, because so does acceleration.
  73.  
  74.  
  75. ****************/
  76.  
  77. // Camera data pass has no settings, except SyncInEditMode being true or false. Settings for brightness adjustment:
  78.  
  79. // {1,1} for no variation across screen
  80. #define BRIGHT_DIMENSIONS {4,4}
  81.  
  82. // Maximum pixel value before blurring to find average
  83. #define DETECT_LIMIT 2.0
  84.  
  85. // Makes bright areas 'spread', sort of. Higher = spread more. Normal gamma would be like 1.2 because it's also multiplied by min(val, 0.9).
  86. #define BRIGHT_BIAS 3.0
  87.  
  88. // float3(...) instead of {...} works better I think? Can't use {} inside an expression? A 'macro' has parantheses directly after the keyword.
  89. #define TARGET_COLOR float3(0.7,0.7,0.7)
  90.  
  91. // Shouldn't be 1 because models tend to have high emissive color. Modifies target color. Note interaction with things like a shader that adds blue on opposite side if light is yellow (= low blue). One problem is that some things, like skydomes, don't vary with light. Another problem is that most models saturate before full light is reached, so increasing light would actually ... darken the scene? Or it's fine? But this filter is supposed to have a time-delay effect, so adjustment for lighting should be for target color, not measured current color. (I was just saying some things here and was wrong. Version 2 adjusts current color.) Divide by zero if weight = 1 and a light component = 0, so don't. *Back to version 1, no division yet.
  92. #define LIGHTING_WEIGHT 0.2
  93.  
  94. // So 'no change' is closer to the default ~155 lighting setting
  95. #define LIGHT_MULTIPLIER 1.35
  96.  
  97. // Color channels are adjusted this amount towards target before being adjusted together. (Before desaturation to avoid out-of-range values.) Can range from 0 to 1. If at 1, no zone of 'no change'.
  98. #define HUE_ADJUST_STRENGTH 0.3
  99.  
  100. // Hue can go this amount up, or reciprocal of this value down. Minimum 1. Comment out in code to disable (cleaner than extra #ifdef statements)
  101. #define HUE_ADJUST_LIMIT 1.3
  102.  
  103. // 'LUM' stands for either luma or luminance, not sure. Average brightness (but not combined using gamma, so it's probably luma)
  104. #define LUM_ADJUST_STRENGTH 0.7
  105.  
  106. // Prevent or slow adjust from reaching its ideal brightness when stationary, set to 1 or more. Uses reciprocal as well.
  107. #define LUM_STATIONARY_BUFFER 1.1
  108.  
  109. /////////////////////////
  110. // Color adjustment stuff
  111.  
  112. // Color increases above this limit are reduced
  113. #define REDUCE_BRIGHTNESS_LIMIT 0.9
  114.  
  115. // Attempt to limit colors to this using desaturation after reducing bright colors. Could be above 1.
  116. #define DESAT_COLOR_LIMIT 0.9
  117.  
  118. // Math stuff, maybe redundant. Ranges from 0 to 1, lower = greater desaturation. 'Distance' from average can be multiplied by this.
  119. #define MIN_DESAT_RATIO 0.2
  120.  
  121. // Limit desaturation strength, maybe redundant with previous but affects all desaturated pixels. Ranges from 0 to 1, used for linear interpolation.
  122. #define DESAT_STRENGTH 0.7
  123.  
  124.  
  125. float3 CameraPosition : POSITION  < string Object = "Camera"; >;
  126. float3 LightAmbient   : AMBIENT   < string Object = "Light"; >;
  127.  
  128. // .x controls
  129. float alpha1 : CONTROLOBJECT < string name = "(self)"; string item = "Tr"; >;
  130. float SizeX10 : CONTROLOBJECT < string name = "(self)"; string item = "Si"; >; // Value in interface times 10
  131. float AdjustSpeedX : CONTROLOBJECT < string name = "(self)"; string item = "X"; >;
  132. static float AdjustSpeed = pow(2,AdjustSpeedX/10);
  133.  
  134.  
  135. // Linear interpolation from third term 0 to 1
  136. static float3 TargetColorNoAlpha = lerp(TARGET_COLOR, TARGET_COLOR * LightAmbient * LIGHT_MULTIPLIER, LIGHTING_WEIGHT) * SizeX10 / 10;
  137. static float4 TargetColor = float4(TargetColorNoAlpha, (TargetColorNoAlpha.r + TargetColorNoAlpha.g + TargetColorNoAlpha.b)/3);
  138.  
  139. // Version 2, use lighting to adjust average color instead of target color
  140. //static float TargetColor = TARGET_COLOR * SizeX10 / 10;
  141. // Back to version 1.
  142. // Math here is more efficient than later?
  143.  
  144.  
  145. // If true, no change to brightness when paused
  146. float fTime : TIME        <bool SyncInEditMode=false;>;
  147. float elaTime : ELAPSEDTIME <bool SyncInEditMode=false;>;
  148.  
  149. // スクリーンサイズ
  150. float2 ViewportSize : VIEWPORTPIXELSIZE;
  151. static float2 ViewportOffset = (float2(0.5,0.5)/ViewportSize);
  152. static float2 ViewportOffset2 = (float2(0.5,0.5)/ViewportSize) * 4;
  153. static float2 BrightDimensions = BRIGHT_DIMENSIONS; //??
  154. static float2 ViewportOffset3 = (float2(0.5,0.5)/BrightDimensions);
  155. static float2 HalfOffset = ViewportOffset3 / 2;
  156. static float2 CameraViewportOffset = float2(0.5,0.5)/float2(3,1);
  157.  
  158. float Script : STANDARDSGLOBAL <
  159.    string ScriptOutput = "color";
  160.    string ScriptClass = "scene";
  161.    string ScriptOrder = "postprocess";
  162. > = 0.8;
  163.  
  164. // レンダリングターゲットのクリア値
  165. float4 ClearColor = {1,1,1,1};
  166. float ClearDepth  = 1.0;
  167.  
  168. //////////////////////////////////////
  169.  
  170. shared texture CameraData : RENDERCOLORTARGET
  171. <
  172.    int Width=3;
  173.    int Height=1;
  174.    //string Format = "A16R16G16B16F" ;
  175.    string Format = "A16B16G16R16F" ;
  176.    //bool antialias = false; // Doesn't fix problem of Tex > 0
  177. >;
  178. sampler CameraDataSampler = sampler_state //Used as both Sampler1D and Sampler2D
  179. {
  180.    Texture = <CameraData>;
  181.    AddressU  = CLAMP;
  182.    AddressV = CLAMP;
  183.    MinFilter = NONE;
  184.    MagFilter = NONE;
  185.    MipFilter = NONE;
  186. };
  187. /* //Unnecessary
  188. texture CameraDataDepthBuffer : RenderDepthStencilTarget <
  189.    int Width=3;
  190.    int Height=1;
  191.    string Format = "D24S8";
  192. >;
  193. */
  194.  
  195. shared texture CameraDataTransfer : RENDERCOLORTARGET
  196. <
  197.    int Width=3;
  198.    int Height=1;
  199.    string Format = "A16B16G16R16F" ;
  200. >;
  201. sampler CameraDataTransferSamp = sampler_state
  202. {
  203.    Texture = <CameraDataTransfer>;
  204.    AddressU  = CLAMP;
  205.    AddressV = CLAMP;
  206.    MinFilter = NONE;
  207.    MagFilter = NONE;
  208.    MipFilter = NONE;
  209. };
  210.  
  211.  
  212. ////////////////////////////////////////////////////////////////////////////////////////////////
  213. struct VS_OUTPUT_CAMERA {
  214.    float4 Pos : POSITION;
  215.    //int Tex : TEXCOORD0;
  216.    //nointerpolation int Tex : TEXCOORD0; // Doesn't change warnings
  217.    float4 Tex : TEXCOORD0;
  218. };
  219.  
  220. ////////////////////////////////////////////////////////////////////////////////////////////////
  221. // 画面更新時刻の計算
  222. VS_OUTPUT_CAMERA VS_UpdateCameraData(float4 Pos : POSITION, float2 Tex : TEXCOORD0)
  223. {
  224.     VS_OUTPUT_CAMERA Out = (VS_OUTPUT_CAMERA)0;
  225.  
  226.     Out.Pos = Pos;
  227.     //Out.Tex = (int)(Tex * 3 + 0.1); //No offset. Rounding problem?
  228.     Out.Tex.a = Tex.x; // Used for switch statement
  229.     Out.Tex.rgb = float3(0.5/3, 1.5/3, 2.5/3); // Fix for dependent texture?
  230.  
  231.     return Out;
  232. }
  233.  
  234. // Not tested: whether a separate texture and pass for each pixel is slower than 'if' statements
  235. float4 PS_UpdateCameraData(float4 Tex: TEXCOORD0) : COLOR
  236. {
  237.    float3 PrevPosition = tex1D(CameraDataSampler, Tex.r).rgb;
  238.    float3 PrevVelocity = tex1D(CameraDataSampler, Tex.g).rgb;
  239.    float3 PrevAccel = tex1D(CameraDataSampler, Tex.b).rgb;
  240.    // "Warning X3509: tex1D will be considered dependent since texcoord was not declared as at least float2"
  241.    // Dependent texture read: https://stackoverflow.com/questions/1054096/what-is-a-dependent-texture-read
  242.  
  243.    // "Branch flow control consumes resources, excessive use can lead to compile errors"
  244.    // So we just compute all the values every time, and select the right one. Boolean '?:' computes both sides because vector operation. No wait, we do multiple passes and textures. Or not.
  245.    // Maybe "'if' is slow" because it delays texture lookup? (Untested.) But wouldn't lead to compilation errors.
  246.  
  247.    float3 CurrentPosition = elaTime ? CameraPosition : PrevPosition;
  248.    float3 CurrentVelocity = elaTime ? (CurrentPosition - PrevPosition) / elaTime : PrevVelocity; // Do some stuff if SyncInEditMode=true and time hasn't changed
  249.    float3 CurrentAccel = elaTime ? (CurrentVelocity - PrevVelocity) / elaTime : PrevAccel; // If we stored the most recent valid elaTime, could calculate accel here but it would be wrong for frame skipping
  250.  
  251.    float4 Out = 0;
  252.  
  253.    //[branch] switch (Tex) //Untested
  254.    /*
  255.    switch ( floor(Tex.a * 3.0 + 0.1) )
  256.    {
  257.       case 0.0: Out.rgb = CurrentPosition;
  258.       case 1.0: Out.rgb = CurrentVelocity;
  259.       case 2.0: Out.rgb = CurrentAccel;
  260.    }
  261.    */
  262.    // "error X3548: in PS_2_0 uints can only be used with known-positive values, use int if possible"
  263.  
  264.    // All sides are calculated for '?:' but no calculation is done here anyway. I guess Tex.a == 0 doesn't work here.
  265.    //Out.rgb = Tex.a == 0 ? CurrentPosition : Tex.a < 0.4 ? CurrentVelocity : CurrentAccel;
  266.  
  267.    // If first pixel uses CurrentVelocity, ... I guess it makes sense for it to 'drift'? As in, after compiling, first few frames are more reasonable but it quickly becomes super-extreme.
  268.    // Value of Tex for first pixel is about 0.0026041. It's probably 1/384 = 1/256 * 2/3, though it's more like 0.002604141 and 1/384 is 0.002604167. 1/(255*1.5) is a significantly worse match. Using (Pos.x / 2 + 0.5) has same result; same with trying 'nointerpolation' which might not even work.
  269.    // Tex.a < 0.002604141 is false for first pixel.
  270.    // Tex.a < 0.002604142 is true for first pixel.
  271.    Out.rgb = Tex.a < 0.1 ? CurrentPosition : Tex.a < 0.4 ? CurrentVelocity : CurrentAccel;
  272.    //Out.rgb = CurrentPosition;
  273.  
  274.    return Out;
  275. }
  276.  
  277.  
  278. ////////////////////////////////////////////////////////
  279.  
  280. // オリジナルの描画結果を記録するためのレンダーターゲット
  281. texture2D ScnMap : RENDERCOLORTARGET <
  282.    float2 ViewPortRatio = {1.0,1.0};
  283.    int MipLevels = 2; //From 1
  284.    //string Format = "A16R16G16B16F" ;
  285.    string Format = "A16B16G16R16F" ;
  286. >;
  287. sampler2D ScnSamp = sampler_state {
  288.    texture = <ScnMap>;
  289.    MinFilter = LINEAR;
  290.    MagFilter = LINEAR;
  291.    MipFilter = POINT;
  292.    AddressU  = CLAMP;
  293.    AddressV = CLAMP;
  294. };
  295. texture2D DepthBuffer : RENDERDEPTHSTENCILTARGET <
  296.    //float2 ViewPortRatio = {1, 1};
  297.    // These numbers don't matter ??
  298.    int2 Dimensions = {1, 1};
  299.    string Format = "D24S8";
  300. >;
  301.  
  302. // フレームを保持するためのレンダーターゲット
  303. texture2D SmallGammaScreen : RENDERCOLORTARGET <
  304.    // "Error: failed to create texture (parameter: 'SmallGammaScreen'): Invalid call (8876086C)"
  305.    //float2 ViewPortRatio = {0.25,0.25};
  306.    int2 Dimensions = {128, 128};
  307.    int MipLevels = 0; //All
  308.    string Format = "A16B16G16R16F" ;
  309. >;
  310. sampler2D SmallGammaSamp = sampler_state {
  311.    texture = <SmallGammaScreen>;
  312.    MinFilter = LINEAR;
  313.    MagFilter = LINEAR;
  314.    MipFilter = NONE;
  315.    AddressU  = CLAMP;
  316.    AddressV = CLAMP;
  317.  
  318. };
  319.  
  320. // Without this, screen is black
  321. /*
  322. texture2D SmallGammaDepth : RENDERDEPTHSTENCILTARGET <
  323.    //float2 ViewPortRatio = {0.25,0.25};
  324.    int2 Dimensions = {128, 128};
  325.    string Format = "D24S8";
  326. >;
  327. */
  328.  
  329. texture2D TinyScreenCurrent : RENDERCOLORTARGET <
  330.    int2 Dimensions = BRIGHT_DIMENSIONS;
  331.    int MipLevels = 1;
  332.    string Format = "A16B16G16R16F" ;
  333. >;
  334. sampler2D TinySampCurrent = sampler_state {
  335.    texture = <TinyScreenCurrent>;
  336.    MinFilter = LINEAR;
  337.    MagFilter = LINEAR;
  338.    MipFilter = NONE;
  339.    AddressU  = CLAMP;
  340.    AddressV = CLAMP;
  341. };
  342.  
  343. /*
  344. texture2D TinyDepth : RENDERDEPTHSTENCILTARGET <
  345.    //float2 ViewPortRatio = {0.25,0.25};
  346.    int2 Dimensions = BRIGHT_DIMENSIONS;
  347.    string Format = "D24S8";
  348. >;
  349. */
  350.  
  351. texture2D TinyScreenPrev : RENDERCOLORTARGET <
  352.    int2 Dimensions = BRIGHT_DIMENSIONS;
  353.    int MipLevels = 1;
  354.    string Format = "A16B16G16R16F" ;
  355. >;
  356. sampler2D TinySampPrev = sampler_state {
  357.    texture = <TinyScreenPrev>;
  358.    MinFilter = NONE;
  359.    MagFilter = NONE;
  360.    MipFilter = NONE;
  361.    AddressU  = CLAMP;
  362.    AddressV = CLAMP;
  363. };
  364.  
  365. /*******************
  366. No good place to put this. Problems diagnosed when getting this effect to work:
  367. 1) Fixing error messages. Most significant was changing to shader model 3_0 for tex2Dlod. Suspected lack of depth buffer for smaller screens was causing other problems, but seems it probably isn't.
  368. 2) Apparently, ScriptExternal=Color does not create mipmaps; this explains why AutoLuminous object effect has passes named "create mipmaps" and stuff. Even with mipmaps specified, they are not created. If tex2Dlod is used, the sample is just black.
  369. 3) Didn't set output Tex in ... ok, it is set ?? Differences in 'return tex2D(ScnSamp, Tex) > 0;' for different pixel shaders? Further testing.
  370.  
  371.  
  372. *******************/
  373.  
  374. ////////////////////////////////////////////////////////////////////////////////////////////////
  375. struct VS_OUTPUT {
  376.    float4 Pos : POSITION;
  377.    float2 Tex : TEXCOORD0;
  378. };
  379.  
  380. ////////////////////////////////////////////////////////////////////////////////////////////////
  381. // コマ撮り共通頂点シェーダ
  382. VS_OUTPUT VS_Screen(float4 Pos : POSITION, float2 Tex : TEXCOORD0, uniform float2 Offset)
  383. {
  384.    VS_OUTPUT Out = (VS_OUTPUT)0;
  385.  
  386.    Out.Pos = Pos;
  387.    //Out.Tex = Tex.xy + ViewportOffset;
  388.    Out.Tex = Tex.xy + Offset;
  389.  
  390.    // For testing
  391.    //Out.Tex = float2(0.5,0.5);
  392.  
  393.    return Out;
  394. }
  395.  
  396. // フレームを保持
  397. float4 PS_CopyFrame(float2 Tex: TEXCOORD0, uniform sampler2D ThisSampler) : COLOR
  398. {
  399.    float4 Color = tex2D(ThisSampler, Tex);
  400.  
  401.    return Color;
  402. }
  403.  
  404. // Shrink frame and use gamma
  405. float4 PS_GammaShrink(float2 Tex: TEXCOORD0) : COLOR
  406. {
  407.    float4 Color = tex2Dlod(ScnSamp, float4(Tex,0,2)); // Miplevel 2 from base image
  408.    Color.rgb = min(Color.rgb, DETECT_LIMIT);
  409.    // Copy from sRGB
  410.    Color.rgb = (Color.rgb + 0.1 ) / 1.1;
  411.    Color.rgb = min(Color.rgb,0.9) * pow(Color.rgb, BRIGHT_BIAS);
  412.  
  413.    // For testing
  414.    //return 1;
  415.  
  416.    return Color;
  417. }
  418.  
  419. float4 PS_TinyBlur(float2 Tex: TEXCOORD0) : COLOR
  420. {
  421.    float4 Color = 0;
  422.  
  423.    // Guessing which miplevel to use. Don't want to sample a 2x2 miplevel here!
  424.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex,0,5)).rgb;
  425.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex + HalfOffset,0,5)).rgb;
  426.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex - HalfOffset,0,5)).rgb;
  427.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex + HalfOffset * float2(1,-1),0,5)).rgb;
  428.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex + HalfOffset * float2(-1,1),0,5)).rgb;
  429.  
  430.    float2 Tex2 = (Tex + float2(0.5,0.5)) / 2; // Halfway to center
  431.  
  432.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex2 + HalfOffset * float2(0.8,0),0,5)).rgb;
  433.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex2 + HalfOffset * float2(-0.8,0),0,5)).rgb;
  434.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex2 + HalfOffset * float2(0,0.8),0,5)).rgb;
  435.    Color.rgb += tex2Dlod(SmallGammaSamp, float4(Tex2 + HalfOffset * float2(0,-0.8),0,5)).rgb;
  436.  
  437.    Color.rgb /= 9; // number of samples used
  438.  
  439.    // For testing
  440.    //return (tex2Dlod(SmallGammaSamp, float4(Tex,0,5)).r > 0.0001); // False
  441.    //return (tex2Dlod(SmallGammaSamp, float4(Tex,0,5)).r > 0.00001); // True
  442.  
  443.    float4 OldAdjust = tex2D(TinySampPrev, Tex); // Was called OldColor
  444.  
  445.    // Working with gamma numbers is too hard, even if it leads to 'darker screen during flicking or strobing'
  446.    Color.rgb = pow(Color.rgb, 1 / (1 + BRIGHT_BIAS));
  447.    // Copy from sRGB
  448.    Color.rgb = Color.rgb * 1.1 - 0.1;
  449.  
  450.    // For testing
  451.    //return tex2D(ScnSamp, saturate(Tex) * 0.0138 );
  452.    return tex2D(ScnSamp, saturate(Tex) * 0.0139 );
  453.    //return Color.r;
  454.    //return float4(Color.rgb, (Color.r + Color.g + Color.b) / 3);
  455.  
  456.    // Adjustable target color from lighting and control mean we have to store the average lighting, instead of the adjustment. But 'no change zone' can be closeness of approach to current lighting, instead of whether current lighting is close to target. Or, light adjustment could be to current average color here, instead of to target level (which affects meaning of previous average color).
  457.  
  458.    //Color.rgb /= lerp(1, LightAmbient * LIGHT_MULTIPLIER, LIGHTING_WEIGHT);
  459.    /*
  460.    same adjustment as if target level was being reduced
  461.    if target level was reduced from 0.5 to 0.01, to do the same change by adjusting Color, would have to multiply by 50?
  462.    let's just subtract it. But wait, if measured color becomes really low, then base screen must be multiplied by really high number to reach target level.
  463.    */
  464.    // Back to version 1, where we store the adjustment.
  465.  
  466.    //Color.a = (Color.r + Color.g + Color.b) / 3; //No gamma as a test. Now done later.
  467.    float4 Adjust;
  468.  
  469.    // Simplest version, and wrong because it duplicates rgb and a, where 'a' adjusts all channels.
  470.    //Adjust = TargetColor / Color;
  471.  
  472.    // 'Adjust' is target adjustment if the current frame was repeated for a long time. Limited hue adjustment is similar to modifying target color based on light.
  473.    Adjust.rgb = (TargetColor.rgb / Color.rgb - 1) * HUE_ADJUST_STRENGTH + 1; // Compiler should optimize/simplify
  474.    Adjust.rgb = min(Adjust.rgb, HUE_ADJUST_LIMIT);
  475.    Adjust.rgb = max(Adjust.rgb, 1.0 / HUE_ADJUST_LIMIT);
  476.  
  477.    // This MIGHT be a problem when lum adjustment assumes that chroma adjustment has already taken place, when in fact it's delayed. Best would probably be to ... do it differently.
  478.    Color.rgb *= Adjust.rgb;
  479.    Color.a = (Color.r + Color.g + Color.b) / 3;
  480.  
  481.    // Discussion! If 'safe zone' is around target color, then scene movements and lighting fluctuations near that color lead to no adjustment change, but elsewhere they do. This could look weird (notice the lack of adjustments in certain situations). Alternative is 'decay towards Adjust from OldAdjust stops at some distance from Adjust, so any lighting level can become the new normal.' Also, rgb adjust should decay more slowly than 'a' (affects all) adjust.
  482.  
  483.    Adjust.a = (TargetColor.a / Color.a - 1) * LUM_ADJUST_STRENGTH + 1;
  484.    float3 Accel = tex2D(CameraDataSampler, 2.5f/3).rgb;
  485.  
  486.    // Discussion! Sudden camera movement: 1/30 sec, camera moves 0.1. Velocity 3 units/sec, acceleration 90 units/sec^2. 60 fps, same velocity, half^W (this stands for delete word) double acceleration. Rotating with r=10 and t=2, velocity ~31, acceleration something like 70~100 units/sec^2. (Normal model height is ~20 units maybe)
  487.  
  488.    // Coefficient. length() is probably slower, even though this is 1~16 pixels. But accel can be negative, unlike color values. Acceleration of 2700 = jump 3 units in 1/30 sec. If adjacent registered camera frames aren't interpolated, 60 fps has 4x (four times) the acceleration here.
  489.    //float AccelCoeff = saturate( ((Accel.x + Accel.y + Accel.z) - 200) / 2500);
  490.    //float AccelCoeff = saturate( (length(Accel) - 200) / 2500);
  491.  
  492.    // At 6 fps with old computer and complicated ('heavy') effects, in 1/6 sec, camera moves 0.5, vel 3, accel 15. Detection is harder. Estimate. Could put this math in CameraData shader instead, but would have to rename stuff to be accurate. This exaggerates rotational acceleration at low fps since it normally doesn't vary with fps, but lerp with low AccelCoeff is less influential at low fps too.
  493.    float AccelCoeff = saturate( (length(Accel) - 200) / 2500 * max(min(abs(elaTime),0.25), 1.0/60) * 30 );
  494.    OldAdjust = all(OldAdjust.rgba == 0) ? 1 : OldAdjust; // Untested. Initialize at 1.
  495.  
  496.    // When camera is stationary.
  497.    float4 stationary;
  498.    //float4 difference = OldAdjust - Adjust; // For sign maybe?
  499.    //float4 ratio = Adjust / OldAdjust;
  500.    bool4 isGreater = Adjust > OldAdjust;
  501.    float closeLimit;
  502.    closeLimit = isGreater.a ? max(Adjust.a / LUM_STATIONARY_BUFFER, OldAdjust.a) : min(Adjust.a * LUM_STATIONARY_BUFFER, OldAdjust.a); // Both sides are computed.
  503.    float4 targetValue;
  504.  
  505.    // Lum (.a) adjusts in about 2 seconds (estimation is hard), chroma adjusts slower
  506.    float4 channelSpeed = {0.2, 0.2, 0.2, 1.0};
  507.  
  508.    // sign() returns 0 if they're equal. Maybe root of ratio, like (Adjust/OldAdjust)^0.5 would be better here, but that's much harder to understand and probably slightly slower.
  509.    targetValue = OldAdjust + ((Adjust - OldAdjust) * 0.5 + sign(Adjust - OldAdjust) * 0.05 ) * elaTime * AdjustSpeed * channelSpeed;
  510.    targetValue = isGreater ? min(targetValue, Adjust) : max(targetValue,Adjust); // Tested per component (4) of isGreater
  511.  
  512.    // Adjustment for luma advances at very slow speed inside the buffer
  513.    stationary.a = targetValue.a - (targetValue.a - closeLimit) * 0.9;
  514.    stationary.rgb = targetValue.rgb;
  515.  
  516.    // Linear interpolation~ not using coefficient as a coefficient but that's fine
  517.    Adjust = lerp(stationary, Adjust, AccelCoeff);
  518.  
  519.    return Adjust;
  520. }
  521.  
  522. //////////////////////////////////////
  523. // Apply the adjustment
  524.  
  525. /*
  526. struct VS_OUTPUT_DRAW {
  527.    float4 Pos : POSITION;
  528.    float2 Tex : TEXCOORD0;
  529.    //float2 TexSmall : TEXCOORD1;
  530. };
  531.  
  532. VS_OUTPUT_DRAW VS_Screen(float4 Pos : POSITION, float2 Tex : TEXCOORD0)
  533.  
  534. {
  535.    VS_OUTPUT Out = (VS_OUTPUT)0;
  536.  
  537.    Out.Pos = Pos;
  538.    Out.Tex = Tex.xy + ViewportOffset;
  539.  
  540.    // Maybe should modify coordinates so it doesn't use, or uses less of, the outermost half-pixels. Wait, this is wrong anyway. Only need one tex coordinate.
  541.    //Out.TexSmall = Tex.xy + ViewportOffset3;
  542.  
  543.    return Out;
  544. }
  545. */
  546.  
  547. // 画面の更新 *Adjust colors, not just update screen
  548. float4 PS_DrawFrame(float2 Tex: TEXCOORD0) : COLOR
  549. {
  550.    float4 OrigColor = tex2D(ScnSamp, Tex);
  551.  
  552.    // Use TinySampCurrent because it has a linear filter, while previous has no/point filter. rgb is per-channel, '.a' is adjustment to all.
  553.    float4 Adjust = tex2D(TinySampCurrent, Tex);
  554.  
  555.    float3 TestColor;
  556.    TestColor = OrigColor.rgb * Adjust.rgb * Adjust.a;
  557.  
  558.    // No gamma because don't understand how it affects this
  559.  
  560.    float3 IncreaseOverLimit = max( max(TestColor - REDUCE_BRIGHTNESS_LIMIT, 0) - max(OrigColor.rgb - REDUCE_BRIGHTNESS_LIMIT, 0), 0);
  561.  
  562.    // We make something up
  563.    IncreaseOverLimit = (sqrt(IncreaseOverLimit + 0.04) - 0.2) / 2.5; // Derivative is 1/x^.5 * 0.5? For x = 0.01, derivative is 5? For 0.04, derivative 2.5; with this, input of 0.1 goes to 0.070, .05 goes to 0.04, 0.5 goes to 0.214, 0.25 goes to 0.135
  564.  
  565.    // Hopefully we won't need the previous value again
  566.    //TestColor = max(TestColor, REDUCE_BRIGHTNESS_LIMIT) + IncreaseOverLimit;
  567.    // I think that was wrong but don't completely understand it.
  568.    TestColor = min(TestColor, REDUCE_BRIGHTNESS_LIMIT) + IncreaseOverLimit;
  569.    // Gamma is more influential here but still not using it
  570.    float averageColor = (TestColor.r + TestColor.g + TestColor.b) / 3;
  571.    averageColor = min(averageColor, DESAT_COLOR_LIMIT); // So the next step is positive or 0. Was '1' before, instead of DESAT_COLOR_LIMIT
  572.  
  573.    // Bring components towards average color based on something
  574.    float DesatRatio = 1 - ( max(TestColor.r - DESAT_COLOR_LIMIT, 0) + max(TestColor.g - DESAT_COLOR_LIMIT, 0) + max(TestColor.r - DESAT_COLOR_LIMIT, 0) ) / ( max(TestColor.r - averageColor, 0) + max(TestColor.g - averageColor, 0) + max(TestColor.b - averageColor, 0) ); // Was '1' instead of DESAT_COLOR_LIMIT
  575.    // Test: {0, 0.7, 1.4}, ratio is (1 - 0.4/0.7) = 0.43. {0, 1, 1.4}, ratio is (1 - 0.4/0.8) = 0.5.
  576.  
  577.    DesatRatio = max(DesatRatio, MIN_DESAT_RATIO);
  578.  
  579.    // I think it's fine to use the adjusted average here. Could make white (1,1,1) darker.
  580.    float3 Desaturated = averageColor + (TestColor - averageColor) * DesatRatio;
  581.  
  582.    // Linear interpolation. Ok, DESAT_STRENGTH in this step instead of previous means it reduces the effect of limiting averageColor to DESAT_COLOR_LIMIT or, previously, 1. Not using gamma means dark components stay darker? Not sure.
  583.    float4 Color = float4(lerp(TestColor, Desaturated, DESAT_STRENGTH), OrigColor.a);
  584.  
  585.    // For bug fixing
  586.    //Color.rgb = tex1D(CameraDataSampler, 0).rgb;
  587.    //Color.rgb = CameraPosition > 1 ? 1 : 0;
  588.    //Color.rgb = elaTime ? 0 : 1;
  589.    //Color.rgb = TestColor;
  590.    //Color.rgb = OrigColor.rgb * Adjust.rgb * Adjust.a;
  591.    Color.rgb = Adjust.a;
  592.    //Color.rgb = tex2Dlod(ScnSamp, float4(Tex,0,2));
  593.  
  594.    Color.rgb = lerp(OrigColor.rgb,Color.rgb,alpha1);
  595.    // No attempt to un-tint background color or whatever. Meant for videos anyway, so alpha should really be 1.
  596.  
  597.    return Color;
  598. }
  599.  
  600.  
  601. ////////////////////////////////////////////////////////////////////////////////////////////////
  602. // テクニック
  603.  
  604. technique MainTec <
  605.     string Script =
  606.     "RenderColorTarget0=CameraData;" //CameraDataTransfer
  607.         //"RenderDepthStencilTarget=CameraDataDepthBuffer;"
  608.         "Pass=WriteAccel;"
  609.     //"RenderColorTarget0=CameraData;"
  610.         //"Pass=CopyAccel;"
  611.  
  612.         "RenderColorTarget0=ScnMap;"
  613.             "RenderDepthStencilTarget=DepthBuffer;"
  614.             "ClearSetColor=ClearColor;"
  615.             "ClearSetDepth=ClearDepth;"
  616.             "Clear=Color;"
  617.             "Clear=Depth;"
  618.             "ScriptExternal=Color;"
  619.  
  620.         "RenderColorTarget0=SmallGammaScreen;"
  621.             //"RenderDepthStencilTarget=DepthBuffer;"
  622.             "Pass=GammaShrink;"
  623.         "RenderColorTarget0=TinyScreenCurrent;"
  624.             //"RenderDepthStencilTarget=TimeDepthBuffer;"
  625.             "Pass=TinyBlur;"
  626.         "RenderColorTarget0=TinyScreenPrev;"
  627.             "Pass=CopyBlur;"
  628.         "RenderColorTarget0=;"
  629.             //"RenderDepthStencilTarget=;"
  630.             "Pass=DrawObject;"
  631.     ;>
  632.  
  633.  
  634. /*
  635. * disable z-write
  636. Offset, ThisSampler
  637. if can't pass static variable as argument to shader, might have to pass something like 1, 0.25, -128 for viewport size, where negative = integer size and positive = ratio of viewportsize
  638. */
  639.  
  640. {
  641.     pass WriteAccel < string Script= "Draw=Buffer;"; > {
  642.         ALPHABLENDENABLE = FALSE;
  643.         ALPHATESTENABLE = FALSE;
  644.     ZWRITEENABLE = false;
  645.     ZENABLE = false;
  646.         VertexShader = compile vs_2_0 VS_UpdateCameraData();
  647.         PixelShader  = compile ps_2_0 PS_UpdateCameraData();
  648.     }
  649. /*
  650.     pass CopyAccel < string Script= "Draw=Buffer;"; > {
  651.         ALPHABLENDENABLE = FALSE;
  652.         ALPHATESTENABLE = FALSE;
  653.     ZWRITEENABLE = false;
  654.     ZENABLE = false;
  655.         VertexShader = compile vs_2_0 VS_Screen(CameraViewportOffset);
  656.         PixelShader  = compile ps_2_0 PS_CopyFrame(CameraDataTransferSamp);
  657.     }
  658. */
  659.  
  660.     pass GammaShrink < string Script= "Draw=Buffer;"; > {
  661.         ALPHABLENDENABLE = FALSE;
  662.         ALPHATESTENABLE = FALSE;
  663.     ZWRITEENABLE = false;
  664.     ZENABLE = false;
  665.     // texlod requires shader model 3_0
  666.         VertexShader = compile vs_3_0 VS_Screen(ViewportOffset2);
  667.         PixelShader  = compile ps_3_0 PS_GammaShrink();
  668.     }
  669.  
  670.     pass TinyBlur < string Script= "Draw=Buffer;"; > {
  671.         ALPHABLENDENABLE = FALSE;
  672.         ALPHATESTENABLE = FALSE;
  673.     ZWRITEENABLE = false;
  674.     ZENABLE = false;
  675.         VertexShader = compile vs_3_0 VS_Screen(ViewportOffset3);
  676.         PixelShader  = compile ps_3_0 PS_TinyBlur();
  677.     }
  678.  
  679.     pass CopyBlur < string Script= "Draw=Buffer;"; > {
  680.         ALPHABLENDENABLE = FALSE;
  681.         ALPHATESTENABLE = FALSE;
  682.     ZWRITEENABLE = false;
  683.     ZENABLE = false;
  684.         VertexShader = compile vs_2_0 VS_Screen(ViewportOffset3);
  685.         PixelShader  = compile ps_2_0 PS_CopyFrame(TinySampCurrent);
  686.     }
  687.  
  688.     pass DrawObject < string Script= "Draw=Buffer;"; > {
  689.         ALPHABLENDENABLE = FALSE;
  690.         ALPHATESTENABLE = FALSE;
  691.     ZWRITEENABLE = false;
  692.     ZENABLE = false;
  693.         VertexShader = compile vs_2_0 VS_Screen(ViewportOffset);
  694.         PixelShader  = compile ps_2_0 PS_DrawFrame();
  695.     }
  696.    
  697. }
  698. ////////////////////////////////////////////////////////////////////////////////////////////////
Advertisement
Add Comment
Please, Sign In to add comment