trueno/src/rendering/pipelines.jai

1001 lines
31 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

SHADOWMAP_SIZE :: 2000;
Pipeline_Binding :: struct {
pipeline : sg_pipeline;
bind : sg_bindings;
attachments : sg_attachments;
pass_action : sg_pass_action;
}
g_specular_lut : sg_image;
g_shadowmap : sg_image;
g_shadowmap_img : sg_image;
g_shadowmap_attachments : sg_attachments;
g_shadowmap_sampler : sg_sampler;
g_rendertex : sg_image;
g_rendertex_depth : sg_image;
g_rendertex_attachments : sg_attachments;
g_gbuf_position : sg_image;
g_gbuf_normal : sg_image;
g_gbuf_depth : sg_image;
g_gbuf_attachments : sg_attachments;
g_ssaobuf : sg_image;
g_ssao_noise_buf : sg_image;
g_ssaobuf_depth : sg_image;
g_ssao_attachments : sg_attachments;
g_postprocess_a : sg_image;
g_postprocess_b : sg_image;
g_postprocess_a_depth : sg_image;
g_postprocess_b_depth : sg_image;
g_postprocess_attach_a : sg_attachments;
g_postprocess_attach_b : sg_attachments;
gPipelines : struct {
// G-Buffer generation for SSAO and other effects
gbuffer: Pipeline_Binding;
// Arbitrary triangle rendering for rendering 2D things on the screen.
// Used for UI rendering.
arbtri : Pipeline_Binding;
// Trixel rendering. Used for Trile editor rendering, in-game triles are rendered from
// generated meshes.
trixel : Pipeline_Binding;
// Sky rendering.
sky : Pipeline_Binding;
// Renders sets of triles
trile : Pipeline_Binding;
// Renders the ground plane. (just water)
plane : Pipeline_Binding;
// Post-processing pipeline
postprocess : Pipeline_Binding;
op : Pipeline_Binding;
mix : Pipeline_Binding;
// Renders the SSAO texture using things from the gbuffer pass.
ssao: Pipeline_Binding;
}
create_final_image :: () {
// @ToDo: Some smarter logic for this.
w,h := get_render_size();
if g_rendertex.id != INVALID_ID then sg_destroy_image(g_rendertex);
if g_rendertex_depth.id != INVALID_ID then sg_destroy_image(g_rendertex);
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA32F,
render_target = true,
};
depth_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .DEPTH,
render_target = true,
};
g_rendertex = sg_make_image(*img_desc);
g_rendertex_depth = sg_make_image(*depth_desc);
attachmentsDesc : sg_attachments_desc;
attachmentsDesc = .{
colors[0].image = g_rendertex,
depth_stencil.image = g_rendertex_depth,
};
sg_destroy_attachments(g_rendertex_attachments);
g_rendertex_attachments = sg_make_attachments(*attachmentsDesc);
}
create_shadowmap_image :: () {
w : s32 = SHADOWMAP_SIZE;
h : s32 = SHADOWMAP_SIZE;
if g_shadowmap.id != INVALID_ID then sg_destroy_image(g_shadowmap);
depth_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .DEPTH,
render_target = true,
};
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA32F,
render_target = true,
};
g_shadowmap = sg_make_image(*depth_desc);
g_shadowmap_img = sg_make_image(*img_desc);
attachmentsDesc : sg_attachments_desc;
attachmentsDesc = .{
colors[0].image = g_shadowmap_img,
depth_stencil.image = g_shadowmap,
};
sg_destroy_attachments(g_shadowmap_attachments);
g_shadowmap_attachments = sg_make_attachments(*attachmentsDesc);
}
create_pipelines :: () {
create_gbuffer_images();
create_gbuffer_pipeline();
create_arbtri_pipeline();
create_trixel_pipeline();
create_trile_pipeline();
create_sky_pipeline();
create_plane_pipeline();
create_postprocess_pipeline();
create_ssao_pipeline();
create_op_pipeline();
create_mix_pipeline();
create_shadowmap_image();
create_final_image();
create_ssao_images();
create_gbuffer_impostors();
}
create_gbuffer_images :: () {
w,h := get_render_size();
if g_gbuf_position.id != INVALID_ID then sg_destroy_image(g_gbuf_position);
if g_gbuf_normal.id != INVALID_ID then sg_destroy_image(g_gbuf_normal);
if g_gbuf_depth.id != INVALID_ID then sg_destroy_image(g_gbuf_depth);
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA16F,
render_target = true,
};
depth_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .DEPTH,
render_target = true,
};
g_gbuf_position = sg_make_image(*img_desc);
g_gbuf_normal = sg_make_image(*img_desc);
g_gbuf_depth = sg_make_image(*depth_desc);
attachmentsDesc : sg_attachments_desc;
attachmentsDesc = .{
colors[0].image = g_gbuf_position,
colors[1].image = g_gbuf_normal,
depth_stencil.image = g_gbuf_depth,
};
sg_destroy_attachments(g_gbuf_attachments);
g_gbuf_attachments = sg_make_attachments(*attachmentsDesc);
}
TRIXEL_SIZE_HALF : float : 1.0/32.0;
TRIXEL_SIZE : float : 1.0/16.0;
gArbtriMem : [100000*3*9]float;
Position_Color :: struct {
pos: Vector4;
col: Vector4;
}
create_trixel_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trixel_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[2].step_func = .PER_INSTANCE;
pipeline.layout.attrs[ATTR_trixel_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.layout.attrs[ATTR_trixel_normal] = .{ format = .FLOAT3, buffer_index = 1 };
pipeline.layout.attrs[ATTR_trixel_inst] = .{ format = .FLOAT4, buffer_index = 2 };
pipeline.layout.attrs[ATTR_trixel_inst_col] = .{ format = .FLOAT4, buffer_index = 2 };
pipeline.index_type = .UINT16;
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
vertices : [24]Vector3 = .[
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, -TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, -TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, TRIXEL_SIZE/2},
.{-TRIXEL_SIZE/2, TRIXEL_SIZE/2, -TRIXEL_SIZE/2}
];
normals : [24]Vector3 = .[
.{0.0, 0.0, 1.0},
.{0.0, 0.0, 1.0},
.{0.0, 0.0, 1.0},
.{0.0, 0.0, 1.0},
.{0.0, 0.0,-1.0},
.{0.0, 0.0,-1.0},
.{0.0, 0.0,-1.0},
.{0.0, 0.0,-1.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0,-1.0, 0.0},
.{0.0,-1.0, 0.0},
.{0.0,-1.0, 0.0},
.{0.0,-1.0, 0.0},
.{1.0, 0.0, 0.0},
.{1.0, 0.0, 0.0},
.{1.0, 0.0, 0.0},
.{1.0, 0.0, 0.0},
.{-1.0, 0.0, 0.0},
.{-1.0, 0.0, 0.0},
.{-1.0, 0.0, 0.0},
.{-1.0, 0.0, 0.0}
];
k : u16 = 0;
i : u16 = 0;
indices : [36]u16;
while i < 36 {
indices[i] = 4*k;
indices[i + 1] = 4*k + 1;
indices[i + 2] = 4*k + 2;
indices[i + 3] = 4*k;
indices[i + 4] = 4*k + 2;
indices[i + 5] = 4*k + 3;
k += 1;
i += 6;
}
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.trixel.pipeline = sg_make_pipeline(*pipeline);
ibuffer := sg_buffer_desc.{ type = .INDEXBUFFER, data = .{ ptr = indices.data, size = 36 * 2 } };
vbuffer := sg_buffer_desc.{ data = .{ ptr = vertices.data, size = 24 * 3 * 4 } };
nbuffer := sg_buffer_desc.{ data = .{ ptr = normals.data, size = 24 * 3 * 4 } };
instance_buffer := sg_buffer_desc.{ usage = .STREAM, size = 4096 * size_of(Position_Color)};
gPipelines.trixel.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.trixel.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.trixel.bind.vertex_buffers[1] = sg_make_buffer(*nbuffer);
gPipelines.trixel.bind.vertex_buffers[2] = sg_make_buffer(*instance_buffer);
}
create_gbuffer_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := gbuffer_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[3].step_func = .PER_INSTANCE;
instance_buffer := sg_buffer_desc.{ usage = .STREAM, size = 16 * 4096 * 4 * 4};
pipeline.layout.attrs[ATTR_trile_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.layout.attrs[ATTR_trile_normal] = .{ format = .FLOAT3, buffer_index = 1 };
pipeline.layout.attrs[ATTR_trile_centre] = .{ format = .FLOAT3, buffer_index = 2 };
pipeline.layout.attrs[ATTR_trile_instance] = .{ format = .FLOAT4, buffer_index = 3 };
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
color_state_pos := sg_color_target_state.{
pixel_format = .RGBA16F,
};
color_state_normal := sg_color_target_state.{
pixel_format = .RGBA16F,
};
pipeline.color_count = 2;
pipeline.colors[0] = color_state_pos;
pipeline.colors[1] = color_state_normal;
gPipelines.gbuffer.pipeline = sg_make_pipeline(*pipeline);
gPipelines.gbuffer.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
gPipelines.gbuffer.bind.vertex_buffers[3] = sg_make_buffer(*instance_buffer);
}
create_trile_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := trile_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.buffers[1].stride = 4*3;
pipeline.layout.buffers[3].step_func = .PER_INSTANCE;
instance_buffer := sg_buffer_desc.{ usage = .STREAM, size = 16 * 4096 * 4 * 4};
pipeline.layout.attrs[ATTR_trile_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.layout.attrs[ATTR_trile_normal] = .{ format = .FLOAT3, buffer_index = 1 };
pipeline.layout.attrs[ATTR_trile_centre] = .{ format = .FLOAT3, buffer_index = 2 };
pipeline.layout.attrs[ATTR_trile_instance] = .{ format = .FLOAT4, buffer_index = 3 };
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.trile.pipeline = sg_make_pipeline(*pipeline);
gPipelines.trile.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
gPipelines.trile.bind.vertex_buffers[3] = sg_make_buffer(*instance_buffer);
}
create_sky_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := sky_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.attrs[ATTR_sky_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.index_type = .UINT16;
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH,
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
vertices : [24]Vector3 = .[
.{-1, -1, 1},
.{1, -1, 1},
.{1, 1, 1},
.{-1, 1, 1},
.{-1, -1, -1},
.{-1, 1, -1},
.{1, 1, -1},
.{1, -1, -1},
.{-1, 1, -1},
.{-1, 1, 1},
.{1, 1, 1},
.{1, 1, -1},
.{-1, -1, -1},
.{1, -1, -1},
.{1, -1, 1},
.{-1, -1, 1},
.{1, -1, -1},
.{1, 1, -1},
.{1, 1, 1},
.{1, -1, 1},
.{-1, -1, -1},
.{-1, -1, 1},
.{-1, 1, 1},
.{-1, 1, -1}
];
k : u16 = 0;
i : u16 = 0;
indices : [36]u16;
while i < 36 {
indices[i] = 4*k;
indices[i + 1] = 4*k + 1;
indices[i + 2] = 4*k + 2;
indices[i + 3] = 4*k;
indices[i + 4] = 4*k + 2;
indices[i + 5] = 4*k + 3;
k += 1;
i += 6;
}
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.sky.pipeline = sg_make_pipeline(*pipeline);
ibuffer := sg_buffer_desc.{ type = .INDEXBUFFER, data = .{ ptr = indices.data, size = 36 * 2 } };
vbuffer := sg_buffer_desc.{ data = .{ ptr = vertices.data, size = 24 * 3 * 4 } };
gPipelines.sky.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.sky.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
}
create_plane_pipeline_reflection_images :: () {
binding := *gPipelines.plane.bind;
if binding.images[4].id != INVALID_ID then sg_destroy_image(binding.images[4]);
if binding.images[5].id != INVALID_ID then sg_destroy_image(binding.images[5]);
if binding.images[0].id != INVALID_ID then sg_destroy_image(binding.images[0]);
w, h := get_render_size();
img_desc := sg_image_desc.{
width = w/2,
height = h/2,
pixel_format = .RGBA32F,
render_target = true,
};
depth_desc := sg_image_desc.{
width = w/2,
height = h/2,
pixel_format = .DEPTH,
render_target = true,
};
binding.images[4] = sg_make_image(*img_desc);
img_desc.sample_count = 1;
binding.images[0] = sg_make_image(*img_desc);
binding.images[5] = sg_make_image(*depth_desc);
attachmentsDesc : sg_attachments_desc;
attachmentsDesc = .{
colors[0].image = gPipelines.plane.bind.images[0],
depth_stencil.image = gPipelines.plane.bind.images[5],
};
sg_destroy_attachments(gPipelines.plane.attachments);
gPipelines.plane.attachments = sg_make_attachments(*attachmentsDesc);
}
create_plane_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := plane_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.attrs[ATTR_plane_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.index_type = .UINT16;
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH
};
color_state := sg_color_target_state.{
pixel_format = .RGBA32F,
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
vertices: [4]Vector3 = .[
.{-1.0, 0.0, -1.0},
.{ 1.0, 0.0, -1.0},
.{ 1.0, 0.0, 1.0},
.{-1.0, 0.0, 1.0},
];
indices: [6]u16 = .[
0, 1, 2,
0, 2, 3,
];
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.plane.pipeline = sg_make_pipeline(*pipeline);
ibuffer := sg_buffer_desc.{ type = .INDEXBUFFER, data = .{ ptr = indices.data, size = 6 * 2 } };
vbuffer := sg_buffer_desc.{ data = .{ ptr = vertices.data, size = 4 * 3 * 4 } };
gPipelines.plane.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.plane.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
create_plane_pipeline_reflection_images();
gPipelines.plane.pass_action = .{
colors[0] = .{ load_action = .CLEAR, clear_value = .{ 0.25, 0.25, 0.25, 1.0 } },
};
gPipelines.plane.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
g_shadowmap_sampler = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .LINEAR,
mag_filter = .LINEAR,
compare = .LESS,
}));
gPipelines.plane.bind.samplers[1] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
gPipelines.plane.bind.samplers[3] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .REPEAT,
wrap_v = .REPEAT,
min_filter = .LINEAR,
mag_filter = .LINEAR,
}));
ground_img_desc := sg_image_desc.{
width = 1000,
height = 1000,
pixel_format = .RGBA8,
render_target = false,
sample_count = 1,
usage = .DYNAMIC,
};
gPipelines.plane.bind.images[1] = sg_make_image(*ground_img_desc);
}
create_arbtri_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := triangle_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_triangle_position] = .{ format = .FLOAT3 };
pipeline.layout.attrs[ATTR_triangle_color0] = .{ format = .FLOAT4 };
pipeline.layout.attrs[ATTR_triangle_uv] = .{ format = .FLOAT2 };
color_state := sg_color_target_state.{
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.arbtri.pipeline = sg_make_pipeline(*pipeline);
buffer := sg_buffer_desc.{ usage = .DYNAMIC, size = size_of(type_of(gArbtriMem)) };
gPipelines.arbtri.bind.vertex_buffers[0] = sg_make_buffer(*buffer);
gPipelines.arbtri.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
create_postprocess_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := postprocess_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_postprocess_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_postprocess_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
color_state := sg_color_target_state.{
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
}
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.postprocess.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0), // top-let
-1.0, -1.0, 0.0, flip_if_plat(0.0), // bottom-let
1.0, -1.0, 1.0, flip_if_plat(0.0), // bottom-right
1.0, 1.0, 1.0, flip_if_plat(1.0), // top-right
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.postprocess.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.postprocess.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.postprocess.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
// Takes in a texture, manipulates it and outputs it.
create_op_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := op_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_op_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_op_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
color_state := sg_color_target_state.{
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
};
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.op.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0), // top-let
-1.0, -1.0, 0.0, flip_if_plat(0.0), // bottom-let
1.0, -1.0, 1.0, flip_if_plat(0.0), // bottom-right
1.0, 1.0, 1.0, flip_if_plat(1.0), // top-right
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.op.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.op.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.op.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
// Takes in 2-3 textures, and mixes them.
create_mix_pipeline :: () {
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := mix_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_mix_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_mix_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
color_state := sg_color_target_state.{
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
};
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH
};
pipeline.color_count = 1;
pipeline.colors[0] = color_state;
gPipelines.mix.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0), // top-let
-1.0, -1.0, 0.0, flip_if_plat(0.0), // bottom-let
1.0, -1.0, 1.0, flip_if_plat(0.0), // bottom-right
1.0, 1.0, 1.0, flip_if_plat(1.0), // top-right
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.mix.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.mix.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.mix.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
create_ssao_images :: () {
if g_ssaobuf.id != INVALID_ID then sg_destroy_image(g_ssaobuf);
if g_ssaobuf_depth.id != INVALID_ID then sg_destroy_image(g_ssaobuf_depth);
if g_postprocess_a.id != INVALID_ID then sg_destroy_image(g_postprocess_a);
if g_postprocess_a_depth.id != INVALID_ID then sg_destroy_image(g_postprocess_a_depth);
if g_postprocess_b.id != INVALID_ID then sg_destroy_image(g_postprocess_b);
if g_postprocess_b_depth.id != INVALID_ID then sg_destroy_image(g_postprocess_b_depth);
w,h := get_render_size();
img_desc := sg_image_desc.{
width = w/2,
height = h/2,
render_target = true,
pixel_format = .RGBA32F
};
img_desc.sample_count = 1;
g_ssaobuf = sg_make_image(*img_desc);
img_desc.width *= 2; img_desc.height *= 2;
g_postprocess_a = sg_make_image(*img_desc);
g_postprocess_b = sg_make_image(*img_desc);
img_desc = sg_image_desc.{
width = w/2,
height = h/2,
pixel_format = .DEPTH,
render_target = true,
};
img_desc.sample_count = 1;
g_ssaobuf_depth = sg_make_image(*img_desc);
img_desc.width *= 2; img_desc.height *= 2;
g_postprocess_a_depth = sg_make_image(*img_desc);
g_postprocess_b_depth = sg_make_image(*img_desc);
attachmentsDesc := sg_attachments_desc.{
colors[0].image = g_ssaobuf,
depth_stencil.image = g_ssaobuf_depth
};
sg_destroy_attachments(g_ssao_attachments);
g_ssao_attachments = sg_make_attachments(*attachmentsDesc);
attachmentsDescA := sg_attachments_desc.{
colors[0].image = g_postprocess_a,
depth_stencil.image = g_postprocess_a_depth
};
attachmentsDescB := sg_attachments_desc.{
colors[0].image = g_postprocess_b,
depth_stencil.image = g_postprocess_b_depth
};
sg_destroy_attachments(g_postprocess_attach_a);
g_postprocess_attach_a = sg_make_attachments(*attachmentsDescA);
sg_destroy_attachments(g_postprocess_attach_b);
g_postprocess_attach_b = sg_make_attachments(*attachmentsDescB);
}
create_ssao_pipeline :: () {
init_ssao();
platconf := get_plat_conf();
pipeline: sg_pipeline_desc;
shader_desc := ssao_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_ssao_position] = .{ format = .FLOAT2 };
pipeline.layout.attrs[ATTR_ssao_uv] = .{ format = .FLOAT2 };
pipeline.index_type = .UINT16;
color_state := sg_color_target_state.{
blend = .{
enabled = true,
src_factor_rgb = .SRC_ALPHA,
dst_factor_rgb = .ONE_MINUS_SRC_ALPHA
},
pixel_format = .RGBA32F,
};
pipeline.color_count = 1;
pipeline.depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
pixel_format = .DEPTH
};
pipeline.colors[0] = color_state;
gPipelines.ssao.pipeline = sg_make_pipeline(*pipeline);
quad_vertices : [16]float = .[
-1.0, 1.0, 0.0, flip_if_plat(1.0), // top-let
-1.0, -1.0, 0.0, flip_if_plat(0.0), // bottom-let
1.0, -1.0, 1.0, flip_if_plat(0.0), // bottom-right
1.0, 1.0, 1.0, flip_if_plat(1.0), // top-right
];
quad_indices : [6]u16 = .[
0, 1, 2, 0, 2, 3
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 16, data = .{
ptr = quad_vertices.data,
size = 16 * 4
}};
ibuffer := sg_buffer_desc.{ size = size_of(u16) * 6, data = .{
ptr = quad_indices.data,
size = 6 * 2
},
type = .INDEXBUFFER,
};
gPipelines.ssao.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
gPipelines.ssao.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.ssao.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .REPEAT,
wrap_v = .REPEAT,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{g_ssao_noise.data, cast(u64) (16*4*4)};
texdesc : sg_image_desc = .{
render_target = false,
width = 4,
height = 4,
pixel_format = sg_pixel_format.RGBA32F,
sample_count = 1,
data = imgdata
};
g_ssao_noise_buf = sg_make_image(*texdesc);
}
init_plane_textures :: () {
gPipelines.plane.bind.images[3] = create_texture_from_pack("./resources/utiltex/water.png");
}
g_plane_gbuffer_vertex_buffer : sg_buffer;
g_plane_gbuffer_normal_buffer : sg_buffer;
g_plane_gbuffer_center_buffer : sg_buffer;
g_plane_gbuffer_instance_buffer : sg_buffer;
create_gbuffer_impostors :: () {
plane_vertices: [6]Vector3 = .[
.{-1.0, 0.0, -1.0},
.{ 1.0, 0.0, -1.0},
.{ 1.0, 0.0, 1.0},
.{-1.0, 0.0, -1.0},
.{ 1.0, 0.0, 1.0},
.{-1.0, 0.0, 1.0},
];
vbuffer := sg_buffer_desc.{ size = size_of(float) * 18, data = .{
ptr = plane_vertices.data,
size = 6 * 3 * 4
}};
g_plane_gbuffer_vertex_buffer = sg_make_buffer(*vbuffer);
plane_normals: [6]Vector3 = .[
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
];
nbuffer := sg_buffer_desc.{ size = size_of(float) * 18, data = .{
ptr = plane_normals.data,
size = 6 * 3 * 4
}};
g_plane_gbuffer_normal_buffer = sg_make_buffer(*nbuffer);
plane_centers: [2]Vector3 = .[ // these are useless, just to fill the pipeline requirement.
.{0.0, 1.0, 0.0},
.{0.0, 1.0, 0.0},
];
cbuffer := sg_buffer_desc.{ size = size_of(float) * 6, data = .{
ptr = plane_centers.data,
size = 3 * 2 * 4
}};
g_plane_gbuffer_center_buffer = sg_make_buffer(*cbuffer);
instances: [1]Vector4 = .[.{0,0,0,0}];
instance_buffer := sg_buffer_desc.{size = 4 * 4, data = .{
ptr = instances.data,
size = 4*4,
}};
g_plane_gbuffer_instance_buffer = sg_make_buffer(*instance_buffer);
}