mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
cf74d55f2e
Specifically, we address three concerns (the image stretching during rotation, artifacts around the image due to clamping to the nearest border color when the image is drawn to a larger space than the image itself takes up, and potential artifacts around a rotated image which accidentally ended up in an atlas and didn't have enough extra space to guarantee the rotation would work). The first concern was addressed by fixing the dimensions of the map images drawn from the UI (so that we always use a square source rectangle, rather than a rectangular one according to the dimensions of the map). We also fixed the way rotation was done in the fragment shader for north-facing sources to make it properly handle aspect ratio (this was already done for north-facing targets). Together, these fix rendering issues peculiar to rectangular maps. The second and third concerns were jointly addressed by adding an optional border color to every 2D image drawn by the UI. This turns out not to waste extra space even though we hold a full f32 color (to avoid an extra dependency on gfx's PackedColor), since voxel images already take up more space than Optiion<[f32; 4]> requires. This is then implemented automatically using the "border color" wrapping method in the attached sampler. Since this is implemented in graphics hardware, it only works (at least naively) if the actual image bounds match the texture bounds. Therefore, we altered the way the graphics cache stores images with a border color to guarantee that they are always in their own texture, whose size exactly matches their extent. Since the easiest currently exposed way to set a border color is to do so for an immutable texture, we went a bit further and added a new "immutable" texture storage type used for these cases; currently, it is always and automatically used only when there is a specified border color, but in theory there's no reason we couldn't provide immutable-only images that use the default wrapping mdoe (though clamp to border is admittedly not a great default). To fix the maps case specifically, we set the border color to a translucent version of the ocean border color. This may need tweaking going forward, which shouldn't be hard. As part of this process, we had to modify graphics replacement to make sure immutable images are *removed* when invalidated, rather than just having a validity flag unset (this is normally done by the UI to try to reuse allocations in place if images are updated in benign ways, since the texture atlases used for Ui do not support deallocation; currently this is only used for item images, so there should be no overlap with immutable image replacement, so this was purely precautionary). Since we were already touching the relevant code, we also updated the image dependency to a newer version that provides more ways to avoid allocations, and made a few other changes that should hopefully eliminate redundant most of the intermediate buffer allocations we were performing for what should be zero-cost conversions. This may slightly improve performance in some cases.
61 lines
2.0 KiB
GLSL
61 lines
2.0 KiB
GLSL
#version 330 core
|
|
|
|
#include <globals.glsl>
|
|
|
|
in vec2 v_pos;
|
|
in vec2 v_uv;
|
|
in vec2 v_center;
|
|
in vec4 v_color;
|
|
in uint v_mode;
|
|
|
|
layout (std140)
|
|
uniform u_locals {
|
|
vec4 w_pos;
|
|
};
|
|
|
|
uniform sampler2D u_tex;
|
|
|
|
out vec2 f_uv;
|
|
flat out uint f_mode;
|
|
out vec4 f_color;
|
|
|
|
void main() {
|
|
f_color = v_color;
|
|
|
|
// vec2 v_pos = vec2(-1.0,1.0) * v_pos;
|
|
/* f_uv = vec2(1.0,1.0) * v_uv; */
|
|
// vec2 v_uv = vec2(1.0,-1.0) * v_uv;
|
|
|
|
if (w_pos.w == 1.0) {
|
|
f_uv = v_uv;
|
|
// Fixed scale In-game element
|
|
vec4 projected_pos = /*proj_mat * view_mat*/all_mat * vec4(w_pos.xyz - focus_off.xyz, 1.0);
|
|
gl_Position = vec4(projected_pos.xy / projected_pos.w + v_pos/* * projected_pos.w*/, -1.0, /*projected_pos.w*/1.0);
|
|
} else if (v_mode == uint(3)) {
|
|
// HACK: North facing source rectangle.
|
|
gl_Position = vec4(v_pos, -1.0, 1.0);
|
|
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
|
|
// TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3).
|
|
vec2 aspect_ratio = textureSize(u_tex, 0).yx;
|
|
mat2 look_at = mat2(look_at_dir.y, look_at_dir.x, -look_at_dir.x, look_at_dir.y);
|
|
vec2 v_centered = (v_uv - v_center) / aspect_ratio;
|
|
vec2 v_rotated = look_at * v_centered;
|
|
f_uv = aspect_ratio * v_rotated + v_center;
|
|
} else if (v_mode == uint(5)) {
|
|
// HACK: North facing target rectangle.
|
|
f_uv = v_uv;
|
|
vec2 look_at_dir = normalize(vec2(-view_mat[0][2], -view_mat[1][2]));
|
|
// TODO: Consider cleaning up matrix to something more efficient (e.g. a mat3).
|
|
vec2 aspect_ratio = screen_res.yx;
|
|
mat2 look_at = mat2(look_at_dir.y, -look_at_dir.x, look_at_dir.x, look_at_dir.y);
|
|
vec2 v_centered = (v_pos - v_center) / aspect_ratio;
|
|
vec2 v_rotated = look_at * v_centered;
|
|
gl_Position = vec4(aspect_ratio * v_rotated + v_center, -1.0, 1.0);
|
|
} else {
|
|
// Interface element
|
|
f_uv = v_uv;
|
|
gl_Position = vec4(v_pos, -1.0, 1.0);
|
|
}
|
|
f_mode = v_mode;
|
|
}
|