Skip to content

Commit

Permalink
Optimize HalftoneEffect
Browse files Browse the repository at this point in the history
also fixes scatterFactor
  • Loading branch information
vanruesc committed Apr 26, 2024
1 parent f1080bd commit b898ad9
Show file tree
Hide file tree
Showing 2 changed files with 303 additions and 173 deletions.
189 changes: 152 additions & 37 deletions src/effects/HalftoneEffect.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Uniform, Vector3 } from "three";
import { HalftoneShape } from "../enums/HalftoneShape.js";
import { LinearDodgeBlendFunction } from "./blending/blend-functions/LinearDodgeBlendFunction.js";
import { Effect } from "./Effect.js";
import { OverlayBlendFunction } from "./blending/blend-functions/OverlayBlendFunction.js";

import fragmentShader from "./shaders/halftone.frag";
import { Uniform, Vector3 } from "three";

/**
* HalftoneEffect options.
Expand All @@ -12,13 +12,73 @@ import { Uniform, Vector3 } from "three";
*/

export interface HalftoneEffectOptions {

/**
* The halftone shape.
*
* @defaultValue {@link HalftoneShape.DOT}
*/

shape?: HalftoneShape;

/**
* The pattern radius.
*
* @defaultValue 6
*/

radius?: number;

/**
* The grid rotation for all color channels in radians.
*
* This setting yields better performance compared to individual rotations per channel.
*
* @defaultValue 0
*/

rotation?: number;

/**
* The grid rotation for the red channel in radians.
*
* @defaultValue {@link rotation}
*/

rotationR?: number;

/**
* The grid rotation for the green channel in radians.
*
* @defaultValue {@link rotationR}
*/

rotationG?: number;

/**
* The grid rotation for the blue channel in radians.
*
* @defaultValue {@link rotationG}
*/

rotationB?: number;

/**
* The halftone scatter factor.
*
* @defaultValue 0
*/

scatterFactor?: number;

/**
* The sample count.
*
* @defaultValue 8
*/

samples?: number;

}

/**
Expand All @@ -39,32 +99,71 @@ export class HalftoneEffect extends Effect {
*/

constructor({
shape = HalftoneShape.ELLIPSE,
shape = HalftoneShape.DOT,
radius = 6,
rotationR = 14,
rotationG = 45,
rotationB = 30,
rotation = 0,
rotationR = rotation,
rotationG = rotationR,
rotationB = rotationG,
scatterFactor = 0,
samples = 8
}: HalftoneEffectOptions = {}) {

super("HalftoneEffect");

this.fragmentShader = fragmentShader;
this.samples = samples;
this.shape = shape;

this.blendMode.blendFunction = new OverlayBlendFunction();
this.blendMode.blendFunction = new LinearDodgeBlendFunction();

const uniforms = this.input.uniforms;
uniforms.set("radius", new Uniform(radius));
uniforms.set("rotationRGB", new Uniform(new Vector3(rotationR, rotationG, rotationB)));
uniforms.set("scatterFactor", new Uniform(scatterFactor));

this.shape = shape;
this.samples = samples;

}

/**
* The halftone shape.
*/

get shape() {

return this.input.defines.get("SHAPE") as number;

}

set shape(value: HalftoneShape) {

this.input.defines.set("SHAPE", value);
this.setChanged();

}

/**
* The halftone dot radius.
* The amount of samples.
*/

get samples(): number {

return this.input.defines.get("SAMPLES") as number;

}

set samples(value: number) {

value = Math.max(value, 1);

this.input.defines.set("SAMPLES", value);
this.input.defines.set("INV_SAMPLES", (1.0 / value).toFixed(9));
this.input.defines.set("INV_SAMPLES_PLUS_ONE", (1.0 / (value + 1.0)).toFixed(9));
this.setChanged();

}

/**
* The pattern radius.
*/

get radius() {
Expand All @@ -80,7 +179,7 @@ export class HalftoneEffect extends Effect {
}

/**
* The halftone dot scatterFactor.
* The halftone scatter factor.
*/

get scatterFactor() {
Expand All @@ -96,7 +195,26 @@ export class HalftoneEffect extends Effect {
}

/**
* The halftone dot grid rotation in the red channel.
* The grid rotation in radians.
*/

get rotation() {

const rotationRGB = this.input.uniforms.get("rotationRGB")!.value as Vector3;
return rotationRGB.x;

}

set rotation(value: number) {

const rotationRGB = this.input.uniforms.get("rotationRGB")!.value as Vector3;
rotationRGB.setScalar(value);
this.updateRGBRotation();

}

/**
* The grid rotation for the red channel in radians.
*/

get rotationR() {
Expand All @@ -110,12 +228,12 @@ export class HalftoneEffect extends Effect {

const rotationRGB = this.input.uniforms.get("rotationRGB")!.value as Vector3;
rotationRGB.x = value;
this.input.uniforms.get("rotationRGB")!.value = rotationRGB;
this.updateRGBRotation();

}

/**
* The halftone dot grid rotation in the green channel.
* The grid rotation for the green channel in radians.
*/

get rotationG() {
Expand All @@ -129,12 +247,12 @@ export class HalftoneEffect extends Effect {

const rotationRGB = this.input.uniforms.get("rotationRGB")!.value as Vector3;
rotationRGB.y = value;
this.input.uniforms.get("rotationRGB")!.value = rotationRGB;
this.updateRGBRotation();

}

/**
* The halftone dot grid rotation in the red channel.
* The grid rotation for the blue channel in radians.
*/

get rotationB() {
Expand All @@ -148,42 +266,39 @@ export class HalftoneEffect extends Effect {

const rotationRGB = this.input.uniforms.get("rotationRGB")!.value as Vector3;
rotationRGB.z = value;
this.input.uniforms.get("rotationRGB")!.value = rotationRGB;
this.updateRGBRotation();

}

/**
* The halftone dot shape.
* Enables or disables RGB rotation based on the current rotation settings.
*/

get shape() {
private updateRGBRotation() {

return this.input.defines.get("SHAPE") as number;
const currentlyEnabled = this.input.defines.has("RGB_ROTATION");

}
const shouldBeEnabled = (
this.rotationR !== this.rotationG ||
this.rotationR !== this.rotationB ||
this.rotationG !== this.rotationB
);

set shape(value: HalftoneShape) {
if(shouldBeEnabled) {

this.input.defines.set("RGB_ROTATION", true);

this.input.defines.set("SHAPE", value);
this.setChanged();

}

/**
* The amount of samples.
*/
} else {

get samples(): number {
this.input.defines.delete("RGB_ROTATION");

return this.input.defines.get("SAMPLES") as number;
}

}
if(currentlyEnabled !== shouldBeEnabled) {

set samples(value: number) {
this.setChanged();

this.input.defines.set("SAMPLES", value);
this.setChanged();
}

}

Expand Down
Loading

0 comments on commit b898ad9

Please sign in to comment.