Skip to content

Commit

Permalink
feat: add pixel line to graphics! (native line from v7) (pixijs#11004)
Browse files Browse the repository at this point in the history
* add pixel perfect line to line style

* fix topology

* add test

* remove only

* update test images

* make topology required

* fix imports

* add pixel perfect line to line style

* fix topology

* add test

* remove only

* update test images

* make topology required

* fix imports

* add warning

---------

Co-authored-by: Zyie <[email protected]>
  • Loading branch information
GoodBoyDigital and Zyie authored Nov 18, 2024
1 parent d8b8e18 commit 6a88679
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/rendering/batcher/gl/GlBatchAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ export class GlBatchAdaptor implements BatcherAdaptor
renderer.texture.bind(textures[i], i);
}

renderer.geometry.draw('triangle-list', batch.size, batch.start);
renderer.geometry.draw(batch.topology, batch.size, batch.start);
}
}
3 changes: 2 additions & 1 deletion src/rendering/batcher/gpu/GpuBatchAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class GpuBatchAdaptor implements BatcherAdaptor
const pipeline = renderer.pipeline.getPipeline(
this._geometry,
program,
tempState
tempState,
batch.topology
);

batch.bindGroup._touch(renderer.textureGC.count);
Expand Down
18 changes: 16 additions & 2 deletions src/rendering/batcher/shared/Batcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { BatchTextureArray } from './BatchTextureArray';

import type { BoundsData } from '../../../scene/container/bounds/Bounds';
import type { BindGroup } from '../../renderers/gpu/shader/BindGroup';
import type { Topology } from '../../renderers/shared/geometry/const';
import type { Geometry, IndexBufferArray } from '../../renderers/shared/geometry/Geometry';
import type { Instruction } from '../../renderers/shared/instructions/Instruction';
import type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';
Expand Down Expand Up @@ -35,6 +36,7 @@ export class Batch implements Instruction
public textures: BatchTextureArray = new BatchTextureArray();

public blendMode: BLEND_MODES = 'normal';
public topology: Topology = 'triangle-strip';

public canBundle = true;

Expand Down Expand Up @@ -113,6 +115,12 @@ export interface BatchableElement
*/
attributeSize: number;

/**
* The topology to be used for rendering.
* @type {Topology}
*/
topology: Topology

/**
* Whether the element should be packed as a quad for better performance.
* @type {boolean}
Expand Down Expand Up @@ -153,6 +161,7 @@ export interface BatchableElement
* @private
*/
_batch: Batch;

}

/**
Expand Down Expand Up @@ -446,6 +455,7 @@ export abstract class Batcher

const firstElement = elements[this.elementStart];
let blendMode = getAdjustedBlendModeBlend(firstElement.blendMode, firstElement.texture._source);
let topology = firstElement.topology;

if (this.attributeSize * 4 > this.attributeBuffer.size)
{
Expand Down Expand Up @@ -479,7 +489,7 @@ export abstract class Batcher

const adjustedBlendMode = getAdjustedBlendModeBlend(element.blendMode, source);

const breakRequired = blendMode !== adjustedBlendMode;
const breakRequired = blendMode !== adjustedBlendMode || topology !== element.topology;

if (source._batchTick === BATCH_TICK && !breakRequired)
{
Expand Down Expand Up @@ -531,6 +541,7 @@ export abstract class Batcher
size - start,
textureBatch,
blendMode,
topology,
instructionSet,
action
);
Expand All @@ -539,6 +550,7 @@ export abstract class Batcher
start = size;
// create a batch...
blendMode = adjustedBlendMode;
topology = element.topology;

batch = getBatchFromPool();
textureBatch = batch.textures;
Expand Down Expand Up @@ -591,6 +603,7 @@ export abstract class Batcher
size - start,
textureBatch,
blendMode,
topology,
instructionSet,
action
);
Expand All @@ -610,6 +623,7 @@ export abstract class Batcher
indexSize: number,
textureBatch: BatchTextureArray,
blendMode: BLEND_MODES,
topology: Topology,
instructionSet: InstructionSet,
action: BatchAction
)
Expand All @@ -621,7 +635,7 @@ export abstract class Batcher
batch.batcher = this;
batch.textures = textureBatch;
batch.blendMode = blendMode;

batch.topology = topology;
batch.start = indexStart;
batch.size = indexSize;

Expand Down
2 changes: 1 addition & 1 deletion src/rendering/renderers/gl/geometry/GlGeometrySystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ export class GlGeometrySystem implements System
const { gl } = this._renderer;
const geometry = this._activeGeometry;

const glTopology = topologyToGlMap[geometry.topology || topology];
const glTopology = topologyToGlMap[topology || geometry.topology];

instanceCount ||= geometry.instanceCount;

Expand Down
5 changes: 5 additions & 0 deletions src/scene/graphics/shared/BatchableGraphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { multiplyHexColors } from '../../container/utils/multiplyHexColors';

import type { Batch, Batcher } from '../../../rendering/batcher/shared/Batcher';
import type { DefaultBatchableMeshElement } from '../../../rendering/batcher/shared/DefaultBatcher';
import type { Topology } from '../../../rendering/renderers/shared/geometry/const';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { Graphics } from './Graphics';

Expand All @@ -19,6 +20,7 @@ export class BatchableGraphics implements DefaultBatchableMeshElement

public texture: Texture;

public topology: Topology = 'triangle-list';
public renderable: Graphics;
public indexOffset: number;
public indexSize: number;
Expand Down Expand Up @@ -94,11 +96,14 @@ export class BatchableGraphics implements DefaultBatchableMeshElement

gpuBuffer.texture = this.texture;
gpuBuffer.geometryData = this.geometryData;

gpuBuffer.topology = this.topology;
}

public reset()
{
this.applyTransform = true;
this.renderable = null;
this.topology = 'triangle-list';
}
}
2 changes: 2 additions & 0 deletions src/scene/graphics/shared/FillTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface StrokeAttributes
join?: LineJoin;
/** The miter limit to use. */
miterLimit?: number;
/** If the stroke is a pixel line. NOTE: this is only available for Graphic fills */
pixelLine?: boolean;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/scene/graphics/shared/GraphicsContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export class GraphicsContext extends EventEmitter<{
matrix: null,
/** The fill pattern to use. */
fill: null,
/** If the stroke is a pixel line. */
pixelLine: false,
};

/** unique id for this graphics context */
Expand Down
10 changes: 0 additions & 10 deletions src/scene/graphics/shared/buildCommands/buildLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,25 +157,15 @@ function round(
* @param flipAlignment
* @param closed
* @param vertices
* @param _verticesStride
* @param _verticesOffset
* @param indices
* @param _indicesOffset
*/
export function buildLine(
points: number[],
lineStyle: StrokeAttributes,
flipAlignment: boolean,
closed: boolean,
// alignment:number,

vertices: number[],
_verticesStride: number,
_verticesOffset: number,

indices: number[],
_indicesOffset: number,

): void
{
// const shape = graphicsData.shape as Polygon;
Expand Down
56 changes: 56 additions & 0 deletions src/scene/graphics/shared/buildCommands/buildPixelLine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { closePointEps } from '../const';

/**
* Builds a line to draw using the polygon method.
* @param points
* @param closed
* @param vertices
* @param indices
*/
export function buildPixelLine(
points: number[],
closed: boolean,
vertices: number[],
indices: number[],
): void
{
const eps = closePointEps;

if (points.length === 0)
{
return;
}

// get first and last point.. figure out the middle!

const fx = points[0];
const fy = points[1];

const lx = points[points.length - 2];

const ly = points[points.length - 1];

const closePath = closed || (Math.abs(fx - lx) < eps && Math.abs(fy - ly) < eps);

const verts = vertices;

const length = points.length / 2;
const indexStart = verts.length / 2;

for (let i = 0; i < length; i++)
{
verts.push(points[(i * 2)]);
verts.push(points[(i * 2) + 1]);
}

for (let i = 0; i < length - 1; i++)
{
indices.push(indexStart + i, indexStart + i + 1);
}

if (closePath)
{
indices.push(indexStart + length - 1, indexStart);
}
}

16 changes: 14 additions & 2 deletions src/scene/graphics/shared/utils/buildContextBatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { BigPool } from '../../../../utils/pool/PoolGroup';
import { BatchableGraphics } from '../BatchableGraphics';
import { buildCircle, buildEllipse, buildRoundedRectangle } from '../buildCommands/buildCircle';
import { buildLine } from '../buildCommands/buildLine';
import { buildPixelLine } from '../buildCommands/buildPixelLine';
import { buildPolygon } from '../buildCommands/buildPolygon';
import { buildRectangle } from '../buildCommands/buildRectangle';
import { buildTriangle } from '../buildCommands/buildTriangle';
import { triangulateWithHoles } from './triangulateWithHoles';

import type { Polygon } from '../../../../maths/shapes/Polygon';
import type { Topology } from '../../../../rendering/renderers/shared/geometry/const';
import type { ShapeBuildCommand } from '../buildCommands/ShapeBuildCommand';
import type { ConvertedFillStyle, ConvertedStrokeStyle } from '../FillTypes';
import type { GraphicsContext, TextureInstruction } from '../GraphicsContext';
Expand Down Expand Up @@ -157,11 +159,12 @@ function addShapePathToGeometryData(
const points: number[] = [];

const build = shapeBuilders[shape.type];

let topology: Topology = 'triangle-list';
// TODO - this can be cached...
// TODO - THIS IS DONE TWICE!!!!!!
// ONCE FOR STROKE AND ONCE FOR FILL
// move to the ShapePath2D class itself?

build.build(shape, points);

if (matrix)
Expand Down Expand Up @@ -202,7 +205,15 @@ function addShapePathToGeometryData(
const close = (shape as Polygon).closePath ?? true;
const lineStyle = style as ConvertedStrokeStyle;

buildLine(points, lineStyle, false, close, vertices, 2, vertOffset, indices, indexOffset);
if (!lineStyle.pixelLine)
{
buildLine(points, lineStyle, false, close, vertices, indices);
}
else
{
buildPixelLine(points, close, vertices, indices);
topology = 'line-list';
}
}

const uvsOffset = uvs.length / 2;
Expand Down Expand Up @@ -242,6 +253,7 @@ function addShapePathToGeometryData(

graphicsBatch.texture = texture;
graphicsBatch.geometryData = geometryData;
graphicsBatch.topology = topology;

batches.push(graphicsBatch);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export function toFillStyle<T extends FillInput>(
*/
export function toStrokeStyle(value: StrokeInput, defaultStyle: ConvertedStrokeStyle): ConvertedStrokeStyle
{
const { width, alignment, miterLimit, cap, join, ...rest } = defaultStyle;
const { width, alignment, miterLimit, cap, join, pixelLine, ...rest } = defaultStyle;
const fill = toFillStyle(value, rest);

if (!fill)
Expand All @@ -213,6 +213,7 @@ export function toStrokeStyle(value: StrokeInput, defaultStyle: ConvertedStrokeS
miterLimit,
cap,
join,
pixelLine,
...fill,
};
}
7 changes: 7 additions & 0 deletions src/scene/mesh/shared/BatchableMesh.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Matrix } from '../../../maths/matrix/Matrix';
import type { Batch, Batcher } from '../../../rendering/batcher/shared/Batcher';
import type { DefaultBatchableMeshElement } from '../../../rendering/batcher/shared/DefaultBatcher';
import type { Topology } from '../../../rendering/renderers/shared/geometry/const';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { ViewContainer } from '../../view/ViewContainer';
import type { MeshGeometry } from './MeshGeometry';
Expand All @@ -12,6 +13,9 @@ import type { MeshGeometry } from './MeshGeometry';
export class BatchableMesh implements DefaultBatchableMeshElement
{
public batcherName = 'default';

public _topology: Topology;

public readonly packAsQuad = false;
public location: number;

Expand All @@ -37,6 +41,9 @@ export class BatchableMesh implements DefaultBatchableMeshElement

get blendMode() { return this.renderable.groupBlendMode; }

get topology() { return this._topology || this.geometry.topology; }
set topology(value: Topology) { this._topology = value; }

public reset()
{
this.renderable = null;
Expand Down
2 changes: 2 additions & 0 deletions src/scene/sprite/BatchableSprite.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Matrix } from '../../maths/matrix/Matrix';
import type { Batch, Batcher } from '../../rendering/batcher/shared/Batcher';
import type { DefaultBatchableQuadElement } from '../../rendering/batcher/shared/DefaultBatcher';
import type { Topology } from '../../rendering/renderers/shared/geometry/const';
import type { Texture } from '../../rendering/renderers/shared/texture/Texture';
import type { BoundsData } from '../container/bounds/Bounds';
import type { Container } from '../container/Container';
Expand All @@ -12,6 +13,7 @@ import type { Container } from '../container/Container';
export class BatchableSprite implements DefaultBatchableQuadElement
{
public batcherName = 'default';
public topology: Topology = 'triangle-list';

// batch specific..
public readonly attributeSize = 4;
Expand Down
1 change: 1 addition & 0 deletions tests/graphics/GraphicsFill.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('convertStrokeInputToStrokeStyle', () =>
texture: Texture.WHITE,
matrix: null,
fill: null,
pixelLine: false,
});

it('should return null when value is undefined', () =>
Expand Down
2 changes: 2 additions & 0 deletions tests/renderering/batch/checkCanUseTexture.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TestBatcher } from './TestBatcher';
import '../../../src/rendering/renderers/shared/texture/sources/ImageSource';

import type { Batch, BatchableMeshElement, Batcher } from '../../../src/rendering/batcher/shared/Batcher';
import type { Topology } from '../../../src/rendering/renderers/shared/geometry/const';
import type { BLEND_MODES } from '../../../src/rendering/renderers/shared/state/const';

class DummyBatchableObject implements BatchableMeshElement
Expand All @@ -18,6 +19,7 @@ class DummyBatchableObject implements BatchableMeshElement
color = 0xFFFFFFF;
attributeOffset = 0;
location = 0;
topology: Topology = 'triangle-list';
readonly packAsQuad = false;
_indexStart = 0;

Expand Down
Loading

0 comments on commit 6a88679

Please sign in to comment.