Skip to content
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

Add NoiseEffect #692

Open
wants to merge 11 commits into
base: v7
Choose a base branch
from
Prev Previous commit
Next Next commit
fix some types in ascii files
  • Loading branch information
LucaArgentieri committed Feb 18, 2025
commit 9dfa2c2904bf3fe33f3d09f7559699dc930f92af
47 changes: 27 additions & 20 deletions src/effects/ASCIIEffect.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,13 @@ import { Effect } from "./Effect.js";

import fragmentShader from "./glsl/ascii.frag";

export interface ASCIIEffectOptions {
asciiTexture?: ASCIITexture;
cellSize?: number;
color?: number | Color;
inverted?: boolean;
}

/**
* An ASCII effect.
*
@@ -21,9 +28,9 @@ export class ASCIIEffect extends Effect {
* @param {Boolean} [options.inverted=false] - Inverts the effect.
*/

constructor({ asciiTexture = new ASCIITexture(), cellSize = 16, color = null, inverted = false } = {}) {
constructor({ asciiTexture = new ASCIITexture(), cellSize = 16, color, inverted = false }: ASCIIEffectOptions = {}) {
super("ASCIIEffect", fragmentShader, {
uniforms: new Map([
uniforms: new Map<string, Uniform>([
["asciiTexture", new Uniform(null)],
["cellCount", new Uniform(new Vector4())],
["color", new Uniform(new Color())],
@@ -49,7 +56,7 @@ export class ASCIIEffect extends Effect {

this.asciiTexture = asciiTexture;
this.cellSize = cellSize;
this.color = color;
this.color = color ?? null;
this.inverted = inverted;
}

@@ -59,13 +66,13 @@ export class ASCIIEffect extends Effect {
* @type {ASCIITexture}
*/

get asciiTexture() {
return this.uniforms.get("asciiTexture").value;
get asciiTexture(): ASCIITexture {
return this.uniforms.get("asciiTexture")!.value as ASCIITexture;
}

set asciiTexture(value) {
const currentTexture = this.uniforms.get("asciiTexture").value;
this.uniforms.get("asciiTexture").value = value;
set asciiTexture(value: ASCIITexture) {
const currentTexture = this.uniforms.get("asciiTexture")!.value as ASCIITexture;
this.uniforms.get("asciiTexture")!.value = value;

if (currentTexture !== null && currentTexture !== value) {
currentTexture.dispose();
@@ -86,13 +93,13 @@ export class ASCIIEffect extends Effect {
* @type {Color | String | Number | null}
*/

get color() {
return this.uniforms.get("color").value;
get color(): Color | null {
return this.uniforms.get("color")!.value as Color;
}

set color(value) {
set color(value: Color | number | null) {
if (value !== null) {
this.uniforms.get("color").value.set(value);
this.uniforms.get("color")!.value.set(value);
}

if (this.defines.has("USE_COLOR") && value === null) {
@@ -110,11 +117,11 @@ export class ASCIIEffect extends Effect {
* @type {Boolean}
*/

get inverted() {
get inverted(): boolean {
return this.defines.has("INVERTED");
}

set inverted(value) {
set inverted(value: boolean) {
if (this.inverted !== value) {
if (value) {
this.defines.set("INVERTED", "1");
@@ -132,11 +139,11 @@ export class ASCIIEffect extends Effect {
* @type {Number}
*/

get cellSize() {
get cellSize(): number {
return this._cellSize;
}

set cellSize(value) {
set cellSize(value: number) {
if (this._cellSize !== value) {
this._cellSize = value;
this.updateCellCount();
@@ -150,11 +157,11 @@ export class ASCIIEffect extends Effect {
*/

updateCellCount() {
const cellCount = this.uniforms.get("cellCount").value;
const cellCount = this.uniforms.get("cellCount")!.value as Vector4;
const resolution = this.resolution;

cellCount.x = resolution.width / this.cellSize;
cellCount.y = resolution.height / this.cellSize;
cellCount.x = resolution.x / this.cellSize;
cellCount.y = resolution.y / this.cellSize;
cellCount.z = 1.0 / cellCount.x;
cellCount.w = 1.0 / cellCount.y;
}
@@ -166,7 +173,7 @@ export class ASCIIEffect extends Effect {
* @param {Number} height - The height.
*/

setSize(width, height) {
setSize(width: number, height: number) {
this.resolution.set(width, height);
this.updateCellCount();
}
39 changes: 39 additions & 0 deletions src/effects/shaders/ascii.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
uniform sampler2D asciiTexture;
uniform vec4 cellCount; // XY = cell count, ZW = inv cell count

#ifdef USE_COLOR

uniform vec3 color;

#endif

void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {

vec2 pixelizedUv = cellCount.zw * (0.5 + floor(uv * cellCount.xy));
vec4 texel = texture2D(inputBuffer, pixelizedUv);
float lum = luminance(texel.rgb);

#ifdef INVERTED

// Only LDR colors can be inverted, so make sure lum doesn't exceed 1.
lum = 1.0 - min(lum, 1.0);

#endif

float characterIndex = floor(CHAR_COUNT_MINUS_ONE * lum);
vec2 characterPosition = vec2(mod(characterIndex, CELL_COUNT), floor(characterIndex * INV_CELL_COUNT));
vec2 offset = vec2(characterPosition.x, -characterPosition.y) * INV_CELL_COUNT;
vec2 characterUv = mod(uv * (cellCount.xy * INV_CELL_COUNT), INV_CELL_COUNT) - vec2(0.0, INV_CELL_COUNT) + offset;
vec4 asciiCharacter = texture2D(asciiTexture, characterUv);

#ifdef USE_COLOR

outputColor = vec4(color * asciiCharacter.r, inputColor.a);

#else

outputColor = vec4(texel.rgb * asciiCharacter.r, inputColor.a);

#endif

}
14 changes: 11 additions & 3 deletions src/textures/ASCIITexture.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { CanvasTexture, RepeatWrapping } from "three";

export interface ASCIITextureOptions {
characters?: string;
font?: string;
fontSize?: number;
size?: number;
cellCount?: number;
}

/**
* An ASCII character lookup texture.
*/
@@ -22,13 +30,13 @@ export class ASCIITexture extends CanvasTexture {
fontSize = 54,
size = 1024,
cellCount = 16,
} = {}) {
}: ASCIITextureOptions = {}) {
super(document.createElement("canvas"), undefined, RepeatWrapping, RepeatWrapping);

const canvas = this.image;
const canvas = this.image as HTMLCanvasElement;
canvas.width = canvas.height = size;

const context = canvas.getContext("2d");
const context = canvas.getContext("2d") as CanvasRenderingContext2D;
const cellSize = size / cellCount;
context.font = `${fontSize}px ${font}`;
context.textAlign = "center";