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

Transparent double-sided materials causes a new Program to be created each frame #22255

Closed
Donitzo opened this issue Aug 3, 2021 · 6 comments

Comments

@Donitzo
Copy link

Donitzo commented Aug 3, 2021

As the title says, if a material uses side = THREE.DoubleSide and transparent, it causes the material properties version to increment each frame creating a new program.

To reproduce, add a breakpoint before program changes due to needsProgramChange === true, and use the following material:

const material = new THREE.MeshBasicMaterial({
  transparent: true,
  side: THREE.DoubleSide,
});

Due to an additional issue which I will submit, the morphTargets will also cause a new program to be created each frame. That issue hides this issue.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 3, 2021

Due to an additional issue which I will submit, the morphTargets will also cause a new program to be created each frame.

This should already be fixed on dev, see #22244.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 3, 2021

it causes the material properties version to increment each frame creating a new program.

I don't think that's true. Programs are internally cached and you can see in the debugger that the material holds two programs for each render pass. They are reused and not recreated.

@Donitzo
Copy link
Author

Donitzo commented Aug 3, 2021

Ah, I understand. I thought that it was constantly updating the program since the material version is incrementing by 1 each frame. This appears to only happen with transparent double-sided materials, and not with opaque double-sided materials.

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 3, 2021

since the material version is incrementing by 1 each frame

The version updates are a small side effect in using needsUpdate in renderObject():

if ( material.transparent === true && material.side === DoubleSide ) {
material.side = BackSide;
material.needsUpdate = true;
_this.renderBufferDirect( camera, scene, geometry, material, object, group );
material.side = FrontSide;
material.needsUpdate = true;
_this.renderBufferDirect( camera, scene, geometry, material, object, group );
material.side = DoubleSide;
} else {

However, it does not recompile shaders.

@Donitzo
Copy link
Author

Donitzo commented Aug 3, 2021

Ah, now I get it.

Then all that remains is a mystery lag when a transparent double-sided object enters the screen the first time, despite calling compile on the entire non-frustum culled scene with all lights present. Is there maybe a bug in .compile for these materials?

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 3, 2021

AIFACS, compile() does not precompile the shader programs for double sided, transparent materials (meaning the programs for the front and back side). The method would require a similar code like renderObject().

Good catch! Do you mind creating a new issue for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants