phoboslab / wipeout-rewrite

2.63k stars 208 forks source link

For nostalgia add a PS1 mode? #1

Closed greggman closed 1 year ago

greggman commented 1 year ago
GithubPrankster commented 1 year ago

Hm, I have implemented shaders before doing this kind of thing and I did a version whilst currently using Raylib for a project. (sidenote, should be simple to add it as a platform wink)

in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec4 vertexColor;

uniform mat4 mvp;

noperspective out vec2 fragTexCoord;
noperspective out vec3 fragColor;

void main()
{
    vec2 res = vec2(160.0, 120.0);
    fragTexCoord = vertexTexCoord;
    fragColor = vertexColor.rgb;

    vec4 pop = mvp*vec4(vertexPosition, 1.0);
    gl_Position = pop;
    gl_Position.xyz = pop.xyz / pop.w;
    gl_Position.xy = floor(res * gl_Position.xy) / res;
    gl_Position.xyz *= pop.w;
}
#version 330

noperspective in vec2 fragTexCoord;
noperspective in vec3 fragColor;

uniform sampler2D texture0;
uniform vec4 colDiffuse;

out vec4 finalColor;

void main()
{
    vec4 texelColor = texture(texture0, fragTexCoord);
    if(texelColor.a < 0.8)
        discard;

    finalColor = texelColor*colDiffuse*vec4(fragColor, 1.0);
}

Should be straightforward to adapt to more general GL use. Here's also a dither + RGBA5551 filter fragment shader to further approach the look:

#version 330

uniform sampler2D texture0;

in vec2 fragTexCoord;

out vec4 finalColor;

const float neareight = 255.0;
vec3 dither(vec3 col, uvec2 fc)
{
    const int mat[16] = int[16] (
        -4, 0, -3, 1,
        2, -2, 3, -1,
        -3, 1, -4, 0,
        3, -1, 2, -2
    );

    ivec3 uncol = ivec3(col * neareight) + mat[(fc.y & uint(3)) * uint(4) + (fc.x & uint(3))];
    return vec3(uncol) / neareight;
}

vec3 band_color(vec3 lol)
{
    ivec3 res = ivec3(clamp(lol, 0.0, 1.0) * neareight) & ivec3(0xFF);
    ivec3 ires = res >> 3;
    ivec3 dres = (ires >> 2) & ivec3(7);
    res = (ires << 3) | dres;
    return vec3(res) / neareight;
}

void main()
{
    vec4 texelColor = texture(texture0, fragTexCoord);
    texelColor.rgb = band_color(dither(texelColor.rgb, uvec2(gl_FragCoord.xy)));

    finalColor = texelColor;
}

I might look into making a little fork tomorrow to try adding this. Also not sure how effective my shader bit shifts are haha, I did them more out of respecting how the quantization would be done from 8-bit to 5-bit. If I make a PR lemme know any better ideas.

stuaxo commented 1 year ago

In another wipeout like game, that allows shaders I had really good results with CRT emulation and scanlines but still with everything at a high res (as if on a giant HD CRT) - somehow it tricked my brain into feeling like as if I was playing the out games.

phoboslab commented 1 year ago

WIP, using this lovely CRT shader from https://github.com/mattiasgustavsson/

Still need to clean up some thing before I can merge it.

F3RrUptXwAAtvqA