| /* | |
| * Copyright 2025 Rive | |
| */ | |
| // This shader provides a mechanism for resolving various atlas types into GL_R8 | |
| // so they can be sampled linearly. | |
| // | |
| // Additionally, EXT_shader_pixel_local_storage extension does not have a | |
| // "clear" function, so this shader also provides a clear mechanism for PLS. | |
| #ifdef @VERTEX | |
| VERTEX_MAIN(@atlasResolveVertexMain, Attrs, attrs, _vertexID, _instanceID) | |
| { | |
| // Draw a right triangle that covers the entire screen. | |
| float4 pos; | |
| pos.x = (_vertexID != 2) ? -1. : 3.; | |
| pos.y = (_vertexID != 1) ? -1. : 3.; | |
| pos.zw = float2(.0, 1.); | |
| EMIT_VERTEX(pos); | |
| } | |
| #endif | |
| #ifdef @FRAGMENT | |
| INLINE ivec2 atlas_frag_coord() { return ivec2(floor(gl_FragCoord)); } | |
| #ifdef @ATLAS_RENDER_TARGET_R32UI_FRAMEBUFFER_FETCH | |
| layout(location = 0) inout uint4 coverageCount; | |
| layout(location = 1) out half4 resolvedCoverage; | |
| void main() { resolvedCoverage.r = uintBitsToFloat(coverageCount.r); } | |
| #elif defined(@ATLAS_RENDER_TARGET_R8_PLS_EXT) | |
| #ifdef @CLEAR_COVERAGE | |
| __pixel_local_outEXT PLS { layout(r32f) float coverageCount; }; | |
| #else | |
| __pixel_local_inEXT PLS { layout(r32f) float coverageCount; }; | |
| layout(location = 0) out half4 resolvedCoverage; | |
| #endif | |
| void main() | |
| { | |
| #ifdef @CLEAR_COVERAGE | |
| coverageCount = .0; | |
| #else | |
| resolvedCoverage.r = coverageCount; | |
| #endif | |
| } | |
| #elif defined(@ATLAS_RENDER_TARGET_R32UI_PLS_ANGLE) | |
| layout(binding = 0, r32ui) uniform highp upixelLocalANGLE coverageCount; | |
| layout(location = 0) out half4 resolvedCoverage; | |
| void main() | |
| { | |
| resolvedCoverage.r = uintBitsToFloat(pixelLocalLoadANGLE(coverageCount).r); | |
| } | |
| #elif defined(@ATLAS_RENDER_TARGET_R32I_ATOMIC_TEXTURE) | |
| layout(binding = 0, r32i) uniform highp coherent iimage2D _atlasImage; | |
| layout(location = 0) out half4 resolvedCoverage; | |
| void main() | |
| { | |
| resolvedCoverage.r = float(imageLoad(_atlasImage, atlas_frag_coord()).r) * | |
| (1. / ATLAS_R32I_FIXED_POINT_FACTOR); | |
| } | |
| #elif defined(@ATLAS_RENDER_TARGET_RGBA8_UNORM) | |
| TEXTURE_RGBA8(PER_FLUSH_BINDINGS_SET, 0, @atlasRenderTexture); | |
| layout(location = 0) out half4 resolvedCoverage; | |
| void main() | |
| { | |
| // Apply the following weights to the RGBA of each u8x4 coverage value: | |
| // - R counts fractional, positive coverage. | |
| // - G counts fractional, negative coverage. | |
| // - B counts integer, positive coverage. | |
| // - A counts integer, negative coverage. | |
| half4 coverages = TEXEL_FETCH(@atlasRenderTexture, atlas_frag_coord()); | |
| resolvedCoverage.r = | |
| (coverages.r - coverages.g) * ATLAS_UNORM8_COVERAGE_SCALE_FACTOR + | |
| (coverages.b - coverages.a) * 255.; | |
| } | |
| #endif | |
| #endif // FRAGMENT |