Phenomenal & Enigmatic, part 3 of 4

#retrocomputing #javascript #demoscene #learning #reverse-engineering

Written by Anders Marzi Tornblad

This is part 3 of the Phenomenal & Enigmatic series. If you haven't read the first part, here it is: Phenomenal & Enigmatic, part 1 of 4

When i made Phenomenal & Enigmatic, I didn't want to reuse any of the graphics art from the original demo. I had decided to take the music and some sense of the overall demo design, but for the Enigmatic logo, I turned to rendering it using code.

Screenshot from the 1991 Amiga demo Enigma by Phenomena. Enigma logotype by Uno of Scoopex.One popular technique of creating good-looking logos back in the Amiga days was to first draw the logo as a flat surface, then duplicating it in a new layer a few pixels off, making that new layer semi-transparent. Then one would paint in side surfaces and edge lines with varying levels of opacity. After adding some final touches, like surface textures or lens flares, the end result would be a glossy, glassy look, much like the original Enigma logo by Uno of Scoopex.

Screenshot from the 2013 JavaScript Canvas demo Phenomenal and Enigmatic. Enigmatic logotype rendered by code.The logo scene uses the same technique, painting the front, back and side of the word ENIGMATIC as filled polgons with slightly different colors and opacity levels. During this scene, I animate some of the transormation vectors for effect. Of course, the original artwork by "Uno" is much better in exactly every way, but it was a fun exercise.

Pseudo code

// Logo renderer
function transformLogoCoord(chapterId, time, x, y) {
    // Left out: Perform a pseudo-3D coordinate transformation
    
    return { x : transformedX, y : transformedY };
}

function logoMoveTo(chapterId, time, x, y, xOffset, yOffset) {
    var coords = transformLogoCoords(chapterId, time, x, y);
    context.moveTo(coords.x, coords.y);
}

function logoLineTo(chapterId, time, x, y, xOffset, yOffset) {
    var coords = transformLogoCoords(chapterId, time, x, y);
    context.lineTo(coords.x, coords.y);
}

function renderLogo(chapterId, time) {
    var xOffset, yOffset;
    // Left out: Calculate xOffset and yOffset from the chapterId and time values
    
    // Draw bottom surfaces
    context.beginPath();
    for (var block, i = 0; block = logoPolygons[i++];) {
        logoMoveTo(chapterId, time, block[0].x, block[0].y, 0, 0);
        for (var coord, j = 1; j = block[j++];) {
            logoLineTo(chapterId, time, coord.x, coord.y, 0, 0);
        }
        
        logoLineTo(chapterId, time, block[0].x, block[0].y, 0, 0);
    }
    
    context.closePath();
    context.fill();
    
    // Left out: draw side surfaces
    
    // Left out: draw top surfaces
}

You can try this solution at atornblad.github.io/enigmatic. The latest version of the code is always available in the GitHub repository.

Articles in this series: