//////////////////////////////////////////////////////////////////////////////////////////////////////// // Droste Effect (Droste.fx) by SirCobra // Version 0.4.3 // You can find info and all my shaders here: https://github.com/LordKobra/CobraFX // // --------Description--------- // The Droste effect warps the image-space to recursively appear within itself. //////////////////////////////////////////////////////////////////////////////////////////////////////// #include "Reshade.fxh" // Shader Start // Namespace Everything! namespace COBRA_DRO { //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Defines & UI // //////////////////////////////////////////////////////////////////////////////////////////////////////// // Defines #define COBRA_DRO_VERSION "0.4.3" #define COBRA_UTL_MODE 0 #include ".\CobraUtility.fxh" // UI uniform int UI_EffectType < ui_label = " Effect Type"; ui_type = "radio"; ui_spacing = 2; ui_items = "Circular\0Rectangular\0"; ui_tooltip = "Shape of the recursive appearance."; ui_category = COBRA_UTL_UI_GENERAL; > = 0; uniform bool UI_Spiral < ui_label = " Spiral"; ui_spacing = 2; ui_tooltip = "Warp space into a spiral."; ui_category = COBRA_UTL_UI_GENERAL; > = true; uniform float UI_OuterRing < ui_label = " Outer Ring Size"; ui_type = "slider"; ui_min = 0.00; ui_max = 1.00; ui_step = 0.01; ui_tooltip = "The outer ring defines the texture border towards the edge of the screen."; ui_category = COBRA_UTL_UI_GENERAL; > = 1.00; uniform float UI_Zoom < ui_label = " Zoom"; ui_type = "slider"; ui_min = 0.00; ui_max = 9.90; ui_step = 0.01; ui_tooltip = "Zoom into the output."; ui_category = COBRA_UTL_UI_GENERAL; > = 1.00; uniform float UI_Frequency < ui_label = " Frequency"; ui_type = "slider"; ui_min = 0.10; ui_max = 5.00; ui_step = 0.01; ui_tooltip = "Defines the frequency of the recursion."; ui_category = COBRA_UTL_UI_GENERAL; > = 1.00; uniform float UI_X_Offset < ui_label = " Center Horizontal Offset"; ui_type = "slider"; ui_min = -0.50; ui_max = 0.50; ui_step = 0.01; ui_tooltip = "Change the horizontal position of the center. Keep it at 0 to get the best results."; ui_category = COBRA_UTL_UI_GENERAL; > = 0.00; uniform float UI_Y_Offset < ui_label = " Center Vertical Offset"; ui_type = "slider"; ui_min = -0.50; ui_max = 0.50; ui_step = 0.01; ui_tooltip = "Change the Y position of the center. Keep it at 0 to get the best results."; ui_category = COBRA_UTL_UI_GENERAL; > = 0.00; uniform int UI_BufferEnd < ui_type = "radio"; ui_spacing = 2; ui_text = " Shader Version: " COBRA_DRO_VERSION; ui_label = " "; > ; //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Helper Functions // //////////////////////////////////////////////////////////////////////////////////////////////////////// #define COBRA_UTL_MODE 2 #include ".\CobraUtility.fxh" //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Shaders // //////////////////////////////////////////////////////////////////////////////////////////////////////// vs2ps VS_Droste(uint id : SV_VertexID) { const float2 AR = UI_EffectType == 0 ? float2(float(BUFFER_WIDTH) / BUFFER_HEIGHT, 1.0) : float2(1.0, 1.0); const float2 OFFSET = float2(UI_X_Offset, UI_Y_Offset); const float NEW_CENTER_ANGLE = abs(OFFSET.x) + abs(OFFSET.y) < 0.01 ? 1 : (atan2_approx(-OFFSET.x * AR.x, -OFFSET.y) + M_PI) / (2 * M_PI); const float INNER_RING = 1 / exp(1 / (UI_Frequency)); return vs_basic(id, float2(NEW_CENTER_ANGLE, INNER_RING)); } void PS_Droste(vs2ps o, out float4 fragment : SV_Target) { // transform coordinate system const float2 AR = UI_EffectType == 0 ? float2(float(BUFFER_WIDTH) / BUFFER_HEIGHT, 1.0) : 1.0; const float2 OFFSET = float2(UI_X_Offset, UI_Y_Offset); float2 new_pos = (o.uv.xy - 0.5 + OFFSET) * AR; // calculate orientation of center and pixel const float NEW_CENTER_DISTANCE = (1 - 2.0 * max(abs(OFFSET.x), abs(OFFSET.y))); const float NEW_CENTER_ANGLE = o.uv.z; // calculate and normalize angle float angle = (atan2_approx(new_pos.x, new_pos.y) + M_PI) / (2 * M_PI); float val = angle * UI_Spiral; angle = 1 - fmod(abs(abs(angle - NEW_CENTER_ANGLE) - 0.5), 0.5) * 2; //smooth off-center projection float angle_smooth = (1 - cos(angle * angle * M_PI)) / 2; float intensity = lerp(NEW_CENTER_DISTANCE, 1, angle_smooth); // calculate distance from center float cicle_dist = sqrt(dot(new_pos,new_pos)) / intensity; float rect_dist = max(abs(new_pos.x), abs(new_pos.y)); float rcdist = UI_EffectType == 0 ? cicle_dist : rect_dist; rcdist = log(rcdist * (10 - UI_Zoom)) * UI_Frequency; val += rcdist; val = (exp(fmod(val, 1) / UI_Frequency) - 1) / (rcp(o.uv.w) - 1); // normalized vector float vector_length = sqrt(dot(new_pos,new_pos)); float unit_circle_ratio = UI_EffectType == 0 ? 0.5 / vector_length : 0.5 / max(abs(new_pos.x), abs(new_pos.y)); float2 normalized = new_pos * unit_circle_ratio; // calculate relative position towards outer and inner ring and interpolate const float INNER_RING = o.uv.w * UI_OuterRing; float real_scale = lerp(INNER_RING, UI_OuterRing,val); real_scale *= intensity; float2 adjusted = normalized * real_scale / AR + 0.5 - OFFSET; fragment = tex2D(ReShade::BackBuffer, adjusted); } //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Techniques // //////////////////////////////////////////////////////////////////////////////////////////////////////// technique TECH_Droste < ui_label = "Droste Effect"; ui_tooltip = "------About-------\n" "Droste.fx warps the image-space to recursively appear within itself.\n\n" "Version: " COBRA_DRO_VERSION "\nAuthor: SirCobra\nCollection: CobraFX\n" " https://github.com/LordKobra/CobraFX"; > { pass Droste { VertexShader = VS_Droste; PixelShader = PS_Droste; } } }