Graphics effects using chunky-to-planar on amiga/c (Ita)

Il cosiddetto modo planar è sempre stato un impedimento per quei programmatori che avevano intenzione di creare effetti grafici tridimensionali sull'Amiga, cosa che invece riusciva facilissima sui pc perchè supportavano nativamente il modo chunky. Esiste infatti una famosa disputa tra chi difendeva le peculiarità del planar (utile per i giochi 2d) e chi invece ne esaltava i difetti (inutile per i giochi 3d), resta comunque una verità indiscutibile: senza chunky non è possibile lavorare direttamente con i pixel, e questa è una gravissima limitazione per chi vuole realizzare effetti grafici di qualsiasi tipo, cioè non ancorati a certe particolari caratteristiche dell'hardware, come rotazioni di immagini, motori in texture mapping, bump mapping, etc.

Fortunatamente esistono delle tecniche di conversione che permettono di minimizzare queste differenze e rendere la vita più facile ai programmatori che tutt'ora, per scopi puramente hobbystici, hanno intenzione di sviluppare qualche piccolo lavoro grafico su questa macchina del passato. Anch'io mi ci sono cimentato con esiti positivi e dato che in rete il materiale scarseggia ho deciso di pubblicare in questo articolo un piccolo progetto che incorpora le tecniche di conversione c2p e p2c più veloci (programmate in assembler) con un esempio di utilizzo all'interno di un listato in c per la visualizzazione degli effetti grafici in tempo reale.


Per chi non dovesse conoscere le terminologie:

- Il planar era una tecnica di visualizzazione delle bitmap con la quale i bit dei pixel da visualizzare sullo schermo dovevano essere memorizzati sotto forma di più array booleani detti appunto bitplane. Un'immagine da 8-bit, ad esempio, era composta da otto bit-plane, cioè da ben otto array booleani in memoria distinti e separati. E' facile capire che se in questo modo avessi avuto la necessità di accedere ad un pixel in memoria, dato che possono essere letti da un array soltanto 8 bit (1 byte)  alla volta, avrei dovuto leggere 8 array diversi per ciascun pixel dell'immagine, il che è così dispendioso da rendere inutilizzabile questa tecnica per effetti real time.

- Il chunky invece è il modo nativo con cui le schede grafiche del pc (ma oggi giorno direi tutte) permettono di visualizzare sullo schermo un'immagine memorizzata come una successione di byte stipati all'interno di un unico array. Uno o più byte, letti in modo sequenziale all'interno dell'array, rappresentano il pixel che verrà visualizzato sullo schermo. Quindi per un'immagine a 8 bit è necessario un unico array, e per accedere ad un pixel serve un solo accesso al relativo byte. Se l'immagine è a 16 bit devo leggere i 2 byte disposti in memoria l'uno dopo l'altro per ciascun pixel, e così via. E' questo il modo corretto di rappresentare, lavorare e visualizzare le immagini digitali.

- Una ChunkyToPlanar è un algoritmo super ottimizzato in assembler (non esistono c2p in c)  che ha lo scopo di convertire in una sola botta l'intera immagine chunky in un'altra di tipo planar, per poter essere visualizzata da un hardware che supporta solo il planar.

- Una PlanarToChunky è lo stesso tipo di algoritmo solo che converte le immagini da planare a chunky. Esso non è usato quasi mai nell'Amiga per effetti in tempo reale, ma probabilmente per catturare degli schermi elaborati via hardware dai chip custom per poi poterli memorizzare in un'immagine digitale da elaborare oppure salvare su file secondo i formati attualmente esistenti.

Nel listato che ho incluso c'è un esempio utile su come aprire uno schermo nuovo con la intuition, per poi creare un semplice algoritmo di disegno (una texture mapping dei pavimenti con filtraggio bilineare) e visualizzare il risultato sullo schermo. Vediamo soltanto di commentare le parti di codice più salienti:

struct Screen *scr;

if(scr=OpenScreenTags(NULL, SA_Title,"New chunky to planar", SA_DisplayID, 0x00000000, SA_Depth, 8, SA_FullPalette, TRUE, SA_Exclusive, TRUE, TAG_DONE))
{//codice}

Questo serve ad aprire uno schermo con le funzioni del sistema operativo. Ciò che viene visualizzato del sistema è una bitmap di tipo planar a 8 bit con palette. Per settare una semplice palette di tipo grayscale:

for (y = 0; y < 256; y++)
SetRGB32( &scr->ViewPort, y, (y << 24), (y << 24), (y << 24));

I canali rgb della palette sono a 8bit ciascuno, tuttavia devono essere shiftati in quel modo, forse per motivi di allineamento in memoria (infatti amiga usa il big-endian). Passiamo al pezzo forte, e cioè alla creazione della struttura per poter in seguito utilizzare la chunky to planar:

// creo un'immagine a 8bit di 320x256

unsigned char *image;
image = new unsigned char[320*256];

// costruisco le informazioni per la ChunkyToPlanar

struct c2pStruct c2p;
c2p.bmap = scr->RastPort.BitMap; //indirizzo bitmap dello schermo amiga
c2p.startX = 0; //posizione x
c2p.startY = 0; //posizione y
c2p.width = 320; //larghezza
c2p.height = 240; //altezza
c2p.ChunkyBuffer = image; //immagine chunky da visualizzare

Questo significa che convertiremo direttamente il contenuto di image nella bitmap di visualizzazione, cioè chiamando la chunkytoplanar visualizzaremo sullo schermo il contenuto di image nel seguente modo:

ChunkyToPlanarAsm(&c2p);

Prima di chiudere il programma non dobbiamo scordarci di rilasciare l'immagine e di chiudere lo schermo amiga:

//rilascio la memoria usata per l'immagine
delete [] image;

//chiudo lo schermo amiga
CloseScreen(scr);

E' ovvio che questi listati possono essere messi insieme in un progetto compilabile solo da persone che hanno una certa esperienza, per questo motivo ho incluso anche l'eseguibile in formato Amiga, come dimostrativo per quegli utenti che vogliono vedere subito il risultato senza avere il tempo di compilare. Ricordate che l'effetto potrebbe sembrarvi lento non perchè la chunky to planar è lenta ma perchè l'algoritmo di disegno implementa un filtraggio di tipo bilineare. Per l'esecuzione sul pc consiglio l'ultima versione di winuae con harddisk e workbench installati, minimo 1mb di memoria e il coprocessore matematico casomai doveste usare  il processore 68030. Per una velocità di esecuzione decente settate il modo JIT (Just In Time).

©2008 Gianpaolo Ingegneri