#version 450
#extension GL_AMD_gpu_shader_int16 : enable
layout(location = 0) in ivec2 position;
layout(location = 1) in ivec2 normal;
layout(location = 2) in uint feature_id;
layout(location = 0) out vec4 outColor;
layout(std140) struct LayerData {
vec4 background_color;
vec4 outline_color;
float border_width;
uint line_width;
float z_index;
};
layout(std140, set = 0, binding = 0) uniform Locals {
vec2 canvas_size;
vec2 _unused;
LayerData layer_datas[1000];
};
layout(std140) struct TileData {
mat4 transform;
float extent;
float _unused;
float _unused2;
float _unused3;
};
layout(std140, set = 0, binding = 1) uniform Transform {
TileData tile_datas[200];
};
void main() {
// Are we handling an outline?
bool is_outline = (gl_InstanceIndex & 0x01) == 0;
// The current tile.
uint tile_id = (gl_InstanceIndex >> 1);
// Shortcut the array indexing.
LayerData layer_data = layer_datas[feature_id];
TileData tile_data = tile_datas[tile_id];
// Is the line we are currently handling sized in world coordinates or pixels?
bool is_world_scale_line = (layer_data.line_width & 0x01) == 1;
// Calculate the tile normal normal in [0.0, 1.0] coordinates.
vec2 local_normal = normal / tile_data.extent;
vec4 tile_local_position = vec4(position / tile_data.extent, 0.0, 1.0);
// If we have a world scale line, add the normal to the vertex before the world transform.
if(is_world_scale_line) {
vec2 n = local_normal / tile_data.extent * (layer_data.line_width >> 1);
tile_local_position.xy += n;
}
// Transform the vertex.
gl_Position = tile_data.transform * tile_local_position;
// If we have a pixel scale line, add the normal to the vertex after the world transform.
if(!is_world_scale_line) {
gl_Position.xy += local_normal / canvas_size * (layer_data.line_width >> 1);
}
// If we handle an outline, add the normal to the vertex (always pixel space) and pick the appropriate color.
if(is_outline){
gl_Position.xy += local_normal / canvas_size * layer_data.border_width * 2;
outColor = layer_data.outline_color;
} else {
outColor = layer_data.background_color;
}
gl_Position.z = layer_data.z_index / 1000 + 0.001;
}