2021-10-20 21:44:06 +00:00
|
|
|
/// Shader used for drawing bitmap fills.
|
|
|
|
|
2023-01-06 22:17:42 +00:00
|
|
|
#import common
|
|
|
|
|
2021-10-20 21:44:06 +00:00
|
|
|
struct VertexOutput {
|
2022-07-02 12:18:30 +00:00
|
|
|
@builtin(position) position: vec4<f32>,
|
|
|
|
@location(0) uv: vec2<f32>,
|
2021-10-20 21:44:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-06 22:17:42 +00:00
|
|
|
#if use_push_constants == true
|
2023-01-07 09:19:14 +00:00
|
|
|
var<push_constant> pc: common::PushConstants;
|
|
|
|
@group(1) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
|
|
|
|
@group(1) @binding(1) var texture: texture_2d<f32>;
|
|
|
|
@group(1) @binding(2) var texture_sampler: sampler;
|
2023-01-06 22:17:42 +00:00
|
|
|
#else
|
|
|
|
@group(1) @binding(0) var<uniform> transforms: common::Transforms;
|
2023-01-07 09:19:14 +00:00
|
|
|
@group(2) @binding(0) var<uniform> colorTransforms: common::ColorTransforms;
|
|
|
|
@group(3) @binding(0) var<uniform> textureTransforms: common::TextureTransforms;
|
|
|
|
@group(3) @binding(1) var texture: texture_2d<f32>;
|
|
|
|
@group(3) @binding(2) var texture_sampler: sampler;
|
2023-01-06 22:17:42 +00:00
|
|
|
#endif
|
|
|
|
|
2022-07-02 12:18:30 +00:00
|
|
|
@vertex
|
2023-01-06 22:17:42 +00:00
|
|
|
fn main_vertex(in: common::VertexInput) -> VertexOutput {
|
2023-01-07 09:19:14 +00:00
|
|
|
#if use_push_constants == true
|
|
|
|
var transforms = pc.transforms;
|
|
|
|
#endif
|
2023-01-19 03:17:54 +00:00
|
|
|
let matrix_ = textureTransforms.texture_matrix;
|
2022-07-02 12:18:30 +00:00
|
|
|
let uv = (mat3x3<f32>(matrix_[0].xyz, matrix_[1].xyz, matrix_[2].xyz) * vec3<f32>(in.position, 1.0)).xy;
|
2023-01-06 22:17:42 +00:00
|
|
|
let pos = common::globals.view_matrix * transforms.world_matrix * vec4<f32>(in.position.x, in.position.y, 0.0, 1.0);
|
2021-10-20 21:44:06 +00:00
|
|
|
return VertexOutput(pos, uv);
|
|
|
|
}
|
|
|
|
|
2022-07-02 12:18:30 +00:00
|
|
|
@fragment
|
|
|
|
fn main_fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
2021-10-26 04:36:19 +00:00
|
|
|
var color: vec4<f32> = textureSample(texture, texture_sampler, in.uv);
|
2023-01-07 09:19:14 +00:00
|
|
|
#if use_push_constants == true
|
|
|
|
var colorTransforms = pc.colorTransforms;
|
|
|
|
#endif
|
2021-10-20 21:44:06 +00:00
|
|
|
// Texture is premultiplied by alpha.
|
|
|
|
// Unmultiply alpha, apply color transform, remultiply alpha.
|
|
|
|
if( color.a > 0.0 ) {
|
|
|
|
color = vec4<f32>(color.rgb / color.a, color.a);
|
2023-03-12 23:43:58 +00:00
|
|
|
color = color * colorTransforms.mult_color + colorTransforms.add_color;
|
render: Compile a different version of 'bitmap.wgsl' for Stage3D
When using the bitmap.wgsl shader for normal rendering, we need
to saturate immediately after applying the color transformation
to reproduce Flash Player's behavior. This makes the (possibly
transformed) alpha value get multiplied by a in-range color,
instead of a potentially out-of-range color.
However, Stage3D just applies a no-op color transformation,
and should only saturate at the very end
(not after the intermediate division by the original alpha value).
To support both of these requirements, I've added in a new
`early_saturate` ifdef that controls when we apply 'saturate'.
We then compile the shader twice (once with early_saturate=true
and once with early_saturate=false), and use the two versions
in the right pipelines.
We could use a simpler shader for Stage3D - however, it can't just
be a plain copy, as we need to apply the viewport transformation.
For now, I'm re-using the shader code to keep things simple. If
this becomes a performance issue in stage3d, we could revisit this.
2023-03-17 14:44:54 +00:00
|
|
|
#if early_saturate == true
|
|
|
|
color = saturate(color);
|
|
|
|
#endif
|
|
|
|
color = vec4<f32>(color.rgb * color.a, color.a);
|
|
|
|
#if early_saturate == false
|
|
|
|
color = saturate(color);
|
|
|
|
#endif
|
2021-10-20 21:44:06 +00:00
|
|
|
}
|
2022-04-14 18:03:45 +00:00
|
|
|
return color;
|
2021-10-20 21:44:06 +00:00
|
|
|
}
|