| Author | Topics » Book an abo for this thread |  |
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 11.05.2007 - 05:15 |  |
...the code wasn't neat enough. 
But general input color reductions...might look nice in a cell shader, otherwise it makes the code only slower since dot products are used in reducing the colors also.
|
|
|
VerGreeneyes Strong supporter
 

Status:Offline Date registered: 26.04.2007 Post:89 Send Message | Created on 11.05.2007 - 12:25 |  |
Hmm, well the dot product doesn't actually reduce the amount of colours, it simply mixes the fraction part of one colour with the integer part of another (unless colours are rounded). I still don't know whether what I did would make any difference though.
|
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 11.05.2007 - 16:32 |  |
Yeah it reduces only the register space used...(and speeds up bool operations).
If some key differences are calculated and the GET_RESULT func. altered then like 12 dot ops. become obsolete OTOH.
PS: But seriously if you want to make a nice cell shader then reducing every input color is the best idea so far. 
|
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 13.05.2007 - 16:59 |  |
I took the liberty to generalize things a bit...
Looks very nice with 1:1 internal res's and the linear filter ON.
| 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: | | | |
| /*
| 2xSaI GLSL shader
|
| - Copyright (C) 2007 guest(r) - guest.r@gmail.com
|
| - License: GNU-GPL
|
| - Enhanced by Ver Greeneyes (10.5.2007)
|
| The 2xSaI algorithm
|
| - Copyright (c) 1999-2001 by Derek Liauw Kie Fa.
| */
|
| const vec4 dt = vec4(65536.,256.,1.,.00390625);
| uniform vec4 OGL2Size, OGL2InvSize;
| uniform sampler2D OGL2Texture;
|
| const float c = 8.0;
|
|
| #define reduce(color)(dot(color,dt))
|
| float GET_RESULT(float A,float B,float C,float D)
| {
| return float(A != C && A != D && B == C && B == D)-float(A == C && A == D);
| }
|
| void main()
| {
|
| // Calculating texel coordinates
|
| vec2 OGL2Pos = gl_TexCoord[0].xy*OGL2Size.xy,
| fp = fract(OGL2Pos),
| g1 = vec2( OGL2InvSize.x,OGL2InvSize.y),
| g2 = vec2(-OGL2InvSize.x,OGL2InvSize.y);
|
| if(fp.x >= .5 && fp.y < .5) g2=-g2;
|
| vec2 pC4 = floor(OGL2Pos)/OGL2Size.xy,
| g3 = .5*(g1-g2), pC8 = pC4+g1, g4 = g2+g3;
|
|
| // Reading the texels
|
| vec4 C0 = floor(c*texture2D(OGL2Texture,pC4-g1 )+.5),
| C1 = floor(c*texture2D(OGL2Texture,pC4-g4 )+.5),
| C2 = floor(c*texture2D(OGL2Texture,pC4-g2 )+.5),
| C3 = floor(c*texture2D(OGL2Texture,pC4-g3 )+.5),
| C4 = floor(c*texture2D(OGL2Texture,pC4 )+.5),
| C5 = floor(c*texture2D(OGL2Texture,pC4+g3 )+.5),
| C6 = floor(c*texture2D(OGL2Texture,pC4+g2 )+.5),
| C7 = floor(c*texture2D(OGL2Texture,pC8-g3 )+.5),
| C8 = floor(c*texture2D(OGL2Texture,pC8 )+.5),
| D0 = floor(c*texture2D(OGL2Texture,pC4+g2+g4)+.5),
| D1 = floor(c*texture2D(OGL2Texture,pC8+g2 )+.5),
| D2 = floor(c*texture2D(OGL2Texture,pC8+g1-g3)+.5),
| D4 = floor(c*texture2D(OGL2Texture,pC8-g2 )+.5),
| D5 = floor(c*texture2D(OGL2Texture,pC8+g3 )+.5),
| p10,p11;
|
| float c0 = reduce(C0),c1 = reduce(C1),c2 = reduce(C2),c3 = reduce(C3),
| c4 = reduce(C4),c5 = reduce(C5),c6 = reduce(C6),c7 = reduce(C7),
| c8 = reduce(C8),d0 = reduce(D0),d1 = reduce(D1),d2 = reduce(D2),
| d4 = reduce(D4),d5 = reduce(D5);
|
|
| /* SaI code */
| /* Copied from the Dosbox source code */
| /* Copyright (C) 2002-2007 The DOSBox Team */
| /* License: GNU-GPL */
| /* Adapted by guest(r) on 20.4 and 9.5. 2007 */
| /* and Ver Greeneyes (10.5.2007) */
|
| if(c4 == c8)
| {
| if(c5 != c7)
| {
| p10 = (c4 == c3 && c7 == d2 || c4 == c5 && c4 == c6 && c3 != c7 && c7 == d0) ? C4 : .5*(C4+C7);
| p11 = C4;
| }
| else
| {
| if(c4 == c5) p11 = (p10 = C4);
| else
| {
| float r = GET_RESULT(c4,c5,c3,c1)+GET_RESULT(c4,c5,d5,d2)
| -GET_RESULT(c5,c4,d4,c2)-GET_RESULT(c5,c4,c6,d1);
| p10 = .5*(C4+C7);
| if(r > 0.) p11 = C4;
| else if(r < 0.) p11 = C5;
| else p11 = .25*(C4+C5+C7+C8);
| }
| }
| }
| else if(c5 == c7)
| {
| p10 = (c7 == c6 && c4 == c2 || c7 == c3 && c7 == c8 && c4 != c6 && c4 == c0) ? C7 : 0.5*(C4+C7);
| p11 = C5;
| }
| else
| {
| p11 = 0.25*(C4+C5+C7+C8);
| if(c4 == c5 && c4 == c6 && c3 != c7 && c7 == d0) p10 = C4;
| else if(c7 == c3 && c7 == c8 && c4 != c6 && c4 == c0) p10 = C7;
| else p10 = 0.5*(C4+C7);
| }
|
| // Distributing the final products
|
| if(fp.x >= .5 && fp.y >= .5) gl_FragColor = p11/c;
| else if(fp.x >= .5 || fp.y >= .5) gl_FragColor = p10/c;
| else gl_FragColor = C4/c;
| }
| | |
|
VerGreeneyes Strong supporter
 

Status:Offline Date registered: 26.04.2007 Post:89 Send Message | Created on 13.05.2007 - 17:20 |  |
Limiting it to 512 (8³) colours + 8 levels of transparancy seems a bit excessive :D I'm considering a version that limits it to RGB565 as per the SNES, might look good for direct conversions like the Final Fantasy ports. It would be a bit slow though, and I don't know if any rounding is needed in these games (as I doubt the playstation does anything fancy 3D-wise in them)
|
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 13.05.2007 - 21:03 |  |
There is much more in it 
1. You got a 4x scale effect on sprites.
2. You got a nicely improoved hi-res 3D part.
3. The color differences are integer-measurable (a good feat. to add nice dark outlines).
4. The reduced linear surface san serve as a cell-template to build an arbitrary scaler.
5. Same can be used with simpler/faster scalers and even better: a color reduced linear enlarged surface is already scaled. 
|
VerGreeneyes Strong supporter
 

Status:Offline Date registered: 26.04.2007 Post:89 Send Message | Created on 13.05.2007 - 23:18 |  |
Alright then, that does sound good. By the way, I'm currently working on combining my weighed average filter with the 2xSaI filter.. got nothing working yet, but it should look great when it works 
|
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 14.05.2007 - 11:11 |  |
I'm looking forward to see it.
Perhaps u can add a nice dot-matrix effect (RGB scaler style).
|
VerGreeneyes Strong supporter
 

Status:Offline Date registered: 26.04.2007 Post:89 Send Message | Created on 14.05.2007 - 11:17 |  |
I'm still having trouble getting it to work. If you're interested, here's what I have so far: | 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: | | | | uniform vec4 OGL2Size, OGL2InvSize;
| uniform sampler2D OGL2Texture;
| const float pi = 1.570796326794896619231321691640;
| vec2 dx = vec2(OGL2InvSize.x,0.),
| dy = vec2(0.,OGL2InvSize.y);
| const vec4 vec1 = vec4(1.),
| dt = vec4(16777216.,65536.,256.,1.);
|
| float reduce(vec4);
| float GET_RESULT(float, float, float, float);
| vec4 xSaI(vec2, vec2);
|
| void main(){
| vec2 OGL2Pos = gl_TexCoord[0].xy*OGL2Size.xy,
| fp = fract(OGL2Pos),
| pC4 = floor(OGL2Pos)/OGL2Size.xy,
| s0 = vec2(float(fp.x< .5),float(fp.y< .5)),
| s1 = vec2(float(fp.x< .5),float(fp.y>=.5)),
| s2 = vec2(float(fp.x>=.5),float(fp.y< .5)),
| s3 = vec2(float(fp.x>=.5),float(fp.y>=.5));
| if(fp.x >= .5){fp.x = 1. - fp.x; dx = -dx;}
| if(fp.y >= .5){fp.y = 1. - fp.y; dy = -dy;}
| fp *= 2.;
| if(fp.x >= .5){fp.x -= .5; dx = vec2(0.);}
| if(fp.y >= .5){fp.y -= .5; dy = vec2(0.);}
| mat4 C = mat4(xSaI(s0,pC4-dx-dy),
| xSaI(s1,pC4-dx ),
| xSaI(s2,pC4 -dy),
| xSaI(s3,pC4 ));
| mat2 gp = mat2((fp+.5)*(fp+.5),
| (fp-.5)*(fp-.5));
| vec4 c = vec4(gp[0][0]+gp[0][1],
| gp[0][0]+gp[1][1],
| gp[1][0]+gp[0][1],
| gp[1][0]+gp[1][1] ;
| c = vec1-sqrt(c);
| c *= vec4(greaterThan(c,vec4(0.)));
| c = -cos(pi*(c+vec1));
| gl_FragColor = (C[0]*c.x+C[1]*c.y+C[2]*c.z+C[3]*c.w)/(c.x+c.y+c.z+c.w);
| }
|
| float reduce(vec4 colour){
| return dot(colour,dt);
| }
|
| float GET_RESULT(float A, float B, float C, float D){
| return float(A != C && A != D && B == C && B == D) - float(A == C && A == D);
| }
|
| vec4 xSaI(vec2 fp, vec2 pC4){
| vec4 rValue;
| vec2 g1 = vec2( OGL2InvSize.x,OGL2InvSize.y),
| g2 = vec2(-OGL2InvSize.x,OGL2InvSize.y);
| if(fp.x == 1. && fp.y == 0.) g2=-g2;
| vec2 g3 = .5*(g1-g2), pC8 = pC4+g1, g4 = g2+g3;
| vec4 C0 = texture2D(OGL2Texture,pC4-g1 ),
| C1 = texture2D(OGL2Texture,pC4-g4 ),
| C2 = texture2D(OGL2Texture,pC4-g2 ),
| C3 = texture2D(OGL2Texture,pC4-g3 ),
| C4 = texture2D(OGL2Texture,pC4 ),
| C5 = texture2D(OGL2Texture,pC4+g3 ),
| C6 = texture2D(OGL2Texture,pC4+g2 ),
| C7 = texture2D(OGL2Texture,pC8-g3 ),
| C8 = texture2D(OGL2Texture,pC8 ),
| D0 = texture2D(OGL2Texture,pC4+g2+g4),
| D1 = texture2D(OGL2Texture,pC8+g2 ),
| D2 = texture2D(OGL2Texture,pC8+g1-g3),
| D4 = texture2D(OGL2Texture,pC8-g2 ),
| D5 = texture2D(OGL2Texture,pC8+g3 ),
| p10,p11;
| float c0 = reduce(C0),c1 = reduce(C1),c2 = reduce(C2),c3 = reduce(C3),
| c4 = reduce(C4),c5 = reduce(C5),c6 = reduce(C6),c7 = reduce(C7),
| c8 = reduce(C8),d0 = reduce(D0),d1 = reduce(D1),d2 = reduce(D2),
| d4 = reduce(D4),d5 = reduce(D5);
| if(c4 == c8){
| if(c5 != c7){
| p10 = (c4 == c3 && c7 == d2 || c4 == c5 && c4 == c6 && c3 != c7 && c7 == d0) ? C4 : .5*(C4+C7);
| p11 = C4;
| }else{
| if(c4 == c5) p11 = (p10 = C4);
| else{
| float r = GET_RESULT(c4,c5,c3,c1)+GET_RESULT(c4,c5,d5,d2)
| -GET_RESULT(c5,c4,d4,c2)-GET_RESULT(c5,c4,c6,d1);
| p10 = .5*(C4+C7);
| if(r > 0.) p11 = C4;
| else if(r < 0.) p11 = C5;
| else p11 = .25*(C4+C5+C7+C8);
| }
| }
| }else if(c5 == c7){
| p10 = (c7 == c6 && c4 == c2 || c7 == c3 && c7 == c8 && c4 != c6 && c4 == c0) ? C7 : 0.5*(C4+C7);
| p11 = C5;
| }else{
| p11 = 0.25*(C4+C5+C7+C8);
| if(c4 == c5 && c4 == c6 && c3 != c7 && c7 == d0) p10 = C4;
| else if(c7 == c3 && c7 == c8 && c4 != c6 && c4 == c0) p10 = C7;
| else p10 = 0.5*(C4+C7);
| }
| if(fp.x == 1. && fp.y == 1.) rValue = p11;
| else if(fp.x == 1. || fp.y == 1.) rValue = p10;
| else rValue = C4;
| return rValue;
| | } | |
Vertex file remains unchanged.
Edit: updated to the latest version. I wonder what's causing those lines.. a rounding error?
[Dieser Beitrag wurde am 14.05.2007 - 14:33 von VerGreeneyes aktualisiert]
|
guest  Real addict
  

Status:Offline Date registered: 30.07.2004 Post:856 Send Message | Created on 14.05.2007 - 16:05 |  |
It's too much for my card.
I think that too many texture lookups are made since a general app. error msg. is all i get.
|