F18 Interceptor: Building my favorite old Amiga game

Added a weird stippling. Its kinda funny how hard this is to look like the “old” way. On the Amiga you ran a blitter co routine (yes they had one of the first gpus) and it was kinda trivial to ‘step over’ a pixel when rendering :slight_smile:

Something to be said for pixel buffers imho.

Heres the shader as well. There are some specific constants in there for my game, read the comments :slight_smile:

varying highp vec4 var_position;
varying mediump vec3 var_normal;
varying mediump vec2 var_texcoord0;
varying mediump vec4 var_light;

// Notes:
//  This is mapped onto a 3DD cylinder made in Blender. It is 2.0 high and the texture is unwrapped so 
//   that the uv mapping is vertical for the height of the cylinder. The cylinder also has had its faces
//   flipped becase you will be inside it :)
//  The var_position is the only weird one here. In the vp I use:
//    var_position = (mtx_proj * p).xyz;
//    otherwise the vp is pretty std model vp.

// This is setup from the render_script with:
// x = resolution width (in my case its a RT width, but you can normally use screen/window)
// y = resolution height 
// z = aspect (just divide the x by the y) I dont use it here, but I do for others :)
// w = altitude of the camera. This is needed because the plane can move up almost as far as the farplane which is 50km.
uniform mediump vec4 params;

// Colors for the top and middle of the atmospehere. Below horizonColor black is drawn
const vec4 peakColor = vec4(0.5372549, 0.545098039, 0.929411764, 1.0);
const vec4 horizonColor = vec4(0.52941176, 0.843137254, 0.98823529, 1.0);
const vec4 black = vec4(0.0,0.0,0.0, 1.0); 

highp float pi = 3.141592653589793;

// These are used in pixel calcs. Because my render texture resolution can change this means
// these need to be dynamic.
mediump float pixelBandX = 1.0 / params.x;
mediump float pixelBandY = 1.0 / params.y;

// How wide to apply a blend for the hiorizon
mediump float colorBand = 1.0 / 256.0;
// How wide to apply the dithering band on the horizon
mediump float colorBandLow = (1.0 / 256.0) * 5;

// Fudge factor to get it looking ok. 
const highp float factor = 0.75;

// These are 'steppers' so that the position of the pixel can be stepped. This isnt overly
// accurate because we are doing this in projected screen coords. Theres probably a better way I suspect.
highp float RESX = (params.x * factor);
highp float RESY = (params.y * factor);
highp float RESHX = (RESX * 0.5);
highp float RESHY = (RESY * 0.5);

// This creates the horizon stipple effect
vec4 stipple( vec4 color, vec2 uv, float level )
{
    float xcoord = uv.x;

    float valy = mod(uv.y, RESY);
    if(valy > RESHY)
        xcoord += RESHX;

    float valx = mod(xcoord, RESX);
    if(valx > RESHX)
        return color * level;
    else
        return vec4(color.xyz, level);
}

void main()
{
    // Yes horrible. Divide by our maximum alt * 2 - because this is mapped onto a cylinder
    float alt = params.w / 90000;

    // Work out where the horizon is using uv coord
    highp float f = floor( (var_texcoord0.y + alt) / colorBand) * colorBand;
    if(f < 0.5) {
        gl_FragColor = black;
    }
    else if(f >= 0.5 && f <= 0.5 + colorBandLow) {
        float level = ((f-0.5)/colorBandLow ) * 0.5 + 0.5;
        gl_FragColor = stipple( mix(horizonColor, peakColor, (f-0.5)/0.05), var_position.xy, level);
    }
    else if(f > 0.5 + colorBandLow && f < 0.55) {
        gl_FragColor = mix(horizonColor, peakColor, (f-0.5)/0.05);
    }
    else if(f >= 0.55){
        gl_FragColor = peakColor;        
    }
}
2 Likes