Algorithmic textures

Table of Contents

Back to BASIC applications collection

1. Circular waves

This QBasic program creates visually captivating circular wave patterns by manipulating pixel colors based on sine function calculations. It's a simple yet effective demonstration of how mathematical functions can be used to generate complex visual patterns.

The program uses two nested loops to iterate over each pixel on the screen. The outer loop handles the vertical axis (y-coordinate), and the inner loop handles the horizontal axis (x-coordinate).

For each pixel, the program calculates a sine value based on the squared distance from the origin (0,0). This calculation involves the formula:

colorvalue = SIN((x^2 + y^2) / 10) * 10

This program is a blend of mathematics and art, showcasing how simple algorithms can produce intricate and visually appealing results.

Circular waves - Screenshot 0.png

The screen is filled with a repeating grid of concentric rings, like ripples tiled across the surface. Each pixel's color comes from SIN((x^2 + y^2) / 10) * 10, clamped to the 0-15 range and shifted by 16 to reach into the upper palette. Because the squared distance grows quickly, the sine oscillates faster and faster away from the origin, and the discrete pixel grid aliases these rapid oscillations into the regular moire-like clusters of rings seen here.

Source code

' Program to render circular wave patterns.
' Algorithm was accidentally discovered while experimenting with sine function.
'
' This program is free software: released under Creative Commons Zero (CC0) license
' by Svjatoslav Agejenko.
' Email: svjatoslav@svjatoslav.eu
' Homepage: http://www.svjatoslav.eu
'
' Changelog:
' 2003, Initial version
' 2025, Improved program readability

SCREEN 13

' Initialize the screen mode to 320x200 with 16 colors

' Outer loop for the vertical axis (y-coordinate)
FOR ycoordinate = 1 TO 199
    ' Inner loop for the horizontal axis (x-coordinate)
    FOR xcoordinate = 1 TO 319
        ' Calculate the sine value based on the squared distances from the origin
        colorvalue = SIN((xcoordinate ^ 2 + ycoordinate ^ 2) / 10) * 10

        ' Clamp the color value to the range [0, 15]
        IF colorvalue < 0 THEN colorvalue = 0
        IF colorvalue > 15 THEN colorvalue = 15

        ' Set the pixel color at (xcoordinate, ycoordinate) with an offset to use the full 16-color palette
        PSET (xcoordinate, ycoordinate), colorvalue + 16
    NEXT xcoordinate
NEXT ycoordinate

' Wait for user key press
WHILE INKEY$ = "": WEND
CLS
END

2. Diamond square clouds

This QBasic program demonstrates the Diamond-Square algorithm, a method used to generate fractal terrain or cloud surfaces. The algorithm is particularly useful for creating realistic landscapes or textures in computer graphics.

Diamond square clouds - Screenshot 0.png

Soft bluish cloud blotches emerge from the black background, their bright misty cores fading into darkness. The palette is custom-programmed so that blue dominates while red and green are scaled down, giving the fractal its cold, smoky tone. The algorithm starts with a coarse 256-pixel grid and halves the scale on every pass: each midpoint and edge center receives the average of its neighbors plus a random displacement proportional to the current scale, clamped to a maximum lightness of 127, so large features appear first and finer detail layers on top.

Source code

DECLARE SUB DrawPixels (x1 AS INTEGER, y1 AS INTEGER, s AS INTEGER)
' Program to render cloud surface using diamond square algorithm.
'
' This program is free software: released under Creative Commons Zero (CC0) license
' by Svjatoslav Agejenko.
' Email: svjatoslav@svjatoslav.eu
' Homepage: http://www.svjatoslav.eu
'
' Changelog:
' 2003.12, Initial version
' 2024.08, Improved program readability

DECLARE SUB DrawBox (x1 AS INTEGER, y1 AS INTEGER, s AS INTEGER)
DECLARE SUB SetPalette ()
DECLARE SUB InitializeProgram ()
DEFINT A-Z
InitializeProgram

DIM SHARED maxLightness AS INTEGER
maxLightness = 127

DIM scale AS INTEGER
scale = 2 ^ 8

1 :
scale = scale \ 2
x1 = (319 \ scale) - 1
y1 = (199 \ scale) - 1

FOR y = 0 TO y1
    FOR x = 0 TO x1
        DrawPixels x * scale, y * scale, scale
    NEXT x
NEXT y

IF scale > 2 THEN GOTO 1
WAITa$ = INPUT$(1)

SUB DrawPixels (x1 AS INTEGER, y1 AS INTEGER, s AS INTEGER)
    ' Get the lightness values for the corners of the box
    c1 = POINT(x1, y1)
    c2 = POINT(x1 + s, y1)
    c3 = POINT(x1, y1 + s)
    c4 = POINT(x1 + s, y1 + s)

    ' Calculate the midpoint lightness values
    sp = s \ 2
    k = s * 2
    kp = k / 2

    cc2 = ((c1 + c2) / 2) + (RND * k) - kp
    IF cc2 > maxLightness THEN cc2 = maxLightness
    IF cc2 < 0 THEN cc2 = 0

    cc3 = ((c1 + c3) / 2) + (RND * k) - kp
    IF cc3 > maxLightness THEN cc3 = maxLightness
    IF cc3 < 0 THEN cc3 = 0

    cc4 = ((c2 + c4) / 2) + (RND * k) - kp
    IF cc4 > maxLightness THEN cc4 = maxLightness
    IF cc4 < 0 THEN cc4 = 0

    cc5 = ((c3 + c4) / 2) + (RND * k) - kp
    IF cc5 > maxLightness THEN cc5 = maxLightness
    IF cc5 < 0 THEN cc5 = 0

    ' Calculate the central lightness value
    cc1 = ((cc2 + cc3 + cc4 + cc5) / 4) + (RND * k) - kp
    IF cc1 > maxLightness THEN cc1 = maxLightness
    IF cc1 < 0 THEN cc1 = 0

    ' Set the calculated lightness values for the box
    PSET (x1 + sp, y1 + sp), cc1
    PSET (x1 + sp, y1), cc2
    PSET (x1, y1 + sp), cc3
    PSET (x1 + s, y1 + sp), cc4
    PSET (x1 + sp, y1 + s), cc5
END SUB

SUB InitializeProgram
    ' Set the screen mode and initialize the color palette
    SCREEN 13
    SetPalette
    RANDOMIZE TIMER
END SUB

SUB SetPalette
    ' Set the color palette for lightness levels
    FOR a = 0 TO 255
        OUT &H3C8, a
        OUT &H3C9, a / 4
        OUT &H3C9, a / 3
        OUT &H3C9, a / 2.3
    NEXT a
END SUB

3. Old paper

This QBasic program generates a procedural texture that simulates the appearance of old paper.

The program initializes the screen to a 320x200 resolution with 256 colors (SCREEN 13 in QBasic) and sets up a grayscale color palette. Each color index from 0 to 63 is assigned a shade of gray, creating a smooth gradient.

The program generates the texture by iterating over each pixel on the screen. For each pixel, it calculates a color value based on the color of the pixel directly above it, adding a small amount of random noise. This creates a smooth transition between pixels with controlled randomness, mimicking the fibrous texture of paper.

Old paper - Screenshot 0.png

The surface reads as aged paper: a smooth gray gradient that darkens towards the bottom, with fibrous vertical streaks along the left side. A grayscale palette of 64 shades is programmed first. Every pixel then averages the pixel directly above it with the previously computed color, adds a small random jitter, and periodically subtracts a fresh random noise offset roughly every ten steps. This feedback loop keeps the tones continuous from row to row while the accumulated noise produces the rough, fibrous grain of worn paper.

Source code

' Program to render surface resembling old paper.
'
' This program is free software: released under Creative Commons Zero (CC0) license
' by Svjatoslav Agejenko.
' Email: svjatoslav@svjatoslav.eu
' Homepage: http://www.svjatoslav.eu
'
' Changelog:
' 2003, Initial version
' 2025, Improved program readability

DEFINT A-Z
SCREEN 13
RANDOMIZE TIMER

' Initialize the color palette to grayscale. Each color index from 0 to 63 has R, G, B values equal to the index,
' creating a smooth grayscale gradient for the 256-color mode.
FOR paletteIndex = 0 TO 63
    OUT &H3C8, paletteIndex
    OUT &H3C9, paletteIndex  ' Set red component
    OUT &H3C9, paletteIndex  ' Set green component
    OUT &H3C9, paletteIndex  ' Set blue component
NEXT paletteIndex

noiseOffset = 0

' Generate a paper-like surface by averaging the color of the pixel above with some randomness.
' This creates a procedural texture that mimics the roughness of paper.
FOR y = 1 TO 190
    FOR x = 1 TO 310
        stepCounter = stepCounter + 1

        ' Approximately every 10 steps, introduce a new random noise offset to create variation in the pattern.
        ' This prevents the surface from becoming too uniform.
        IF stepCounter > 10 THEN
            noiseOffset = RND * currentColor / 20
            stepCounter = stepCounter - (RND * 20 + 10)
        END IF

        ' Get the color of the pixel directly above the current position.
        topColor = POINT(x, y - 1)

        ' Calculate the current color as the average of the top color and the previous current color,
        ' plus a small random noise and minus the noise offset. This creates a smooth transition with
        ' controlled randomness.
        currentColor = (topColor + currentColor) \ 2 + ((RND * 2) - noiseOffset)

        ' Clamp the color value to stay within the valid palette range (0 to 63).
        IF currentColor < 0 THEN currentColor = 0
        IF currentColor > 63 THEN currentColor = 63

        ' Plot the current pixel at (x-1, y) using the calculated color.
        PSET (x - 1, y), currentColor
    NEXT x

    ' Set the starting color for the next row to the last calculated color of the current row.
    ' This ensures continuity between rows.
    PSET (0, y + 1), currentColor
NEXT y

' Wait for a single key press before exiting the program.
inputKey$ = INPUT$(1)

SYSTEM

4. Wood

This QBasic program creates a visually appealing simulation of a wood surface. It is designed to generate a realistic wood grain texture using simple graphical techniques.

Wood - Screenshot 1.png

Overlapping wooden boards fill the screen, each showing wavy horizontal grain, vertical plank seams and bright beveled edges. A sixteen-color palette ramps from black to warm orange, with blue fixed at zero. Each board is framed by nested black, gray and white rectangles, then filled pixel by pixel: the new color is a weighted average of the pixels above and behind plus the previous result and a pinch of noise, while a sine-wave counter SIN((y + phaseOffset) / 100) bends the grain into waves. The main loop keeps drawing new boards at random positions forever.

Source code

' Program to render surface resembling wood.
'
' This program is free software: released under Creative Commons Zero (CC0) license
' by Svjatoslav Agejenko.
' Email: svjatoslav@svjatoslav.eu
' Homepage: http://www.svjatoslav.eu
'
' Changelog:
' 2003.12, Initial version
' 2024 - 2025, Improved program readability

DECLARE SUB DrawWoodSurface (woodX%, woodY%)
DECLARE SUB DrawPaper (xPos%, y1Pos%)
DEFINT A-Z
SCREEN 12
RANDOMIZE TIMER

' Set palette colors
FOR colorIndex = 0 TO 15
    OUT &H3C8, colorIndex
    OUT &H3C9, colorIndex * 4
    OUT &H3C9, colorIndex * 3
    OUT &H3C9, colorIndex * 0
NEXT colorIndex

' Main loop to draw wood at random positions
100:
woodX = RND * 400 + 200
woodY = RND * 100 + 200
CALL DrawWoodSurface(woodX, woodY)

SOUND 0, 10
GOTO 100

' Wait for user input to exit
exitKey$ = INPUT$(1)

SUB DrawWoodSurface (woodX, woodY)
    DIM lowerY AS INTEGER
    DIM phaseOffset AS INTEGER
    DIM xStepCounter AS INTEGER
    DIM randomOffset AS INTEGER
    DIM newColor AS INTEGER
    DIM upperColor AS INTEGER
    DIM currentColor AS INTEGER

    ' Draw the outline of the wood
    lowerY = woodY + 1
    LINE (0, 0)-(woodX, woodY), 0, BF  ' Black background
    LINE (5, 5)-(woodX - 5, lowerY - 5), 8, BF  ' Gray wood outline
    LINE (10, 10)-(woodX - 10, lowerY - 10), 15, BF  ' White inner highlight

    ' Initialize random phase offset for color variation
    phaseOffset = RND * 300

    ' Draw the wood texture
    FOR y = woodY - 1 TO 0 STEP -1
        FOR x = woodX - 1 TO 0 STEP -1
            xStepCounter = xStepCounter + 1
            IF xStepCounter > woodX THEN
                randomOffset = RND * 13  ' Small random noise for texture variation
                xStepCounter = SIN((y + phaseOffset) / 100) * woodX  ' Sine wave to create wavy grain pattern
            END IF
            upperColor = POINT(x, y + 1)  ' Get color from upper pixel
            currentColor = POINT(x, y)    ' Get color from current pixel
            newColor = (upperColor * 2 + currentColor + newColor * 3 + randomOffset) / 7 + RND * 1

            ' Ensure color value is within the valid range (0-15)
            IF newColor < 0 THEN newColor = 0
            IF newColor > 15 THEN newColor = 15

            ' Set the pixel color for the wood texture
            PSET (x + 1, y), newColor
        NEXT x
    NEXT y

END SUB

5. Yellow flame

"Yellow Flame" is a visually captivating program written in QBasic that generates a dynamic flame-like pattern on the screen.

Program initializes the color palette using sine waves to create a smooth gradient of colors. This gradient is essential for the flame effect.

The core of the program involves generating a surface pattern that mimics a flame. It does this by iterating over each pixel on the screen and calculating the average color of the surrounding pixels. A small amount of randomness is added to this average to create a natural, flickering effect.

Yellow flame - Screenshot 0.png

The texture glows like fire: bright yellow-white tongues at the bottom cool into orange and deep red swirls towards the top. The palette itself is built from three sine waves with different periods (21, 34 and 10 for red, green and blue), producing a smooth flame-like color gradient. Every pixel averages four already-drawn neighbors, the ones above, left, diagonally up-left and two to the left, and adds a random jitter between -2 and +2, so the heat appears to diffuse and flicker as it rises across the screen.

Source code

' Yellow flame.
'
' This program is free software: released under Creative Commons Zero (CC0) license
' by Svjatoslav Agejenko.
' Email: svjatoslav@svjatoslav.eu
' Homepage: http://www.svjatoslav.eu
'
' Changelog:
' 2003.12, Initial version
' 2024.08, Improved program readability


DEFINT A-Z ' Define all variables as integers
SCREEN 13 ' Set graphics mode to 320x200 with 256 colors
RANDOMIZE TIMER ' Seed the random number generator

' Initialize palette registers with sine wave colors
FOR paletteIndex = 0 TO 255
    OUT &H3C8, paletteIndex
    OUT &H3C9, INT(SIN(paletteIndex / 21) * 30 + 30)
    OUT &H3C9, INT(SIN(paletteIndex / 34) * 30 + 30)
    OUT &H3C9, INT(SIN(paletteIndex / 10) * 30 + 30)
NEXT paletteIndex

' Generate the surface pattern
FOR y = 1 TO 199
    FOR x = 1 TO 319
        prevPixel = POINT(x, y - 1)
        leftPixel = POINT(x - 1, y)
        diagPixel = POINT(x - 1, y - 1)
        left2Pixel = POINT(x - 2, y)

        ' Calculate the average of surrounding pixels and add some randomness
        newColor = (prevPixel + leftPixel + diagPixel + left2Pixel) \ 4 + (RND * 5 - 2)

        ' Clamp the color value within the valid range
        IF newColor < 0 THEN newColor = 0
        IF newColor > 63 THEN newColor = 63

        ' Set the pixel with the calculated color
        PSET (x, y), newColor
    NEXT x
NEXT y

' Wait for user input to exit
userInput$ = INPUT$(1)

Created: 2026-10-04 su 20:41

Validate