Skip to content

Commit

Permalink
feat/Add ScanlineEffect & demo to v7 (#602)
Browse files Browse the repository at this point in the history
* Add working scanline effect and demo

* Export ScanlineEffect

* Add unit test

* Update formatting

* Remove stale todo

* Formatting

* Fix uniforms being updated before they're defined

* Update setSize

* Improve count uniform update

* Add end of file newline

* Apply some suggestions from code review

Co-authored-by: Raoul v. R. <[email protected]>

* Alphabetise exports

* Address further code review items of feedback

* Restore update count method

---------

Co-authored-by: Raoul v. R. <[email protected]>
  • Loading branch information
balraj-johal and vanruesc authored Feb 20, 2024
1 parent f096f15 commit 8c59fee
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 12 deletions.
23 changes: 12 additions & 11 deletions manual/assets/js/src/demos/scanlines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import {

import {
ClearPass,
EffectPass,
GeometryPass,
RenderPipeline
OverlayBlendFunction,
RenderPipeline,
ScanlineEffect,
ToneMappingEffect
} from "postprocessing";

import { Pane } from "tweakpane";
Expand All @@ -31,7 +35,7 @@ function load(): Promise<Map<string, Texture>> {
loadingManager.onLoad = () => resolve(assets);
loadingManager.onError = (url) => reject(new Error(`Failed to load ${url}`));

cubeTextureLoader.load(Utils.getSkyboxUrls("space"), (t) => {
cubeTextureLoader.load(Utils.getSkyboxUrls("space", ".jpg"), (t) => {

t.colorSpace = SRGBColorSpace;
assets.set("sky", t);
Expand Down Expand Up @@ -79,33 +83,30 @@ window.addEventListener("load", () => void load().then((assets) => {

// Post Processing

const effect = new ScanlineEffect({ scrollSpeed: 0.006 });
effect.blendMode.opacity = 0.25;
effect.blendMode.blendFunction = new OverlayBlendFunction();

const pipeline = new RenderPipeline(renderer);
pipeline.add(
new ClearPass(),
new GeometryPass(scene, camera, {
frameBufferType: HalfFloatType,
samples: 4
})
}),
new EffectPass(effect, new ToneMappingEffect())
);

/*
const effect = new ScanlineEffect({ scrollSpeed: 0.006 });
effect.blendMode.opacity = 0.25;
pipeline.addPass(new EffectPass(effect, new ToneMappingEffect()));
*/

// Settings

const pane = new Pane({ container: container.querySelector(".tp") as HTMLElement });
const fpsGraph = Utils.createFPSGraph(pane);

/*
const folder = pane.addFolder({ title: "Settings" });
folder.addBinding(effect, "density", { min: 0, max: 2, step: 1e-3 });
folder.addBinding(effect, "scrollSpeed", { min: -0.02, max: 0.02, step: 1e-3 });

Utils.addBlendModeBindings(folder, effect.blendMode);
*/

// Resize Handler

Expand Down
2 changes: 1 addition & 1 deletion manual/content/demos/special-effects/scanlines.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: single
collection: sections
title: Scanlines
draft: true
draft: false
menu:
demos:
parent: special-effects
Expand Down
134 changes: 134 additions & 0 deletions src/effects/ScanlineEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Uniform } from "three";
import { Effect } from "./Effect.js";
import { Resolution } from "../utils/Resolution.js";

import fragmentShader from "./shaders/scanline.frag";

/**
* ScanlineEffect options.
*
* @category Effects
*/

export interface ScanlineEffectOptions {

/**
* The scanline density.
*
* @defaultValue 1.25
*/

density?: number;

/**
* The scanline scroll speed.
*
* @defaultValue 0.0
*/

scrollSpeed?: number;

}

/**
* A scanline effect.
*
* Based on an implementation by Georg 'Leviathan' Steinrohder (CC BY 3.0):
* http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html
*
* @category Effects
*/

export class ScanlineEffect extends Effect {

/**
* @see {@link density}
*/

private _density: number;

/**
* Constructs a new scanline effect.
*
* @param {Object} [options] - The options.
*/

constructor({
density = 1.25,
scrollSpeed = 0.0
}: ScanlineEffectOptions = {}) {

super("ScanlineEffectOptions");

this.fragmentShader = fragmentShader;

const uniforms = this.input.uniforms;
uniforms.set("count", new Uniform(0.0));
uniforms.set("scrollSpeed", new Uniform(0.0));

this._density = density;
this.scrollSpeed = scrollSpeed;

}

/**
* The scanline density.
*/

get density() {

return this._density;

}

set density(value: number) {

this._density = value;
this.updateCount(this.resolution.height);

}

/**
* The scanline scroll speed.
*/

get scrollSpeed() {

return this.input.uniforms.get("scrollSpeed")!.value as number;

}

set scrollSpeed(value: number) {

this.input.uniforms.get("scrollSpeed")!.value = value;

if(value === 0) {

if(this.input.defines.delete("SCROLL")) {

this.setChanged();

}

} else if(!this.input.defines.has("SCROLL")) {

this.input.defines.set("SCROLL", "1");
this.setChanged();

}

}

protected override onResolutionChange(resolution: Resolution) {

this.updateCount(resolution.height);

}

private updateCount(height: number) {

this.input.uniforms.get("count")!.value = Math.round(height * this.density);

}

}
1 change: 1 addition & 0 deletions src/effects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from "./blending/index.js";
export * from "./BloomEffect.js";
export * from "./Effect.js";
export * from "./FXAAEffect.js";
export * from "./ScanlineEffect.js";
export * from "./ToneMappingEffect.js";
export * from "./VignetteEffect.js";
23 changes: 23 additions & 0 deletions src/effects/shaders/scanline.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
uniform float count;

#ifdef SCROLL

uniform float scrollSpeed;

#endif

vec4 mainImage(const in vec4 inputColor, const in vec2 uv, const in GData gData) {

float y = uv.y;

#ifdef SCROLL

y += time * scrollSpeed;

#endif

vec2 sl = vec2(sin(y * count), cos(y * count));

return vec4(sl.xyx, inputColor.a);

}
11 changes: 11 additions & 0 deletions test/effects/ScanlineEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import test from "ava";
import { ScanlineEffect } from "postprocessing";

test("can be created and destroyed", t => {

const object = new ScanlineEffect();
object.dispose();

t.pass();

});

0 comments on commit 8c59fee

Please sign in to comment.