diff options
Diffstat (limited to 'src/tests')
| -rw-r--r-- | src/tests/test_3d.cc | 9 | ||||
| -rw-r--r-- | src/tests/test_3d_render.cc | 193 | ||||
| -rw-r--r-- | src/tests/test_texture_manager.cc | 26 |
3 files changed, 121 insertions, 107 deletions
diff --git a/src/tests/test_3d.cc b/src/tests/test_3d.cc index 33e6a04..88b8db9 100644 --- a/src/tests/test_3d.cc +++ b/src/tests/test_3d.cc @@ -33,10 +33,10 @@ void test_object_transform() { std::cout << "Testing Object Transform..." << std::endl; Object3D obj; obj.position = vec3(10, 0, 0); - + // Model matrix should translate by (10,0,0) mat4 m = obj.get_model_matrix(); - assert(near(m.m[12], 10.0f)); // Col 3, Row 0 is x translation in Col-Major? + assert(near(m.m[12], 10.0f)); // Col 3, Row 0 is x translation in Col-Major? // Wait, my mat4 struct: // r.m[12] = t.x; // Index 12 is translation X assert(near(m.m[12], 10.0f)); @@ -44,11 +44,12 @@ void test_object_transform() { // Rotate 90 deg Y obj.rotation = quat::from_axis(vec3(0, 1, 0), 1.570796f); m = obj.get_model_matrix(); - + // Transform point (1,0,0) -> Rot(0,0,-1) -> Trans(10,0,-1) vec4 p(1, 0, 0, 1); vec4 res = m * p; - assert(near(res.x, 10.0f)); // Rotated vector is (0,0,-1). + (10,0,0) translation -> (10,0,-1) + assert(near(res.x, 10.0f)); // Rotated vector is (0,0,-1). + (10,0,0) + // translation -> (10,0,-1) assert(near(res.z, -1.0f)); } diff --git a/src/tests/test_3d_render.cc b/src/tests/test_3d_render.cc index 4be7153..e4477a0 100644 --- a/src/tests/test_3d_render.cc +++ b/src/tests/test_3d_render.cc @@ -5,11 +5,13 @@ #include "3d/object.h" #include "3d/renderer.h" #include "3d/scene.h" +#include "gpu/texture_manager.h" #include "platform.h" -#include <iostream> -#include <vector> +#include "procedural/generator.h" #include <cmath> #include <cstring> +#include <iostream> +#include <vector> #if defined(DEMO_CROSS_COMPILE_WIN32) #include <webgpu/webgpu.h> @@ -19,6 +21,7 @@ // Global State static Renderer3D g_renderer; +static TextureManager g_textures; static Scene g_scene; static Camera g_camera; static WGPUDevice g_device = nullptr; @@ -29,18 +32,18 @@ static WGPUTextureFormat g_format = WGPUTextureFormat_Undefined; static int g_width = 1280; static int g_height = 720; -// Reimplementing basic WebGPU init here +// ... (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); + 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); + std::cerr << "Failed to create WGPU surface." << std::endl; + exit(1); } WGPURequestAdapterOptions adapter_opts = {}; @@ -50,21 +53,17 @@ void init_wgpu() { #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; - } else { - std::cerr << "Adapter Error: " << (message ? message : "null") << std::endl; - } + 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; - } else { - std::cerr << "Adapter Error: " << (message.data ? message.data : "null") << std::endl; - } + if (status == WGPURequestAdapterStatus_Success) { + *(WGPUAdapter*)userdata = adapter; + } }; WGPURequestAdapterCallbackInfo adapter_cb = {}; adapter_cb.mode = WGPUCallbackMode_WaitAnyOnly; @@ -73,34 +72,33 @@ void init_wgpu() { wgpuInstanceRequestAdapter(instance, &adapter_opts, adapter_cb); #endif - // Spin wait for adapter #if !defined(DEMO_CROSS_COMPILE_WIN32) while (!g_adapter) { - wgpuInstanceProcessEvents(instance); + wgpuInstanceProcessEvents(instance); } #endif - + if (!g_adapter) { - std::cerr << "Failed to get adapter." << std::endl; - exit(1); + 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; - } + 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; - } + if (status == WGPURequestDeviceStatus_Success) { + *(WGPUDevice*)userdata = device; + } }; WGPURequestDeviceCallbackInfo device_cb = {}; device_cb.mode = WGPUCallbackMode_WaitAnyOnly; @@ -108,19 +106,18 @@ void init_wgpu() { device_cb.userdata1 = &g_device; wgpuAdapterRequestDevice(g_adapter, &device_desc, device_cb); #endif - + #if !defined(DEMO_CROSS_COMPILE_WIN32) - // Poll until device is ready (WaitAny is unimplemented in current wgpu-native build) while (!g_device) { - wgpuInstanceProcessEvents(instance); + wgpuInstanceProcessEvents(instance); } #endif if (!g_device) { - std::cerr << "Failed to get device." << std::endl; - exit(1); + std::cerr << "Failed to get device." << std::endl; + exit(1); } - + g_queue = wgpuDeviceGetQueue(g_device); WGPUSurfaceCapabilities caps = {}; @@ -140,95 +137,105 @@ void init_wgpu() { void setup_scene() { g_scene.clear(); - // Center Red Cube (Wireframe Proxy) - Object3D center(ObjectType::CUBE); + Object3D center(ObjectType::BOX); center.position = vec3(0, 0, 0); center.color = vec4(1, 0, 0, 1); g_scene.add_object(center); - // Orbiting Objects 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; - + 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); - + + 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; // Approx 60fps - - // Animate Objects - 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; - } - - // Animate Camera Height and Radius + 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) - ); - - // Render Frame + 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); + 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); } - -#if !defined(DEMO_CROSS_COMPILE_WIN32) - // Poll events for wgpu-native to ensure callbacks fire and frame presents? - // We don't have easy access to instance here unless we store it globally. - // Let's just assume Present handles enough synchronization for this demo. -#endif } - + g_renderer.shutdown(); + g_textures.shutdown(); platform_shutdown(); return 0; } diff --git a/src/tests/test_texture_manager.cc b/src/tests/test_texture_manager.cc index 7f40447..5741d8c 100644 --- a/src/tests/test_texture_manager.cc +++ b/src/tests/test_texture_manager.cc @@ -1,5 +1,6 @@ // This file is part of the 64k demo project. -// It tests the TextureManager (mocking the GPU parts where possible or running with valid device). +// It tests the TextureManager (mocking the GPU parts where possible or running +// with valid device). #include "gpu/texture_manager.h" #include "procedural/generator.h" @@ -15,28 +16,33 @@ // Forward decls from platform.h or similar (simplifying for test) // Note: This test requires a valid WebGPU device, which is hard in CI/headless. // We will structure it to compile, but runtime might skip if no device. -// For now, we just test the C++ side logic if possible, but TextureManager depends heavily on WGPU calls. +// For now, we just test the C++ side logic if possible, but TextureManager +// depends heavily on WGPU calls. // We will use a "Headless" approach if possible, or just skip if Init fails. -// Actually, let's just make it a compilation test + basic logic check if we can mock or stub. -// Since we don't have a mocking framework, we'll try to init wgpu-native. +// Actually, let's just make it a compilation test + basic logic check if we can +// mock or stub. Since we don't have a mocking framework, we'll try to init +// wgpu-native. int main() { - // Need to init GLFW for surface creation usually, even for headless in some impls? + // Need to init GLFW for surface creation usually, even for headless in some + // impls? if (!glfwInit()) { std::cerr << "Failed to init GLFW" << std::endl; return 1; } - + // NOTE: In a real CI environment without GPU, this will likely fail or hang. - // For this "demo" context, we assume the user has a GPU or we just verify it compiles. - // We'll skip actual GPU init for this simple test to avoid hanging the agent if no GPU. + // For this "demo" context, we assume the user has a GPU or we just verify it + // compiles. We'll skip actual GPU init for this simple test to avoid hanging + // the agent if no GPU. std::cout << "TextureManager Compilation Test Passed." << std::endl; - + /* TextureManager tm; // tm.init(device, queue); // execution would happen here - // tm.create_procedural_texture("noise", {256, 256, procedural::gen_noise, {1234, 1.0f}}); + // tm.create_procedural_texture("noise", {256, 256, procedural::gen_noise, + {1234, 1.0f}}); */ return 0; |
