Skip to content

Commit

Permalink
new sample layerrender-sapp.c
Browse files Browse the repository at this point in the history
  • Loading branch information
floooh committed Oct 28, 2023
1 parent 3e9a5a2 commit 6ca954b
Show file tree
Hide file tree
Showing 6 changed files with 341 additions and 3 deletions.
1 change: 1 addition & 0 deletions fips-files/verbs/webpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def get_build_config(api):
[ 'cubemap-jpeg', 'cubemap-jpeg-sapp.c', 'cubemap-jpeg-sapp.glsl' ],
[ 'cubemaprt', 'cubemaprt-sapp.c', 'cubemaprt-sapp.glsl' ],
[ 'miprender', 'miprender-sapp.c', 'miprender-sapp.glsl' ],
[ 'layerrender', 'layerrender-sapp.c', 'layerrender-sapp.glsl' ],
[ 'primtypes', 'primtypes-sapp.c', 'primtypes-sapp.glsl'],
[ 'uvwrap', 'uvwrap-sapp.c', 'uvwrap-sapp.glsl'],
[ 'mipmap', 'mipmap-sapp.c', 'mipmap-sapp.glsl'],
Expand Down
14 changes: 14 additions & 0 deletions sapp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,20 @@ fips_begin_app(miprender-sapp-ui windowed)
target_compile_definitions(miprender-sapp-ui PRIVATE USE_DBG_UI)
fips_end_app()

fips_ide_group(Samples)
fips_begin_app(layerrender-sapp windowed)
fips_files(layerrender-sapp.c)
sokol_shader(layerrender-sapp.glsl ${slang})
fips_deps(sokol)
fips_end_app()
fips_ide_group(SamplesWithDebugUI)
fips_begin_app(layerrender-sapp-ui windowed)
fips_files(layerrender-sapp.c)
sokol_shader(layerrender-sapp.glsl ${slang})
fips_deps(sokol dbgui)
target_compile_definitions(layerrender-sapp-ui PRIVATE USE_DBG_UI)
fips_end_app()

fips_ide_group(Samples)
fips_begin_app(sdf-sapp windowed)
fips_files(sdf-sapp.c)
Expand Down
262 changes: 262 additions & 0 deletions sapp/layerrender-sapp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
//------------------------------------------------------------------------------
// layerrender-sapp.c
//
// Rendering into texture-array layers.
//------------------------------------------------------------------------------
#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_log.h"
#include "sokol_glue.h"
#define SOKOL_SHAPE_IMPL
#include "sokol_shape.h"
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h"
#include "dbgui/dbgui.h"
#include "layerrender-sapp.glsl.h"

#define IMG_WIDTH (512)
#define IMG_HEIGHT (512)
#define IMG_NUM_LAYERS (3)

#define SHAPE_BOX (0)
#define SHAPE_DONUT (1)
#define SHAPE_CYLINDER (2)
#define NUM_SHAPES (3)

static struct {
float rx, ry;
double time;
sg_buffer vbuf;
sg_buffer ibuf;
sg_image img;
sg_sampler smp;
struct {
sg_pipeline pip;
sg_pass_action pass_action;
sg_bindings bindings;
sshape_element_range_t shapes[NUM_SHAPES];
sg_pass pass[IMG_NUM_LAYERS];
} offscreen;
struct {
sg_pipeline pip;
sg_pass_action pass_action;
sg_bindings bindings;
sshape_element_range_t plane;
} display;
} state;

static vs_params_t compute_offscreen_vsparams(float rx, float ry);
static vs_params_t compute_display_vsparams(void);

static void init(void) {
sg_setup(&(sg_desc){
.context = sapp_sgcontext(),
.logger.func = slog_func,
});
__dbgui_setup(sapp_sample_count());

// setup a couple of shape geometries
static sshape_vertex_t vertices[4 * 1024];
static uint16_t indices[12 * 1024];
sshape_buffer_t buf = {
.vertices.buffer = SSHAPE_RANGE(vertices),
.indices.buffer = SSHAPE_RANGE(indices),
};
buf = sshape_build_box(&buf, &(sshape_box_t){ .width = 1.5f, .height = 1.5f, .depth = 1.5f });
state.offscreen.shapes[SHAPE_BOX] = sshape_element_range(&buf);
buf = sshape_build_torus(&buf, &(sshape_torus_t){ .radius = 1.0f, .ring_radius = 0.3f, .rings = 36, .sides = 18 });
state.offscreen.shapes[SHAPE_DONUT] = sshape_element_range(&buf);
buf = sshape_build_cylinder(&buf, &(sshape_cylinder_t){ .radius = 1.0f, .height = 1.5f, .slices = 36, .stacks = 1 });
state.offscreen.shapes[SHAPE_CYLINDER] = sshape_element_range(&buf);
buf = sshape_build_plane(&buf, &(sshape_plane_t){ .width = 2.0f, .depth = 2.0f });
state.display.plane = sshape_element_range(&buf);
assert(buf.valid);

// create one vertex- and one index-buffer for all shapes
const sg_buffer_desc vbuf_desc = sshape_vertex_buffer_desc(&buf);
const sg_buffer_desc ibuf_desc = sshape_index_buffer_desc(&buf);
state.vbuf = sg_make_buffer(&vbuf_desc);
state.ibuf = sg_make_buffer(&ibuf_desc);

// create an array-texture as render target
state.img = sg_make_image(&(sg_image_desc){
.render_target = true,
.type = SG_IMAGETYPE_ARRAY,
.width = IMG_WIDTH,
.height = IMG_HEIGHT,
.num_slices = IMG_NUM_LAYERS,
.num_mipmaps = 1,
.pixel_format = SG_PIXELFORMAT_RGBA8,
.sample_count = 1,
});

// ...and a matching depth buffer image
sg_image depth_img = sg_make_image(&(sg_image_desc){
.render_target = true,
.width = IMG_WIDTH,
.height = IMG_HEIGHT,
.num_mipmaps = 1,
.pixel_format = SG_PIXELFORMAT_DEPTH,
.sample_count = 1,
});

// a sampler for sampling the array texture
state.smp = sg_make_sampler(&(sg_sampler_desc){
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_EDGE,
.wrap_v = SG_WRAP_CLAMP_TO_EDGE,
});

// one render pass object per texture array layer
for (int i = 0; i < IMG_NUM_LAYERS; i++) {
state.offscreen.pass[i] = sg_make_pass(&(sg_pass_desc){
.color_attachments[0] = { .image = state.img, .slice = i },
.depth_stencil_attachment = { .image = depth_img },
});
}

// a pipeline object for the offscreen pass
state.offscreen.pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.buffers[0].stride = sizeof(sshape_vertex_t),
.attrs = {
[ATTR_vs_offscreen_in_pos] = sshape_position_vertex_attr_state(),
[ATTR_vs_offscreen_in_nrm] = sshape_normal_vertex_attr_state(),
},
},
.shader = sg_make_shader(offscreen_shader_desc(sg_query_backend())),
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_BACK,
.sample_count = 1,
.depth = {
.write_enabled = true,
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.pixel_format = SG_PIXELFORMAT_DEPTH,
},
.colors[0].pixel_format = SG_PIXELFORMAT_RGBA8,
});

// ...and a pipeline object for the display pass
state.display.pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.buffers[0].stride = sizeof(sshape_vertex_t),
.attrs = {
[ATTR_vs_display_in_pos] = sshape_position_vertex_attr_state(),
[ATTR_vs_display_in_uv] = sshape_texcoord_vertex_attr_state(),
},
},
.shader = sg_make_shader(display_shader_desc(sg_query_backend())),
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_BACK,
.sample_count = 1,
.depth = {
.write_enabled = true,
.compare = SG_COMPAREFUNC_LESS_EQUAL,
},
});

// initialize resource bindings
state.offscreen.bindings = (sg_bindings){
.vertex_buffers[0] = state.vbuf,
.index_buffer = state.ibuf,
};
state.display.bindings = (sg_bindings){
.vertex_buffers[0] = state.vbuf,
.index_buffer = state.ibuf,
.fs = {
.images[SLOT_tex] = state.img,
.samplers[SLOT_smp] = state.smp,
},
};

// initialize pass actions
state.offscreen.pass_action = (sg_pass_action){
.colors[0] = { .load_action = SG_LOADACTION_CLEAR, .clear_value = { 0.5f, 0.5f, 0.5f, 1.0f } },
};
state.display.pass_action = (sg_pass_action){
.colors[0] = { .load_action = SG_LOADACTION_CLEAR, .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f } },
};
}

static void frame(void) {
double dt = sapp_frame_duration();
state.time += dt;
state.rx += (float)(dt * 20.0f);
state.ry += (float)(dt * 40.0f);

const vs_params_t display_vsparams = compute_display_vsparams();

// render different shapes into each texture array layer
for (int i = 0; i < IMG_NUM_LAYERS; i++) {
sg_begin_pass(state.offscreen.pass[i], &state.offscreen.pass_action);
sg_apply_pipeline(state.offscreen.pip);
sg_apply_bindings(&state.offscreen.bindings);
float rx = state.rx;
float ry = state.ry;
switch (i) {
case 0: break;
case 1: rx = -rx; break;
default: ry = -ry; break;
}
const vs_params_t offscreen_vsparams = compute_offscreen_vsparams(rx, ry);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, &SG_RANGE(offscreen_vsparams));
const sshape_element_range_t shape = state.offscreen.shapes[i];
sg_draw(shape.base_element, shape.num_elements, 1);
sg_end_pass();
}

// default pass: render a textured plane which accesses all texture layers in the fragment shader
sg_begin_default_pass(&state.display.pass_action, sapp_width(), sapp_height());
sg_apply_pipeline(state.display.pip);
sg_apply_bindings(&state.display.bindings);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, &SG_RANGE(display_vsparams));
sg_draw(state.display.plane.base_element, state.display.plane.num_elements, 1);
__dbgui_draw();
sg_end_pass();
sg_commit();
}

static void cleanup(void) {
__dbgui_shutdown();
sg_shutdown();
}

// compute a model-view-projection matrix for offscreen rendering (aspect ratio 1:1)
static vs_params_t compute_offscreen_vsparams(float rx, float ry) {
hmm_mat4 proj = HMM_Perspective(60.0f, 1.0f, 0.01f, 10.0f);
hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 0.0f, 3.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f));
hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view);
hmm_mat4 rxm = HMM_Rotate(rx, HMM_Vec3(1.0f, 0.0f, 0.0f));
hmm_mat4 rym = HMM_Rotate(ry, HMM_Vec3(0.0f, 0.0f, 1.0f));
hmm_mat4 model = HMM_MultiplyMat4(rxm, rym);
return (vs_params_t){ .mvp = HMM_MultiplyMat4(view_proj, model) };
}

// compute a model-view-projection matrix with display aspect ratio
static vs_params_t compute_display_vsparams(void) {
const float w = sapp_widthf();
const float h = sapp_heightf();
hmm_mat4 proj = HMM_Perspective(40.0f, w/h, 0.01f, 10.0f);
hmm_mat4 view = HMM_LookAt(HMM_Vec3(0.0f, 0.0f, 5.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f));
hmm_mat4 view_proj = HMM_MultiplyMat4(proj, view);
hmm_mat4 model = HMM_Rotate(90.0f, HMM_Vec3(1.0f, 0.0f, 0.0f));
return (vs_params_t){ .mvp = HMM_MultiplyMat4(view_proj, model) };
}

sapp_desc sokol_main(int argc, char* argv[]) {
(void)argc; (void)argv;
return (sapp_desc) {
.init_cb = init,
.frame_cb = frame,
.cleanup_cb = cleanup,
.event_cb = __dbgui_event,
.width = 800,
.height = 600,
.sample_count = 1,
.window_title = "layerrender-sapp.c",
.icon.sokol_default = true,
.logger.func = slog_func,
};
}
61 changes: 61 additions & 0 deletions sapp/layerrender-sapp.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@ctype mat4 hmm_mat4

@block vs_uniforms
uniform vs_params {
mat4 mvp;
};
@end

@vs vs_offscreen
@include_block vs_uniforms

in vec4 in_pos;
in vec3 in_nrm;
out vec3 nrm;

void main() {
gl_Position = mvp * in_pos;
nrm = in_nrm;
}
@end

@fs fs_offscreen
in vec3 nrm;
out vec4 frag_color;

void main() {
frag_color = vec4(nrm * 0.5 + 0.5, 1.0);
}
@end

@program offscreen vs_offscreen fs_offscreen

@vs vs_display
@include_block vs_uniforms

in vec4 in_pos;
in vec2 in_uv;
out vec2 uv;

void main() {
gl_Position = mvp * in_pos;
uv = in_uv;
}
@end

@fs fs_display
uniform texture2DArray tex;
uniform sampler smp;

in vec2 uv;
out vec4 frag_color;

void main() {
vec3 c0 = texture(sampler2DArray(tex, smp), vec3(uv, 0)).xyz;
vec3 c1 = texture(sampler2DArray(tex, smp), vec3(uv, 1)).xyz;
vec3 c2 = texture(sampler2DArray(tex, smp), vec3(uv, 2)).xyz;
frag_color = vec4((c0 + c1 + c2) * 0.34, 1.0);
}
@end

@program display vs_display fs_display
6 changes: 3 additions & 3 deletions sapp/miprender-sapp.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// miprender-sapp.c
//
// Offscreen rendering into into mipmaps.
// Rendering into into texture mipmaps.
//------------------------------------------------------------------------------
#include "sokol_app.h"
#include "sokol_gfx.h"
Expand Down Expand Up @@ -122,7 +122,7 @@ static void init(void) {
});
}

// a render pipeline object for the offscreen passes
// a pipeline object for the offscreen passes
state.offscreen.pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.buffers[0].stride = sizeof(sshape_vertex_t),
Expand All @@ -143,7 +143,7 @@ static void init(void) {
.colors[0].pixel_format = SG_PIXELFORMAT_RGBA8,
});

// ...and a render pipeline object for the display pass
// ...and a pipeline object for the display pass
state.display.pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.buffers[0].stride = sizeof(sshape_vertex_t),
Expand Down
Binary file added webpage/layerrender.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6ca954b

Please sign in to comment.