summaryrefslogtreecommitdiff
path: root/src/3d/renderer.h
blob: 5c9fd38354cb355daf103164ea11d788e1bd3bb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// This file is part of the 64k demo project.
// It defines the Renderer3D class.
// Handles WebGPU pipeline creation and execution for 3D scenes.

#pragma once

#include "3d/camera.h"
#include "3d/scene.h"
#include "3d/bvh.h"
#include "gpu/gpu.h"
#include <map>
#include <vector>

#if !defined(STRIP_ALL)
#include "3d/visual_debug.h"
#endif

// Matches the GPU struct layout
struct GlobalUniforms {
  mat4 view_proj;
  mat4 inv_view_proj;   // Added for skybox/raymarching
  vec4 camera_pos_time; // xyz = camera_pos, w = time
  vec4 params;          // x = num_objects, yzw = padding
  vec2 resolution;
  vec2 padding;
};

// Matches the GPU struct layout
struct ObjectData {
  mat4 model;
  mat4 inv_model;
  vec4 color;
  vec4 params; // Type, etc.
};

class Renderer3D {
 public:
  void init(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format);
  void shutdown();

#if !defined(STRIP_ALL)
  static void SetDebugEnabled(bool enabled) {
    s_debug_enabled_ = enabled;
  }
#endif

  // Renders the scene to the given texture view (Convenience: creates a pass)
  void render(const Scene& scene, const Camera& camera, float time,
              WGPUTextureView target_view,
              WGPUTextureView depth_view_opt = nullptr);

  // Records draw commands to an existing pass.
  // Assumes the pass has a compatible pipeline (or we set it here).
  void draw(WGPURenderPassEncoder pass, const Scene& scene,
            const Camera& camera, float time);

  void set_noise_texture(WGPUTextureView noise_view);
  void set_sky_texture(WGPUTextureView sky_view);

  void add_debug_aabb(const vec3& min, const vec3& max, const vec3& color);

  // Resize handler (if needed for internal buffers)
  void resize(int width, int height);

  // Set whether to use BVH acceleration
  void SetBvhEnabled(bool enabled) { bvh_enabled_ = enabled; }

  struct MeshGpuData {
    WGPUBuffer vertex_buffer;
    WGPUBuffer index_buffer;
    uint32_t num_indices;
  };

  // HACK for test_mesh tool
  void override_mesh_buffers(const MeshGpuData* data) {
    temp_mesh_override_ = data;
  }

#if !defined(STRIP_ALL)
  VisualDebug& GetVisualDebug() { return visual_debug_; }
#endif

 private:

  void create_pipeline();
  WGPURenderPipeline create_pipeline_impl(bool use_bvh);
  void create_mesh_pipeline();
  void create_skybox_pipeline();
  void create_default_resources();
  void update_uniforms(const Scene& scene, const Camera& camera, float time);
  const MeshGpuData* get_or_create_mesh(AssetId asset_id);

  WGPUDevice device_ = nullptr;
  WGPUQueue queue_ = nullptr;
  WGPUTextureFormat format_ = WGPUTextureFormat_Undefined;

  WGPURenderPipeline pipeline_ = nullptr;        // BVH enabled
  WGPURenderPipeline pipeline_no_bvh_ = nullptr; // BVH disabled
  WGPUBindGroup bind_group_ = nullptr;
  WGPURenderPipeline mesh_pipeline_ = nullptr;
  WGPURenderPipeline skybox_pipeline_ = nullptr;
  WGPUBindGroup skybox_bind_group_ = nullptr;
  WGPUBuffer global_uniform_buffer_ = nullptr;
  WGPUBuffer object_storage_buffer_ = nullptr;
  WGPUBuffer bvh_storage_buffer_ = nullptr;

  BVH cpu_bvh_; // Keep a CPU-side copy for building/uploading
  bool bvh_enabled_ = true;

  std::map<AssetId, MeshGpuData> mesh_cache_;
  const MeshGpuData* temp_mesh_override_ = nullptr; // HACK for test_mesh tool

  WGPUTextureView noise_texture_view_ = nullptr;
  WGPUTextureView sky_texture_view_ = nullptr;
  WGPUSampler default_sampler_ = nullptr;

  // Depth buffer management
  WGPUTexture depth_texture_ = nullptr;
  WGPUTextureView depth_view_ = nullptr;
  int width_ = 0;
  int height_ = 0;

  // Max objects capacity
  static const int kMaxObjects = 100;

#if !defined(STRIP_ALL)
  VisualDebug visual_debug_;
  static bool s_debug_enabled_;
#endif
};