scene

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Scene

type Scene interface {
	common.Delegate[Scene]

	// Name returns the scene's identifier.
	Name() string

	// SetName sets the scene's identifier.
	SetName(name string)

	// Active returns whether this scene is currently active for rendering.
	Active() bool

	// SetActive sets whether this scene is active for rendering.
	SetActive(active bool)

	// Camera returns the scene's camera.
	Camera() camera.Camera

	// SetCamera replaces the scene's camera.
	//
	// Parameters:
	//   - cam: the new camera
	SetCamera(cam camera.Camera)

	// Renderer returns the scene's renderer.
	Renderer() renderer.Renderer

	// SetRenderer replaces the scene's renderer.
	//
	// Parameters:
	//   - r: the new renderer
	SetRenderer(r renderer.Renderer)

	// SetPhysicsHandler replaces the scene's physics handler. This should be called
	// before adding any rigid body objects. If not set, a default handler is created
	// lazily when the first rigid body object is added.
	//
	// Parameters:
	//   - ph: the pre-configured Physics instance
	SetPhysicsHandler(ph physics.Physics)

	// Count returns the number of persisted GameObjects in the scene's registry. Does not include ephemeral objects.
	//
	// Returns:
	//   - int: count of non-ephemeral GameObjects in the registry
	Count() int

	// CountEphemeral returns the number of ephemeral GameObjects currently being rendered through the scene's animators.
	//
	// Returns:
	//   - int: count of ephemeral GameObjects currently rendered
	CountEphemeral() int

	// Add adds a GameObject to the scene. The scene's Renderer must be attached
	// and the object must carry a Model. The scene automatically creates and manages
	// an Animator for each unique Model, registers its compute and render pipelines,
	// initializes GPU resources, and adds a new instance wired with the object's
	// initial transform data. If the object is not ephemeral it is also persisted
	// in the registry for later lookup or removal by ID.
	//
	// Compute, vertex, and fragment shaders are resolved automatically from the
	// engine's standard shader assets based on whether the model is skinned.
	//
	// Panics if the scene has no Renderer or the object has no Model.
	//
	// Parameters:
	//   - obj: the GameObject to add
	//   - pipelineOpts: optional pipeline builder options for the render pipeline (e.g., blending)
	//
	// Returns:
	//   - uint64: the assigned object ID
	Add(obj game_object.GameObject, pipelineOpts ...pipeline.PipelineBuilderOption) uint64

	// Get retrieves a non-ephemeral GameObject by its ID.
	// Returns nil if not found.
	//
	// Parameters:
	//   - id: the object's unique ID
	//
	// Returns:
	//   - game_object.GameObject: the object or nil
	Get(id uint64) game_object.GameObject

	// Remove removes a non-ephemeral GameObject from the registry by ID
	// and swap-removes the instance data from its animator.
	//
	// Parameters:
	//   - id: the object's unique ID
	Remove(id uint64)

	// PrepareCompute updates camera matrices, advances animation state,
	// uploads staged buffer writes, and dispatches all compute shaders for this scene.
	// Must be called within a BeginComputeFrame/EndComputeFrame block on the renderer.
	//
	// Parameters:
	//   - deltaTime: elapsed time since the last frame in seconds
	PrepareCompute(deltaTime float32)

	// CullingDisabled returns whether GPU frustum culling is explicitly disabled for this scene.
	// When true, the scene will not distribute frustum planes to animators, keeping them in
	// non-culled mode even when a camera is present.
	//
	// Returns:
	//   - bool: true if culling is disabled
	CullingDisabled() bool

	// SetCullingDisabled enables or disables GPU frustum culling for this scene.
	// When set to true, the scene skips frustum plane distribution and animators
	// fall back to non-culled rendering with regular draw calls.
	//
	// Parameters:
	//   - disabled: true to disable culling, false to enable it
	SetCullingDisabled(disabled bool)

	// DrawCalls issues instanced draw calls for each registered animator.
	// Must be called within a BeginFrame/EndFrame block on the renderer.
	//
	// Returns:
	//   - error: error if a draw call fails
	DrawCalls() error

	// AddLight adds a light source to the scene and lazily initializes the full
	// lighting pipeline (light storage buffer, shadow map, Forward+ culling) on
	// the first call. Subsequent calls simply append the light without
	// re-initializing GPU resources. The lighting shaders are loaded internally
	// from the engine's standard light shader assets. Screen dimensions for
	// Forward+ tile culling are taken from the scene's stored screen size
	// (set via Resize or WithScreenSize).
	//
	// Parameters:
	//   - l: the Light to add
	AddLight(l light.Light)

	// Resize updates the scene's stored screen dimensions and propagates the
	// change to the renderer surface, camera aspect ratio, and (when lighting
	// is enabled) the Forward+ tile grid. Call this from the window's resize
	// callback or whenever the surface dimensions change.
	//
	// Parameters:
	//   - width: the new width in pixels
	//   - height: the new height in pixels
	Resize(width, height int)

	// RemoveLight removes a light source from the scene by reference.
	//
	// Parameters:
	//   - l: the Light to remove
	RemoveLight(l light.Light)

	// DetachLight removes a game object's attached light from the scene's tracking
	// and light lists. This is the cleanup counterpart for objects whose lights
	// were auto-registered during Add(). Non-ephemeral objects are cleaned up
	// automatically via Remove(), but ephemeral object owners must call this
	// explicitly when the object's lifetime ends.
	//
	// Parameters:
	//   - obj: the GameObject whose attached light should be detached
	DetachLight(obj game_object.GameObject)

	// Lights returns all lights currently registered in the scene.
	//
	// Returns:
	//   - []light.Light: the scene's light list
	Lights() []light.Light

	// AmbientColor returns the scene's ambient light color.
	//
	// Returns:
	//   - [3]float32: the ambient RGB color
	AmbientColor() [3]float32

	// SetAmbientColor sets the scene's ambient light color.
	//
	// Parameters:
	//   - color: the ambient RGB color
	SetAmbientColor(color [3]float32)

	// PrepareShadows computes the directional light's view-projection, updates the
	// shadow uniform buffer, and renders the depth-only shadow pass for all drawables.
	// Must be called after PrepareCompute and before BeginFrame each frame.
	// No-ops if no shadow map has been initialized or no shadow-casting directional
	// light exists.
	PrepareShadows()

	// PrepareShadowBlur runs the VSM post-processing step: either separable Gaussian
	// blur passes (constant-width soft shadows) or SAT generation (PCSS variable-width).
	// Must be called after PrepareShadows and after the shadow render pass has been
	// submitted to the GPU (i.e. after EndGeometryFrame when using merged geometry passes).
	PrepareShadowBlur()

	// PrepareLightCulling updates the light cull uniform buffer and dispatches the
	// light culling compute shader. Must be called after PrepareCompute (so lights
	// are uploaded) and before DrawCalls.
	PrepareLightCulling()

	// PrepareGBuffer renders the G-Buffer MRT pre-pass for all drawables.
	// Writes world position, normals, and albedo to off-screen textures
	// consumed by screen-space effects (SSAO, SSR). Must be called after
	// PrepareCompute and before PrepareSSAO each frame.
	// No-ops if the G-Buffer subsystem has not been initialized.
	PrepareGBuffer()

	// PrepareSSAO dispatches the SSAO hemisphere sampling compute shader
	// and the bilateral blur passes. Must be called after PrepareGBuffer
	// (so G-Buffer textures are populated) and before DrawCalls.
	// No-ops if the SSAO subsystem has not been initialized.
	PrepareSSAO()

	// PrepareProbes performs incremental probe baking for the irradiance probe
	// grid. For each dirty probe, renders 6 cubemap faces into the bake
	// texture, then dispatches the SH projection compute shader to accumulate
	// L2 spherical harmonic coefficients into the probe storage buffer.
	// Must be called after PrepareCompute and before DrawCalls each frame.
	// No-ops if the probe grid subsystem has not been initialized or there
	// are no dirty probes.
	PrepareProbes()

	// PrepareSSR dispatches the SSR compute shader to perform screen-space ray
	// marching against the G-Buffer. Must be called after DrawCalls (so the HDR
	// texture is populated) and before PrepareComposition. No-ops if the SSR
	// subsystem has not been initialized.
	PrepareSSR()

	// PrepareComposition runs the fullscreen composition pass: acquires the
	// swapchain, samples the HDR lit texture and optional SSR texture, applies
	// ACES tone mapping and gamma correction, and writes the final LDR result
	// to the swapchain. Must be called after DrawCalls (and PrepareSSR if active)
	// and before Present. No-ops if the composition subsystem has not been
	// initialized.
	PrepareComposition()

	// BeginHDRFrame starts the HDR render pass using this scene's composition
	// handler textures. Returns an error if the composition handler is
	// not initialized or the render pass cannot be started.
	//
	// Returns:
	//   - error: an error if the HDR frame could not be started
	BeginHDRFrame() error
}

Scene manages a collection of Animators (registered implicitly via Add) and an optional registry of non-ephemeral GameObjects, with a Camera and Renderer for rendering. Rendering is driven entirely by the registered Animator list — each Animator owns its instance data and material. Scenes can be hot-swapped via the Active flag to switch between different views or levels. Thread-safe for concurrent access.

func NewScene

func NewScene(name string, cam camera.Camera, r renderer.Renderer, options ...SceneBuilderOption) Scene

NewScene creates a new Scene with the given camera and renderer. Both are required and NewScene panics if either is nil. The camera's bind group layout is resolved from the pre-processor declarations of the engine's standard vertex shader (engine/model/assets/simple-vert.wgsl).

Parameters:

  • name: the name of the scene
  • cam: the camera to attach (must not be nil)
  • r: the renderer to attach (must not be nil)
  • options: functional options to further configure the scene

Returns:

  • Scene: the newly created scene

type SceneBuilderOption

type SceneBuilderOption func(s *scene)

SceneBuilderOption is a functional option for configuring a Scene. Use the With* functions to create options.

func WithActive

func WithActive(active bool) SceneBuilderOption

WithActive sets whether the scene is active for rendering.

Parameters:

  • active: whether the scene is active

Returns:

  • SceneBuilderOption: option function to apply

func WithComputeWorkers

func WithComputeWorkers(n int) SceneBuilderOption

WithComputeWorkers sets the number of worker goroutines used during the parallel CPU prep phase of PrepareCompute. Defaults to runtime.NumCPU()-1. Higher values may improve throughput with many animator groups or skeletal animators; lower values reduce scheduling overhead for simple scenes.

Parameters:

  • n: the number of compute workers (minimum 1)

Returns:

  • SceneBuilderOption: option function to apply

func WithCullingDisabled

func WithCullingDisabled(disabled bool) SceneBuilderOption

WithCullingDisabled disables GPU frustum culling for the scene. When set to true, the scene will not distribute frustum planes to animators, causing them to remain in non-culled mode and use regular draw calls instead of indirect draw calls. By default culling is enabled (disabled = false).

Parameters:

  • disabled: true to disable frustum culling, false to enable it (default)

Returns:

  • SceneBuilderOption: option function to apply

func WithLighting added in v0.1.0

func WithLighting(handler light.LightingHandler) SceneBuilderOption

WithLighting attaches a pre-configured LightingHandler to the scene, replacing the default handler created by NewScene. Use light.NewLightingHandler with light.WithShadow* options to configure shadow mapping and ambient color before passing the handler here. GPU resources are initialized lazily when the first light is added via AddLight.

Parameters:

  • handler: the pre-configured LightingHandler

Returns:

  • SceneBuilderOption: option function to apply

func WithObjects

func WithObjects(objects ...game_object.GameObject) SceneBuilderOption

WithObjects adds initial objects to the scene. Objects without IDs will be assigned new IDs. Non-ephemeral objects are persisted in the registry; their animators are auto-registered.

Parameters:

  • objects: the objects to add

Returns:

  • SceneBuilderOption: option function to apply

func WithPhysics added in v0.1.0

func WithPhysics(opts ...physics.PhysicsBuilderOption) SceneBuilderOption

WithPhysics creates a Physics instance with the given options and attaches it to the scene. GPU resources are initialized lazily when the first rigid body object is added via Add. If not called, objects with RigidBodies will be rendered without physics simulation — no forces, collisions, or integration will be applied.

Parameters:

  • opts: variadic physics builder options to configure the physics simulation

Returns:

  • SceneBuilderOption: option function to apply

func WithScreenSize added in v0.1.0

func WithScreenSize(width, height int) SceneBuilderOption

WithScreenSize sets the initial screen dimensions on the scene. These dimensions are used for Forward+ tile culling calculations and are automatically updated when Resize is called. If not set, AddLight will use zero dimensions until the first Resize call.

Parameters:

  • width: screen width in pixels
  • height: screen height in pixels

Returns:

  • SceneBuilderOption: option function to apply

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL