-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
GSOC 26: render multi-material models per part #8955
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
base: main
Are you sure you want to change the base?
Changes from 10 commits
bfec2d4
e812dae
962112d
b086d81
1234024
0101168
40d520a
ef33f8e
c9c0cc4
c7db707
e303901
c8f0ec2
aba7591
59b2cce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -589,7 +589,28 @@ export class Renderer3D extends Renderer { | |
| geometry.vertices.length >= 3 && | ||
| ![constants.LINES, constants.POINTS].includes(mode) | ||
| ) { | ||
| this._drawFills(geometry, { mode, count }); | ||
| // draw every part. a part with no material state draws straight (no | ||
| // push/pop); a single-material geometry is its own part, so that case is | ||
| // exactly the old single draw. multi-material parts each apply their own | ||
| // material around the draw. | ||
| const parts = geometry.parts && geometry.parts.length | ||
| ? geometry.parts | ||
| : [geometry]; | ||
| for (const part of parts) { | ||
| const state = part.partState; | ||
| const hasMaterial = state && ( | ||
| state.fill || state.texture || state.ambientColor || | ||
| state.specularColor || state.shininess != null | ||
| ); | ||
| if (hasMaterial) { | ||
| this.push(); | ||
| this._applyPartState(state); | ||
| this._drawFills(part, { mode, count }); | ||
| this.pop(); | ||
| } else { | ||
| this._drawFills(part, { mode, count }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (this.states.strokeColor && geometry.lineVertices.length >= 1) { | ||
|
|
@@ -628,6 +649,31 @@ export class Renderer3D extends Renderer { | |
| shader.unbindShader(); | ||
| } | ||
|
|
||
| // apply a part's material to the renderer before it's drawn. only non-null | ||
| // fields are set, so an empty part state leaves the uniforms untouched. | ||
| _applyPartState(partState) { | ||
| if (!partState) return; | ||
| if (partState.fill) { | ||
| const c = partState.fill; | ||
| this.states.setValue('curFillColor', [c[0], c[1], c[2], 1]); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason why it's not possible for a part to have alpha in the fill? Although the obj/mtl spec puts transparency into its own command, in p5 fills can have alpha (e.g. geometry that comes from
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah that makes sense. fills carry alpha in p5, so i'll store the mtl d/Tr transparency in the fill colour's alpha (4th component) instead of forcing 1. that also covers the buildGeometry fill(255,100) case. nice, this brings transparency back in the right place |
||
| } | ||
| if (partState.texture) { | ||
| this.states.setValue('_tex', partState.texture); | ||
| this.states.setValue('drawMode', constants.TEXTURE); | ||
| } | ||
| if (partState.ambientColor) { | ||
| this.states.setValue('curAmbientColor', partState.ambientColor); | ||
| this.states.setValue('_hasSetAmbient', true); | ||
| } | ||
| if (partState.specularColor) { | ||
| this.states.setValue('curSpecularColor', partState.specularColor); | ||
| this.states.setValue('_useSpecularMaterial', true); | ||
| } | ||
| if (partState.shininess != null) { | ||
| this.states.setValue('_useShininess', partState.shininess); | ||
| } | ||
| } | ||
|
|
||
| _drawStrokes(geometry, { count } = {}) { | ||
|
|
||
| this._useLineColor = geometry.vertexStrokeColors.length > 0; | ||
|
|
||
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.
What's a scenario where we'd end up with no parts?
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.
there isn't one. the constructor always sets parts = [this] and loaders replace it, so a geometry always has at least one part. i'll make that an invariant and just loop geometry.parts directly, dropping the fallback