Pete´s Messageboard... No ISO/BIOS requests!

Homepage Members Register Login Search Old board


Neuer Thread ...
More : [1] [2]


AuthorTopics » Book an abo for this threadClose Thread Move Thread Fix the thread Print view Delete this thread

80T 



...

Status:Offline
Date registered: 22.06.2011
Post:4
Send Message
...   Created on 22.06.2011 - 01:20Jump to top Quote this post Report this post Edit Delete


Hi I'm a big PS1 fan and this is my first post here :D
I've just registered because I found something very interesting that I was searching for quite some time now...

Since I don't have place for a classic CRT TV any more, I've switched playing my PS1 games on emulators and I found ePSXe the most suited for this purpose being the fact that it supports plugins.
And what GPU plugin can be more sweet than Pete's OGL2... :D

All in all, things are pretty good, but I'm not really satisfied with the shaders that I've found...
Indeed there are some of them which looks nice, enhances graphics and all... But my main purpose is to get that classic feeling of an old SD CRT TV display. That kind of display which has the native kind of "filtering" which make SD signal look AWESOME!
I mean the small triads of phosphorus pixels with black mask between them and a little color bleed and the way those pixels are lit etc...

Here is a little example pic of a common CRT mask pattern:


Ok, so the thing is that while I was browsing for a CRT shader on the net I accidentally bumped into a forum where another emulator (bSnes - SNES emulator) was making use of shaders for enhancing the graphical experience.
So I took a look there and I've found some awesome CRT shaders different from OGL2 ones found here. The problem is those are in another format ".shader" and not ".slv/.slf" or ".vp/.fp"
While I saw on that forum ePSXe OGL2 shaders rewritten to bSnes I want to ask: Is it possible to rewrite bSnes shaders to ePSXe OGL2 ?

This is where I found the awesome shaders: Click!
and this is one of the CRT shaders:

Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
 
  <?xml version="1.0" encoding="UTF-8" ?> 
- <!-- 
    cgwg's CRT shader

    Copyright (C) 2010 cgwg    

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.

    (cgwg gave their consent to have their code distributed under the GPL in
    this message:

        http://board.byuu.org/viewtopic.php?p=26075#p26075

        "Feel free to distribute my shaders under the GPL. After all, the
        barrel distortion code was taken from the Curvature shader, which is
        under the GPL."
    )
    

  --> 
- <shader language="GLSL">
- <fragment>
- <![CDATA[ 
        
        uniform sampler2D rubyTexture;
        uniform vec2 rubyInputSize;
        uniform vec2 rubyOutputSize;
        uniform vec2 rubyTextureSize;

        // Abbreviations
        //#define TEX2D(c) texture2D(rubyTexture, (c))
        #define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(inputGamma))                
        #define FIX(c)   max(abs(c), 1e-6);
        #define PI 3.141592653589

        // Adjusts the vertical position of scanlines. Useful if the output
        // pixel size is large compared to the scanline width (so, scale
        // factors less than 4x or so). Ranges from 0.0 to 1.0.
        #define phase 0.0

        // Assume NTSC 2.2 Gamma for linear blending
        #define inputGamma 2.2

        // Simulate a CRT gamma of 2.5
        #define outputGamma 2.5

        // Controls the intensity of the barrel distortion used to emulate the
        // curvature of a CRT. 0.0 is perfectly flat, 1.0 is annoyingly
        // distorted, higher values are increasingly ridiculous.
        #define distortion 0.0

        // Apply radial distortion to the given coordinate.
        vec2 radialDistortion(vec2 coord) {
                coord *= rubyTextureSize / rubyInputSize;
                vec2 cc = coord - 0.5;
                float dist = dot(cc, cc) * distortion;                
                return (coord + cc * (1.0 + dist) * dist) * rubyInputSize / rubyTextureSize;
        }
                
        // 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.
        vec4 scanlineWeights(float distance, vec4 color)
        {
                // The "width" of the scanline beam is set as 2*(1 + x^4) for
                // each RGB channel.
                vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));

                // 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.
                vec4 weights = vec4(distance * 3.333333);                
                return 0.51 * exp(-pow(weights * sqrt(2.0 / wid), wid)) / (0.18 + 0.06 * wid);
        }
                
        void main()
        {
                // 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.

                // The size of one texel, in texture-coordinates.
                vec2 one = 1.0 / rubyTextureSize;

                // Texture coordinates of the texel containing the active pixel                
                vec2 xy = radialDistortion(gl_TexCoord[0].xy);

                // Of all the pixels that are mapped onto the texel we are
                // currently rendering, which pixel are we currently rendering?
                vec2 uv_ratio = fract(xy * rubyTextureSize) - vec2(0.5);

                // Snap to the center of the underlying texel.                
                xy = (floor(xy * rubyTextureSize) + vec2(0.5)) / rubyTextureSize;
                
                // Calculate Lanczos scaling coefficients describing the effect
                // of various neighbour texels in a scanline on the current
                // pixel.                
                vec4 coeffs = PI * vec4(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);
                coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
                
                // Normalize
                coeffs /= dot(coeffs, vec4(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.                                
                vec4 col  = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, 0.0))   + coeffs.y * TEX2D(xy)                    + coeffs.z * TEX2D(xy + vec2(one.x, 0.0)) + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, 0.0)),   0.0, 1.0);
                vec4 col2 = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, one.y)) + coeffs.y * TEX2D(xy + vec2(0.0, one.y)) + coeffs.z * TEX2D(xy + one)              + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, one.y)), 0.0, 1.0);

                // col  = pow(col, vec4(inputGamma));    
                // col2 = pow(col2, vec4(inputGamma));
                
                // Calculate the influence of the current and next scanlines on
                // the current pixel.
                vec4 weights  = scanlineWeights(abs(uv_ratio.y) , col);
                vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
                vec3 mul_res  = (col * weights + col2 * weights2).xyz;

                // mod_factor is the x-coordinate of the current output pixel.
                float mod_factor = gl_TexCoord[0].x * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x;
                
                // dot-mask emulation:
                // Output pixels are alternately tinted green and magenta.
                vec3 dotMaskWeights = mix(
                        vec3(1.05, 0.75, 1.05),
                        vec3(0.75, 1.05, 0.75),
                        floor(mod(mod_factor, 2.0))
                    );
                    
                mul_res *= dotMaskWeights;
                
                // Convert the image gamma for display on our output device.
                mul_res = pow(mul_res, vec3(1.0 / (2.0 * inputGamma - outputGamma)));
                
                gl_FragColor = vec4(mul_res, 1.0);
        }
    

  ]]> 
  </fragment>
  </shader>


As you can see, the code looks quite similar to GLSL

[Dieser Beitrag wurde am 22.06.2011 - 15:38 von 80T aktualisiert]





Signature
Get things right or don't bother at all

KrossX 
Real addict
.........

...

Status:Offline
Date registered: 16.06.2008
Post:122
Send Message
...   Created on 25.06.2011 - 03:59Jump to top Quote this post Report this post Edit Delete


Yup, I had followed that thread some months ago. It ain´t that it looks like GLSL, it IS GLSL as you can see from the following line: shader language="GLSL". And everything under fragment would be your gpuPeteOGL2.slf file.

Still, a mere copy paste wouldn´t make it work. It would have to be ... ported, and then it may not work at all.

#EDIT: Here's a tryout.
If rubyTextureSize, rubyInputSize and rubyOutputSize would have proper "ported" values, it might work nicely. As of now, it just merely works.

gpuPeteOGL2.slv

Code:
1:
2:
3:
4:
5:
6:
 
void main()

{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}


gpuPeteOGL2.slf
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
 

/*    
    cgwg's CRT shader
    Copyright (C) 2010 cgwg    

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.

    cgwg gave their consent to have their code distributed under the GPL in
    this message:

        http://board.byuu.org/viewtopic.php?p=26075#p26075

        "Feel free to distribute my shaders under the GPL. After all, the
        barrel distortion code was taken from the Curvature shader, which is
        under the GPL."
    
*/
    
uniform sampler2D OGL2Texture;
uniform vec4 OGL2Param, OGL2Size;

vec2 rubyTextureSize = OGL2Size.xy;
vec2 rubyInputSize = vec2(320.0f, 240.0f);
vec2 rubyOutputSize = vec2(800.0f,600.0f);

// Abbreviations
//#define TEX2D(c) texture2D(OGL2Texture, (c))
#define TEX2D(c) pow(texture2D(OGL2Texture, (c)), vec4(inputGamma))                
#define FIX(c)   max(abs(c), 1e-6);
#define PI 3.141592653589

// Adjusts the vertical position of scanlines. Useful if the output
// pixel size is large compared to the scanline width (so, scale
// factors less than 4x or so). Ranges from 0.0 to 1.0.
#define phase 0.0

// Assume NTSC 2.2 Gamma for linear blending
#define inputGamma 2.2

// Simulate a CRT gamma of 2.5
#define outputGamma 2.5

// Controls the intensity of the barrel distortion used to emulate the
// curvature of a CRT. 0.0 is perfectly flat, 1.0 is annoyingly
// distorted, higher values are increasingly ridiculous.
#define distortion 0.0

// Apply radial distortion to the given coordinate.
vec2 radialDistortion(vec2 coord) {
        coord *= rubyTextureSize / rubyInputSize;
        vec2 cc = coord - 0.5;
        float dist = dot(cc, cc) * distortion;                
        return (coord + cc * (1.0 + dist) * dist) * rubyInputSize / rubyTextureSize;
}

        
// 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.
vec4 scanlineWeights(float distance, vec4 color)
{
        // The "width" of the scanline beam is set as 2*(1 + x^4) for
        // each RGB channel.
        vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));

        // 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.
        vec4 weights = vec4(distance * 3.333333);                
        return 0.51 * exp(-pow(weights * sqrt(2.0 / wid), wid)) / (0.18 + 0.06 * wid);
}
        
void main()
{
        // 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.

        // The size of one texel, in texture-coordinates.
        vec2 one = 1.0 / rubyTextureSize;

        // Texture coordinates of the texel containing the active pixel                
        vec2 xy = radialDistortion(gl_TexCoord[0].xy);

        // Of all the pixels that are mapped onto the texel we are
        // currently rendering, which pixel are we currently rendering?
        vec2 uv_ratio = fract(xy * rubyTextureSize) - vec2(0.5);

        // Snap to the center of the underlying texel.                
        xy = (floor(xy * rubyTextureSize) + vec2(0.5)) / rubyTextureSize;
        
        // Calculate Lanczos scaling coefficients describing the effect
        // of various neighbour texels in a scanline on the current
        // pixel.                
        vec4 coeffs = PI * vec4(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);
        coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
        
        // Normalize
        coeffs /= dot(coeffs, vec4(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.                                
        vec4 col  = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, 0.0))   + coeffs.y * TEX2D(xy)                    + coeffs.z * TEX2D(xy + vec2(one.x, 0.0)) + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, 0.0)),   0.0, 1.0);
        vec4 col2 = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, one.y)) + coeffs.y * TEX2D(xy + vec2(0.0, one.y)) + coeffs.z * TEX2D(xy + one)              + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, one.y)), 0.0, 1.0);

        // col  = pow(col, vec4(inputGamma));    
        // col2 = pow(col2, vec4(inputGamma));
        
        // Calculate the influence of the current and next scanlines on
        // the current pixel.
        vec4 weights  = scanlineWeights(abs(uv_ratio.y) , col);
        vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
        vec3 mul_res  = (col * weights + col2 * weights2).xyz;

        // mod_factor is the x-coordinate of the current output pixel.
        float mod_factor = gl_TexCoord[0].x * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x;
        
        // dot-mask emulation:
        // Output pixels are alternately tinted green and magenta.
        vec3 dotMaskWeights = mix(
                vec3(1.05, 0.75, 1.05),
                vec3(0.75, 1.05, 0.75),
                floor(mod(mod_factor, 2.0))
            );
            
        mul_res *= dotMaskWeights;
        
        // Convert the image gamma for display on our output device.
        mul_res = pow(mul_res, vec3(1.0 / (2.0 * inputGamma - outputGamma)));
        
        gl_FragColor = vec4(mul_res, 1.0);
}    


[Dieser Beitrag wurde am 25.06.2011 - 04:40 von KrossX aktualisiert]





Signature


80T 



...

Status:Offline
Date registered: 22.06.2011
Post:4
Send Message
...   Created on 25.06.2011 - 20:47Jump to top Quote this post Report this post Edit Delete


KrossX schrieb

    Yup, I had followed that thread some months ago. It ain´t that it looks like GLSL, it IS GLSL as you can see from the following line: shader language="GLSL". And everything under fragment would be your gpuPeteOGL2.slf file.

    Still, a mere copy paste wouldn´t make it work. It would have to be ... ported, and then it may not work at all.

    #EDIT: Here's a tryout.
    If rubyTextureSize, rubyInputSize and rubyOutputSize would have proper "ported" values, it might work nicely. As of now, it just merely works.






Thanx for reply KrossX. I just tried the "port" and it gives an error:





Signature
Get things right or don't bother at all

KrossX 
Real addict
.........

...

Status:Offline
Date registered: 16.06.2008
Post:122
Send Message
...   Created on 26.06.2011 - 04:50Jump to top Quote this post Report this post Edit Delete


I don't get any error, but just try removing the f's on the following lines, since it seems that's what it doesn't like.

Code:
1:
2:
3:
4:
5:
 

//Instead of .0f, make it .0

vec2 rubyInputSize = vec2(320.0f, 240.0f);
vec2 rubyOutputSize = vec2(800.0f,600.0f);




[Dieser Beitrag wurde am 26.06.2011 - 04:52 von KrossX aktualisiert]





Signature


80T 



...

Status:Offline
Date registered: 22.06.2011
Post:4
Send Message
...   Created on 26.06.2011 - 08:53Jump to top Quote this post Report this post Edit Delete


KrossX schrieb

    I don't get any error, but just try removing the f's on the following lines, since it seems that's what it doesn't like.

    Code:
    1:
    2:
    3:
    4:
    5:
     

    //Instead of .0f, make it .0

    vec2 rubyInputSize = vec2(320.0f, 240.0f);
    vec2 rubyOutputSize = vec2(800.0f,600.0f);







Thanx again. Now it works





Signature
Get things right or don't bother at all

RyuRanX 



...

Status:Offline
Date registered: 02.04.2012
Post:1
Send Message
...   Created on 02.04.2012 - 01:13Jump to top Quote this post Report this post Edit Delete


How can I make distortion work correctly? I tried setting 0.05 as value but the screen is flickering like crazy.




R4Zi3L 



...

Status:Offline
Date registered: 09.07.2012
Post:1
Send Message
...   Created on 09.07.2012 - 22:26Jump to top Quote this post Report this post Edit Delete


What about new version?




Leila 
Strong supporter
......

...

Status:Offline
Date registered: 27.09.2009
Post:25
Send Message
...   Created on 17.09.2012 - 02:25Jump to top Quote this post Report this post Edit Delete


You have absolutely no idea what you're doing. You can't make a technically accurate mask because the triads won't physically align with the pixels, even if the image is adequately upscaled (no possible fix here)

Furthermore, if your approach was rather "visual", it failed miserably because all this is doing is dim down the already opaque and poorly-contrasting LCD displays. And to make things worse, you're not even supposed to be able to distinguish the triads, unless you're sitting like a centimeter from the source.




vook 



...

Status:Offline
Date registered: 06.12.2012
Post:1
Send Message
...   Created on 06.12.2012 - 10:47Jump to top Quote this post Report this post Edit Delete


Hi there is a new version of this plugin @ http://filthypants.blogspot.com/2012/07 … hader.html

I've spent hours trying to get it working but I am over my head. All I can get is 1/16 of the screen to display. I wonder if someone else can take a look at it since there needs to be a good CRT filter for PSX emulation by now.

Original:

Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
 
<?xml version="1.0" encoding="UTF-8"?>
<!--
    CRT shader

    Copyright (C) 2010-2012 cgwg, Themaister and DOLLS

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.
    -->
<shader language="GLSL">
    <vertex><![CDATA[
varying float CRTgamma;
varying float monitorgamma;
varying vec2 overscan;
varying vec2 aspect;
varying float d;
varying float R;
varying float cornersize;
varying float cornersmooth;

varying vec3 stretch;
varying vec2 sinangle;
varying vec2 cosangle;

uniform vec2 rubyInputSize;
uniform vec2 rubyTextureSize;
uniform vec2 rubyOutputSize;

varying vec2 texCoord;
varying vec2 one;
varying float mod_factor;
varying vec2 ilfac;

#define FIX(c) max(abs(c), 1e-5);

float intersect(vec2 xy)
{
  float A = dot(xy,xy)+d*d;
  float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}

vec2 bkwtrans(vec2 xy)
{
  float c = intersect(xy);
  vec2 point = vec2(c)*xy;
  point -= vec2(-R)*sinangle;
  point /= vec2(R);
  vec2 tang = sinangle/cosangle;
  vec2 poc = point/cosangle;
  float A = dot(tang,tang)+1.0;
  float B = -2.0*dot(poc,tang);
  float C = dot(poc,poc)-1.0;
  float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  vec2 uv = (point-a*sinangle)/cosangle;
  float r = R*acos(a);
  return uv*r/sin(r/R);
}

vec2 fwtrans(vec2 uv)
{
  float r = FIX(sqrt(dot(uv,uv)));
  uv *= sin(r/R)/r;
  float x = 1.0-cos(r/R);
  float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  return d*(uv*cosangle-x*sinangle)/D;
}

vec3 maxscale()
{
  vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
  vec2 a = vec2(0.5,0.5)*aspect;
  vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
         fwtrans(vec2(c.x,-a.y)).y)/aspect;
  vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
         fwtrans(vec2(c.x,+a.y)).y)/aspect;
  return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}


void main()
{

  // START of parameters

  // gamma of simulated CRT
  CRTgamma = 2.4;
  // gamma of display monitor (typically 2.2 is correct)
  monitorgamma = 2.2;
  // overscan (e.g. 1.02 for 2% overscan)
  overscan = vec2(1.00,1.00);
  // aspect ratio
  aspect = vec2(1.0, 0.75);
  // lengths are measured in units of (approximately) the width of the monitor
  // simulated distance from viewer to monitor
  d = 2.0;
  // radius of curvature
  R = 1.5;
  // tilt angle in radians
  // (behavior might be a bit wrong if both components are nonzero)
  const vec2 angle = vec2(0.0,-0.15);
  // size of curved corners
  cornersize = 0.001;
  // border smoothness parameter
  // decrease if borders are too aliased
  cornersmooth = 1000.0;

  // END of parameters

  // Do the standard vertex processing.
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

  // Precalculate a bunch of useful values we'll need in the fragment
  // shader.
  sinangle = sin(angle);
  cosangle = cos(angle);
  stretch = maxscale();

  // Texture coords.
  texCoord = gl_MultiTexCoord0.xy;
  
  ilfac = vec2(1.0,floor(rubyInputSize.y/200.0));

  // The size of one texel, in texture-coordinates.
  one = ilfac / rubyTextureSize;

  // Resulting X pixel-coordinate of the pixel we're drawing.
  mod_factor = texCoord.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;            
}
    ]]></vertex>
    <fragment><![CDATA[
// Comment the next line to disable interpolation in linear gamma (and gain speed).
//#define LINEAR_PROCESSING

// Enable screen curvature.
//#define CURVATURE

// Enable 3x oversampling of the beam profile
#define OVERSAMPLE

// Use the older, purely gaussian beam profile
//#define USEGAUSSIAN

// Macros.
#define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589

#ifdef LINEAR_PROCESSING
#       define TEX2D(c) pow(texture2D(rubyTexture, (c)), vec4(CRTgamma))
#else
#       define TEX2D(c) texture2D(rubyTexture, (c))
#endif

uniform sampler2D rubyTexture;
uniform vec2 rubyInputSize;
uniform vec2 rubyTextureSize;
uniform int rubyFrameCount;

varying vec2 texCoord;
varying vec2 one;
varying float mod_factor;
varying vec2 ilfac;

varying float CRTgamma;
varying float monitorgamma;

varying vec2 overscan;
varying vec2 aspect;

varying float d;
varying float R;

varying float cornersize;
varying float cornersmooth;

varying vec3 stretch;
varying vec2 sinangle;
varying vec2 cosangle;

float intersect(vec2 xy)
{
  float A = dot(xy,xy)+d*d;
  float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}

vec2 bkwtrans(vec2 xy)
{
  float c = intersect(xy);
  vec2 point = vec2(c)*xy;
  point -= vec2(-R)*sinangle;
  point /= vec2(R);
  vec2 tang = sinangle/cosangle;
  vec2 poc = point/cosangle;
  float A = dot(tang,tang)+1.0;
  float B = -2.0*dot(poc,tang);
  float C = dot(poc,poc)-1.0;
  float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  vec2 uv = (point-a*sinangle)/cosangle;
  float r = FIX(R*acos(a));
  return uv*r/sin(r/R);
}

vec2 transform(vec2 coord)
{
  coord *= rubyTextureSize / rubyInputSize;
  coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
  return (bkwtrans(coord)/overscan/aspect+vec2(0.5)) * rubyInputSize / rubyTextureSize;
}

float corner(vec2 coord)
{
  coord *= rubyTextureSize / rubyInputSize;
  coord = (coord - vec2(0.5)) * overscan + vec2(0.5);
  coord = min(coord, vec2(1.0)-coord) * aspect;
  vec2 cdist = vec2(cornersize);
  coord = (cdist - min(coord,cdist));
  float dist = sqrt(dot(coord,coord));
  return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
}

// 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.
vec4 scanlineWeights(float distance, vec4 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
  vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
  vec4 weights = vec4(distance / wid);
  return 0.4 * exp(-weights * weights) / wid;
#else
  vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
  vec4 weights = vec4(distance / 0.3);
  return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}

void main()
{
  // 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.
#ifdef CURVATURE
  vec2 xy = transform(texCoord);
#else
  vec2 xy = texCoord;
#endif
  float cval = corner(xy);

  // Of all the pixels that are mapped onto the texel we are
  // currently rendering, which pixel are we currently rendering?
  vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(rubyFrameCount),2.0) : 0.0);
  vec2 ratio_scale = (xy * rubyTextureSize - vec2(0.5) + ilvec)/ilfac;
#ifdef OVERSAMPLE
  float filter = fwidth(ratio_scale.y);
#endif
  vec2 uv_ratio = fract(ratio_scale);

  // Snap to the center of the underlying texel.
  xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / rubyTextureSize;

  // Calculate Lanczos scaling coefficients describing the effect
  // of various neighbour texels in a scanline on the current
  // pixel.
  vec4 coeffs = PI * vec4(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, vec4(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.
  vec4 col  = clamp(mat4(
             TEX2D(xy + vec2(-one.x, 0.0)),
             TEX2D(xy),
             TEX2D(xy + vec2(one.x, 0.0)),
             TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
            0.0, 1.0);
  vec4 col2 = clamp(mat4(
             TEX2D(xy + vec2(-one.x, one.y)),
             TEX2D(xy + vec2(0.0, one.y)),
             TEX2D(xy + one),
             TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
            0.0, 1.0);

#ifndef LINEAR_PROCESSING
  col  = pow(col , vec4(CRTgamma));
  col2 = pow(col2, vec4(CRTgamma));
#endif

  // Calculate the influence of the current and next scanlines on
  // the current pixel.
  vec4 weights  = scanlineWeights(uv_ratio.y, col);
  vec4 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
  vec3 mul_res  = (col * weights + col2 * weights2).rgb * vec3(cval);

  // dot-mask emulation:
  // Output pixels are alternately tinted green and magenta.
  vec3 dotMaskWeights = mix(
          vec3(1.0, 0.7, 1.0),
          vec3(0.7, 1.0, 0.7),
          floor(mod(mod_factor, 2.0))
      );
                    
  mul_res *= dotMaskWeights;

  // Convert the image gamma for display on our output device.
  mul_res = pow(mul_res, vec3(1.0 / monitorgamma));

  // Color the texel.
  gl_FragColor = vec4(mul_res, 1.0);
}
    ]]></fragment>
</shader>


Here's what I tried but didn't really work:
SLV
Code:
1:
2:
3:
4:
5:
6:
7:
 
void main()

{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
    
}


SLF
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
 
uniform sampler2D OGL2Texture;
 float CRTgamma;
 float monitorgamma;
 vec2 overscan;
 vec2 aspect;
 float d;
 float R;
 float cornersize;
 float cornersmooth;

 vec3 stretch;
 vec2 sinangle;
 vec2 cosangle;

uniform vec4 OGL2Size;
vec2 rubyInputSize=vec2(320.0f, 240.0f);
vec2 rubyTextureSize=OGL2Size.xy;
vec2 rubyOutputSize=vec2(640.0f, 480.0f);


// vec2 gl_TexCoord;
 vec2 one;
 float mod_factor;
 vec2 ilfac;
// Comment the next line to disable interpolation in linear gamma (and gain speed).
//#define LINEAR_PROCESSING

// Enable screen curvature.
//#define CURVATURE

// Enable 3x oversampling of the beam profile
#define OVERSAMPLE

// Use the older, purely gaussian beam profile
#define USEGAUSSIAN

// Macros.
#define FIX(c) max(abs(c), 1e-5);
#define PI 3.141592653589

#ifdef LINEAR_PROCESSING
#       define TEX2D(c) pow(texture2D(OGL2Texture, (c)), vec4(CRTgamma))
#else
#       define TEX2D(c) texture2D(OGL2Texture, (c))
#endif

uniform int rubyFrameCount;

#define FIX(c) max(abs(c), 1e-5);

float intersect(vec2 xy)
{
  float A = dot(xy,xy)+d*d;
  float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
  float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
  return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
}

vec2 bkwtrans(vec2 xy)
{
  float c = intersect(xy);
  vec2 point = vec2(c)*xy;
  point -= vec2(-R)*sinangle;
  point /= vec2(R);
  vec2 tang = sinangle/cosangle;
  vec2 poc = point/cosangle;
  float A = dot(tang,tang)+1.0;
  float B = -2.0*dot(poc,tang);
  float C = dot(poc,poc)-1.0;
  float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
  vec2 uv = (point-a*sinangle)/cosangle;
  float r = R*acos(a);
  return uv*r/sin(r/R);
}

vec2 fwtrans(vec2 uv)
{
  float r = FIX(sqrt(dot(uv,uv)));
  uv *= sin(r/R)/r;
  float x = 1.0-cos(r/R);
  float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
  return d*(uv*cosangle-x*sinangle)/D;
}

vec3 maxscale()
{
  vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
  vec2 a = vec2(0.5,0.5)*aspect;
  vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
         fwtrans(vec2(c.x,-a.y)).y)/aspect;
  vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
         fwtrans(vec2(c.x,+a.y)).y)/aspect;
  return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
}



float corner(vec2 coord)
{
  coord *= rubyTextureSize / rubyInputSize;
  coord = (coord - vec2(0.5)) * overscan + vec2(0.5);
  coord = min(coord, vec2(1.0)-coord) * aspect;
  vec2 cdist = vec2(cornersize);
  coord = (cdist - min(coord,cdist));
  float dist = sqrt(dot(coord,coord));
  return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
}

// 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.
vec4 scanlineWeights(float distance, vec4 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
  vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
  vec4 weights = vec4(distance / wid);
  return 0.4 * exp(-weights * weights) / wid;
#else
  vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
  vec4 weights = vec4(distance / 0.3);
  return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
#endif
}

void main()
{

  // START of parameters

  // gamma of simulated CRT
  CRTgamma = 2.4;
  // gamma of display monitor (typically 2.2 is correct)
  monitorgamma = 2.2;
  // overscan (e.g. 1.02 for 2% overscan)
  overscan = vec2(1.00,1.00);
  // aspect ratio
  aspect = vec2(1.0, 0.75);
  // lengths are measured in units of (approximately) the width of the monitor
  // simulated distance from viewer to monitor
  d = 2.0;
  // radius of curvature
  R = 1.5;
  // tilt angle in radians
  // (behavior might be a bit wrong if both components are nonzero)
  const vec2 angle = vec2(0.0,-0.15);
  // size of curved corners
  cornersize = 0.001;
  // border smoothness parameter
  // decrease if borders are too aliased
  cornersmooth = 1000.0;

  // END of parameters

  // Do the standard vertex processing.
//  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

  // Precalculate a bunch of useful values we'll need in the fragment
  // shader.
  sinangle = sin(angle);
  cosangle = cos(angle);
  stretch = maxscale();

  // Texture coords.
  //gl_TexCoord = gl_MultiTexCoord0.xy;
  
  ilfac = vec2(1.0,floor(rubyInputSize.y/200.0));

  // The size of one texel, in texture-coordinates.
  one = ilfac / rubyTextureSize;

  // Resulting X pixel-coordinate of the pixel we're drawing.
  mod_factor = gl_TexCoord[0].x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x;            

  // 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.
#ifdef CURVATURE
  vec2 xy = transform(gl_TexCoord[0].xy);
#else
  vec2 xy = gl_TexCoord[0].xy;
#endif
  float cval = corner(xy);

  // Of all the pixels that are mapped onto the texel we are
  // currently rendering, which pixel are we currently rendering?
  vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(rubyFrameCount),2.0) : 0.0);
  vec2 ratio_scale = (xy * rubyTextureSize - vec2(0.5) + ilvec)/ilfac;
#ifdef OVERSAMPLE
  float filter = fwidth(ratio_scale.y);
#endif
  vec2 uv_ratio = fract(ratio_scale);

  // Snap to the center of the underlying texel.
  xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / rubyTextureSize;

  // Calculate Lanczos scaling coefficients describing the effect
  // of various neighbour texels in a scanline on the current
  // pixel.
  vec4 coeffs = PI * vec4(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, vec4(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.
  vec4 col  = clamp(mat4(
             TEX2D(xy + vec2(-one.x, 0.0)),
             TEX2D(xy),
             TEX2D(xy + vec2(one.x, 0.0)),
             TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
            0.0, 1.0);
  vec4 col2 = clamp(mat4(
             TEX2D(xy + vec2(-one.x, one.y)),
             TEX2D(xy + vec2(0.0, one.y)),
             TEX2D(xy + one),
             TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
            0.0, 1.0);

#ifndef LINEAR_PROCESSING
  col  = pow(col , vec4(CRTgamma));
  col2 = pow(col2, vec4(CRTgamma));
#endif

  // Calculate the influence of the current and next scanlines on
  // the current pixel.
  vec4 weights  = scanlineWeights(uv_ratio.y, col);
  vec4 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
  vec3 mul_res  = (col * weights + col2 * weights2).rgb * vec3(cval);

  // dot-mask emulation:
  // Output pixels are alternately tinted green and magenta.
  vec3 dotMaskWeights = mix(
          vec3(1.0, 0.7, 1.0),
          vec3(0.7, 1.0, 0.7),
          floor(mod(mod_factor, 2.0))
      );
                    
  mul_res *= dotMaskWeights;

  // Convert the image gamma for display on our output device.
  mul_res = pow(mul_res, vec3(1.0 / monitorgamma));

  // Color the texel.
  gl_FragColor = vec4(mul_res, 1.0);
}  


Thanks




gblues 



...

Status:Offline
Date registered: 26.12.2012
Post:1
Send Message
...   Created on 26.12.2012 - 07:17Jump to top Quote this post Report this post Edit Delete


I've successfully ported a CRT shader from BSNES!

Requirements:

1) Internal X Resolution and Internal Y Resolution settings must both be set to "0: Low - native PSX resolution"
2) Disable "Screen Filtering" and "Scanlines" settings.

gpuPeteOGL2.slv:

Code:
1:
2:
3:
4:
5:
 
void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
}


gpuPeteOGL2.slf:
Code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
 
/*
    cgwg's CRT shader

    Copyright (C) 2010 cgwg    

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the Free
    Software Foundation; either version 2 of the License, or (at your option)
    any later version.

    (cgwg gave their consent to have their code distributed under the GPL in
    this message:

        http://board.byuu.org/viewtopic.php?p=26075#p26075

        "Feel free to distribute my shaders under the GPL. After all, the
        barrel distortion code was taken from the Curvature shader, which is
        under the GPL."
    )
*/
uniform sampler2D OGL2Texture;
uniform vec4 OGL2Param, OGL2Size;

// Convert the uniforms output by Pete's OpenGL2 plugin to the uniforms expected by the BSNES shader
vec2 rubyInputSize = vec2(OGL2Size.x, OGL2Size.y);
vec2 rubyOutputSize = vec2(OGL2Size.z, OGL2Size.w);
vec2 rubyTextureSize = vec2(OGL2Size.x, OGL2Size.y);

// Abbreviations
//#define TEX2D(c) texture2D(OGL2Texture, (c))
#define TEX2D(c) pow(texture2D(OGL2Texture, (c)), vec4(inputGamma))
#define FIX(c)   max(abs(c), 1e-6);
#define PI 3.141592653589

// Adjusts the vertical position of scanlines. Useful if the output
// pixel size is large compared to the scanline width (so, scale
// factors less than 4x or so). Ranges from 0.0 to 1.0.
#define phase 0.0

// Assume NTSC 2.2 Gamma for linear blending
#define inputGamma 2.2

// Simulate a CRT gamma of 2.5
#define outputGamma 2.5

// Controls the intensity of the barrel distortion used to emulate the
// curvature of a CRT. 0.0 is perfectly flat, 1.0 is annoyingly
// distorted, higher values are increasingly ridiculous.
#define distortion 0.0

// Apply radial distortion to the given coordinate.
vec2 radialDistortion(vec2 coord) {
    coord *= rubyTextureSize / rubyInputSize;
    vec2 cc = coord - 0.5;
    float dist = dot(cc, cc) * distortion;
    return (coord + cc * (1.0 + dist) * dist) * rubyInputSize / rubyTextureSize;
}

// 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.
vec4 scanlineWeights(float distance, vec4 color)
{
    // The "width" of the scanline beam is set as 2*(1 + x^4) for
    // each RGB channel.
    vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));

    // 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.
    vec4 weights = vec4(distance * 3.333333);
    return 0.51 * exp(-pow(weights * sqrt(2.0 / wid), wid)) / (0.18 + 0.06 * wid);
}

void main()
{
    // 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.

    // The size of one texel, in texture-coordinates.
    vec2 one = 1.0 / rubyTextureSize;

    // Texture coordinates of the texel containing the active pixel
    vec2 xy = radialDistortion(gl_TexCoord[0].xy);

    // Of all the pixels that are mapped onto the texel we are
    // currently rendering, which pixel are we currently rendering?
    vec2 uv_ratio = fract(xy * rubyTextureSize) - vec2(0.5);

    // Snap to the center of the underlying texel.
    xy = (floor(xy * rubyTextureSize) + vec2(0.5)) / rubyTextureSize;

    // Calculate Lanczos scaling coefficients describing the effect
    // of various neighbour texels in a scanline on the current
    // pixel.
    vec4 coeffs = PI * vec4(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);
    coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);

    // Normalize
    coeffs /= dot(coeffs, vec4(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.
    vec4 col  = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, 0.0))   + coeffs.y * TEX2D(xy)    + coeffs.z * TEX2D(xy + vec2(one.x, 0.0)) + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, 0.0)),   0.0, 1.0);
    vec4 col2 = clamp(coeffs.x * TEX2D(xy + vec2(-one.x, one.y)) + coeffs.y * TEX2D(xy + vec2(0.0, one.y)) + coeffs.z * TEX2D(xy + one)      + coeffs.w * TEX2D(xy + vec2(2.0 * one.x, one.y)), 0.0, 1.0);

    // col  = pow(col, vec4(inputGamma));    
    // col2 = pow(col2, vec4(inputGamma));

    // Calculate the influence of the current and next scanlines on
    // the current pixel.
    vec4 weights  = scanlineWeights(abs(uv_ratio.y) , col);
    vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
    vec3 mul_res  = (col * weights + col2 * weights2).xyz;

    // mod_factor is the x-coordinate of the current output pixel.
    float mod_factor = gl_TexCoord[0].x * rubyOutputSize.x * rubyTextureSize.x / rubyInputSize.x;

    // dot-mask emulation:
    // Output pixels are alternately tinted green and magenta.
    vec3 dotMaskWeights = mix(
        vec3(1.05, 0.75, 1.05),
        vec3(0.75, 1.05, 0.75),
        floor(mod(mod_factor, 2.0))
        );

    mul_res *= dotMaskWeights;

    // Convert the image gamma for display on our output device.
    mul_res = pow(mul_res, vec3(1.0 / (2.0 * inputGamma - outputGamma)));

    gl_FragColor = vec4(mul_res, 1.0);
}


Comparison!

Without the shader:



With the shader:




More : [1] [2]

Similarly threads:
Topics Created by Replies Boardname
4-in-1 Shader v1.10 MegaManJuno 3 pete_bernert
Natural Vision Shader + AA Shader v2.o = Best Shader for 2d !! zaykho 16 pete_bernert
xbr shader pmc2 26 pete_bernert
another CRT-TV shader aliaspider -1 pete_bernert
HEAVEN IS REAL BUT SO IS HELL - Der Himmel ist real, die Hölle aber auch loveshalom 0 caeleste_desiderium
Neuer Thread ...





Masthead

This forum is a free service of razyboard.com
Do you want a free forum in less than two minutes? Then click here!



Verwandte Suchbegriffe:
epsxe crt shader | crt shader | espxe pixel shader crt | epsxe scanlines dor matrix | psx shader distort | crt filters for psx 1.13 | slv slf | epsxe crt
blank