// This file is part of the 64k demo project. // Standalone "mini-demo" for testing the 3D renderer. #include "3d/camera.h" #include "3d/object.h" #include "3d/renderer.h" #include "3d/scene.h" #include "gpu/texture_manager.h" #include "platform.h" #include "procedural/generator.h" #include #include #include #include #if defined(DEMO_CROSS_COMPILE_WIN32) #include #else #include #endif // Global State static Renderer3D g_renderer; static TextureManager g_textures; static Scene g_scene; static Camera g_camera; static WGPUDevice g_device = nullptr; static WGPUQueue g_queue = nullptr; static WGPUSurface g_surface = nullptr; static WGPUAdapter g_adapter = nullptr; static WGPUTextureFormat g_format = WGPUTextureFormat_Undefined; static int g_width = 1280; static int g_height = 720; // ... (init_wgpu implementation same as before) void init_wgpu() { WGPUInstance instance = wgpuCreateInstance(nullptr); if (!instance) { std::cerr << "Failed to create WGPU instance." << std::endl; exit(1); } g_surface = platform_create_wgpu_surface(instance); if (!g_surface) { std::cerr << "Failed to create WGPU surface." << std::endl; exit(1); } WGPURequestAdapterOptions adapter_opts = {}; adapter_opts.compatibleSurface = g_surface; adapter_opts.powerPreference = WGPUPowerPreference_HighPerformance; #if defined(DEMO_CROSS_COMPILE_WIN32) auto on_adapter = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* message, void* userdata) { if (status == WGPURequestAdapterStatus_Success) { *(WGPUAdapter*)userdata = adapter; } }; wgpuInstanceRequestAdapter(instance, &adapter_opts, on_adapter, &g_adapter); #else auto on_adapter = [](WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, void* userdata, void* user2) { if (status == WGPURequestAdapterStatus_Success) { *(WGPUAdapter*)userdata = adapter; } }; WGPURequestAdapterCallbackInfo adapter_cb = {}; adapter_cb.mode = WGPUCallbackMode_WaitAnyOnly; adapter_cb.callback = on_adapter; adapter_cb.userdata1 = &g_adapter; wgpuInstanceRequestAdapter(instance, &adapter_opts, adapter_cb); #endif #if !defined(DEMO_CROSS_COMPILE_WIN32) while (!g_adapter) { wgpuInstanceProcessEvents(instance); } #endif if (!g_adapter) { std::cerr << "Failed to get adapter." << std::endl; exit(1); } WGPUDeviceDescriptor device_desc = {}; #if defined(DEMO_CROSS_COMPILE_WIN32) auto on_device = [](WGPURequestDeviceStatus status, WGPUDevice device, const char* message, void* userdata) { if (status == WGPURequestDeviceStatus_Success) { *(WGPUDevice*)userdata = device; } }; wgpuAdapterRequestDevice(g_adapter, &device_desc, on_device, &g_device); #else auto on_device = [](WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, void* userdata, void* user2) { if (status == WGPURequestDeviceStatus_Success) { *(WGPUDevice*)userdata = device; } }; WGPURequestDeviceCallbackInfo device_cb = {}; device_cb.mode = WGPUCallbackMode_WaitAnyOnly; device_cb.callback = on_device; device_cb.userdata1 = &g_device; wgpuAdapterRequestDevice(g_adapter, &device_desc, device_cb); #endif #if !defined(DEMO_CROSS_COMPILE_WIN32) while (!g_device) { wgpuInstanceProcessEvents(instance); } #endif if (!g_device) { std::cerr << "Failed to get device." << std::endl; exit(1); } g_queue = wgpuDeviceGetQueue(g_device); WGPUSurfaceCapabilities caps = {}; wgpuSurfaceGetCapabilities(g_surface, g_adapter, &caps); g_format = caps.formats[0]; WGPUSurfaceConfiguration config = {}; config.device = g_device; config.format = g_format; config.usage = WGPUTextureUsage_RenderAttachment; config.width = g_width; config.height = g_height; config.presentMode = WGPUPresentMode_Fifo; config.alphaMode = WGPUCompositeAlphaMode_Opaque; wgpuSurfaceConfigure(g_surface, &config); } void setup_scene() { g_scene.clear(); Object3D center(ObjectType::BOX); center.position = vec3(0, 0, 0); center.color = vec4(1, 0, 0, 1); g_scene.add_object(center); for (int i = 0; i < 8; ++i) { ObjectType type = ObjectType::SPHERE; if (i % 3 == 1) type = ObjectType::TORUS; if (i % 3 == 2) type = ObjectType::BOX; Object3D obj(type); float angle = (i / 8.0f) * 6.28318f; obj.position = vec3(std::cos(angle) * 4.0f, 0, std::sin(angle) * 4.0f); obj.scale = vec3(0.5f, 0.5f, 0.5f); if (type == ObjectType::SPHERE) obj.color = vec4(0, 1, 0, 1); else if (type == ObjectType::TORUS) obj.color = vec4(0, 0.5, 1, 1); else obj.color = vec4(1, 1, 0, 1); g_scene.add_object(obj); } } // Wrapper to generate periodic noise void gen_periodic_noise(uint8_t* buffer, int w, int h, const float* params, int num_params) { procedural::gen_noise(buffer, w, h, params, num_params); float p_params[] = {0.1f}; // 10% overlap procedural::make_periodic(buffer, w, h, p_params, 1); } int main() { platform_init_window(false); init_wgpu(); g_renderer.init(g_device, g_queue, g_format); g_renderer.resize(g_width, g_height); g_textures.init(g_device, g_queue); ProceduralTextureDef noise_def; noise_def.width = 256; noise_def.height = 256; noise_def.gen_func = gen_periodic_noise; noise_def.params = {1234.0f, 16.0f}; // Seed, Frequency (Increased for more detail) g_textures.create_procedural_texture("noise", noise_def); g_renderer.set_noise_texture(g_textures.get_texture_view("noise")); setup_scene(); g_camera.position = vec3(0, 5, 10); g_camera.target = vec3(0, 0, 0); float time = 0.0f; while (!platform_should_close()) { platform_poll(); time += 0.016f; float cam_radius = 10.0f + std::sin(time * 0.3f) * 4.0f; float cam_height = 5.0f + std::cos(time * 0.4f) * 3.0f; g_camera.set_look_at(vec3(std::sin(time * 0.5f) * cam_radius, cam_height, std::cos(time * 0.5f) * cam_radius), vec3(0, 0, 0), vec3(0, 1, 0)); for (size_t i = 1; i < g_scene.objects.size(); ++i) { g_scene.objects[i].rotation = quat::from_axis(vec3(0, 1, 0), time * 2.0f + i); g_scene.objects[i].position.y = std::sin(time * 3.0f + i) * 1.5f; } WGPUSurfaceTexture surface_tex; wgpuSurfaceGetCurrentTexture(g_surface, &surface_tex); if (surface_tex.status == WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal) { WGPUTextureViewDescriptor view_desc = {}; view_desc.format = g_format; view_desc.dimension = WGPUTextureViewDimension_2D; view_desc.baseMipLevel = 0; view_desc.mipLevelCount = 1; view_desc.baseArrayLayer = 0; view_desc.arrayLayerCount = 1; view_desc.aspect = WGPUTextureAspect_All; WGPUTextureView view = wgpuTextureCreateView(surface_tex.texture, &view_desc); g_renderer.render(g_scene, g_camera, time, view); wgpuTextureViewRelease(view); wgpuSurfacePresent(g_surface); wgpuTextureRelease(surface_tex.texture); } } g_renderer.shutdown(); g_textures.shutdown(); platform_shutdown(); return 0; }