-
Notifications
You must be signed in to change notification settings - Fork 32
Refactor/remove render ops #727
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 all commits
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 |
|---|---|---|
|
|
@@ -23,6 +23,9 @@ import { | |
| mergeColorAlphaPremultiplied, | ||
| } from '../utils.js'; | ||
| import type { TextureOptions } from './CoreTextureManager.js'; | ||
| import type { WebGlRenderer } from './renderers/webgl/WebGlRenderer.js'; | ||
| import type { WebGlCtxTexture } from './renderers/webgl/WebGlCtxTexture.js'; | ||
| import type { BufferCollection } from './renderers/webgl/internal/BufferCollection.js'; | ||
| import type { CoreRenderer } from './renderers/CoreRenderer.js'; | ||
| import type { Stage } from './Stage.js'; | ||
| import { | ||
|
|
@@ -738,6 +741,12 @@ export class CoreNode extends EventEmitter { | |
| readonly children: CoreNode[] = []; | ||
| protected _id: number = getNewId(); | ||
| readonly props: CoreNodeProps; | ||
| public readonly isCoreNode = true as const; | ||
|
|
||
| // WebGL Render Op State | ||
| public renderOpBufferIdx: number = 0; | ||
| public numQuads: number = 0; | ||
| public renderOpTextures: WebGlCtxTexture[] = []; | ||
|
|
||
| private hasShaderUpdater = false; | ||
| public hasShaderTimeFn = false; | ||
|
|
@@ -794,6 +803,10 @@ export class CoreNode extends EventEmitter { | |
| constructor(readonly stage: Stage, props: CoreNodeProps) { | ||
| super(); | ||
| const p = (this.props = {} as CoreNodeProps); | ||
|
|
||
| // Initialize the renderOpTextures array with a capacity of 16 (typical max textures) | ||
| this.renderOpTextures = []; | ||
|
|
||
| //inital update type | ||
| let initialUpdateType = | ||
| UpdateType.Local | UpdateType.RenderBounds | UpdateType.RenderState; | ||
|
|
@@ -1800,47 +1813,43 @@ export class CoreNode extends EventEmitter { | |
| return; | ||
| } | ||
|
|
||
| const p = this.props; | ||
| const t = this.globalTransform!; | ||
| const coords = this.renderCoords; | ||
| const texture = p.texture || this.stage.defaultTexture; | ||
| const textureCoords = | ||
| this.textureCoords || this.stage.renderer.defaultTextureCoords; | ||
| const texture = this.renderTexture; | ||
|
|
||
| // There is a race condition where the texture can be null | ||
| // with RTT nodes. Adding this defensively to avoid errors. | ||
| if (texture && texture.state !== 'loaded') { | ||
| // Also check if we have a valid texture or default texture to render | ||
| if (!texture || texture.state !== 'loaded') { | ||
| return; | ||
| } | ||
|
|
||
| renderer.addQuad({ | ||
| width: p.w, | ||
| height: p.h, | ||
| colorTl: this.premultipliedColorTl, | ||
| colorTr: this.premultipliedColorTr, | ||
| colorBl: this.premultipliedColorBl, | ||
| colorBr: this.premultipliedColorBr, | ||
| texture, | ||
| textureOptions: p.textureOptions, | ||
| textureCoords: textureCoords, | ||
| shader: p.shader as CoreShaderNode<any>, | ||
| alpha: this.worldAlpha, | ||
| clippingRect: this.clippingRect, | ||
| tx: t.tx, | ||
| ty: t.ty, | ||
| ta: t.ta, | ||
| tb: t.tb, | ||
| tc: t.tc, | ||
| td: t.td, | ||
| renderCoords: coords, | ||
| rtt: p.rtt, | ||
| zIndex: this.calcZIndex, | ||
| parentHasRenderTexture: this.parentHasRenderTexture, | ||
| framebufferDimensions: this.parentHasRenderTexture | ||
| ? this.parentFramebufferDimensions | ||
| : null, | ||
| time: this.hasShaderTimeFn === true ? this.getTimerValue() : null, | ||
| }); | ||
| renderer.addQuad(this); | ||
| } | ||
|
|
||
| get renderTexture(): Texture | null { | ||
| return this.props.texture || this.stage.defaultTexture; | ||
| } | ||
|
|
||
| get renderTextureCoords(): TextureCoords | undefined { | ||
| return this.textureCoords || this.stage.renderer.defaultTextureCoords; | ||
| } | ||
|
|
||
| get quadBufferCollection(): BufferCollection { | ||
|
Collaborator
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. This is very WebGl specific, handle this in WebGLRenderer.
Contributor
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. CoreNodes are now renderOps. |
||
| return (this.stage.renderer as WebGlRenderer).quadBufferCollection; | ||
| } | ||
|
|
||
| get width(): number { | ||
|
Collaborator
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. don't need these, use get w if you really must, but if its for internal use, avoid using getters and just use props.w / props.h
Contributor
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. That's a lot of overhead. With the change to w / h it wasn't done throughout the code base. So now we face w => width and vice versa and same with height. That requires if statements in a lot of places. If you and the team want to spend the time to make it consistent through out the code base that would allow removing this. |
||
| return this.props.w; | ||
| } | ||
|
|
||
| get height(): number { | ||
| return this.props.h; | ||
| } | ||
|
|
||
| get time(): number { | ||
| if (this.hasShaderTimeFn === true) { | ||
| return this.getTimerValue(); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| getTimerValue(): number { | ||
|
|
@@ -2621,12 +2630,12 @@ export class CoreNode extends EventEmitter { | |
| /** | ||
| * Returns the framebuffer dimensions of the RTT parent | ||
| */ | ||
| get parentFramebufferDimensions(): Dimensions { | ||
| get parentFramebufferDimensions(): Dimensions | null { | ||
| if (this.rttParent !== null) { | ||
| return this.rttParent.framebufferDimensions as Dimensions; | ||
| return this.rttParent.framebufferDimensions; | ||
| } | ||
| this.rttParent = this.findParentRTTNode() as CoreNode; | ||
| return this.rttParent.framebufferDimensions as Dimensions; | ||
| this.rttParent = this.findParentRTTNode(); | ||
| return this.rttParent ? this.rttParent.framebufferDimensions : null; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -2719,5 +2728,69 @@ export class CoreNode extends EventEmitter { | |
| // no-op | ||
| } | ||
|
|
||
| /** | ||
| * Add a texture to the current RenderOp. | ||
| * | ||
| * @param texture | ||
| * @returns Assigned Texture Index of the texture in the render op | ||
| */ | ||
| addTexture(texture: WebGlCtxTexture): number { | ||
| const textures = this.renderOpTextures; | ||
| const length = textures.length; | ||
|
|
||
| for (let i = 0; i < length; i++) { | ||
| if (textures[i] === texture) { | ||
| return i; | ||
| } | ||
| } | ||
|
|
||
| if (length >= 1) { | ||
| return 0xffffffff; | ||
| } | ||
|
|
||
| textures.push(texture); | ||
| return length; | ||
| } | ||
|
|
||
| draw(renderer: WebGlRenderer) { | ||
| const { glw, options, stage } = renderer; | ||
| const shader = this.props.shader as any; | ||
|
|
||
| stage.shManager.useShader(shader.program); | ||
| shader.program.bindRenderOp(this); | ||
|
|
||
| // Clipping | ||
| if (this.clippingRect.valid === true) { | ||
| const pixelRatio = this.parentHasRenderTexture ? 1 : stage.pixelRatio; | ||
|
|
||
| const clipX = Math.round(this.clippingRect.x * pixelRatio); | ||
| const clipWidth = Math.round(this.clippingRect.width * pixelRatio); | ||
| const clipHeight = Math.round(this.clippingRect.height * pixelRatio); | ||
| let clipY = Math.round( | ||
| options.canvas.height - clipHeight - this.clippingRect.y * pixelRatio, | ||
| ); | ||
| // if parent has render texture, we need to adjust the scissor rect | ||
| // to be relative to the parent's framebuffer | ||
| if (this.parentHasRenderTexture) { | ||
| clipY = this.parentFramebufferDimensions | ||
| ? this.parentFramebufferDimensions.h - this.props.h | ||
| : 0; | ||
| } | ||
|
|
||
| glw.setScissorTest(true); | ||
| glw.scissor(clipX, clipY, clipWidth, clipHeight); | ||
| } else { | ||
| glw.setScissorTest(false); | ||
| } | ||
|
|
||
| const quadIdx = (this.renderOpBufferIdx / 32) * 6 * 2; | ||
| glw.drawElements( | ||
| glw.TRIANGLES, | ||
| 6 * this.numQuads, | ||
| glw.UNSIGNED_SHORT, | ||
| quadIdx, | ||
| ); | ||
| } | ||
|
|
||
| //#endregion Properties | ||
| } | ||
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.
This is very WebGl specific, handle this in WebGLRenderer.
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.
Canvas renderer needs this as well