Three.js pixelated lo-fi energy look

Napoleon Services
3 min readJun 5, 2020

--

Three.js comes with a pre build in WebGLRenderer. The other day I wanted to create a scene in a pixelated low quality look. By just turning down the Pixel-Ratio it still will *antialias* some parts of the scene. This has more to do with the internal GPU, rather than three.js.

renderer.setPixelRatio( 0.2 );

Not my kind of lo-fi energy

Now what we can do is to create a new scene. This scene consists of a new camera and texture. The camera is an orthographic camera, which means it does not have a perspective. Everything Orthographic-Scene related will be called dummy.

renderer.setPixelRatio( window.devicePixelRatio )dummyTexture = new THREE.WebGLRenderTarget(  container.clientWidth/4, //resolution x  container.clientHeight/4, //resolution y  {    minFilter: THREE.LinearFilter,    magFilter: THREE.NearestFilter,    format: THREE.RGBFormat  }
);
That’s the spirit

Basically we’ll just use the RenderToTexture.

Because the Scene gets rendered as a texture via vertexShader, we can ignore the MSAA as well.

Quick fiddle: https://jsfiddle.net/joooo0/2y3qc7sw/

Including a FragmentShader

Now that we have our render to texture in place, we can add some fine shader on top of it. These won’t affect the big pixels, but the smaller device pixels. Let’s just add a little wobbly wave.

The FragmentShader looks like this: (I copied this from ToyShader, don’t tell anyone)

#include <common>

uniform vec3 iResolution;
uniform float iTime;
varying vec2 vUv;
uniform sampler2D tDiffuse;
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
vec2 uv = vUv / 1.0;
fragColor = texture2D(tDiffuse, uv + vec2(sin(iTime*3.0 + uv.x * 10.0) * 0.003, 0.0));
}void main() {
mainImage(gl_FragColor, gl_FragCoord.xy);
}

Next, edit our code and split the uniforms, so it’s cleaner; and we add a iTime value. This will make the wobble go wobble 💃

var uniforms = {
tDiffuse: { value: rtTexture.texture },
iTime: { value: 0 },
iResolution: { value: new THREE.Vector3() },
};

After that, we edit our animation so it’ll update the iTime value.

function animate(time) {
time *= 0.001;
uniforms.iResolution.value.set(window.innerWidth, window.innerHeight, 1);
uniforms.iTime.value = time;
requestAnimationFrame( animate );
render();
}
Wobble

The final fiddle: https://jsfiddle.net/joooo0/akmcexfv/

Now it’s time to just experiment with different shaders. Maybe add a cool outline?

--

--

No responses yet