summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/effects/shaders.cc8
-rw-r--r--src/gpu/effects/shaders.h2
-rw-r--r--src/gpu/texture_manager.cc354
-rw-r--r--src/gpu/texture_manager.h10
-rw-r--r--src/tests/test_3d_render.cc39
5 files changed, 399 insertions, 14 deletions
diff --git a/src/gpu/effects/shaders.cc b/src/gpu/effects/shaders.cc
index 5c6dd37..6ed82d5 100644
--- a/src/gpu/effects/shaders.cc
+++ b/src/gpu/effects/shaders.cc
@@ -103,6 +103,14 @@ const char* gen_noise_compute_wgsl =
SafeGetAsset(AssetId::ASSET_SHADER_COMPUTE_GEN_NOISE);
+const char* gen_perlin_compute_wgsl =
+
+ SafeGetAsset(AssetId::ASSET_SHADER_COMPUTE_GEN_PERLIN);
+
+const char* gen_grid_compute_wgsl =
+
+ SafeGetAsset(AssetId::ASSET_SHADER_COMPUTE_GEN_GRID);
+
const char* vignette_shader_wgsl =
SafeGetAsset(AssetId::ASSET_SHADER_VIGNETTE);
diff --git a/src/gpu/effects/shaders.h b/src/gpu/effects/shaders.h
index b629e30..a0f91da 100644
--- a/src/gpu/effects/shaders.h
+++ b/src/gpu/effects/shaders.h
@@ -19,3 +19,5 @@ extern const char* distort_shader_wgsl;
extern const char* chroma_aberration_shader_wgsl;
extern const char* vignette_shader_wgsl;
extern const char* gen_noise_compute_wgsl;
+extern const char* gen_perlin_compute_wgsl;
+extern const char* gen_grid_compute_wgsl;
diff --git a/src/gpu/texture_manager.cc b/src/gpu/texture_manager.cc
index aff106a..9a19957 100644
--- a/src/gpu/texture_manager.cc
+++ b/src/gpu/texture_manager.cc
@@ -22,6 +22,8 @@ void TextureManager::init(WGPUDevice device, WGPUQueue queue) {
device_ = device;
queue_ = queue;
noise_compute_pipeline_ = nullptr;
+ perlin_compute_pipeline_ = nullptr;
+ grid_compute_pipeline_ = nullptr;
}
void TextureManager::shutdown() {
@@ -34,6 +36,14 @@ void TextureManager::shutdown() {
wgpuComputePipelineRelease(noise_compute_pipeline_);
noise_compute_pipeline_ = nullptr;
}
+ if (perlin_compute_pipeline_) {
+ wgpuComputePipelineRelease(perlin_compute_pipeline_);
+ perlin_compute_pipeline_ = nullptr;
+ }
+ if (grid_compute_pipeline_) {
+ wgpuComputePipelineRelease(grid_compute_pipeline_);
+ grid_compute_pipeline_ = nullptr;
+ }
}
void TextureManager::create_procedural_texture(
@@ -297,6 +307,350 @@ void TextureManager::create_gpu_noise_texture(
#endif
}
+void TextureManager::dispatch_perlin_compute(WGPUTexture target,
+ const GpuProceduralParams& params) {
+ // Lazy-init compute pipeline
+ if (!perlin_compute_pipeline_) {
+ extern const char* gen_perlin_compute_wgsl;
+ ShaderComposer& composer = ShaderComposer::Get();
+ std::string resolved_shader = composer.Compose({}, gen_perlin_compute_wgsl);
+
+ WGPUShaderSourceWGSL wgsl_src = {};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(resolved_shader.c_str());
+ WGPUShaderModuleDescriptor shader_desc = {};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ WGPUShaderModule shader_module =
+ wgpuDeviceCreateShaderModule(device_, &shader_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[2] = {};
+ bgl_entries[0].binding = 0;
+ bgl_entries[0].visibility = WGPUShaderStage_Compute;
+ bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly;
+ bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm;
+ bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D;
+ bgl_entries[1].binding = 1;
+ bgl_entries[1].visibility = WGPUShaderStage_Compute;
+ bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform;
+ bgl_entries[1].buffer.minBindingSize = 32; // sizeof(PerlinParams)
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = 2;
+ bgl_desc.entries = bgl_entries;
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ WGPUPipelineLayoutDescriptor pl_desc = {};
+ pl_desc.bindGroupLayoutCount = 1;
+ pl_desc.bindGroupLayouts = &bind_group_layout;
+ WGPUPipelineLayout pipeline_layout =
+ wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+
+ WGPUComputePipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.compute.module = shader_module;
+ pipeline_desc.compute.entryPoint = str_view("main");
+
+ perlin_compute_pipeline_ =
+ wgpuDeviceCreateComputePipeline(device_, &pipeline_desc);
+
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+ wgpuShaderModuleRelease(shader_module);
+ }
+
+ // Create uniform buffer
+ struct PerlinParams {
+ uint32_t width;
+ uint32_t height;
+ float seed;
+ float frequency;
+ float amplitude;
+ float amplitude_decay;
+ uint32_t octaves;
+ float _pad0;
+ };
+ PerlinParams uniform_data = {
+ (uint32_t)params.width,
+ (uint32_t)params.height,
+ params.params[0], // seed
+ params.params[1], // frequency
+ params.num_params > 2 ? params.params[2] : 1.0f, // amplitude
+ params.num_params > 3 ? params.params[3] : 0.5f, // amplitude_decay
+ params.num_params > 4 ? (uint32_t)params.params[4] : 4u, // octaves
+ 0.0f // padding
+ };
+
+ WGPUBufferDescriptor buf_desc = {};
+ buf_desc.size = sizeof(PerlinParams);
+ buf_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst;
+ buf_desc.mappedAtCreation = WGPUOptionalBool_True;
+ WGPUBuffer uniform_buf = wgpuDeviceCreateBuffer(device_, &buf_desc);
+ void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, sizeof(PerlinParams));
+ memcpy(mapped, &uniform_data, sizeof(PerlinParams));
+ wgpuBufferUnmap(uniform_buf);
+
+ WGPUTextureViewDescriptor view_desc = {};
+ view_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ view_desc.dimension = WGPUTextureViewDimension_2D;
+ view_desc.mipLevelCount = 1;
+ view_desc.arrayLayerCount = 1;
+ WGPUTextureView target_view = wgpuTextureCreateView(target, &view_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[2] = {};
+ bgl_entries[0].binding = 0;
+ bgl_entries[0].visibility = WGPUShaderStage_Compute;
+ bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly;
+ bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm;
+ bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D;
+ bgl_entries[1].binding = 1;
+ bgl_entries[1].visibility = WGPUShaderStage_Compute;
+ bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform;
+ bgl_entries[1].buffer.minBindingSize = 32;
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = 2;
+ bgl_desc.entries = bgl_entries;
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ WGPUBindGroupEntry bg_entries[2] = {};
+ bg_entries[0].binding = 0;
+ bg_entries[0].textureView = target_view;
+ bg_entries[1].binding = 1;
+ bg_entries[1].buffer = uniform_buf;
+ bg_entries[1].size = sizeof(PerlinParams);
+
+ WGPUBindGroupDescriptor bg_desc = {};
+ bg_desc.layout = bind_group_layout;
+ bg_desc.entryCount = 2;
+ bg_desc.entries = bg_entries;
+ WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup(device_, &bg_desc);
+
+ WGPUCommandEncoderDescriptor enc_desc = {};
+ WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, &enc_desc);
+ WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
+ wgpuComputePassEncoderSetPipeline(pass, perlin_compute_pipeline_);
+ wgpuComputePassEncoderSetBindGroup(pass, 0, bind_group, 0, nullptr);
+ wgpuComputePassEncoderDispatchWorkgroups(pass, (params.width + 7) / 8,
+ (params.height + 7) / 8, 1);
+ wgpuComputePassEncoderEnd(pass);
+
+ WGPUCommandBufferDescriptor cmd_desc = {};
+ WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, &cmd_desc);
+ wgpuQueueSubmit(queue_, 1, &cmd);
+
+ wgpuCommandBufferRelease(cmd);
+ wgpuCommandEncoderRelease(encoder);
+ wgpuComputePassEncoderRelease(pass);
+ wgpuBindGroupRelease(bind_group);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+ wgpuBufferRelease(uniform_buf);
+ wgpuTextureViewRelease(target_view);
+}
+
+void TextureManager::create_gpu_perlin_texture(
+ const std::string& name, const GpuProceduralParams& params) {
+ WGPUTextureDescriptor tex_desc = {};
+ tex_desc.usage =
+ WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding;
+ tex_desc.dimension = WGPUTextureDimension_2D;
+ tex_desc.size = {(uint32_t)params.width, (uint32_t)params.height, 1};
+ tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ tex_desc.mipLevelCount = 1;
+ tex_desc.sampleCount = 1;
+ WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc);
+
+ dispatch_perlin_compute(texture, params);
+
+ WGPUTextureViewDescriptor view_desc = {};
+ view_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ view_desc.dimension = WGPUTextureViewDimension_2D;
+ view_desc.mipLevelCount = 1;
+ view_desc.arrayLayerCount = 1;
+ WGPUTextureView view = wgpuTextureCreateView(texture, &view_desc);
+
+ GpuTexture gpu_tex;
+ gpu_tex.texture = texture;
+ gpu_tex.view = view;
+ gpu_tex.width = params.width;
+ gpu_tex.height = params.height;
+ textures_[name] = gpu_tex;
+
+#if !defined(STRIP_ALL)
+ printf("Generated GPU perlin texture: %s (%dx%d)\n", name.c_str(),
+ params.width, params.height);
+#endif
+}
+
+void TextureManager::dispatch_grid_compute(WGPUTexture target,
+ const GpuProceduralParams& params) {
+ // Lazy-init compute pipeline
+ if (!grid_compute_pipeline_) {
+ extern const char* gen_grid_compute_wgsl;
+ ShaderComposer& composer = ShaderComposer::Get();
+ std::string resolved_shader = composer.Compose({}, gen_grid_compute_wgsl);
+
+ WGPUShaderSourceWGSL wgsl_src = {};
+ wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
+ wgsl_src.code = str_view(resolved_shader.c_str());
+ WGPUShaderModuleDescriptor shader_desc = {};
+ shader_desc.nextInChain = &wgsl_src.chain;
+ WGPUShaderModule shader_module =
+ wgpuDeviceCreateShaderModule(device_, &shader_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[2] = {};
+ bgl_entries[0].binding = 0;
+ bgl_entries[0].visibility = WGPUShaderStage_Compute;
+ bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly;
+ bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm;
+ bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D;
+ bgl_entries[1].binding = 1;
+ bgl_entries[1].visibility = WGPUShaderStage_Compute;
+ bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform;
+ bgl_entries[1].buffer.minBindingSize = 16; // sizeof(GridParams)
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = 2;
+ bgl_desc.entries = bgl_entries;
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ WGPUPipelineLayoutDescriptor pl_desc = {};
+ pl_desc.bindGroupLayoutCount = 1;
+ pl_desc.bindGroupLayouts = &bind_group_layout;
+ WGPUPipelineLayout pipeline_layout =
+ wgpuDeviceCreatePipelineLayout(device_, &pl_desc);
+
+ WGPUComputePipelineDescriptor pipeline_desc = {};
+ pipeline_desc.layout = pipeline_layout;
+ pipeline_desc.compute.module = shader_module;
+ pipeline_desc.compute.entryPoint = str_view("main");
+
+ grid_compute_pipeline_ =
+ wgpuDeviceCreateComputePipeline(device_, &pipeline_desc);
+
+ wgpuPipelineLayoutRelease(pipeline_layout);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+ wgpuShaderModuleRelease(shader_module);
+ }
+
+ // Create uniform buffer
+ struct GridParams {
+ uint32_t width;
+ uint32_t height;
+ uint32_t grid_size;
+ uint32_t thickness;
+ };
+ GridParams uniform_data = {
+ (uint32_t)params.width,
+ (uint32_t)params.height,
+ params.num_params > 0 ? (uint32_t)params.params[0] : 32u, // grid_size
+ params.num_params > 1 ? (uint32_t)params.params[1] : 2u // thickness
+ };
+
+ WGPUBufferDescriptor buf_desc = {};
+ buf_desc.size = sizeof(GridParams);
+ buf_desc.usage = WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst;
+ buf_desc.mappedAtCreation = WGPUOptionalBool_True;
+ WGPUBuffer uniform_buf = wgpuDeviceCreateBuffer(device_, &buf_desc);
+ void* mapped = wgpuBufferGetMappedRange(uniform_buf, 0, sizeof(GridParams));
+ memcpy(mapped, &uniform_data, sizeof(GridParams));
+ wgpuBufferUnmap(uniform_buf);
+
+ WGPUTextureViewDescriptor view_desc = {};
+ view_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ view_desc.dimension = WGPUTextureViewDimension_2D;
+ view_desc.mipLevelCount = 1;
+ view_desc.arrayLayerCount = 1;
+ WGPUTextureView target_view = wgpuTextureCreateView(target, &view_desc);
+
+ WGPUBindGroupLayoutEntry bgl_entries[2] = {};
+ bgl_entries[0].binding = 0;
+ bgl_entries[0].visibility = WGPUShaderStage_Compute;
+ bgl_entries[0].storageTexture.access = WGPUStorageTextureAccess_WriteOnly;
+ bgl_entries[0].storageTexture.format = WGPUTextureFormat_RGBA8Unorm;
+ bgl_entries[0].storageTexture.viewDimension = WGPUTextureViewDimension_2D;
+ bgl_entries[1].binding = 1;
+ bgl_entries[1].visibility = WGPUShaderStage_Compute;
+ bgl_entries[1].buffer.type = WGPUBufferBindingType_Uniform;
+ bgl_entries[1].buffer.minBindingSize = 16;
+
+ WGPUBindGroupLayoutDescriptor bgl_desc = {};
+ bgl_desc.entryCount = 2;
+ bgl_desc.entries = bgl_entries;
+ WGPUBindGroupLayout bind_group_layout =
+ wgpuDeviceCreateBindGroupLayout(device_, &bgl_desc);
+
+ WGPUBindGroupEntry bg_entries[2] = {};
+ bg_entries[0].binding = 0;
+ bg_entries[0].textureView = target_view;
+ bg_entries[1].binding = 1;
+ bg_entries[1].buffer = uniform_buf;
+ bg_entries[1].size = sizeof(GridParams);
+
+ WGPUBindGroupDescriptor bg_desc = {};
+ bg_desc.layout = bind_group_layout;
+ bg_desc.entryCount = 2;
+ bg_desc.entries = bg_entries;
+ WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup(device_, &bg_desc);
+
+ WGPUCommandEncoderDescriptor enc_desc = {};
+ WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(device_, &enc_desc);
+ WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(encoder, nullptr);
+ wgpuComputePassEncoderSetPipeline(pass, grid_compute_pipeline_);
+ wgpuComputePassEncoderSetBindGroup(pass, 0, bind_group, 0, nullptr);
+ wgpuComputePassEncoderDispatchWorkgroups(pass, (params.width + 7) / 8,
+ (params.height + 7) / 8, 1);
+ wgpuComputePassEncoderEnd(pass);
+
+ WGPUCommandBufferDescriptor cmd_desc = {};
+ WGPUCommandBuffer cmd = wgpuCommandEncoderFinish(encoder, &cmd_desc);
+ wgpuQueueSubmit(queue_, 1, &cmd);
+
+ wgpuCommandBufferRelease(cmd);
+ wgpuCommandEncoderRelease(encoder);
+ wgpuComputePassEncoderRelease(pass);
+ wgpuBindGroupRelease(bind_group);
+ wgpuBindGroupLayoutRelease(bind_group_layout);
+ wgpuBufferRelease(uniform_buf);
+ wgpuTextureViewRelease(target_view);
+}
+
+void TextureManager::create_gpu_grid_texture(
+ const std::string& name, const GpuProceduralParams& params) {
+ WGPUTextureDescriptor tex_desc = {};
+ tex_desc.usage =
+ WGPUTextureUsage_StorageBinding | WGPUTextureUsage_TextureBinding;
+ tex_desc.dimension = WGPUTextureDimension_2D;
+ tex_desc.size = {(uint32_t)params.width, (uint32_t)params.height, 1};
+ tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ tex_desc.mipLevelCount = 1;
+ tex_desc.sampleCount = 1;
+ WGPUTexture texture = wgpuDeviceCreateTexture(device_, &tex_desc);
+
+ dispatch_grid_compute(texture, params);
+
+ WGPUTextureViewDescriptor view_desc = {};
+ view_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ view_desc.dimension = WGPUTextureViewDimension_2D;
+ view_desc.mipLevelCount = 1;
+ view_desc.arrayLayerCount = 1;
+ WGPUTextureView view = wgpuTextureCreateView(texture, &view_desc);
+
+ GpuTexture gpu_tex;
+ gpu_tex.texture = texture;
+ gpu_tex.view = view;
+ gpu_tex.width = params.width;
+ gpu_tex.height = params.height;
+ textures_[name] = gpu_tex;
+
+#if !defined(STRIP_ALL)
+ printf("Generated GPU grid texture: %s (%dx%d)\n", name.c_str(),
+ params.width, params.height);
+#endif
+}
+
#if !defined(STRIP_ALL)
WGPUTextureView TextureManager::get_or_generate_gpu_texture(
const std::string& name, const GpuProceduralParams& params) {
diff --git a/src/gpu/texture_manager.h b/src/gpu/texture_manager.h
index 0cffe0c..b2dea84 100644
--- a/src/gpu/texture_manager.h
+++ b/src/gpu/texture_manager.h
@@ -46,6 +46,10 @@ class TextureManager {
// GPU procedural generation
void create_gpu_noise_texture(const std::string& name,
const GpuProceduralParams& params);
+ void create_gpu_perlin_texture(const std::string& name,
+ const GpuProceduralParams& params);
+ void create_gpu_grid_texture(const std::string& name,
+ const GpuProceduralParams& params);
#if !defined(STRIP_ALL)
// On-demand lazy generation (stripped in final builds)
@@ -59,8 +63,14 @@ class TextureManager {
private:
void dispatch_noise_compute(WGPUTexture target,
const GpuProceduralParams& params);
+ void dispatch_perlin_compute(WGPUTexture target,
+ const GpuProceduralParams& params);
+ void dispatch_grid_compute(WGPUTexture target,
+ const GpuProceduralParams& params);
WGPUDevice device_;
WGPUQueue queue_;
std::map<std::string, GpuTexture> textures_;
WGPUComputePipeline noise_compute_pipeline_ = nullptr;
+ WGPUComputePipeline perlin_compute_pipeline_ = nullptr;
+ WGPUComputePipeline grid_compute_pipeline_ = nullptr;
};
diff --git a/src/tests/test_3d_render.cc b/src/tests/test_3d_render.cc
index fa13a43..eee46ba 100644
--- a/src/tests/test_3d_render.cc
+++ b/src/tests/test_3d_render.cc
@@ -220,25 +220,36 @@ int main(int argc, char** argv) {
g_renderer.resize(platform_state.width, platform_state.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.push_back(1234.0f);
- noise_def.params.push_back(16.0f);
- g_textures.create_procedural_texture("noise", noise_def);
+ // GPU Noise texture (replaces CPU procedural)
+ GpuProceduralParams noise_params = {};
+ noise_params.width = 256;
+ noise_params.height = 256;
+ float noise_vals[2] = {1234.0f, 16.0f};
+ noise_params.params = noise_vals;
+ noise_params.num_params = 2;
+ g_textures.create_gpu_noise_texture("noise", noise_params);
g_renderer.set_noise_texture(g_textures.get_texture_view("noise"));
- ProceduralTextureDef sky_def;
- sky_def.width = 512;
- sky_def.height = 256;
- sky_def.gen_func = procedural::gen_perlin;
- sky_def.params = {42.0f, 4.0f, 1.0f, 0.5f, 6.0f};
- g_textures.create_procedural_texture("sky", sky_def);
-
+ // GPU Perlin texture for sky (replaces CPU procedural)
+ GpuProceduralParams sky_params = {};
+ sky_params.width = 512;
+ sky_params.height = 256;
+ float sky_vals[5] = {42.0f, 4.0f, 1.0f, 0.5f, 6.0f};
+ sky_params.params = sky_vals;
+ sky_params.num_params = 5;
+ g_textures.create_gpu_perlin_texture("sky", sky_params);
g_renderer.set_sky_texture(g_textures.get_texture_view("sky"));
+ // GPU Grid texture (new!)
+ GpuProceduralParams grid_params = {};
+ grid_params.width = 256;
+ grid_params.height = 256;
+ float grid_vals[2] = {32.0f, 2.0f}; // grid_size, thickness
+ grid_params.params = grid_vals;
+ grid_params.num_params = 2;
+ g_textures.create_gpu_grid_texture("grid", grid_params);
+
setup_scene();
g_camera.position = vec3(0, 5, 10);