-
-
Notifications
You must be signed in to change notification settings - Fork 288
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
Refactor 2d render pipeline #1708
base: dev/1.3
Are you sure you want to change the base?
Refactor 2d render pipeline #1708
Conversation
for (let i = 0; i < charCount; ++i) { | ||
const charRenderData = charRenderDatas[i]; | ||
const spriteRenderData = spriteRenderDataPool.getFromPool(); | ||
spriteRenderData.set(this, material, charRenderData.renderData, charRenderData.texture, i); | ||
charsData[i] = spriteRenderData; | ||
spriteRenderData.set(this, material, charRenderData.renderData, charRenderData.texture); |
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.
charRenderData.usage = RenderDataUsage.Sprite;
packages/core/src/Camera.ts
Outdated
@@ -70,6 +71,9 @@ export class Camera extends Component { | |||
_renderPipeline: BasicRenderPipeline; | |||
/** @internal */ | |||
@ignoreClone | |||
_batcherManager: BatcherManager; |
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.
Why not in BasicRenderPipeline
.
} | ||
|
||
commitRenderData(context: RenderContext, data: RenderData | Array<RenderData>): void { | ||
if (!data) return; |
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 line can be deleted.
/** @internal */ | ||
_meshCount: number = 1; | ||
/** @internal */ | ||
_subMeshPool: ClassPool<SubMesh> = new ClassPool(SubMesh); |
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.
Can be a static variable.
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.
Can be a static variable.
has deleted
|
||
commitRenderData(context: RenderContext, data: SpriteRenderData): void { | ||
if (this._preSpriteRenderData) { | ||
if (this._vertexCount + data.verticesData.vertexCount > Batcher2D.MAX_VERTEX_COUNT) { |
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.
Need to judge index
this._cascadedShadowCaster = new CascadedShadowCasterPass(camera); | ||
this._depthOnlyPass = new DepthOnlyPass(engine); | ||
this._spriteMaskManager = new SpriteMaskManager(camera.engine); |
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.
Is it better to put SpriteMaskManager
in Scene
? Because :
- Mask does not depend on rendering timing.
- More memory efficient.
batcher.freeChunk(renderer._chunk); | ||
renderer._chunk = batcher.allocateChunk(4); | ||
} else { | ||
renderer._chunk = batcher.allocateChunk(4); |
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.
Same code
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.
done
positions[i] ||= new Vector3(); | ||
uvs[i] ||= new Vector2(); | ||
const batcher = | ||
renderer instanceof SpriteRenderer |
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.
instanceof
is not good!
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.
But this is not a high-frequency called function
} | ||
verticesData.triangles = SimpleSpriteAssembler._rectangleTriangles; | ||
renderer._chunk._indices = this._rectangleTriangles; |
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.
Dirty code, opt like this!
static resetData(renderer: SpriteRenderer | SpriteMask): void {
const batcher =
renderer instanceof SpriteRenderer
? renderer.engine._batcherManager._batcher2D
: renderer.engine._spriteMaskManager._batcher;
const lastChunk = renderer._chunk;
if (lastChunk) {
batcher.freeChunk(lastChunk);
}
const chunk = batcher.allocateChunk(4);
chunk._indices = this._rectangleTriangles;
renderer._chunk = chunk;
}
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.
done
} | ||
|
||
static updatePositions(renderer: SpriteRenderer | SpriteMask): void { | ||
const { width, height, sprite } = renderer; | ||
const { x: pivotX, y: pivotY } = sprite.pivot; | ||
// Renderer's worldMatrix; | ||
const { _worldMatrix: worldMatrix } = SimpleSpriteAssembler; | ||
const { _worldMatrix: worldMatrix } = this; |
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.
Clear comments, remove ;
.
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.
done
* @internal | ||
*/ | ||
export class MBChunk implements IPoolElement { | ||
_mbId: number = -1; |
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.
A bunch of weird and wordy names!!!
index += 9; | ||
vertices[index] = right; | ||
vertices[index + 1] = top; | ||
} |
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.
Better per and less code
static updateUVs(renderer: SpriteRenderer | SpriteMask): void {
const spriteUVs = renderer.sprite._getUVs();
const { x: left, y: bottom } = spriteUVs[0];
const { x: right, y: top } = spriteUVs[3];
const chunk = renderer._chunk;
const vertices = chunk._meshBuffer._vertices;
const index = chunk._vEntry.start + 3;
vertices[index] = left;
vertices[index + 1] = bottom;
vertices[index + 10] = right;
vertices[index + 11] = bottom;
vertices[index + 20] = left;
vertices[index + 21] = top;
vertices[index + 30] = right;
vertices[index + 31] = top;
}
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.
done
} | ||
verticesData.triangles = SlicedSpriteAssembler._rectangleTriangles; | ||
renderer._chunk._indices = this._rectangleTriangles; |
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.
Same with SimpleSpriteAssembler
index += 9; | ||
} | ||
} | ||
} |
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.
Before has BUG when set uv in updatePositions
?
vertices[index + 3] = a; | ||
index += 9; | ||
} | ||
} |
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.
static updateColor(renderer: SpriteRenderer): void {
const chunk = renderer._chunk;
const vertices = chunk._meshBuffer._vertices;
const color = renderer.color;
let index = chunk._vEntry.start + 5;
for (let i = 0; i < 16; ++i) {
color.copyToArray(vertices, index);
index += 9;
}
}
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.
Adding one more API call compared to direct invocation
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.
And r g b a should be get repeat in loop
indicesCount += 6; | ||
} | ||
} | ||
this.resetData(renderer, vertexCount, indicesCount); |
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.
Code of this quality should not exist in the CR stage
const uvB = uvColumn.get(doubleJ); | ||
const uvR = uvRow.get(2 * i + 1); | ||
const uvT = uvColumn.get(doubleJ + 1); | ||
if (isNaN(uvL) || isNaN(uvL) || isNaN(uvR) || isNaN(uvT)) { |
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.
isNaN(xxx)
seems strange
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 block, I just reused the existing code
vertices[index + 3] = a; | ||
index += 9; | ||
} | ||
} |
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.
Refer to previous suggestions
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.
the same as my opinion
// @ts-ignore | ||
this._updateTransformShaderData(context, Matrix._identity); | ||
} | ||
} |
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.
Just don't want use worldMatrix
?
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.
_updateTransformShaderData consumes a lot of performance,for 2d with default material, just use renderer_MVPMat
renderData.set(this, material, this._verticesData); | ||
engine._spriteMaskManager.addMask(this); | ||
const renderData = engine._spriteRenderDataPool.getFromPool(); | ||
const { _chunk: chunk } = this; |
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.
It is not recommended to declare a single variable cache like this
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.
can not understand
@@ -284,13 +294,13 @@ export class SpriteRenderer extends Renderer { | |||
* @internal | |||
*/ | |||
override _updateShaderData(context: RenderContext, onlyMVP: boolean): void { | |||
if (onlyMVP) { | |||
if (this.getMaterial() === this.engine._spriteDefaultMaterial || onlyMVP) { |
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.
Why add this.getMaterial() === this.engine._spriteDefaultMaterial
this condition?
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.
Custom material may be use other matrix
this._resetSubFont(); | ||
} | ||
return this._subFont; | ||
} |
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 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.
should be internal, has change
@@ -354,13 +370,13 @@ export class TextRenderer extends Renderer { | |||
* @internal | |||
*/ | |||
override _updateShaderData(context: RenderContext, onlyMVP: boolean): void { | |||
if (onlyMVP) { | |||
if (this.getMaterial() === this.engine._spriteDefaultMaterial || onlyMVP) { |
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.
Same with before
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.
Custom material may be use other matrix
const worldPosition0 = TextRenderer._worldPositions[0]; | ||
const worldPosition1 = TextRenderer._worldPositions[1]; | ||
const worldPosition2 = TextRenderer._worldPositions[2]; | ||
const worldPosition3 = TextRenderer._worldPositions[3]; |
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.
Don't make stupid mistakes
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 do you mean ??
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.
done
vertices[index + 1] = position.y; | ||
vertices[index + 2] = position.z; | ||
index += 9; | ||
} |
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.
const worldPositions = TextRenderer._worldPositions;
...
const { chunk } = charRenderInfo;
const vertices = chunk._meshBuffer._vertices;
const index = chunk._vEntry.start;
for (let i = 0; i < 4; ++i) {
worldPositions[i].copyToArray(vertices, index + 9 * i);
}
vertices[index + 2] = r; | ||
vertices[index + 3] = g; | ||
vertices[index + 4] = b; | ||
vertices[index + 5] = a; |
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.
Opt!!!
@@ -1,4 +1,3 @@ | |||
export { Font } from "./Font"; | |||
export { TextRenderer } from "./TextRenderer"; | |||
// Export for CanvasRenderer plugin. | |||
export { TextUtils } from "./TextUtils"; |
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 can delete now?
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.
of cause, CanvasRenderer has deleted
packages/core/src/Engine.ts
Outdated
@@ -268,6 +264,9 @@ export class Engine extends EventDispatcher { | |||
this._textDefaultFont = Font.createFromOS(this, "Arial"); | |||
this._textDefaultFont.isGCIgnored = true; | |||
|
|||
this.inputManager = new InputManager(this); |
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.
merge error?
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 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.
done
this._preElement = null; | ||
} | ||
|
||
batch(srcElements, dstElements): void { |
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.
any?
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 still 2D specialization logic
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.
RenderElement, sorry, i forget write, want batch logic write here, now, only 2D
/** @internal */ | ||
_componentInstanceId: number; | ||
/** @internal */ | ||
_distanceForSort: number; |
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 a internal class, why use internal property?
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.
I will change
|
||
/** | ||
* Render queue. | ||
*/ | ||
export class RenderQueue { | ||
private static _textureProperty: ShaderProperty = ShaderProperty.getByName("renderer_SpriteTexture"); | ||
|
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.
you define a render property in Renderqueue
?
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.
Just for text that with multi-texture, i do not have any good idea now
} else { | ||
return distanceDiff; | ||
} | ||
return dataA._distanceForSort - dataB._distanceForSort || instanceIdDiff; |
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 not OK?
return (
dataA._priority - dataB._priority ||
dataA._distanceForSort - dataB._distanceForSort ||
dataA._componentInstanceId - dataB._componentInstanceId ||
dataA._materialPriority - dataB._materialPriority
);
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.
Yeah, in some case, the same renderer wo want control the sort just for material priority, link lottie or spine
// TextRenderer may be has multi-texture. | ||
const isText = usage === RenderDataUsage.Text; | ||
// @ts-ignore | ||
isText && rendererData.setTexture(RenderQueue._textureProperty, data.texture); |
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.
No!!!!! This configuration should be done at the upper level
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.
I don't has a good idea how to handle a text renderer with multi-texture right now
const { usage } = data; | ||
const needMask = usage === RenderDataUsage.Sprite || usage === RenderDataUsage.Text; | ||
const renderer = data.component; | ||
needMask && spriteMaskManager.preRender(camera, <SpriteRenderer>renderer); |
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.
- Type is not write
compileMacros | ||
); | ||
const { usage } = data; | ||
const needMask = usage === RenderDataUsage.Sprite || usage === RenderDataUsage.Text; |
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.
SpriteMask is still very specialized!
import { SpriteMaskBatcher } from "./SpriteMaskBatcher"; | ||
import { SpriteMaskRenderData } from "./SpriteMaskRenderData"; | ||
import { StencilOperation } from "../shader"; | ||
import { SpriteMaskBatcher } from "./batcher/SpriteMaskBatcher"; |
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.
Need to discuss!!!
} | ||
|
||
set( | ||
override set( |
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.
Further abstraction is needed. In addition, this is a common class between text and elves. The current definition is unreasonable.
import { RenderDataUsage } from "../enums/RenderDataUsage"; | ||
import { Batcher2D } from "./Batcher2D"; | ||
|
||
export class BatcherManager { |
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 is the value of this class?
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.
future, i want handle all batch logic in batch function
/** | ||
* @internal | ||
*/ | ||
export class MeshBuffer { |
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.
Vague definition, and needs to be redesigned!!!!!!!!!
import { SpriteRenderData } from "../SpriteRenderData"; | ||
import { Batcher2D } from "./Batcher2D"; | ||
|
||
export class SpriteMaskBatcher extends Batcher2D { |
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.
Basically no design, may need to be rewritten
*/ | ||
export class MeshBuffer { | ||
/** @internal */ | ||
_mesh: BufferMesh; |
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.
Use Primitive
galacean-refactor-2d-render-pipeline.zip