|
4 | 4 |
|
5 | 5 | uniform float u_opacity; |
6 | 6 |
|
| 7 | +#ifdef DITHERED_DISCARD |
| 8 | +uniform float u_dithered_discard_threshold; |
| 9 | +#endif |
| 10 | + |
7 | 11 | uniform vec3 u_lightcolor; |
8 | 12 | uniform vec3 u_lightpos; |
9 | 13 | uniform float u_lightintensity; |
@@ -546,6 +550,27 @@ vec4 finalColor; |
546 | 550 | finalColor = vec4(color, opacity); |
547 | 551 | #endif // !DIFFUSE_SHADED |
548 | 552 |
|
| 553 | +#ifdef DITHERED_DISCARD |
| 554 | + // fade in/out using discard and 4x4 Bayer matrix for dithering |
| 555 | + // creates a smooth transition without alpha blending |
| 556 | + // if u_dithered_discard_threshold == 1 or -1, the model gets fully rendered, at 0 it is fully discarded |
| 557 | + // values between 0 and +1/-1 get partically discarded, using the ditherValue or the negated dither value as the threshold |
| 558 | + // this allows to cross-fade between two models |
| 559 | + if (abs(u_dithered_discard_threshold) < 1.0) { |
| 560 | + |
| 561 | + // Get dither value for pixel at coordinate using "Interleaved gradient noise" |
| 562 | + float ditherValue = fract(52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); |
| 563 | + |
| 564 | + // Fade in: discard if threshold < ditherValue |
| 565 | + // Fade out: discard if -threshold < 1.0 - ditherValue |
| 566 | + // Use mix to select values without branching |
| 567 | + float compareValue = mix(1.0 - ditherValue, ditherValue, step(0.0, u_dithered_discard_threshold)); |
| 568 | + if (abs(u_dithered_discard_threshold) < compareValue) { |
| 569 | + discard; |
| 570 | + } |
| 571 | + } |
| 572 | +#endif |
| 573 | + |
549 | 574 | #ifdef FOG |
550 | 575 | finalColor = fog_dither(fog_apply_premultiplied(finalColor, v_fog_pos, v_position_height.w)); |
551 | 576 | #endif |
|
0 commit comments