Mikemon/assets/shader/world.slang
Sven Balzer 88da989ad7 major refactor and add a camera
change asset loading of images to be sRGB
use wayland by default on linux unless we are running under renderdoc
changed shaders to be combined vertex and fragment in a single file
require Vulkan 1.3 and enable shaderDrawParameters
2025-03-08 19:39:48 +01:00

114 lines
3.0 KiB
Plaintext

struct VertexShaderInput {
// Per Vertex
uint vertex_id : SV_VertexID;
float3 pos;
// Per Instance
uint instance_id : SV_InstanceID;
uint tile_info;
};
struct VertexShaderOutput {
float4 pos : SV_POSITION;
float2 uv;
};
struct PixelShaderOutput {
float4 color : SV_TARGET;
};
[[vk::binding(0, 1)]]
cbuffer constants {
float aspect_ratio;
float fovy_degrees;
float camera_x;
float camera_y;
float camera_z;
uint map_width;
};
[[vk::binding(0, 0)]]
StructuredBuffer<float4> tile_infos;
float4x4 projection(float fovy, float aspect, float near) {
float g = 1.0 / tan(fovy * 0.5);
return {
g / aspect, 0, 0, 0,
0, g, 0, 0,
0, 0, 0, near,
0, 0, 1, 0,
};
}
float4x4 view(float3 pos) {
return {
1, 0, 0, -pos.x,
0, 1, 0, -pos.y,
0, 0, 1, -pos.z,
0, 0, 0, 1,
};
}
[shader("vertex")]
VertexShaderOutput main_vertex(VertexShaderInput input) {
VertexShaderOutput output;
float2 tile_pos = float2(input.instance_id % map_width, -float(input.instance_id / map_width));
uint tile_type = input.tile_info & 0xffff;
uint rotation = (input.tile_info >> 16) & 0x3;
float fovy = radians(fovy_degrees);
float4x4 view_matrix = view(float3(camera_x, -camera_y, camera_z));
float4x4 projection_matrix = projection(fovy, aspect_ratio, 0.001);
float4x4 view_projection_matrix = mul(projection_matrix, view_matrix);
output.pos = mul(view_projection_matrix, float4(tile_pos + input.pos.xy, 0, 1));
float4 uv_min_max = tile_infos.Load(tile_type);
switch (rotation) {
case 0: switch (input.vertex_id) {
case 0: output.uv = uv_min_max.xy; break;
case 1: output.uv = uv_min_max.zy; break;
case 2: output.uv = uv_min_max.zw; break;
case 3: output.uv = uv_min_max.xw; break;
} break;
case 1: switch (input.vertex_id) {
case 0: output.uv = uv_min_max.zy; break;
case 1: output.uv = uv_min_max.zw; break;
case 2: output.uv = uv_min_max.xw; break;
case 3: output.uv = uv_min_max.xy; break;
} break;
case 2: switch (input.vertex_id) {
case 0: output.uv = uv_min_max.zw; break;
case 1: output.uv = uv_min_max.xw; break;
case 2: output.uv = uv_min_max.xy; break;
case 3: output.uv = uv_min_max.zy; break;
} break;
case 3: switch (input.vertex_id) {
case 0: output.uv = uv_min_max.xw; break;
case 1: output.uv = uv_min_max.xy; break;
case 2: output.uv = uv_min_max.zy; break;
case 3: output.uv = uv_min_max.zw; break;
} break;
}
return output;
}
[[vk::binding(0, 2)]]
Sampler2D<float4> tex1;
[shader("fragment")]
PixelShaderOutput main_fragment(VertexShaderOutput input) {
PixelShaderOutput output;
output.color = tex1.Sample(float2(input.uv));
return output;
}