// BEWARE std140 packing: // https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules typedef struct My_Cbuffer { Vector2 mouse_pos_screen; // We use this to make a light around the mouse cursor Vector2 window_size; // We only use this to revert the Y in the shader because for some reason d3d11 inverts it. } My_Cbuffer; // We implement these details which we implement in the shader #define DETAIL_TYPE_ROUNDED_CORNERS 1 #define DETAIL_TYPE_OUTLINED 2 // With custom shading we can extend the rendering library! Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius); Draw_Quad *draw_rounded_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float radius); Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width); Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width); int entry(int argc, char **argv) { window.title = STR("Custom Shader Example"); window.scaled_width = 1280; window.scaled_height = 720; window.x = 200; window.y = 90; window.clear_color = hex_to_rgba(0x6495EDff); string source; bool ok = os_read_entire_file("oogabooga/examples/custom_shader.hlsl", &source, get_heap_allocator()); assert(ok, "Could not read oogabooga/examples/custom_shader.hlsl"); // This is slow and needs to recompile the shader. However, it should probably only happen once (or each hot reload) // If it fails, it will return false and return to whatever shader it was before. shader_recompile_with_extension(source, sizeof(My_Cbuffer)); dealloc_string(get_heap_allocator(), source); // This memory needs to stay alive throughout the frame because we pass the pointer to it in draw_frame.cbuffer. // If this memory is invalidated before gfx_update after setting draw_frame.cbuffer, then gfx_update will copy // memory from an invalid address. My_Cbuffer cbuffer; float64 last_time = os_get_current_time_in_seconds(); while (!window.should_close) { float64 now = os_get_current_time_in_seconds(); if ((int)now != (int)last_time) { log("%.2f FPS\n%.2fms", 1.0/(now-last_time), (now-last_time)*1000); } last_time = now; reset_temporary_storage(); cbuffer.mouse_pos_screen = v2(input_frame.mouse_x, input_frame.mouse_y); cbuffer.window_size = v2(window.width, window.height); draw_frame.cbuffer = &cbuffer; // Just draw a big rect to cover background, so our lighting shader will apply to background draw_rect(v2(-5, -5), v2(10, 10), v4(.4, .4, .4, 1.0)); Matrix4 rect_xform = m4_scalar(1.0); rect_xform = m4_rotate_z(rect_xform, (f32)now); rect_xform = m4_translate(rect_xform, v3(-.25f, -.25f, 0)); Draw_Quad *q = draw_rounded_rect_xform(rect_xform, v2(.5f, .5f), COLOR_GREEN, 0.1); draw_outlined_rect(v2(sin(now), -.8), v2(.5, .25), COLOR_RED, 15); // Shader hot reloading if (is_key_just_pressed('R')) { ok = os_read_entire_file("oogabooga/examples/custom_shader.hlsl", &source, get_heap_allocator()); assert(ok, "Could not read oogabooga/examples/custom_shader.hlsl"); shader_recompile_with_extension(source, sizeof(My_Cbuffer)); dealloc_string(get_heap_allocator(), source); } os_update(); gfx_update(); } return 0; } Draw_Quad *draw_rounded_rect(Vector2 p, Vector2 size, Vector4 color, float radius) { Draw_Quad *q = draw_rect(p, size, color); // detail_type q->userdata[0].x = DETAIL_TYPE_ROUNDED_CORNERS; // corner_radius q->userdata[0].y = radius; return q; } Draw_Quad *draw_rounded_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float radius) { Draw_Quad *q = draw_rect_xform(xform, size, color); // detail_type q->userdata[0].x = DETAIL_TYPE_ROUNDED_CORNERS; // corner_radius q->userdata[0].y = radius; return q; } Draw_Quad *draw_outlined_rect(Vector2 p, Vector2 size, Vector4 color, float line_width) { Draw_Quad *q = draw_rect(p, size, color); // detail_type q->userdata[0].x = DETAIL_TYPE_OUTLINED; // line_width q->userdata[0].y = line_width; return q; } Draw_Quad *draw_outlined_rect_xform(Matrix4 xform, Vector2 size, Vector4 color, float line_width) { Draw_Quad *q = draw_rect_xform(xform, size, color); // detail_type q->userdata[0].x = DETAIL_TYPE_OUTLINED; // line_width q->userdata[0].y = line_width; return q; }