simvx.graphics.renderer.post_process¶
Post-processing pass: HDR tone mapping, FXAA, bloom, DoF, motion blur, film grain, vignette, chromatic aberration.
Module Contents¶
Classes¶
Renders HDR scene to offscreen target, then tone-maps to swapchain. |
Functions¶
Recover (near, far) from a reverse-Z projection matrix. |
Data¶
API¶
- simvx.graphics.renderer.post_process.__all__¶
[‘PostProcessPass’, ‘near_far_from_proj’]
- simvx.graphics.renderer.post_process.log¶
‘getLogger(…)’
- simvx.graphics.renderer.post_process.near_far_from_proj(proj: numpy.ndarray) tuple[float, float]¶
Recover (near, far) from a reverse-Z projection matrix.
For SimVX’s perspective (
perspective()in core.math): row-major,m[2,2] = n/(f-n),m[2,3] = fn/(f-n),m[3,2] = -1(the Vulkan Y-flip only touchesm[1,1]). For its orthographic,m[2,2] = 1/(f-n)andm[2,3] = f/(f-n)with a constant w row, which is what tells the two apart. Both invert asn = m23 / (m22 + 1)under perspective andf = m23 / m22under either. Falls back to a sane 0.1/100 if the matrix is degenerate.A camera’s near and far planes are nowhere else in the render path:
- Class:
~simvx.graphics.types.Viewportcarries only the two matrices, so anything that needs the planes recovers them from the projection here.
- simvx.graphics.renderer.post_process.FLAG_FXAA¶
None
- simvx.graphics.renderer.post_process.FLAG_BLOOM¶
None
- simvx.graphics.renderer.post_process.FLAG_SSAO¶
None
- simvx.graphics.renderer.post_process.FLAG_DOF¶
None
- simvx.graphics.renderer.post_process.FLAG_GRAIN¶
None
- simvx.graphics.renderer.post_process.FLAG_VIGNETTE¶
None
- simvx.graphics.renderer.post_process.FLAG_CHROMATIC¶
None
- simvx.graphics.renderer.post_process.FLAG_MOTION_BLUR¶
None
- simvx.graphics.renderer.post_process.FLAG_VOLUMETRIC_FOG¶
None
- simvx.graphics.renderer.post_process.FLAG_LUT¶
None
- simvx.graphics.renderer.post_process.FLAG_CRT¶
None
- simvx.graphics.renderer.post_process.FLAG_PIXELATE¶
None
- simvx.graphics.renderer.post_process.FLAG_BLUR¶
None
- class simvx.graphics.renderer.post_process.PostProcessPass(engine: Any)¶
Renders HDR scene to offscreen target, then tone-maps to swapchain.
The pass owns an HDR render target. When enabled:
3D scene renders to the HDR target (pre_render phase)
Bloom extraction + blur (optional)
Tone mapping + FXAA + cinematic effects renders to swapchain (main render pass)
Initialization
- property enabled: bool¶
- property hdr_target: simvx.graphics.renderer.render_target.RenderTarget | None¶
- property gbuffer_view: Any¶
Thin G-buffer normal/roughness view, or
Nonewhen inactive.
- property bloom_enabled: bool¶
- property motion_blur_enabled: bool¶
- property lut_tex_id: int¶
- setup() None¶
Initialize HDR target and tonemap pipeline.
- update_ssao_descriptor(ao_view: Any) None¶
Update binding 4 with the SSAO output image view.
- register_lut(tex_id: int, lut_data: numpy.ndarray, *, pool: Any) None¶
Upload a 3D colour-grading LUT and register it under
tex_id.lut_datais an(size, size, size, 4)uint8 array (the format produced bycolour_grading.generate_*_lut), uploaded as a 3Drgba8image: byte-for-byte the web runtime’s LUT representation. Re-registering an id replaces the previous texture. Select the active LUT withlut_tex_id.poolis the command pool the staging copy is recorded into, passed down to :func:~.colour_grading.upload_lut_3d, whose docstring says which pool each caller owes.Engine.register_lutis the tick-time entry point and hands over the engine’s upload pool with its lock held.
- update_motion_blur_matrices(view: numpy.ndarray, proj: numpy.ndarray) None¶
Update the motion blur UBO with current inverse VP and previous VP.
Call once per frame before render_tonemap() with the current camera matrices. Uses temporal smoothing to prevent sudden jumps from frame time variance.
- next_taa_jitter(width: float, height: float) tuple[float, float]¶
Advance the Halton jitter index and return this frame’s sub-pixel offset.
Called once per frame (only when
taa_enabled) before the forward draw. The renderer applies the returned offset to the forward-draw projection via :func:simvx.core.math.apply_jitter, while leaving the unjitteredcamera_projintact for culling and motion-vector reprojection. The jitter is stored so :meth:taa_jittercan hand it to the resolve pass.width/heightare the render extent; the offset is in pixels.
- update_taa_matrices(view: numpy.ndarray, proj: numpy.ndarray) None¶
Capture the unjittered current/previous view-projection for TAA resolve.
Call once per frame (only when
taa_enabled) with the clean (unjittered) camera matrices, before the forward pass jitters its own projection copy. Stores the current VP, its inverse, and rolls the previous-frame VP so the future resolve pass can reconstruct each pixel’s world position from depth and reproject it through the previous VP (camera + static-geometry motion).Independent of motion blur so TAA functions whether or not motion blur is enabled. On the first frame
prev_vp == cur_vpto avoid a velocity spike.
- property taa_jitter: tuple[float, float]¶
This frame’s applied sub-pixel jitter (pixels); for un-jittering in resolve.
- property taa_cur_vp: numpy.ndarray¶
Unjittered current-frame view-projection (row-major).
- property taa_prev_vp: numpy.ndarray¶
Unjittered previous-frame view-projection (row-major).
- property taa_inv_vp: numpy.ndarray¶
Inverse of the unjittered current VP (depth->world for resolve).
- property taa_depth_view: Any¶
HDR target’s samplable depth view: the resolve pass’s reprojection source.
- begin_hdr_pass(cmd: Any) None¶
Begin the HDR render pass (call before 3D rendering).
- end_hdr_pass(cmd: Any) None¶
End the HDR render pass.
- rebegin_hdr_pass(cmd: Any) None¶
Re-begin the HDR pass with the colour+depth LOAD variant.
Used by the scene-read pass split: after
end_hdr_passand the scene colour/depth copy, this loads the opaque colour + depth (no clear) so the transparent phase blends over the scene and depth-tests against it.
- render_bloom(cmd: Any) None¶
Execute bloom pass (extract + blur). Call after end_hdr_pass.
- render_tonemap(cmd: Any, x: int, y: int, width: int, height: int) None¶
Render the tone-mapped quad into
(x, y, width, height)of the swapchain.The whole swapchain in the ordinary case. A letterboxed presentation passes its sub-rect: the fullscreen triangle’s UVs still span the whole HDR target, so the scene arrives scaled into the rect, and the scissor leaves the bars carrying the swapchain’s own clear rather than post-processed clear colour.
- resize(width: int, height: int) None¶
Recreate HDR target and pipeline for new dimensions.
- cleanup() None¶
Release all GPU resources.