Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* COMPATIBILITY
- - HLSL compilers
- - Cg compilers
- */
- // This is a good place for any #defines you might have
- #define FIX(c) max(abs(c), 1e-5);
- // Comment the next line to disable interpolation in linear gamma (and gain speed).
- #define LINEAR_PROCESSING
- // Enable 3x oversampling of the beam profile
- #define OVERSAMPLE
- // Use the older, purely gaussian beam profile
- //#define USEGAUSSIAN
- // Use interlacing detection; may interfere with other shaders if combined
- #define INTERLACED
- #define SHARPER
- // Macros.
- #define FIX(c) max(abs(c), 1e-5);
- #define PI 3.141592653589
- #ifdef LINEAR_PROCESSING
- # define TEX2D(c) pow(tex2D(IN.texture, (c)), float4(CRTgamma))
- #else
- # define TEX2D(c) tex2D(IN.texture, (c))
- #endif
- // gamma of simulated CRT
- #define CRTgamma 2.4
- // gamma of display monitor (typically 2.2 is correct)
- #define monitorgamma 2.2
- struct input // These are things that can attach to 'IN' to achieve similar function to ruby* stuff in existing GLSL shaders. NOTE: the ruby* prefix is deprecated but still works in GLSL for legacy compatibility purposes.
- {
- float2 video_size;
- float2 texCoord_size;
- float2 output_size;
- float frame_count;
- float frame_direction;
- float frame_rotation;
- float texture_size;
- sampler2D texture : TEXUNIT0;
- };
- struct tex_coords
- {
- float2 texCoord : TEXCOORD0;
- float2 one : TEXCOORD2;
- };
- // VERTEX SHADER //
- void main_vertex
- (
- float4 position : POSITION,
- out float4 oPosition : POSITION,
- uniform float4x4 modelViewProj,
- float4 color : COLOR,
- out float4 oColor : COLOR,
- float2 tex : TEXCOORD,
- uniform input IN,
- out tex_coords coords
- )
- {
- oPosition = mul(modelViewProj, position);
- oColor = color;
- #ifdef SHARPER
- float2 TextureSize = float2(2.0*IN.texture_size.x, IN.texture_size.y);
- #else
- float2 TextureSize = IN.texture_size;
- #endif
- coords.texCoord = tex + float2(0.0, 0.0);
- coords.one = 1.0 / TextureSize;
- }
- // Calculate the influence of a scanline on the current pixel.
- //
- // 'distance' is the distance in texture coordinates from the current
- // pixel to the scanline in question.
- // 'color' is the colour of the scanline at the horizontal location of
- // the current pixel.
- float4 scanlineWeights(float distance, float4 color)
- {
- // "wid" controls the width of the scanline beam, for each RGB channel
- // The "weights" lines basically specify the formula that gives
- // you the profile of the beam, i.e. the intensity as
- // a function of distance from the vertical center of the
- // scanline. In this case, it is gaussian if width=2, and
- // becomes nongaussian for larger widths. Ideally this should
- // be normalized so that the integral across the beam is
- // independent of its width. That is, for a narrower beam
- // "weights" should have a higher peak at the center of the
- // scanline than for a wider beam.
- #ifdef USEGAUSSIAN
- float4 wid = 0.3 + 0.1 * pow(color, float4(3.0));
- float4 weights = float4(distance / wid);
- return 0.4 * exp(-weights * weights) / wid;
- #else
- float4 wid = 2.0 + 2.0 * pow(color, float4(4.0));
- float4 weights = float4(distance / 0.4);
- return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
- #endif
- }
- // FRAGMENT SHADER //
- float4 main_fragment(in tex_coords co, uniform input IN, uniform sampler2D s_p : TEXUNIT0) : COLOR
- {
- // Paste your fragment code--the part that is inside the GLSL shader's "void main(){ ... }"--here:
- // Here's a helpful diagram to keep in mind while trying to
- // understand the code:
- //
- // | | | | |
- // -------------------------------
- // | | | | |
- // | 01 | 11 | 21 | 31 | <-- current scanline
- // | | @ | | |
- // -------------------------------
- // | | | | |
- // | 02 | 12 | 22 | 32 | <-- next scanline
- // | | | | |
- // -------------------------------
- // | | | | |
- //
- // Each character-cell represents a pixel on the output
- // surface, "@" represents the current pixel (always somewhere
- // in the bottom half of the current scan-line, or the top-half
- // of the next scanline). The grid of lines represents the
- // edges of the texels of the underlying texture.
- // Texture coordinates of the texel containing the active pixel.
- float2 xy = co.texCoord;
- float2 ilfac = float2(1.0,floor(IN.video_size.y/200.0));
- #ifdef SHARPER
- float2 TextureSize = float2(2.0*IN.texture_size.x, IN.texture_size.y);
- #else
- float2 TextureSize = IN.texture_size;
- #endif
- // The size of one texel, in texture-coordinates.
- float2 one = ilfac / TextureSize;
- float2 ilvec = float2(0.0,ilfac.y > 1.5 ? mod(float(IN.frame_count),2.0) : 0.0);
- // Of all the pixels that are mapped onto the texel we are
- // currently rendering, which pixel are we currently rendering?
- #ifdef INTERLACED
- float2 ratio_scale = (xy * TextureSize - float2(0.5) + ilvec)/ilfac;
- #else
- float2 ratio_scale = xy * TextureSize - float2(0.5);
- #endif
- #ifdef OVERSAMPLE
- float filter = (IN.video_size / (IN.output_size * TextureSize)) *(ratio_scale.y);
- #endif
- float2 uv_ratio = fract(ratio_scale);
- // Snap to the center of the underlying texel.
- #ifdef INTERLACED
- xy = (floor(ratio_scale)*ilfac + float2(0.5) - ilvec) / TextureSize;
- #else
- xy = (floor(ratio_scale) + float2(0.5)) / TextureSize;
- #endif
- // Calculate Lanczos scaling coefficients describing the effect
- // of various neighbour texels in a scanline on the current
- // pixel.
- float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
- // Prevent division by zero.
- coeffs = FIX(coeffs);
- // Lanczos2 kernel.
- coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
- // Normalize.
- coeffs /= dot(coeffs, float4(1.0));
- // Calculate the effective colour of the current and next
- // scanlines at the horizontal location of the current pixel,
- // using the Lanczos coefficients above.
- float4 col = clamp(mul(coeffs, float4x4(
- TEX2D(xy + float2(-co.one.x, 0.0)),
- TEX2D(xy),
- TEX2D(xy + float2(co.one.x, 0.0)),
- TEX2D(xy + float2(2.0 * co.one.x, 0.0)))),
- 0.0, 1.0);
- float4 col2 = clamp(mul(coeffs, float4x4(
- TEX2D(xy + float2(-co.one.x, co.one.y)),
- TEX2D(xy + float2(0.0, co.one.y)),
- TEX2D(xy + co.one),
- TEX2D(xy + float2(2.0 * co.one.x, co.one.y)))),
- 0.0, 1.0);
- #ifndef LINEAR_PROCESSING
- col = pow(col , float4(CRTgamma));
- col2 = pow(col2, float4(CRTgamma));
- #endif
- // Calculate the influence of the current and next scanlines on
- // the current pixel.
- float4 weights = scanlineWeights(uv_ratio.y, col);
- float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
- #ifdef OVERSAMPLE
- uv_ratio.y =uv_ratio.y+1.0/3.0*filter;
- weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
- weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
- uv_ratio.y =uv_ratio.y-2.0/3.0*filter;
- weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
- weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
- #endif
- float3 mul_res = (col * weights + col2 * weights2).rgb;
- // Convert the image gamma for display on our output device.
- mul_res = pow(mul_res, float3(1.0 / monitorgamma));
- return float4(mul_res, 1.0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement