veloren/assets/voxygen/shaders/premultiply-alpha-vert.glsl
Imbris 63096b2042 Complete GPU based alpha premultiplication impl and make the CPU version
even faster.

* GPU based version started in previous commit, but this fixes errors
  and bugs and gets it actually compiling and running.
* Add a way to batch together images to use the same render pass for GPU
  premultiplication if they all target the same texture.
* Pending premultiplication uploads are automatically done when calling
  `Drawer::third_pass`.
* `fast-srgb8` dep removed, we no longer convert to `f32`s to do the
  premultiplication. Two `[u16; 256]` tables are combined to compute the
  alpa premultiplied color within the same error bounds used by the
  `fast-srgb8` crate. We also no longer use explicit simd.
* Remove explicit lifetimes from `PlayState::render` since `&self` and
  `Drawer<'_>` don't need to have the same lifetime.
* Fix existing bug where invalidated cache entries were never set to
  valid when reusing them.
* `prepare_graphic` now runs some heuristics to determine whether
  premultiplication should be executed CPU side or GPU side and then
  returns a bool indicating if GPU premultiplication is needed.
2023-04-08 00:28:31 -04:00

49 lines
1.3 KiB
GLSL

#version 420 core
layout(push_constant) uniform Params {
// Size of the source image.
uint source_size_xy;
// Offset to place the image at in the target texture.
//
// Origin is the top-left.
uint target_offset_xy;
// Size of the target texture.
uint target_size_xy;
};
layout(location = 0) out vec2 source_coords;
uvec2 unpack(uint xy) {
return uvec2(
bitfieldExtract(xy, 0, 16),
bitfieldExtract(xy, 16, 16)
);
}
void main() {
vec2 source_size = vec2(unpack(source_size_xy));
vec2 target_offset = vec2(unpack(target_offset_xy));
vec2 target_size = vec2(unpack(target_size_xy));
// Generate rectangle (counter clockwise triangles)
//
// 0 0 1 1 1 0
float x_select = float(((uint(gl_VertexIndex) + 1u) / 3u) % 2u);
// 1 0 0 0 1 1
float y_select = float(((uint(gl_VertexIndex) + 5u) / 3u) % 2u);
source_coords = vec2(
// left -> right (on screen)
mix(0.0, 1.0, x_select),
// bottom -> top (on screen)
mix(1.0, 0.0, y_select)
) * source_size;
vec2 target_coords_normalized = (target_offset + source_coords) / target_size;
// Flip y and transform [0.0, 1.0] -> [-1.0, 1.0] to get NDC coordinates.
vec2 v_pos = ((target_coords_normalized * 2.0) - vec2(1.0)) * vec2(1.0, -1.0);
gl_Position = vec4(v_pos, 0.0, 1.0);
}