Initial commit: Retro 90s flight simulator MVP
Loading screen, main menu, 3D flight sim with CRT post-processing, procedural terrain, airport with buildings, low-poly aircraft, flight physics, HUD instruments, and sound. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
export class RetroEffect {
|
||||
constructor(renderer, width, height) {
|
||||
this.renderer = renderer;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.renderTarget = new THREE.WebGLRenderTarget(width, height, {
|
||||
minFilter: THREE.NearestFilter,
|
||||
magFilter: THREE.NearestFilter,
|
||||
});
|
||||
|
||||
this.scene = new THREE.Scene();
|
||||
this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
||||
|
||||
this.quad = new THREE.Mesh(
|
||||
new THREE.PlaneGeometry(2, 2),
|
||||
new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
tDiffuse: { value: null },
|
||||
resolution: { value: new THREE.Vector2(width, height) },
|
||||
time: { value: 0 },
|
||||
},
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
uniform sampler2D tDiffuse;
|
||||
uniform vec2 resolution;
|
||||
uniform float time;
|
||||
varying vec2 vUv;
|
||||
|
||||
vec2 barrelDistortion(vec2 uv, float amount) {
|
||||
vec2 center = uv - 0.5;
|
||||
float dist = dot(center, center);
|
||||
return uv + center * dist * amount;
|
||||
}
|
||||
|
||||
vec3 quantize(vec3 color, float levels) {
|
||||
return floor(color * levels + 0.5) / levels;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 distortedUv = barrelDistortion(vUv, 0.25);
|
||||
|
||||
// Clamp distorted UV
|
||||
distortedUv = clamp(distortedUv, 0.0, 1.0);
|
||||
|
||||
// Chromatic aberration
|
||||
float aberration = 0.0015;
|
||||
vec2 dir = distortedUv - 0.5;
|
||||
float dist = length(dir);
|
||||
|
||||
float r = texture2D(tDiffuse, distortedUv + dir * aberration).r;
|
||||
vec2 gbSample = distortedUv - dir * aberration * 0.5;
|
||||
float g = texture2D(tDiffuse, gbSample).g;
|
||||
float b = texture2D(tDiffuse, distortedUv - dir * aberration).b;
|
||||
vec3 color = vec3(r, g, b);
|
||||
|
||||
// Scanline
|
||||
float scanline = sin(vUv.y * resolution.y * 3.14159) * 0.08;
|
||||
color -= scanline;
|
||||
|
||||
// Quantize to EGA-like palette
|
||||
color = quantize(color, 16.0);
|
||||
|
||||
// Vignette
|
||||
float vignette = 1.0 - dist * 0.6;
|
||||
vignette = smoothstep(0.0, 1.0, vignette);
|
||||
color *= vignette;
|
||||
|
||||
// Subtle phosphor warmth
|
||||
color.r += 0.01;
|
||||
color.g += 0.005;
|
||||
|
||||
// CRT curvature darkening at edges
|
||||
float edgeDarken = smoothstep(0.3, 1.2, dist);
|
||||
color *= 1.0 - edgeDarken * 0.3;
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
`,
|
||||
})
|
||||
);
|
||||
|
||||
this.scene.add(this.quad);
|
||||
}
|
||||
|
||||
update(time) {
|
||||
this.quad.material.uniforms.time.value = time;
|
||||
}
|
||||
|
||||
render(scene, camera) {
|
||||
// Render scene to offscreen target
|
||||
this.renderer.setRenderTarget(this.renderTarget);
|
||||
this.renderer.render(scene, camera);
|
||||
|
||||
// Render post-processed quad to screen
|
||||
this.renderer.setRenderTarget(null);
|
||||
this.quad.material.uniforms.tDiffuse.value = this.renderTarget.texture;
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user