|
1 | 1 | /// |
2 | 2 | /// variable-pixel-width outline shader |
3 | 3 | /// Based on juju adams' selective outline and improved with alpha fading and variable thickness |
| 4 | +/// even on HTML5 target |
4 | 5 | /// |
5 | 6 | /// (c)2022 Grisgram aka Haerion@GameMakerKitchen Discord |
6 | 7 | /// Please respect the MIT License for this Library. |
|
9 | 10 |
|
10 | 11 | const float ALPHA_THRESHOLD = 1.0/255.0; |
11 | 12 | const float BRIGHTNESS_THRESHOLD = 1.0; |
| 13 | +const float MAX_OUTLINE_STRENGTH = 10.0; |
12 | 14 |
|
13 | 15 | varying vec2 v_vTexcoord; |
14 | 16 | varying vec4 v_vColour; |
@@ -39,27 +41,46 @@ void main() |
39 | 41 | float alphaVal = 0.0; // set by both for loops below (decides alpha fading) |
40 | 42 | float edgeAlphaMax = 0.0; |
41 | 43 |
|
| 44 | + // The "continue" and "breaks" in the loops below are for HTML/WEBGL compatibility |
| 45 | + // A WebGL shader must be compiled with a constant range in "for" loops. |
| 46 | + // So I defined a max-width of 10 for the outline but skip all values |
| 47 | + // below and above the desired range. A minor performance loss and a great comfort gain |
| 48 | + |
42 | 49 | if (u_vThickness.y == 1.0) { // Alpha fading = true |
43 | 50 | float pxCount = u_vThickness.x * u_vThickness.x * 2.0; |
44 | | - float pxHit = 0.0; |
| 51 | + float pxHit = 0.0; |
45 | 52 | float curA = 0.0; |
46 | | - for(float dX = -u_vThickness.x; dX <= u_vThickness.x; dX += 1.0) |
| 53 | + for(float dX = -MAX_OUTLINE_STRENGTH; dX <= MAX_OUTLINE_STRENGTH; dX += 1.0) |
47 | 54 | { |
48 | | - for(float dY = -u_vThickness.x; dY <= u_vThickness.x; dY += 1.0) |
| 55 | + if (dX < -u_vThickness.x) continue; |
| 56 | + |
| 57 | + for(float dY = -MAX_OUTLINE_STRENGTH; dY <= MAX_OUTLINE_STRENGTH; dY += 1.0) |
49 | 58 | { |
| 59 | + if (dY < -u_vThickness.x) continue; |
| 60 | + |
50 | 61 | curA = texture2D(u_sSpriteSurface, v_vSurfaceUV + vec2(dX, dY)*u_vTexel).a; |
51 | 62 | if (curA >= ALPHA_THRESHOLD) pxHit++; |
52 | 63 | edgeAlphaMax = max(edgeAlphaMax, curA); |
| 64 | + |
| 65 | + if (dY > u_vThickness.x) break; |
53 | 66 | } |
| 67 | + |
| 68 | + if (dX > u_vThickness.x) break; |
54 | 69 | } |
55 | 70 | alphaVal = 0.25 + pxHit/pxCount; |
56 | 71 | } else { // no alpha fading |
57 | | - for(float dX = -u_vThickness.x; dX <= u_vThickness.x; dX += 1.0) |
| 72 | + for(float dX = -MAX_OUTLINE_STRENGTH; dX <= MAX_OUTLINE_STRENGTH; dX += 1.0) |
58 | 73 | { |
59 | | - for(float dY = -u_vThickness.x; dY <= u_vThickness.x; dY += 1.0) |
| 74 | + if (dX < -u_vThickness.x) continue; |
| 75 | + |
| 76 | + for(float dY = -MAX_OUTLINE_STRENGTH; dY <= MAX_OUTLINE_STRENGTH; dY += 1.0) |
60 | 77 | { |
| 78 | + if (dY < -u_vThickness.x) continue; |
61 | 79 | edgeAlphaMax = max(edgeAlphaMax, texture2D(u_sSpriteSurface, v_vSurfaceUV + vec2(dX, dY)*u_vTexel).a); |
| 80 | + if (dY > u_vThickness.x) break; |
62 | 81 | } |
| 82 | + |
| 83 | + if (dX > u_vThickness.x) break; |
63 | 84 | } |
64 | 85 | alphaVal = edgeAlphaMax; |
65 | 86 | } |
|
0 commit comments