Skip to content

Commit

Permalink
more examples
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane committed Jan 12, 2024
1 parent 92b555d commit 3f2f890
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ jobs:
sudo apt-get install libglu1-mesa-dev mesa-common-dev xorg-dev libasound-dev
- name: Build
run: zig build -DZigCC --summary all
run: zig build -DzigCC --summary all
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ On Linux install the following packages: libglu1-mesa-dev, mesa-common-dev, xorg
zig build -Doptimize=ReleaseFast

# build sokol shared library + all examples
zig build -Doptimize=ReleaseFast -DShared
zig build -Doptimize=ReleaseFast -Dshared

# Run Examples
zig build run-blend -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-clear -Doptimize=ReleaseFast # works
zig build run-debugtext-print -Doptimize=ReleaseFast # works
zig build run-sgl-context -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-cube -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-blend -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-debugtext-print -Doptimize=ReleaseFast # works
zig build run-mrt -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-saudio -Doptimize=ReleaseFast # run (fixme)
zig build run-sgl-context -Doptimize=ReleaseFast # run, but no anims (fixme)
zig build run-triangle -Doptimize=ReleaseFast # run, but no anims (fixme)

zig build --help
Expand All @@ -46,9 +47,9 @@ zig build --help
# ReleaseSafe
# ReleaseFast
# ReleaseSmall
# -DShared=[bool] Build sokol dynamic library [default: static]
# -DBetterC=[bool] Omit generating some runtime information and helper functions. [default: false]
# -DZigCC=[bool] Use zig cc as compiler and linker. [default: false]
# -Dshared=[bool] Build sokol dynamic library (default: static)
# -DbetterC=[bool] Omit generating some runtime information and helper functions. (default: false)
# -DzigCC=[bool] Use zig cc as compiler and linker. (default: false)
```

## Shaders
Expand Down
8 changes: 4 additions & 4 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn rootPath() []const u8 {

// build sokol into a static library
pub fn buildSokol(b: *Build, target: CrossTarget, optimize: OptimizeMode, config: Config, comptime prefix_path: []const u8) *CompileStep {
const sharedlib = b.option(bool, "Shared", "Build sokol dynamic library [default: static]") orelse false;
const sharedlib = b.option(bool, "shared", "Build sokol dynamic library (default: static)") orelse false;
const lib = if (sharedlib) b.addSharedLibrary(.{
.name = "sokol",
.target = target,
Expand Down Expand Up @@ -196,8 +196,8 @@ pub fn build(b: *Build) !void {
const sokol = buildSokol(b, target, optimize, config, "");

// LDC-config options
const enable_betterC = b.option(bool, "BetterC", "Omit generating some runtime information and helper functions. [default: false]") orelse false;
const enable_zigcc = b.option(bool, "ZigCC", "Use zig cc as compiler and linker. [default: false]") orelse false;
const enable_betterC = b.option(bool, "betterC", "Omit generating some runtime information and helper functions. (default: false)") orelse false;
const enable_zigcc = b.option(bool, "zigCC", "Use zig cc as compiler and linker. (default: false)") orelse false;

if (enable_zigcc)
buildZigCC(b);
Expand All @@ -215,7 +215,7 @@ pub fn build(b: *Build) !void {
// "offscreen",
// "instancing",
"mrt",
// "saudio",
"saudio",
// "sgl",
"sgl-context",
// "sgl-points",
Expand Down
1 change: 0 additions & 1 deletion dub.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"configurations": [
{
"name": "debugtext_print",
"targetPath": "examples",
"targetType": "executable",
"sourceFiles": ["src/examples/debugtext_print.d"],
"buildTypes": {
Expand Down
193 changes: 190 additions & 3 deletions src/examples/mrt.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ import sg = sokol.gfx;
import app = sokol.app;
import log = sokol.log;
import handmade.math : Mat4, Vec3, Vec2;
import std.math : sin, cos;
import sgapp = sokol.glue;
import shd = shaders.mrt;

extern (C):
@safe:

enum offscreen_sample_count = 1;
enum OFFSCREEN_SAMPLE_COUNT = 1;

struct Offscreen {
sg.PassAction pass_action;
Expand Down Expand Up @@ -64,11 +65,197 @@ void init()
logger: {func: &log.slog_func}
};
sg.setup(gfx);

// setup pass action for default render pass
state.dflt.pass_action.colors[0].load_action = sg.LoadAction.Dontcare;
state.dflt.pass_action.depth.load_action = sg.LoadAction.Dontcare;
state.dflt.pass_action.stencil.load_action = sg.LoadAction.Dontcare;

// set pass action for offscreen render pass
state.offscreen.pass_action.colors[0].load_action = sg.LoadAction.Clear,
state.offscreen.pass_action.colors[0].clear_value.r = 0.25;
state.offscreen.pass_action.colors[0].clear_value.g = 0.0;
state.offscreen.pass_action.colors[0].clear_value.b = 0.0;
state.offscreen.pass_action.colors[0].clear_value.a = 1.0;

state.offscreen.pass_action.colors[1].load_action = sg.LoadAction.Clear;
state.offscreen.pass_action.colors[1].clear_value.r = 0.0;
state.offscreen.pass_action.colors[1].clear_value.g = 0.25;
state.offscreen.pass_action.colors[1].clear_value.b = 0.0;
state.offscreen.pass_action.colors[1].clear_value.a = 1.0;

state.offscreen.pass_action.colors[2].load_action = sg.LoadAction.Clear;
state.offscreen.pass_action.colors[2].clear_value.r = 0.0;
state.offscreen.pass_action.colors[2].clear_value.g = 0.0;
state.offscreen.pass_action.colors[2].clear_value.b = 0.25;
state.offscreen.pass_action.colors[2].clear_value.a = 1.0;

// setup the offscreen render pass and render target images,
// this will also be called when the window resizes
createOffscreenPass(app.width(), app.height());

float[] VERTICES = [
// positions brightness
-1.0, -1.0, -1.0, 1.0,
1.0, -1.0, -1.0, 1.0,
1.0, 1.0, -1.0, 1.0,
-1.0, 1.0, -1.0, 1.0,

-1.0, -1.0, 1.0, 0.8,
1.0, -1.0, 1.0, 0.8,
1.0, 1.0, 1.0, 0.8,
-1.0, 1.0, 1.0, 0.8,

-1.0, -1.0, -1.0, 0.6,
-1.0, 1.0, -1.0, 0.6,
-1.0, 1.0, 1.0, 0.6,
-1.0, -1.0, 1.0, 0.6,

1.0, -1.0, -1.0, 0.0,
1.0, 1.0, -1.0, 0.0,
1.0, 1.0, 1.0, 0.0,
1.0, -1.0, 1.0, 0.0,

-1.0, -1.0, -1.0, 0.5,
-1.0, -1.0, 1.0, 0.5,
1.0, -1.0, 1.0, 0.5,
1.0, -1.0, -1.0, 0.5,

-1.0, 1.0, -1.0, 0.7,
-1.0, 1.0, 1.0, 0.7,
1.0, 1.0, 1.0, 0.7,
1.0, 1.0, -1.0, 0.7,
];

// create vertex buffer for a cube
sg.BufferDesc buf = { data: sg.asRange(VERTICES) };
auto cube_vbuf = sg.makeBuffer(buf);

double[] INDICES = [
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20,
];

// index buffer for a cube
sg.BufferDesc ibuf = {
type: sg.BufferType.Indexbuffer,
data: sg.asRange(INDICES),
};
auto cube_ibuf = sg.makeBuffer(ibuf);

// resource bindings for offscreen rendering
state.offscreen.bind.vertex_buffers[0] = cube_vbuf;
state.offscreen.bind.index_buffer = cube_ibuf;

// shader and pipeline state object for rendering cube into MRT render targets
auto sh = shd.offscreen_shader_desc(sg.queryBackend());
sg.PipelineDesc offscreen_pip_desc = {
shader: sg.makeShader(sh),
index_type: sg.IndexType.Uint16,
cull_mode: sg.CullMode.Back,
sample_count: OFFSCREEN_SAMPLE_COUNT,
depth: {
pixel_format: sg.PixelFormat.Depth,
compare: sg.CompareFunc.Less_equal,
write_enabled: true,
},
color_count: 3,
};
offscreen_pip_desc.layout.attrs[shd.ATTR_VS_OFFSCREEN_POS].format = sg.VertexFormat.Float3;
offscreen_pip_desc.layout.attrs[shd.ATTR_VS_OFFSCREEN_BRIGHT0].format = sg.VertexFormat.Float;
state.offscreen.pip = sg.makePipeline(offscreen_pip_desc);

float[] QUAD_VERTICES = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
// a vertex buffer to render a fullscreen quad
sg.BufferDesc quad_buf = { data: sg.asRange(QUAD_VERTICES) };
const quad_vbuf = sg.makeBuffer(quad_buf);

// shader and pipeline object to render a fullscreen quad which composes
// the 3 offscreen render targets into the default framebuffer
auto shader2 = shd.fsq_shader_desc(sg.queryBackend());
sg.PipelineDesc fsq_pip_desc = {
shader: sg.makeShader(shader2),
primitive_type: sg.PrimitiveType.Triangle_strip,
};
fsq_pip_desc.layout.attrs[shd.ATTR_VS_FSQ_POS].format = sg.VertexFormat.Float2;
state.fsq.pip = sg.makePipeline(fsq_pip_desc);

// a sampler to sample the offscreen render targets as texture
sg.SamplerDesc sampler = {
min_filter: sg.Filter.Linear,
mag_filter: sg.Filter.Linear,
wrap_u: sg.Wrap.Clamp_to_edge,
wrap_v: sg.Wrap.Clamp_to_edge,
};
sg.Sampler smp = sg.makeSampler(sampler);

// resource bindings to render the fullscreen quad (composed from the
// offscreen render target textures
state.fsq.bind.vertex_buffers[0] = quad_vbuf;
foreach (i;[0,1,2]) {
state.fsq.bind.fs.images[i] = state.offscreen.pass_desc.color_attachments[i].image;
}
state.fsq.bind.fs.samplers[0] = smp;

// shader, pipeline and resource bindings to render debug visualization quads
auto dbg_shader = shd.dbg_shader_desc(sg.queryBackend());
sg.PipelineDesc dbg_pip_desc = {
shader: sg.makeShader(dbg_shader),
primitive_type: sg.PrimitiveType.Triangle_strip,
};
dbg_pip_desc.layout.attrs[shd.ATTR_VS_DBG_POS].format = sg.VertexFormat.Float2;
state.dbg.pip = sg.makePipeline(dbg_pip_desc);

// resource bindings to render the debug visualization
// (the required images will be filled in during rendering)
state.dbg.bind.vertex_buffers[0] = quad_vbuf;
state.dbg.bind.fs.samplers[0] = smp;
}

void frame()
{
//
immutable (float) dt = (app.frameDuration() * 60.0);
state.rx += 1.0 * dt;
state.ry += 2.0 * dt;

// compute shader uniform data
shd.OffscreenParams offscreen_params = { mvp: compute_mvp(state.rx, state.ry) };
shd.FsqParams fsq_params = {
offset: Vec2(sin(state.rx * 0.01) * 0.1, cos(state.ry * 0.01) * 0.1),
};

// render cube into MRT offscreen render targets
sg.beginPass(state.offscreen.pass, state.offscreen.pass_action);
sg.applyPipeline(state.offscreen.pip);
sg.applyBindings(state.offscreen.bind);
sg.applyUniforms(
sg.ShaderStage.Vs,
shd.SLOT_OFFSCREEN_PARAMS,
sg.asRange(offscreen_params),
);
sg.draw(0, 36, 1);
sg.endPass();

// render fullscreen quad with the composed offscreen-render images,
// 3 a small debug view quads at the bottom of the screen
sg.beginDefaultPass(state.dflt.pass_action, app.width(), app.height());
sg.applyPipeline(state.fsq.pip);
sg.applyBindings(state.fsq.bind);
sg.applyUniforms(sg.ShaderStage.Vs, shd.SLOT_FSQ_PARAMS, sg.asRange(fsq_params));
sg.draw(0, 4, 1);
sg.applyPipeline(state.dbg.pip);
foreach(i;[0,1,2]) {
sg.applyViewport(i * 100, 0, 100, 100, false);
state.dbg.bind.fs.images[0] = state.offscreen.pass_desc.color_attachments[i].image;
sg.applyBindings(state.dbg.bind);
sg.draw(0, 4, 1);
}
sg.endPass();
sg.commit();
}

void event(const app.Event* ev)
Expand Down Expand Up @@ -115,7 +302,7 @@ void createOffscreenPass(int width, int height)
render_target: true,
width: width,
height: height,
sample_count: offscreen_sample_count,
sample_count: OFFSCREEN_SAMPLE_COUNT,
};
sg.ImageDesc depth_img_desc = color_img_desc;
depth_img_desc.pixel_format = sg.PixelFormat.Depth;
Expand Down
82 changes: 82 additions & 0 deletions src/examples/saudio.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// saudio.d
// Test sokol-audio D bindings
//------------------------------------------------------------------------------
module examples.saudio;

import sg = sokol.gfx;
import app = sokol.app;
import log = sokol.log;
import sgapp = sokol.glue;
import saudio = sokol.audio;

extern (C):
@safe:

enum NUM_SAMPLES = 32;

struct State {
sg.PassAction pass_action = {
colors: [{
load_action: sg.LoadAction.Clear,
clear_value: { r: 1.0, g: 0.5, b: 0.0, a: 1.0 },
}]
};
int even_odd;
size_t sample_pos;
float[NUM_SAMPLES] samples;
}

static State state;

void init()
{
sg.Desc gfx = {
context: sgapp.context(),
logger: {func: &log.slog_func}
};
sg.setup(gfx);
saudio.Desc audio = {logger: {func: &log.slog_func}};
saudio.setup(audio);
}

void frame(){
immutable num_frames = saudio.expect();

foreach (_; 0..num_frames) {
state.even_odd += 1;
state.sample_pos += 1;

if (state.sample_pos == NUM_SAMPLES) {
state.sample_pos = 0;
saudio.push(&state.samples[0], NUM_SAMPLES);
}

state.samples[state.sample_pos] = (0 != (state.even_odd & 0x20)) ? 0.1 : -0.1;
}

sg.beginDefaultPass(state.pass_action, app.width(), app.height());
sg.endPass();
sg.commit();
}

void cleanup()
{
saudio.shutdown();
sg.shutdown();
}

void main()
{
app.Desc runner = {
window_title: "saudio.d",
init_cb: &init,
frame_cb: &frame,
cleanup_cb: &cleanup,
width: 640,
height: 480,
icon: {sokol_default: true},
logger: {func: &log.func}
};
app.run(runner);
}

0 comments on commit 3f2f890

Please sign in to comment.