This commit is contained in:
Andras Schmelczer 2026-05-17 17:21:49 +01:00
parent ced0ac56f3
commit d6a8f898d1
27 changed files with 760 additions and 363 deletions

View file

@ -15,6 +15,66 @@ interface LineSegment {
to: vec2;
}
interface BrushParameterSettings extends BrushSettings {
devicePixelRatio?: number;
selectedColorIndex: number;
}
export const getSafeDevicePixelRatio = (devicePixelRatio: number | undefined): number =>
typeof devicePixelRatio === 'number' &&
Number.isFinite(devicePixelRatio) &&
devicePixelRatio > 0
? devicePixelRatio
: 1;
export const setBrushUniformValues = (
target: Float32Array,
{
brushSize,
brushSizeVariation,
brushAlpha,
brushFeatherRatio,
brushMinimumFeather,
brushDiscardThreshold,
brushCoarseNoiseScale,
brushGrainNoiseScale,
brushGrainNoiseOffsetX,
brushGrainNoiseOffsetY,
brushGrainMinStrength,
brushGrainMaxStrength,
selectedColorIndex,
devicePixelRatio,
}: BrushParameterSettings
): void => {
const pixelRatio = getSafeDevicePixelRatio(devicePixelRatio);
const brushRadius = (brushSize * pixelRatio) / 2;
const brushRadiusVariation = Math.floor(brushRadius * brushSizeVariation);
const brushMinimumFeatherPixels = brushMinimumFeather * pixelRatio;
const brushFeather = Math.max(
brushMinimumFeatherPixels,
brushRadius * brushFeatherRatio
);
const brushGeometryRadius =
brushRadius + Math.max(0, brushRadiusVariation) + brushFeather;
target[0] = brushRadius;
target[1] = brushRadiusVariation;
target[2] = brushFeatherRatio;
target[3] = brushMinimumFeatherPixels;
target[4] = selectedColorIndex === 0 ? 1 : 0;
target[5] = selectedColorIndex === 1 ? 1 : 0;
target[6] = selectedColorIndex === 2 ? 1 : 0;
target[7] = brushAlpha;
target[8] = brushCoarseNoiseScale * pixelRatio;
target[9] = brushGrainNoiseScale * pixelRatio;
target[10] = brushGrainNoiseOffsetX;
target[11] = brushGrainNoiseOffsetY;
target[12] = brushDiscardThreshold;
target[13] = brushGrainMinStrength;
target[14] = brushGrainMaxStrength;
target[15] = brushGeometryRadius;
};
export class BrushPipeline {
private static readonly UNIFORM_COUNT = 16;
private static readonly MAX_LINE_COUNT = appConfig.pipelines.brush.maxLineCount;
@ -87,43 +147,8 @@ export class BrushPipeline {
this.actualSegments.length = 0;
}
public setParameters({
brushSize,
brushSizeVariation,
brushAlpha,
brushFeatherRatio,
brushMinimumFeather,
brushDiscardThreshold,
brushCoarseNoiseScale,
brushGrainNoiseScale,
brushGrainNoiseOffsetX,
brushGrainNoiseOffsetY,
brushGrainMinStrength,
brushGrainMaxStrength,
selectedColorIndex,
}: BrushSettings & { selectedColorIndex: number }) {
const brushRadius = brushSize / 2;
const brushRadiusVariation = Math.floor(brushRadius * brushSizeVariation);
const brushFeather = Math.max(brushMinimumFeather, brushRadius * brushFeatherRatio);
const brushGeometryRadius =
brushRadius + Math.max(0, brushRadiusVariation) + brushFeather;
this.uniformValues[0] = brushRadius;
this.uniformValues[1] = brushRadiusVariation;
this.uniformValues[2] = brushFeatherRatio;
this.uniformValues[3] = brushMinimumFeather;
this.uniformValues[4] = selectedColorIndex === 0 ? 1 : 0;
this.uniformValues[5] = selectedColorIndex === 1 ? 1 : 0;
this.uniformValues[6] = selectedColorIndex === 2 ? 1 : 0;
this.uniformValues[7] = brushAlpha;
this.uniformValues[8] = brushCoarseNoiseScale;
this.uniformValues[9] = brushGrainNoiseScale;
this.uniformValues[10] = brushGrainNoiseOffsetX;
this.uniformValues[11] = brushGrainNoiseOffsetY;
this.uniformValues[12] = brushDiscardThreshold;
this.uniformValues[13] = brushGrainMinStrength;
this.uniformValues[14] = brushGrainMaxStrength;
this.uniformValues[15] = brushGeometryRadius;
public setParameters(parameters: BrushParameterSettings) {
setBrushUniformValues(this.uniformValues, parameters);
writeFloat32BufferIfChanged(
this.device,
this.uniforms,