Skip to content

Commit

Permalink
add: better surface noise & grit
Browse files Browse the repository at this point in the history
  • Loading branch information
goldbuick committed May 18, 2024
1 parent 4793232 commit abb9442
Showing 1 changed file with 166 additions and 22 deletions.
188 changes: 166 additions & 22 deletions zss/terminal/crt.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
import { EffectProps, wrapEffect } from '@react-three/postprocessing'
import { BlendFunction, Effect, EffectAttribute } from 'postprocessing'
import { Texture, Uniform, WebGLRenderTarget, WebGLRenderer } from 'three'
import {
BlendFunction,
Effect,
EffectAttribute,
ColorChannel,
} from 'postprocessing'
import {
Texture,
Uniform,
UnsignedByteType,
WebGLRenderTarget,
WebGLRenderer,
} from 'three'
import { MAYBE, ispresent } from 'zss/mapping/types'

type CRTEffectOpts = {
texture?: Texture
}

const CRTShapeVertShader = `
#ifdef ASPECT_CORRECTION
uniform float scale;
#else
uniform mat3 uvTransform;
#endif
varying vec2 vUv2;
void mainSupport(const in vec2 uv) {
#ifdef ASPECT_CORRECTION
vUv2 = uv * vec2(aspect, 1.0) * scale;
#else
vUv2 = (uvTransform * vec3(uv, 1.0)).xy;
#endif
}
`

const CRTShapeFragShader = `
// #ifdef TEXTURE_PRECISION_HIGH
// uniform highp sampler2D splat;
// #else
// uniform mediump sampler2D splat;
// #endif
uniform sampler2D splat;
const CRTShapeFragmentShader = `
float rectdistance(vec2 uv) {
vec2 tl = vec2(-1.0);
vec2 br = vec2(1.0);
Expand All @@ -24,6 +66,12 @@ vec2 bendy(const in vec2 xn) {
}
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
#ifdef UV_TRANSFORM
vec4 texel = texture2D(splat, vUv2);
#else
vec4 texel = texture2D(splat, uv);
#endif
vec2 xn = 2.0 * (uv.st - 0.5);
vec2 edge = bendy(xn);
vec2 bent = edge.xy * 0.5 + 0.5;
Expand All @@ -35,7 +83,9 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor)
float doot = max(abs(edge.x), abs(edge.y));
if (doot < 1.0) {
// display
outputColor = texture2D(inputBuffer, bent);
vec4 displaycolor = texture2D(inputBuffer, bent);
vec4 fuxtcolor = texel;
outputColor = mix(displaycolor, fuxtcolor, 0.04);
} else if (doot > 1.004) {
// display shell
vec3 matte = vec3(205.0 / 255.0, 205.0 / 255.0, 193.0 / 255.0);
Expand All @@ -48,7 +98,7 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor)
}
// apply inner shade
if (doot < 1.0) {
if (doot >= 0.5 && doot < 1.0) {
float sh = clamp(0.0, 1.0, 1.0 - bx - 0.7);
vec3 shade = mix(outputColor.rgb, vec3(0.0), pow(sh, 4.0));
outputColor = vec4(shade, inputColor.a);
Expand All @@ -65,18 +115,121 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor)
`
// 205 205 193
class CRTShapeEffect extends Effect {
constructor() {
super('CRTShapeEffect', CRTShapeFragmentShader, {
constructor({ texture }: CRTEffectOpts = {}) {
super('CRTShapeEffect', CRTShapeFragShader, {
blendFunction: BlendFunction.NORMAL,
attributes: EffectAttribute.CONVOLUTION,
defines: new Map([
['TEXEL', 'texel'],
['TEXTURE_PRECISION_HIGH', '1'],
]),
uniforms: new Map<string, Uniform>([['splat', new Uniform(texture)]]),
})
}

get texture(): MAYBE<Texture> {
return this.uniforms.get('splat')?.value
}

set texture(value: Texture) {
const { texture: prevTexture, uniforms, defines } = this
const uniformmap = uniforms.get('splat')
const uniformuvTransform = uniforms.get('uvTransform')

if (prevTexture !== value && uniformmap && uniformuvTransform) {
uniformmap.value = value
uniformuvTransform.value = value.matrix
defines.delete('TEXTURE_PRECISION_HIGH')

if (value !== null) {
if (value.matrixAutoUpdate) {
defines.set('UV_TRANSFORM', '1')
this.setVertexShader(CRTShapeVertShader)
} else {
defines.delete('UV_TRANSFORM')
this.setVertexShader(null as any)
}

if (value.type !== UnsignedByteType) {
defines.set('TEXTURE_PRECISION_HIGH', '1')
}

if (
prevTexture === null ||
prevTexture?.type !== value.type ||
prevTexture?.encoding !== value.encoding
) {
this.setChanged()
}
}
}
}

getTexture() {
return this.texture
}

setTexture(value: Texture) {
this.texture = value
}

get aspectCorrection() {
return this.defines.has('ASPECT_CORRECTION')
}

set aspectCorrection(value) {
if (this.aspectCorrection !== value) {
if (value) {
this.defines.set('ASPECT_CORRECTION', '1')
} else {
this.defines.delete('ASPECT_CORRECTION')
}

this.setChanged()
}
}

get uvTransform() {
const texture = this.texture
return !!texture?.matrixAutoUpdate
}

set uvTransform(value: boolean) {
const texture = this.texture

if (ispresent(texture)) {
texture.matrixAutoUpdate = value
}
}

setTextureSwizzleRGBA(r: number, g = r, b = r, a = r) {
const rgba = 'rgba'
let swizzle = ''

if (
r !== ColorChannel.RED ||
g !== ColorChannel.GREEN ||
b !== ColorChannel.BLUE ||
a !== ColorChannel.ALPHA
) {
swizzle = ['.', rgba[r], rgba[g], rgba[b], rgba[a]].join('')
}

this.defines.set('TEXEL', 'texel' + swizzle)
this.setChanged()
}

update(): void {
if (this.texture?.matrixAutoUpdate) {
this.texture.updateMatrix()
}
}
}

export type CRTShapeProps = EffectProps<typeof CRTShapeEffect>
export const CRTShape = wrapEffect(CRTShapeEffect)

const CRTLinesFragmentShader = `
const CRTLinesFragShader = `
uniform float count;
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
Expand All @@ -101,23 +254,17 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor)
}
`

type CRTLinesEffectOpts = {
texture?: Texture
}

class CRTLinesEffect extends Effect {
constructor({ texture }: CRTLinesEffectOpts = {}) {
super('CRTLinesEffect', CRTLinesFragmentShader, {
// eslint-disable-next-line no-empty-pattern
constructor({}: any = {}) {
super('CRTLinesEffect', CRTLinesFragShader, {
blendFunction: BlendFunction.MULTIPLY,
uniforms: new Map<string, Uniform>([
['count', new Uniform(1)],
['splat', new Uniform(texture)],
]),
uniforms: new Map<string, Uniform>([['count', new Uniform(1)]]),
})
}

update(
renderer: WebGLRenderer,
_renderer: WebGLRenderer,
inputBuffer: WebGLRenderTarget<Texture>,
): void {
const count = this.uniforms.get('count')
Expand All @@ -129,6 +276,3 @@ class CRTLinesEffect extends Effect {

export type CRTLinesProps = EffectProps<typeof CRTLinesEffect>
export const CRTLines = wrapEffect(CRTLinesEffect)

// export type TextureSplatProps = EffectProps<typeof TextureEffect>
// export const TextureSplat = wrapEffect(TextureEffect)

0 comments on commit abb9442

Please sign in to comment.