GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Implement basic rendering flow by tychedelia · Pull Request #1322 · processing/processing4

Conversation

@tychedelia

@tychedelia tychedelia commented Nov 11, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Rendering

Closes #1271

Processing has a rendering lifecycle for each PGraphics instance:

  • beginDraw: called at beginning of frame or manually by the user to initialize the drawing state for a given surface. For us, this doesn't do much at the moment.
  • flush: this lifecyle hook was added for OpenGL in order to flush accumulated state to the gpu. We'll use this similarly to render the currently accumulated draw state. TBD if the appropriate flushes are added everywhere we need them relative to what OpenGL does.
  • endDraw: called at the end of frame or manually by the user to write to the surface/render target.

Bevy's rendering loop

Bevy uses pipelined rendering. Specifically, there is an ECS "main" world and "render" world that run on separate timelines. We've currently disabled ECS multi-threading to ensure comparability, which means that the render world schedule runs after the main world serially, but conceptually they should be understood as independent. This isn't relevant for reviewing this PR but is an important implementation detail to know in general.

A Camera in Bevy represents a coarse grained unit of rendering work tied to an output render target. In other words, Camera == PGraphics and RenderTarget == PSurface for our concerns. Bevy really want to batch, both cameras and render state internal to cameras (i.e. opaque render items). On the contrary, processing really wants to force immediate mode.

In Bevy, every camera renders to a ViewTarget, which is an intermediate texture that accumulates rendering state while walking the render graph. At the end of the render graph, that texture is blitted to the RenderTarget which will be presented at the end of the frame.

This is important for understanding how clear state and ClearColorConfig works.... The clear_color field on Camera controls the clear for the internal rendering texture. Right now we are setting this with background color, but it should basically always be load in order to preserve the sketch across flushes. The output_mode field contains CameraOutputMode, which controls whether that internal texture is written to the render target at the end of the processing the camera. For us, we only want to set CameraOutputMode::Write on endDraw, which means we set Skip by default to preserve immediate mode semantics.

Bridging immediate mode and batching

This PR faithfully implements the processing lifecycle, which requires a bit of juggling to ensure that we are only ever processing one Camera at a time. This will be important for preserving backwards compatibility with #1320, although we may be able to do additional optimization in the future.

Every time the user calls a processing API that needs to update the draw state, we record a DrawCommand that is stored in a buffer on the surface (typically the Window entity, this PR does not yet support off-screen rendering).

At the start of every App update, we ensure that all cameras are disabled by setting active = false, this ensures that regardless of the configured output_mode, that camera will not be processed for rendering. In Bevy terms, this guarantees the camera is not extracted to the render world.

When flush is called, we insert a market component Flushing on the surface that we intend to flush. First, we clear any previous meshes associated with this surface. Then, we ensure the camera is set to active and thus we process only that camera.

We then drain the command buffer for that camera and render into a new set of meshes. We are using the lyon library to handle tessellation. See that libraries docs to understand how it works.

We currently implement some very simple batching logic meant to preserve the painter's algo used by Processing. Basically, we'll continue rendering into what I affectionately call a "mega mesh" that contains all the primitives (i.e. vertex data) for items that share the same material state. In this way, vertex order preserves the imperative draw order. We also apply a small z offset to ensure that when breaking up batches, we still draw in the correct order.

Right now, we don't really support much material configuration besides setting the alpha mode. This may change in the future when we enable users to write their own materials.

Entity hierarchy

We're currently using the following entity hierarchy to help keep track of state per surface:

  • (Window, CommandBuffer): This is our "root" entity and the entity id that the Java side stores.
    • Camera: The camera configured for this surface which points to the surface as render target. This is what "sees" everything that we render for a given PGraphics as controlled by the RenderLayers we insert on both camera and mesh.
    • TransientMesh these (potentially multiple children) are meshes that we render into for this PGraphics. Right now we clear them at the beginning of each draw cycle.

Testing

You can run the new WebGPU.java example to easily test.

Minor changes

  • Formatted all our rust files. Oops! We should probably add a CI hook for this. I use the following nightly options: imports_granularity and group_imports to make the imports clean.
  • Renamed window to surface in most places. Technically in the future a surface may also be an off screen texture, so this is more accurate.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@tychedelia
Implement basic rendering flow
c39fb34
@tychedelia
tychedelia requested a review from catilac November 11, 2025 21:15
@tychedelia
Fix naming.
c198e16
@catilac

catilac commented Nov 18, 2025

Copy link
Copy Markdown
Collaborator

I'm going to branch off of this to add linux raw window support. I could also just merge this into the feature branch. let me know @tychedelia

tychedelia reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@catilac catilac mentioned this pull request Nov 18, 2025
Wayland support for simple rendering #1305
Closed
@tychedelia
Actually fix rename.
42a1928
catilac
catilac approved these changes Nov 20, 2025
View reviewed changes

@catilac catilac left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay this works, i'll follow up with a wayland PR

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread core/examples/src/main/java/WebGPU.java
}

public static void main(String[] args) {
PApplet.disableAWT = true;

@catilac catilac Nov 18, 2025

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah great, so for now this is how people could set up their sketch

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@catilac
catilac merged commit 351737c into processing:the-wgpu-moment Nov 20, 2025
catilac added a commit that referenced this pull request Jul 8, 2026
@tychedelia @catilac @Stefterv
Merge WebGPU backend (#1514)
25bca44
* *:ꔫ:*Renderer Project*:ꔫ:*

* Create workspaces for ffi and the renderer (#1275)

* Inital scaffold for libprocessing ffi.

* Remove EAP.

* Update docs.

* Factor out gradle utils. Add flag for disabling webgpu and enforcing android source level compat.

* Remove processing.h

* Set java version for all projects.

* libprocessing ffi error handling (#1293)

* FFI error setup

* Clear before init.

* Basic app lifecycle / surface creation.

* Throw when not on macos.

* Implement `background` method (#1308)

* Implement background.

* Install wayland deps.

* Support for windows surfaces. (#1310)

* Implement basic rendering flow (#1322)

* Implement basic rendering flow

* Fix naming.

* Actually fix rename.

* libprocessing submodule

* --recursive when cloning repo

* Enable submodule checkout in Gradle workflow

Added support for submodules in the checkout step.

* Enable submodules in checkout steps

Added submodule support to the checkout steps.

* Wayland support with new WebGPU renderer

* Gradle fixes from libprocessing refactor. (#1346)

* Updates from libprocessing. (#1392)

* Updates from libprocessing.

* Fixes for compat with main 17.

* Fixup docs.

* Upgrade to jdk-25.

* Upgrade to jdk-25.

* Materials, lights, input event forwarding, ellipse fix.

* Get the gradle sketch runner working locally.

* Conditionally execute webgpu tests

* ProcessingLibraryPlugin JVM Toggle update

* 4.5.5 in gradle.properties

* ProcessingPlugin fixes

---------

Co-authored-by: Moon D. <[email protected]>
Co-authored-by: Moon <[email protected]>
Co-authored-by: Stef Tervelde <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@catilac catilac catilac approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@tychedelia @catilac
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.