SBgl 0.1.0
A graphics framework in C99
Loading...
Searching...
No Matches
batch_main.c
Go to the documentation of this file.
1#include "core/sbl_arena.h"
2#include <math.h>
3#include <sbgl.h>
4#include <sbgl_camera.h>
5#include <sbgl_math.h>
6#include <stdio.h>
7#include <time.h>
8#include "batching_vert.h"
9#include "batching_frag.h"
10
11#define PACK_POS(x, y, z) { (int16_t)((x) * 32767.0f), (int16_t)((y) * 32767.0f), (int16_t)((z) * 32767.0f), 32767 }
12#define PACK_COL(r, g, b, a) (uint32_t)(((uint32_t)((r)*255.0f) << 0) | ((uint32_t)((g)*255.0f) << 8) | ((uint32_t)((b)*255.0f) << 16) | ((uint32_t)((a)*255.0f) << 24))
13
14int main(void) {
15 sbgl_InitResult res = sbgl_Init(800, 600, "SBgl Advanced 3D Batching");
16 if (res.error != SBGL_SUCCESS)
17 return 1;
18 sbgl_Context* ctx = res.ctx;
19
20 SblArena arena;
21 sbl_arena_init(&arena, 10 * 1024 * 1024); // 10MB for render queues
22
23 sbgl_Shader vert =
24 sbgl_LoadShader(ctx, SBGL_SHADER_STAGE_VERTEX, (const uint32_t*)batching_vert_spv, batching_vert_spv_len);
25 sbgl_Shader frag =
26 sbgl_LoadShader(ctx, SBGL_SHADER_STAGE_FRAGMENT, (const uint32_t*)batching_frag_spv, batching_frag_spv_len);
27
28 sbgl_Vertex vertices[] = { // Triangle (Mesh 0)
29 { PACK_POS(0.0f, 0.5f, 0.0f), PACK_COL(1, 0, 0, 1), 0 },
30 { PACK_POS(0.5f, -0.5f, 0.0f), PACK_COL(0, 1, 0, 1), 0 },
31 { PACK_POS(-0.5f, -0.5f, 0.0f), PACK_COL(0, 0, 1, 1), 0 },
32
33 // Cube (Mesh 1)
34 { PACK_POS(-0.5f, -0.5f, -0.5f), PACK_COL(1, 1, 1, 1), 0 },
35 { PACK_POS(0.5f, -0.5f, -0.5f), PACK_COL(1, 1, 1, 1), 0 },
36 { PACK_POS(0.5f, 0.5f, -0.5f), PACK_COL(1, 1, 1, 1), 0 },
37 { PACK_POS(-0.5f, 0.5f, -0.5f), PACK_COL(1, 1, 1, 1), 0 },
38 { PACK_POS(-0.5f, -0.5f, 0.5f), PACK_COL(1, 1, 1, 1), 0 },
39 { PACK_POS(0.5f, -0.5f, 0.5f), PACK_COL(1, 1, 1, 1), 0 },
40 { PACK_POS(0.5f, 0.5f, 0.5f), PACK_COL(1, 1, 1, 1), 0 },
41 { PACK_POS(-0.5f, 0.5f, 0.5f), PACK_COL(1, 1, 1, 1), 0 },
42
43 // Pyramid (Mesh 2)
44 { PACK_POS(0.0f, 0.5f, 0.0f), PACK_COL(1, 1, 0, 1), 0 }, // Top
45 { PACK_POS(-0.5f, -0.5f, -0.5f), PACK_COL(1, 0, 1, 1), 0 }, // base
46 { PACK_POS(0.5f, -0.5f, -0.5f), PACK_COL(1, 0, 1, 1), 0 },
47 { PACK_POS(0.5f, -0.5f, 0.5f), PACK_COL(1, 0, 1, 1), 0 },
48 { PACK_POS(-0.5f, -0.5f, 0.5f), PACK_COL(1, 0, 1, 1), 0 }
49 };
50
51 uint32_t indices[] = { // Triangle
52 0,
53 2,
54 1,
55
56 // Cube
57 0,
58 3,
59 2,
60 2,
61 1,
62 0,
63 4,
64 5,
65 6,
66 6,
67 7,
68 4,
69 0,
70 4,
71 7,
72 7,
73 3,
74 0,
75 1,
76 2,
77 6,
78 6,
79 5,
80 1,
81 2,
82 3,
83 7,
84 7,
85 6,
86 2,
87 0,
88 1,
89 5,
90 5,
91 4,
92 0,
93
94 // Pyramid
95 0,
96 2,
97 1,
98 0,
99 3,
100 2,
101 0,
102 4,
103 3,
104 0,
105 1,
106 4,
107 1,
108 2,
109 3,
110 3,
111 4,
112 1
113 };
114
115 sbgl_Buffer vbo = sbgl_CreateBuffer(ctx, SBGL_BUFFER_USAGE_VERTEX, sizeof(vertices), vertices);
116 sbgl_Buffer ibo = sbgl_CreateBuffer(ctx, SBGL_BUFFER_USAGE_INDEX, sizeof(indices), indices);
117
118 sbgl_VertexAttribute attributes[] = {
119 { 0, offsetof(sbgl_Vertex, position), SBGL_FORMAT_R16G16B16A16_SNORM },
120 { 1, offsetof(sbgl_Vertex, color), SBGL_FORMAT_R8G8B8A8_UNORM }
121 };
122
123 sbgl_PipelineConfig config = { .vertexShader = vert,
124 .fragmentShader = frag,
125 .vertexLayout = { sizeof(sbgl_Vertex), 2, attributes } };
126
127 sbgl_Pipeline pipeline = sbgl_CreatePipeline(ctx, &config);
128 sbgl_RenderQueue* queue = sbgl_CreateRenderQueue(ctx, &arena);
129
130 int width, height;
131 sbgl_GetWindowSize(ctx, &width, &height);
132 sbgl_Camera camera =
133 sbgl_CameraPerspective(SBGL_PI / 4.0f, (float)width / (float)height, 0.1f, 1000.0f);
134 camera.position = sbgl_Vec3Set(0.0f, 50.0f, 200.0f);
135 camera.target = sbgl_Vec3Set(0.0f, 0.0f, 0.0f);
136 camera.up = sbgl_Vec3Set(0.0f, 1.0f, 0.0f);
137
138 float pitch = -0.2f;
139 float yaw = -SBGL_PI / 2.0f;
140 bool mouse_locked = false;
141 float move_speed = 100.0f;
142 float mouse_sensitivity = 0.005f;
143
144 double start_time = sbgl_GetTime(ctx);
145 double last_time = start_time;
146 float fps_timer = 0.0f;
147 int frame_count = 0;
148
149 printf("--- Batching Controls ---\n");
150 printf("W/A/S/D: Move\n");
151 printf("Q/E: Vertical Move\n");
152 printf("TAB: Lock/Unlock Mouse\n");
153 printf("ESC: Exit\n");
154 printf("-------------------------\n");
155
156 while (!sbgl_WindowShouldClose(ctx)) {
157 sbgl_Clear(ctx, 0.02f, 0.02f, 0.02f, 1.0f);
159
160 const sbgl_InputState* input = sbgl_GetInputState(ctx);
161 if (input->keysDown[SBGL_KEY_ESCAPE]) {
162 sbgl_EndDrawing(ctx);
163 break;
164 }
165
166 double current_time = sbgl_GetTime(ctx);
167 float dt = (float)(current_time - last_time);
168 last_time = current_time;
169 float time = (float)(current_time - start_time);
170
171 // Calculate and display FPS
172 frame_count++;
173 fps_timer += dt;
174 if (fps_timer >= 1.0f) {
175 printf(
176 "FPS: %d | Frame Time: %.2f ms\n",
177 frame_count,
178 (fps_timer / (float)frame_count) * 1000.0f
179 );
180 fps_timer = 0.0f;
181 frame_count = 0;
182 }
183
184 if (input->keysPressed[SBGL_KEY_TAB]) {
185 mouse_locked = !mouse_locked;
187 ctx,
189 );
190 }
191
192 if (mouse_locked) {
193 yaw += (float)input->mouseDeltaX * mouse_sensitivity;
194 pitch -= (float)input->mouseDeltaY * mouse_sensitivity;
195
196 if (pitch > 1.5f)
197 pitch = 1.5f;
198 if (pitch < -1.5f)
199 pitch = -1.5f;
200 }
201
202 sbgl_Vec3 front;
203 front.x = cosf(yaw) * cosf(pitch);
204 front.y = sinf(pitch);
205 front.z = sinf(yaw) * cosf(pitch);
206 front = sbgl_Vec3Normalize(front);
207
208 sbgl_Vec3 right = sbgl_Vec3Normalize(sbgl_Vec3Cross(front, sbgl_Vec3Set(0.0f, 1.0f, 0.0f)));
209 sbgl_Vec3 up = sbgl_Vec3Normalize(sbgl_Vec3Cross(right, front));
210
211 float velocity = move_speed * dt;
212
213 if (input->keysDown[SBGL_KEY_W])
214 camera.position = sbgl_Vec3Add(camera.position, sbgl_Vec3Mul(front, velocity));
215 if (input->keysDown[SBGL_KEY_S])
216 camera.position = sbgl_Vec3Sub(camera.position, sbgl_Vec3Mul(front, velocity));
217 if (input->keysDown[SBGL_KEY_A])
218 camera.position = sbgl_Vec3Sub(camera.position, sbgl_Vec3Mul(right, velocity));
219 if (input->keysDown[SBGL_KEY_D])
220 camera.position = sbgl_Vec3Add(camera.position, sbgl_Vec3Mul(right, velocity));
221 if (input->keysDown[SBGL_KEY_E])
222 camera.position = sbgl_Vec3Add(
223 camera.position,
224 sbgl_Vec3Mul(sbgl_Vec3Set(0.0f, 1.0f, 0.0f), velocity)
225 );
226 if (input->keysDown[SBGL_KEY_Q])
227 camera.position = sbgl_Vec3Sub(
228 camera.position,
229 sbgl_Vec3Mul(sbgl_Vec3Set(0.0f, 1.0f, 0.0f), velocity)
230 );
231
232 camera.target = sbgl_Vec3Add(camera.position, front);
233 camera.up = up;
234
236
237 // Submit 10,000 instances
238 for (int i = 0; i < 10000; i++) {
239 uint32_t meshId = i % 3;
240
241 float angle = time + (float)i;
243 ((float)(i % 100) - 50.0f) * 10.0f,
244 ((float)(i / 100 % 100) - 50.0f) * 10.0f,
245 ((float)(i / 10000) - 0.5f) * 10.0f
246 );
247
249 data.transform = sbgl_Mat4Mul(
251 sbgl_Mat4Rotate(angle, sbgl_Vec3Set(0.4f, 1.0f, 0.2f))
252 );
253
254 float r = (float)(i % 255) / 255.0f;
255 float g = (float)((i * 7) % 255) / 255.0f;
256 float b = (float)((i * 13) % 255) / 255.0f;
257 data.color = sbgl_Vec4Set(r, g, b, 1.0f);
258
259 // Use meshId as the sort key for maximum batching
260 sbgl_SubmitDraw(queue, meshId, 0, 0, 0, 0, (sbgl_SortKey)meshId, &data);
261 }
262
263 sbgl_BindPipeline(ctx, pipeline);
266
267 sbgl_RenderQueues(ctx, &queue, 1, &vp);
268
269 sbgl_EndDrawing(ctx);
270 }
271
273
274 sbgl_DestroyPipeline(ctx, pipeline);
275 sbgl_DestroyShader(ctx, vert);
276 sbgl_DestroyShader(ctx, frag);
277 sbgl_DestroyBuffer(ctx, vbo);
278 sbgl_DestroyBuffer(ctx, ibo);
279
280 sbl_arena_free(&arena);
281 sbgl_Shutdown(ctx);
282
283 return 0;
284}
int main(void)
Definition batch_main.c:14
#define PACK_POS(x, y, z)
Definition batch_main.c:11
#define PACK_COL(r, g, b, a)
Definition batch_main.c:12
@ SBGL_MOUSE_MODE_NORMAL
Definition sbgl_input.h:154
@ SBGL_MOUSE_MODE_CAPTURED
Definition sbgl_input.h:156
API for the SiputBiru Graphics Library (SBgl).
#define SBGL_KEY_A
Definition sbgl.h:42
sbgl_InitResult sbgl_Init(int w, int h, const char *title)
Initializes the engine and opens a window.
Definition sbgl_core.c:193
#define SBGL_KEY_E
Definition sbgl.h:46
void sbgl_SubmitDraw(sbgl_RenderQueue *queue, uint32_t mesh, uint32_t material, uint32_t blendMode, uint32_t sidedness, uint32_t tags, sbgl_SortKey key, const sbgl_InstanceData *data)
Appends a draw command to the render queue.
Definition sbgl_core.c:772
void sbgl_GetWindowSize(sbgl_Context *ctx, int *w, int *h)
Retrieves the current window dimensions.
Definition sbgl_core.c:252
bool sbgl_WindowShouldClose(sbgl_Context *ctx)
Checks if the user or OS has requested to close the window.
Definition sbgl_core.c:238
const sbgl_InputState * sbgl_GetInputState(sbgl_Context *ctx)
Retrieves the input state for the current frame.
Definition sbgl_core.c:413
sbgl_Pipeline sbgl_CreatePipeline(sbgl_Context *ctx, const sbgl_PipelineConfig *config)
Creates a graphics pipeline.
Definition sbgl_core.c:587
#define SBGL_KEY_S
Definition sbgl.h:60
void sbgl_DestroyShader(sbgl_Context *ctx, sbgl_Shader shader)
Destroys a shader module.
Definition sbgl_core.c:565
sbgl_Shader sbgl_LoadShader(sbgl_Context *ctx, sbgl_ShaderStage stage, const uint32_t *bytecode, size_t size)
Loads a shader from SPIR-V bytecode.
Definition sbgl_core.c:523
void sbgl_SetMouseMode(sbgl_Context *ctx, sbgl_MouseMode mode)
Sets the cursor behavior and visibility.
Definition sbgl_core.c:422
void sbgl_EndDrawing(sbgl_Context *ctx)
Finalizes the current frame and presents it to the screen.
Definition sbgl_core.c:315
#define SBGL_KEY_ESCAPE
Definition sbgl.h:84
#define SBGL_KEY_D
Definition sbgl.h:45
void sbgl_BindPipeline(sbgl_Context *ctx, sbgl_Pipeline pipeline)
Binds a graphics pipeline for subsequent draw calls.
Definition sbgl_core.c:673
#define SBGL_KEY_Q
Definition sbgl.h:58
#define sbgl_Clear
Backward compatibility alias for sbgl_SetClearColor.
Definition sbgl.h:229
void sbgl_DestroyBuffer(sbgl_Context *ctx, sbgl_Buffer buffer)
Destroys a GPU buffer.
Definition sbgl_core.c:457
#define SBGL_KEY_TAB
Definition sbgl.h:86
sbgl_RenderQueue * sbgl_CreateRenderQueue(sbgl_Context *ctx, struct SblArena *arena)
Creates a thread-local render queue for collecting draw commands.
Definition sbgl_core.c:743
void sbgl_DeviceWaitIdle(sbgl_Context *ctx)
Synchronizes the CPU with the GPU, waiting for all commands to complete.
Definition sbgl_core.c:391
double sbgl_GetTime(sbgl_Context *ctx)
Retrieves the current monotonic system time in seconds.
Definition sbgl_core.c:245
void sbgl_Shutdown(sbgl_Context *ctx)
Gracefully shuts down the engine and releases all resources.
Definition sbgl_core.c:204
void sbgl_BeginDrawing(sbgl_Context *ctx)
Prepares the engine for a new frame of drawing.
Definition sbgl_core.c:262
void sbgl_BindBuffer(sbgl_Context *ctx, sbgl_Buffer buffer, sbgl_BufferUsage usage)
Binds a buffer to the pipeline.
Definition sbgl_core.c:681
#define SBGL_KEY_W
Definition sbgl.h:64
void sbgl_DestroyPipeline(sbgl_Context *ctx, sbgl_Pipeline pipeline)
Destroys a graphics pipeline.
Definition sbgl_core.c:597
sbgl_Buffer sbgl_CreateBuffer(sbgl_Context *ctx, sbgl_BufferUsage usage, size_t size, const void *data)
Creates a GPU buffer.
Definition sbgl_core.c:445
void sbgl_RenderQueues(sbgl_Context *ctx, sbgl_RenderQueue **queues, uint32_t queueCount, const sbgl_Mat4 *viewProj)
Merges, sorts, and submits pending draw commands to the GPU.
Definition sbgl_core.c:808
Camera system and batch collision math for SBgl.
static sbgl_Camera sbgl_CameraPerspective(float fov_y_rad, float aspect, float near_p, float far_p)
Initializes a camera with perspective projection.
Definition sbgl_camera.h:86
static sbgl_Mat4 sbgl_CameraGetProjection(const sbgl_Camera *cam)
Computes the projection matrix for the given camera.
static sbgl_Mat4 sbgl_CameraGetView(const sbgl_Camera *cam)
Computes the view matrix for the given camera.
Single-header math library for SBgl.
static sbgl_Vec3 sbgl_Vec3Set(float x, float y, float z)
Creates a Vec3, correctly padded.
Definition sbgl_math.h:93
static sbgl_Vec3 sbgl_Vec3Add(sbgl_Vec3 a, sbgl_Vec3 b)
Adds two Vec3 vectors.
Definition sbgl_math.h:132
static sbgl_Vec3 sbgl_Vec3Mul(sbgl_Vec3 a, float s)
Multiplies a Vec3 by a scalar.
Definition sbgl_math.h:142
static sbgl_Mat4 sbgl_Mat4Translate(sbgl_Vec3 v)
Creates a translation matrix.
Definition sbgl_math.h:260
#define SBGL_PI
Definition sbgl_math.h:22
static sbgl_Mat4 sbgl_Mat4Rotate(float angle_rad, sbgl_Vec3 axis)
Creates a rotation matrix from axis and angle.
Definition sbgl_math.h:290
static sbgl_Mat4 sbgl_Mat4Mul(sbgl_Mat4 a, sbgl_Mat4 b)
Multiplies two matrices.
Definition sbgl_math.h:240
static sbgl_Vec3 sbgl_Vec3Cross(sbgl_Vec3 a, sbgl_Vec3 b)
Computes the cross product of two Vec3 vectors.
Definition sbgl_math.h:152
static sbgl_Vec3 sbgl_Vec3Normalize(sbgl_Vec3 v)
Normalizes a Vec3.
Definition sbgl_math.h:162
static sbgl_Vec4 sbgl_Vec4Set(float x, float y, float z, float w)
Creates a Vec4.
Definition sbgl_math.h:98
static sbgl_Vec3 sbgl_Vec3Sub(sbgl_Vec3 a, sbgl_Vec3 b)
Subtracts b from a.
Definition sbgl_math.h:137
@ SBGL_BUFFER_USAGE_INDEX
Definition sbgl_types.h:124
@ SBGL_BUFFER_USAGE_VERTEX
Definition sbgl_types.h:123
@ SBGL_SUCCESS
Definition sbgl_types.h:215
@ SBGL_FORMAT_R8G8B8A8_UNORM
Definition sbgl_types.h:160
@ SBGL_FORMAT_R16G16B16A16_SNORM
Definition sbgl_types.h:159
uint32_t sbgl_Buffer
Handle for a GPU-side buffer.
Definition sbgl_types.h:37
uint32_t sbgl_Shader
Handle for a shader module.
Definition sbgl_types.h:42
uint64_t sbgl_SortKey
Bit-packed key used for sorting draw commands to minimize state changes.
Definition sbgl_types.h:57
@ SBGL_SHADER_STAGE_FRAGMENT
Definition sbgl_types.h:135
@ SBGL_SHADER_STAGE_VERTEX
Definition sbgl_types.h:134
uint32_t sbgl_Pipeline
Handle for a graphics pipeline.
Definition sbgl_types.h:47
Arena allocator implementation.
SBL_ARENA_DEF void sbl_arena_free(SblArena *arena)
SBL_ARENA_DEF bool sbl_arena_init(SblArena *arena, uint64_t initial_size)
Arena allocator.
Definition sbl_arena.h:47
Stateful camera representation.
Definition sbgl_camera.h:27
sbgl_Vec3 target
Definition sbgl_camera.h:31
sbgl_Vec3 up
Definition sbgl_camera.h:32
sbgl_Vec3 position
Definition sbgl_camera.h:30
Engine context.
Definition sbgl_types.h:268
Result structure for initialization.
Definition sbgl_types.h:339
sbgl_Context * ctx
Definition sbgl_types.h:340
sbgl_Result error
Definition sbgl_types.h:341
Represents the real-time state of physical inputs.
Definition sbgl_input.h:165
bool keysPressed[SBGL_SCANCODE_MAX]
Definition sbgl_input.h:167
bool keysDown[SBGL_SCANCODE_MAX]
Definition sbgl_input.h:166
Per-instance data for automated batching.
Definition sbgl_types.h:19
sbgl_Mat4 transform
Definition sbgl_types.h:20
sbgl_Vec4 color
Definition sbgl_types.h:21
4x4 Matrix, 16-byte aligned, column-major.
Definition sbgl_math.h:83
Configuration for creating a graphics pipeline.
Definition sbgl_types.h:204
Internal storage for draw packets awaiting submission.
Definition sbgl_core.c:25
Vertex attribute definition.
Definition sbgl_types.h:166
Standard vertex structure for basic geometry rendering. Optimized for cache density (16 bytes).
Definition sbgl_types.h:28
3D Vector, 16-byte aligned and padded for SIMD safety.
Definition sbgl_math.h:49
float y
Definition sbgl_math.h:52
float z
Definition sbgl_math.h:52
float x
Definition sbgl_math.h:52