Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGLRenderer modularization experiment #6782

Closed
wants to merge 4 commits into from

Conversation

Projects
None yet
2 participants
@dubejf
Copy link
Contributor

commented Jul 3, 2015

There has been a lot of talk on breaking up the renderer into smaller components, but I have not seen a lot of details on how to accomplish this refactoring.

Would this PR be a pattern you would consider?

I've only limited myself to transforming four small parts of the renderer. In case you find the diff too unruly, I suggest that you take a look at the more digestible individual commits.

In any case, here is an overview of the approach.

Instead of a monolithic renderer, the logic is broken down into smaller functions. The prototypes of the renderable objects (material, lights, etc) are extended with these functions. Implementation details are pushed into the objects, which become responsible to update the gl state. The renderer is just the orchestrator.

This is similar to how the Raycaster was split up with the introduction of object.prototype.raycast() (7ff6237), with the difference that the functions are "plugged in" the prototypes at runtime (when the first WebGLRenderer is constructed). This method ensures that the core classes are not coupled to any specific renderer implementation (THREE.MeshBasicMaterial initially knows nothing about WebGLRenderer, yet is still able to encapsulate type-dependent logic on behalf of the renderer).

One large switch block like this:

if ( material instanceof THREE.MeshBasicMaterial ) {

    refreshUniformsBasic( m_uniforms, material );

} else if ( material instanceof THREE.MeshPhongMaterial ) {

    refreshUniformsPhong( m_uniforms, material );

} else if ( material instanceof THREE.MeshLambertMaterial ) {
    // ...

is replaced by this single line dispatch:

material.refreshUniforms( m_uniforms );

// well, the actual line looks more like...
// material.__refreshUniforms( this /* renderer */, m_uniforms );

dubejf added some commits Jul 3, 2015

Refactor WebGLRenderer fog
There has been a lot of talk on breaking down the renderer in smaller
components, but I have not seen a lot of detail on how to accomplish
this refactoring. Would this be a pattern you would consider?

I've only touched three small part of the renderer - but in case the
changelog is too confusing, here is an overview of the approach.
@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jul 3, 2015

Ideally the renders shouldn't add/modify/remove anything from the scenegraph objects. This is something that has brought a lot of problems and that we're finally starting to get under control (ie. #6723).

@dubejf

This comment has been minimized.

Copy link
Contributor Author

commented Jul 3, 2015

To clarity, objects are extended with static "pure" functions.

Not data (like the old __webglTexture) and not closure (not tied to a specific instance of WebGLRenderer instance: any number of renderers can call the functions).

No new state is carried by the object.

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jul 3, 2015

I know, I know. But if this became a common pattern, other renderers could also add their things and then collisions could happen.

@mrdoob mrdoob closed this Jul 12, 2015

@dubejf dubejf referenced this pull request Aug 12, 2015

Closed

Model Diet #6987

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.