|
| 1 | +uniform sampler2D EdgesTex; |
| 2 | +uniform sampler2D AreaTex; |
| 3 | +uniform sampler2D SearchTex; |
| 4 | +uniform vec2 invTexSize; |
| 5 | + |
| 6 | +const float kMaxSearchSteps = 8.0; |
| 7 | +const float kAreaMaxDistance = 16.0; |
| 8 | +const vec2 kAreaTexPixelSize = vec2( 1.0 / 160.0, 1.0 / 560.0 ); |
| 9 | +const float kAreaTexSubtexSize = 1.0 / 7.0; |
| 10 | +const vec2 kSearchTexSize = vec2( 66.0, 33.0 ); |
| 11 | +const vec2 kSearchTexPackedSize = vec2( 64.0, 16.0 ); |
| 12 | + |
| 13 | +vec2 RoundVec2( vec2 value ) { |
| 14 | + return floor( value + vec2( 0.5, 0.5 ) ); |
| 15 | +} |
| 16 | + |
| 17 | +float SampleSearchLength( vec2 e, float offsetValue ) { |
| 18 | + vec2 scale = kSearchTexSize * vec2( 0.5, -1.0 ); |
| 19 | + vec2 bias = kSearchTexSize * vec2( offsetValue, 1.0 ); |
| 20 | + |
| 21 | + scale += vec2( -1.0, 1.0 ); |
| 22 | + bias += vec2( 0.5, -0.5 ); |
| 23 | + |
| 24 | + scale /= kSearchTexPackedSize; |
| 25 | + bias /= kSearchTexPackedSize; |
| 26 | + |
| 27 | + return texture2D( SearchTex, scale * e + bias ).r; |
| 28 | +} |
| 29 | + |
| 30 | +float SearchXLeft( vec2 texcoord, float endValue ) { |
| 31 | + vec2 e = vec2( 0.0, 1.0 ); |
| 32 | + while ( texcoord.x > endValue && e.g > 0.8281 && e.r == 0.0 ) { |
| 33 | + e = texture2D( EdgesTex, texcoord ).rg; |
| 34 | + texcoord -= vec2( 2.0 * invTexSize.x, 0.0 ); |
| 35 | + } |
| 36 | + |
| 37 | + float offsetValue = -( 255.0 / 127.0 ) * SampleSearchLength( e, 0.0 ) + 3.25; |
| 38 | + return invTexSize.x * offsetValue + texcoord.x; |
| 39 | +} |
| 40 | + |
| 41 | +float SearchXRight( vec2 texcoord, float endValue ) { |
| 42 | + vec2 e = vec2( 0.0, 1.0 ); |
| 43 | + while ( texcoord.x < endValue && e.g > 0.8281 && e.r == 0.0 ) { |
| 44 | + e = texture2D( EdgesTex, texcoord ).rg; |
| 45 | + texcoord += vec2( 2.0 * invTexSize.x, 0.0 ); |
| 46 | + } |
| 47 | + |
| 48 | + float offsetValue = -( 255.0 / 127.0 ) * SampleSearchLength( e, 0.5 ) + 3.25; |
| 49 | + return -invTexSize.x * offsetValue + texcoord.x; |
| 50 | +} |
| 51 | + |
| 52 | +float SearchYUp( vec2 texcoord, float endValue ) { |
| 53 | + vec2 e = vec2( 1.0, 0.0 ); |
| 54 | + while ( texcoord.y > endValue && e.r > 0.8281 && e.g == 0.0 ) { |
| 55 | + e = texture2D( EdgesTex, texcoord ).rg; |
| 56 | + texcoord -= vec2( 0.0, 2.0 * invTexSize.y ); |
| 57 | + } |
| 58 | + |
| 59 | + float offsetValue = -( 255.0 / 127.0 ) * SampleSearchLength( e.gr, 0.0 ) + 3.25; |
| 60 | + return invTexSize.y * offsetValue + texcoord.y; |
| 61 | +} |
| 62 | + |
| 63 | +float SearchYDown( vec2 texcoord, float endValue ) { |
| 64 | + vec2 e = vec2( 1.0, 0.0 ); |
| 65 | + while ( texcoord.y < endValue && e.r > 0.8281 && e.g == 0.0 ) { |
| 66 | + e = texture2D( EdgesTex, texcoord ).rg; |
| 67 | + texcoord += vec2( 0.0, 2.0 * invTexSize.y ); |
| 68 | + } |
| 69 | + |
| 70 | + float offsetValue = -( 255.0 / 127.0 ) * SampleSearchLength( e.gr, 0.5 ) + 3.25; |
| 71 | + return -invTexSize.y * offsetValue + texcoord.y; |
| 72 | +} |
| 73 | + |
| 74 | +vec2 SampleArea( vec2 dist, float e1, float e2, float offsetValue ) { |
| 75 | + vec2 texcoord = vec2( kAreaMaxDistance, kAreaMaxDistance ) * RoundVec2( 4.0 * vec2( e1, e2 ) ) + dist; |
| 76 | + texcoord = kAreaTexPixelSize * texcoord + 0.5 * kAreaTexPixelSize; |
| 77 | + texcoord.y = kAreaTexSubtexSize * offsetValue + texcoord.y; |
| 78 | + return texture2D( AreaTex, texcoord ).rg; |
| 79 | +} |
| 80 | + |
| 81 | +void main() { |
| 82 | + vec2 texcoord = gl_TexCoord[0].st; |
| 83 | + vec2 rtSize = 1.0 / max( invTexSize, vec2( 0.000001, 0.000001 ) ); |
| 84 | + vec2 pixcoord = texcoord * rtSize; |
| 85 | + |
| 86 | + vec4 offset0 = invTexSize.xyxy * vec4( -0.25, -0.125, 1.25, -0.125 ) + texcoord.xyxy; |
| 87 | + vec4 offset1 = invTexSize.xyxy * vec4( -0.125, -0.25, -0.125, 1.25 ) + texcoord.xyxy; |
| 88 | + vec4 offset2 = vec4( invTexSize.x, invTexSize.x, invTexSize.y, invTexSize.y ) * |
| 89 | + ( vec4( -2.0, 2.0, -2.0, 2.0 ) * kMaxSearchSteps ) + |
| 90 | + vec4( offset0.x, offset0.z, offset1.y, offset1.w ); |
| 91 | + |
| 92 | + vec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 ); |
| 93 | + vec2 e = texture2D( EdgesTex, texcoord ).rg; |
| 94 | + |
| 95 | + if ( e.g > 0.0 ) { |
| 96 | + vec3 coords; |
| 97 | + coords.x = SearchXLeft( offset0.xy, offset2.x ); |
| 98 | + coords.y = offset1.y; |
| 99 | + float leftEdge = texture2D( EdgesTex, coords.xy ).r; |
| 100 | + |
| 101 | + coords.z = SearchXRight( offset0.zw, offset2.y ); |
| 102 | + vec2 d = abs( RoundVec2( rtSize.xx * vec2( coords.x, coords.z ) - pixcoord.xx ) ); |
| 103 | + vec2 sqrtD = sqrt( d ); |
| 104 | + float rightEdge = texture2D( EdgesTex, coords.zy + vec2( invTexSize.x, 0.0 ) ).r; |
| 105 | + |
| 106 | + weights.rg = SampleArea( sqrtD, leftEdge, rightEdge, 0.0 ); |
| 107 | + } |
| 108 | + |
| 109 | + if ( e.r > 0.0 ) { |
| 110 | + vec3 coords; |
| 111 | + coords.y = SearchYUp( offset1.xy, offset2.z ); |
| 112 | + coords.x = offset0.x; |
| 113 | + float topEdge = texture2D( EdgesTex, coords.xy ).g; |
| 114 | + |
| 115 | + coords.z = SearchYDown( offset1.zw, offset2.w ); |
| 116 | + vec2 d = abs( RoundVec2( rtSize.yy * vec2( coords.y, coords.z ) - pixcoord.yy ) ); |
| 117 | + vec2 sqrtD = sqrt( d ); |
| 118 | + float bottomEdge = texture2D( EdgesTex, coords.xz + vec2( 0.0, invTexSize.y ) ).g; |
| 119 | + |
| 120 | + weights.ba = SampleArea( sqrtD, topEdge, bottomEdge, 0.0 ); |
| 121 | + } |
| 122 | + |
| 123 | + gl_FragColor = weights; |
| 124 | +} |
0 commit comments