Skip to content

Commit

Permalink
🌈 More post effect shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
benc-uk committed Dec 18, 2023
1 parent 63db4ec commit 9d253c6
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 57 deletions.
80 changes: 60 additions & 20 deletions dist-single/gsots3d.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist-single/gsots3d.js.map

Large diffs are not rendered by default.

19 changes: 12 additions & 7 deletions examples/effects/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ ctx.hud.addHUDItem(note)
window.addEventListener('keydown', (e) => {
if (e.key === ' ') {
effectNum++
if (effectNum > 5) effectNum = 0
if (effectNum > 6) effectNum = 0

switchEffect(effectNum)
}
Expand All @@ -93,16 +93,16 @@ ctx.start()
function switchEffect(effectNum) {
switch (effectNum) {
case 0:
customEdgeEffect()
customEdgeEffect(6.0, 2.0)
note.innerHTML = 'Effect: Custom'
break
case 1:
ctx.setEffectGlitch()
note.innerHTML = 'Effect: Glitch'
break
case 2:
ctx.setEffectMonochrome()
note.innerHTML = 'Effect: Grayscale'
ctx.setEffectDuotone()
note.innerHTML = 'Effect: DuoTone'
break
case 3:
ctx.setEffectScanlines()
Expand All @@ -116,13 +116,18 @@ function switchEffect(effectNum) {
ctx.setEffectContrast()
note.innerHTML = 'Effect: Contrast'
break
case 6:
ctx.removeEffect()
note.innerHTML = 'Effect: None'
break
}
}

function customEdgeEffect() {
function customEdgeEffect(speed = 4.0, scale = 2.0) {
// This shader is a Sobel filter with a rainbow effect
ctx.setEffectCustom(`
float speed = 3.0;
float speed = ${speed.toFixed(2)};
float scale = ${scale.toFixed(2)};
vec3 rainbow(float t) {
return vec3(
Expand All @@ -134,7 +139,7 @@ function customEdgeEffect() {
void main() {
// Sobel filter
vec2 texel = vec2(1.0 / width, 1.0 /height) * 2.0;
vec2 texel = vec2(1.0 / width, 1.0 /height) * scale;
float gx = 0.0;
float gy = 0.0;
Expand Down
4 changes: 1 addition & 3 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ <h1>🥽 GSOTS-3D &mdash; Examples & Samples</h1>
<li><a href="dice/">Dice with physics</a> - Dice falling onto a table with real time physics</li>
<li><a href="particles/">Particle system</a> - Showcases some particle system features</li>
<li><a href="teapot/">Utah teapots</a> - Who can resist this classic 3D model</li>
<li>
<a href="effects/">Post processing</a> - Showing full screen post processing effects with custom shaders
</li>
<li><a href="effects/">Post processing</a> - Showing full screen post processing effects</li>
<li><a href="shadow-test/">Shadow test</a> - Simple test scene for debugging shadows</li>
<li><a href="earth/">Planet Earth</a> - Very simple demo with the earth spinning in space</li>
<li><a href="hello-world/">Hello World</a> - Minimal GOSTS example, a single sphere</li>
Expand Down
14 changes: 8 additions & 6 deletions examples/physics/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ ctx.globalLight.enableShadows({
const floorMat = Material.createBasicTexture('../_textures/brickwall.jpg')
floorMat.specular = [0.6, 0.6, 0.6]
floorMat.addNormalTexture('../_textures/brickwall_normal.jpg')
const floor = ctx.createCubeInstance(floorMat, 400, 6)
floor.position = [0, -200, 0]
const floor = ctx.createCubeInstance(floorMat, 400, 5)
floor.position = [0, -20, 0]
floor.scale = [1, 0.1, 1]
floor.rotate(0, 0, -0.1)
floor.receiveShadow = true

Expand Down Expand Up @@ -81,7 +82,7 @@ ctx.hud.addHUDItem(note)

function addBall() {
const sphere = ctx.createSphereInstance(metalMat, 7, 32, 32)
sphere.position = [-150, 125, Math.random() * 300 - 150]
sphere.position = [-150, Math.random() * 50 + 80, Math.random() * 380 - 190]
const sphereBody = Physics.createSphereBody(sphere, 0.1, sphereMat)
world.addBody(sphereBody)

Expand All @@ -95,9 +96,10 @@ function addBall() {
}

function addCrate() {
const crate = ctx.createCubeInstance(crateMat, 20)
const x = Math.random() * 300 - 150
crate.position = [x, 1 - x / 8 + 5, Math.random() * 300 - 150]
const crate = ctx.createCubeInstance(crateMat, 18)
const x = Math.random() * 380 - 190
const z = Math.random() * 380 - 190
crate.position = [x, 1 - x / 8.5 + 5, z]
crate.rotateYDeg(Math.random() * 360)
const crateBody = Physics.createBoxBody(crate, 0, floorMat)
world.addBody(crateBody)
Expand Down
16 changes: 14 additions & 2 deletions src/core/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,12 +749,24 @@ export class Context {
log.info(`🌈 Post effects noise shader added`)
}

setEffectMonochrome(amount = 1.0) {
this.postEffects = PostEffects.monochrome(this.gl, amount)
/**
* Use bulit-in duotone post effect shader for monotone images
* @param colour1 - First colour, default [0.15, 0.09, 0.309]
* @param colour2 - Second colour, default [0.96, 0.39, 0.407]
* @param contrast - Contrast, default 1.5
*/
setEffectDuotone(colour1: RGB = [0.15, 0.09, 0.309], colour2: RGB = [0.96, 0.39, 0.407], contrast = 1.5) {
this.postEffects = PostEffects.duotone(this.gl, colour1, colour2, contrast)

log.info(`🌈 Post effects monochrome shader added`)
}

/**
* Use bulit-in contrast post effect shader, which reduces the image to two solid colours
* @param threshold
* @param darkColour
* @param lightColour
*/
setEffectContrast(threshold = 0.2, darkColour: RGB = [0, 0, 0], lightColour: RGB = [1, 1, 1]) {
this.postEffects = PostEffects.contrast(this.gl, threshold, darkColour, lightColour)

Expand Down
2 changes: 1 addition & 1 deletion src/engine/physics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function createBoxBody(inst: Instance, mass: number, material?: CANNON.Material,

if (inst.renderable instanceof PrimitiveCube) {
const size = (inst.renderable as PrimitiveCube).size
sizeVec = new CANNON.Vec3(size / 2, size / 2, size / 2)
sizeVec = new CANNON.Vec3((size / 2) * inst.scale[0], (size / 2) * inst.scale[1], (size / 2) * inst.scale[2])
}

if (inst.renderable instanceof Model) {
Expand Down
62 changes: 45 additions & 17 deletions src/engine/post-effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ export class PostEffects {
/**
* Create a simple scanlines effect with noise and flickering
* Taken from https://www.shadertoy.com/view/3dBSRD
* @param gl WebGL2RenderingContext
* @param density Density of scanlines, 0.0 - 1.0
* @param opacity Opacity of scanlines, 0.0 - 1.0
* @param noise Amount of noise, 0.0 - 1.0
* @param flicker Amount of flickering, 0.0 - 1.0
*/
static scanlines(gl: WebGL2RenderingContext, density: number, opacity: number, noise: number, flicker: number) {
const shader = `
Expand All @@ -147,10 +152,14 @@ export class PostEffects {
pixel = vec4(col, 1.0);
}`

const effect = new PostEffects(gl, shader)
return effect
return new PostEffects(gl, shader)
}

/**
* Create a glitch effect with horizontal lines
* @param gl WebGL2RenderingContext
* @param amount Amount of glitch, 0.0 - 1.0
*/
static glitch(gl: WebGL2RenderingContext, amount: number) {
const shader = `
float amount = ${amount.toFixed(3)};
Expand All @@ -167,27 +176,41 @@ export class PostEffects {
pixel = vec4(col, 1.0);
}`

const effect = new PostEffects(gl, shader)
return effect
return new PostEffects(gl, shader)
}

static monochrome(gl: WebGL2RenderingContext, amount: number) {
const shader = `
float amount = ${amount.toFixed(3)};
/**
* Create duotone effect with two colours and contrast
* @param gl WebGL2RenderingContext
*/
static duotone(gl: WebGL2RenderingContext, colour1: RGB, colour2: RGB, contrast: number) {
const shader = `
vec3 col1 = vec3(${colour1[0].toFixed(3)}, ${colour1[1].toFixed(3)}, ${colour1[2].toFixed(3)});
vec3 col2 = vec3(${colour2[0].toFixed(3)}, ${colour2[1].toFixed(3)}, ${colour2[2].toFixed(3)});
float contrast = ${contrast.toFixed(3)};
void main() {
vec3 col = texture(image, pos).rgb;
float mono = (col.r + col.g + col.b) / 3.0;
col = mix(col, vec3(mono), amount);
vec3 lumFactor = vec3(0.2126, 0.7152, 0.0722);
vec3 desat = vec3(dot(col, lumFactor));
pixel = vec4(col, 1.0);
// increase contrast
desat = pow(desat, vec3(contrast));
desat *= contrast;
pixel = vec4(mix(col1, col2, desat), 1.0);
}`

const effect = new PostEffects(gl, shader)
return effect
return new PostEffects(gl, shader)
}

/**
* Create a noise effect
* @param gl WebGL2RenderingContext
* @param amount Amount of noise, 0.0 - 1.0
* @param speed Speed of noise change
*/
static noise(gl: WebGL2RenderingContext, amount: number, speed: number) {
const shader = `
float amount = ${amount.toFixed(3)};
Expand All @@ -205,10 +228,16 @@ export class PostEffects {
pixel = vec4(col, 1.0);
}`

const effect = new PostEffects(gl, shader)
return effect
return new PostEffects(gl, shader)
}

/**
* Create a two colour contrast threshold effect
* @param gl WebGL2RenderingContext
* @param threshold Threshold value, 0.0 - 1.0
* @param colourDark Dark colour
* @param colourBright Bright colour
*/
static contrast(gl: WebGL2RenderingContext, threshold: number, colourDark: RGB, colourBright: RGB) {
const shader = `
float threshold = ${threshold.toFixed(3)};
Expand All @@ -228,7 +257,6 @@ export class PostEffects {
}
}`

const effect = new PostEffects(gl, shader)
return effect
return new PostEffects(gl, shader)
}
}

0 comments on commit 9d253c6

Please sign in to comment.