«[Figlio dell'uomo] Porgi l'orecchio e ascolta le parole di KGB
e applica la tua mente alla SUA istruzione
» Pv. 22,17

Qui si straparla di vari argomenti:
1. Il genere dei pezzi è segnalato da varie immagini, vedi Legenda
2. Per contattarmi e istruzioni per i nuovi lettori (occasionali e non) qui
3. L'ultimo corto è questo
4. Molti articoli di questo blog fanno riferimento a definizioni e concetti che ho enunciato nella mia Epitome gratuitamente scaricabile QUI. Tali riferimenti sono identificati da una “E” fra parentesi quadre e uno o più capitoli. Per esempio: ([E] 5.1 e 5.4)

venerdì 11 settembre 2015

KGB vs la OpenGL (5/??)

Ottavo giorno
Ieri avevo un po' le pile scariche ma ho voluto comunque iniziare a leggere la lezione sui cosiddetti frame buffer. Alla prima lettura ho capito solo il principio generale: usando specifiche istruzioni si può istruire la scheda video in maniera che crei le proprie immagini non sul “video” ma in apposite aree di memoria, i frame buffer appunto, che poi possono essere successivamente rielaborate o usate come se fossero immagini (texture). Per capirci posso usare questa tecnica per, ad esempio, riempire il contenuto di uno specchio, oppure potrei far apparire in un riquadro le immagini riprese da una telecamera...
In pratica la pletora di nuove chiamate alla OpenGL mi ha però confuso. L'autore del minicorso deve poi stare iniziando a stufarsi e tralascia qua e là qualche dettaglio che evidentemente ritiene banale.
Comunque non mi sono preoccupato troppo: con gli stencil avevo capito ancora meno ma poi, giocando con l'esempio pratico, mi si era chiarito tutto.
Così ho copiato e incollato il codice per creare un frame buffer, senza comunque utilizzarlo, e ho provato a vedere cosa succedeva. Risultato: finestra vuota.
Finestra vuota significa in genere che gli sheader hanno avuto un problema nel compilare il proprio codice ma, in questo caso, era il risultato voluto: il mio cubo rotante non veniva più “disegnato” sullo schermo ma sul frame buffer e per questo non vedevo niente...

Ma era veramente questo il caso? Nel dubbio ho provato a riattivare la modalità “normale”. Secondo il minicorso sarebbe in teoria bastato aggiungere la linea... glBindFramebuffer(GL_FRAMEBUFFER, 0);
...dopo aver creato (e non usato) il frame buffer.
Risultato ancora finestra vuota ma adesso significava che qualcosa non andava! Come detto ero però piuttosto stanco e così ho lasciato perdere...

Nono giorno
Per prima cosa ho cercato di scoprire dov'era il problema nel nuovo codice: l'ho tutto commentato, ho ricompilato e lanciato. La finestra mostrava di nuovo il cubo ruotante col gattino: ottimo.
Poi ho iniziato a scommentare un paio di linee del frame buffer e subito la finestra è tornata vuota. Così ho osservato bene le linee scommentate e i miei sospetti si sono concentrati su:
glBindTexture(GL_TEXTURE_2D, texColorBuffer);

Devo fare qui un piccolo inciso sulle funzioni “glBindXXX” della OpenGL. Quando si chiama una funzione della libreria OpenGL che agisce su, ad esempio, una texture per me sarebbe naturale specificare la texture da elaborare fra i parametri. Invece no, nella OpenGL la texture da usare è implicitamente quella attiva: e per rendere attiva una texture si usa appunto la funzione glBindTexture (che secondo me si sarebbe dovuta chiamare glEnableTexture!).
Suppongo che il motivo di questa scelta sia massimizzare l'efficienza, evitando di passare più volte un parametro sempre uguale (nel mio esempio la texture), anche a scapito della chiarezza...

Così ho immaginato che non bastasse chiamare glBindFrameBuffer ma che servisse anche aggiornare la texture attiva: e infatti, aggiungendo una chiamata alla glBindTexture con la texture con l'immagine del gattino, il problema si è risolto.
Ora posso creare il mio frame buffer, non utilizzarlo (!), e ripristinare la situazione originale.

Le istruzioni del minicorso si sono fatte un po' vaghe: se ho ben capito dovrei adesso far apparire un rettangolo 2D davanti al mio cubo roteante. In teoria non dovrebbe essere difficile: si tratta di replicare tutto il codice mischiando in pratica il sorgente del cubo con quello del rettangolo. L'autore è sarcastico: già notato in precedenza nei commenti, ignora al 100% le domande più stupide ed elogia quelle intelligenti, ma adesso è evidente.
Alla fine il mio codice scritto da zero funziona e il mio rettangolo appare correttamente: il problema è che non si vede il cubo rotante. Chiaramente è colpa delle istruzioni fornite dal minicorso su come alternare i due disegni. Sicuramente l'errore sarà mio ma come ho già detto l'autore adesso tende a tralasciare molti dettagli...
Non ho voglia di spidocchiare il mio codice confrontandolo con quello fornito di esempio e, anzi, mi limito a riadattare quest'ultimo (solito problema della libreria per la gestione delle finestre).
Sorpresa: in questo caso c'è il cubo rotante ma il rettangolo non si vede!
Un po' annoiato decido di lasciar perdere per il resto della serata...

Decimo giorno
Mi sono limitato a cercare di capire cosa facesse e come funzionasse il codice dell'esempio.
Alla fine sono arrivato alla conclusione che il rettangolo non si vede perché viene direttamente usato come destinazione dell'immagine del cubo rotante: per rendersene conto basta deformare il rettangolo cambiando le coordinate di uno solo dei suoi vertici. Il risultato è che anche il cubo viene a sua volta deformato seguendo la prospettiva della “tela” (texture) su cui è disegnato.

Successivamente mi sono limitato a compilare delle modifiche del codice dell'esempio per ottenere degli effetti di post processing: lo sfocamento, il bianco e nero e l'algoritmo di Sobel per l'evidenziamento dei bordi.
Di seguito un'immagine di questo terzo effetto:
È buffo: dal vivo il cubo ruota con l'usuale fluidità ma, per qualche motivo, la schermata lo ha ripreso in diversi momenti della rotazione chiaramente individuabili nelle successive strisce parallele....

Comunque, come giustamente evidenzia l'autore, è impressionante la potenza di queste nuove schede grafiche. Ad esempio, per l'effetto di sfocatura, per ogni singolo fotogramma del cubo rotante, si analizza per ciascun pixel dell'immagine risultante, gli 80 pixel che lo circondano e se ne calcola la media delle componenti del colore. Tutto questo è possibile grazie al parallelismo massiccio delle GPU.

giovedì 10 settembre 2015

Una nozione al giorno toglie...

Da un po' mi era venuta in mente l'idea di iniziare una nuova serie di pezzi nei quali descrivere almeno una nuova nozione imparata durante la giornata.
Sicuramente potrebbero venire degli articoli interessanti però ho il dubbio che, a lungo andare, possa divenire un impegno troppo stressante...

Magari posso provare a scrivere degli interventi in cui metto insieme le scoperte di più giorni. Ma anche in questo caso dovrei farmi degli appunti.... Bo...

Vabbè, io provo a iniziare poi, se vedo che mi prende troppo tempo o mi stresso, lascerò perdere...

Dunque, oggi verso 12:00, ero in attesa del mio maestro di chitarra in una piazzetta con a lato un piccolo giardino. Il sole batteva forte e così me ne stavo all'ombra di un alberello striminzito.
Improvvisamente ho sentito qualcosa cadere alla mia destra, non so, forse ho anche intravisto un movimento con la coda dell'occhio, comunque mi sono girato guardandomi intorno.

Sul marciapiede ho visto due grilli: uno grosso con uno più piccolo aggrappato alla sua schiena.
Ho così scoperto che i grilli maschi sono più piccoli delle femmine (da verificare su Wikipedia!).
Mi ha stupito che a fine estate sia ancora stagione di accoppiamenti: questa perplessità mi ha fatto riflettere su un'ovvietà: la notte sento ancora il frinire dei grilli e, se ancora si chiamano fra loro, vuol dire che la stagione degli amori non è finita. E queste sono due nuove cose imparate in un giorno solo!

Ah, e poi oggi ho avuto la lezione di chitarra durante la quale ho imparato un buon numero di nuove informazioni: ma di questa scriverò a parte nell'apposita rubrica...
E meno male che non ho guardato la OpenGL!!

Ah! E a cena ho provato una nuova ricetta: Tagliata di pollo con cipolle di Tropea da me opportunamente modificata per “funzionare” con le cipollacce della Lidl e un petto di pollo fatto già a pezzetti invece che intero...
Risultato ottimo, forse appena un po' troppo sale.

Temo che la mole di informazioni che si impara quotidianamente sia troppo imponente per poterne fare un elenco quotidiano.

Conclusione: grilli esibizionisti e sporcaccioni!

mercoledì 9 settembre 2015

Varoufakis spiega le ragioni della crisi greca

Su FB mi sono imbattuto in un articolo di Varoufakis (*1), scritto ad agosto, molto interessante. Credo che il documento sia stato preparato per una conferenza in Francia, perché più volte si rivolge direttamente ai francesi, però il suo interesse è generale e riguarda molto da vicino anche l'Italia.

L'articolo originale in inglese è questo: Our Athens Spring. L'articolo è stato tradotto in tre parti anche sul sito EssereSinistra.Wordpress.com: Parte 1, Parte 2 e Parte 3.

Io sto leggendo l'articolo originale, di circa 20 pagine, e al momento sono appena arrivato alla quinta prima di precipitarmi a scrivere questo pezzo.
Perché così tanto entusiasmo? Paradossalmente perché in queste cinque pagine non ho letto nessuna novità... per me (*2)...
Quello che voglio dire è che tutti i concetti espressi mi erano già noti e li avevo più volte divulgati su questo viario. Chiaramente Varoufakis scrive molto meglio di me e, a differenze dei miei pezzi, il suo articolo scorre benissimo.
La sostanza è però la stessa: la crisi greca ha mostrato che ciò che è veramente in ballo non è/era l'economia (o il suo debito) della penisola ellenica, ma la democrazia dell'intero continente europeo (e io aggiungerei dell'intero mondo occidentale). Inutile che riassuma le sue riflessioni: leggete il suo articolo che è meglio.

Almeno nella parte iniziale che ho già letto Varoufakis non cerca però di spiegare i motivi dietro a questa crisi democratica ma si limita a palesarla e a elencarne gli effetti in Grecia e la minaccia per il resto d'Europa. Magari ne parlerà in seguito... comunque, a tale riguardo, per un'analisi generale della crisi democratica rimando ai miei pezzi KGB sullo stato del mondo 1, KGB sullo stato del mondo 2 e KGB sullo stato del mondo 3...

Conclusione: appena posso completerò la lettura dell'articolo di Varoufakis e, se introduce dei concetti nuovi, vedrò di scriverci sopra un aggiornamento. In particolare sono curioso di scoprire se aggiunge qualche nuovo commento (*3) alla scelta di Tsipras di rinnegare l'esito del referendum...

Nota (*1): finalmente ho imparato a scrivere questo nome a memoria senza fare copia e incolla!!
Nota (*2): e, ovviamente, per gli indefessi lettori di questo viario!
Nota (*3): altrove non ha mai attaccato Tsipras frontalmente e ha dato gran parte della colpa alle pressioni esterne. Ha anche però detto che l'alternativa c'era... e le sue dimissioni parlano chiaro su cosa avrebbe voluto fare lui.

martedì 8 settembre 2015

KGB vs la OpenGL (4/??)

Sesto giorno
Stamani ho iniziato la terza lezione che è su traslazioni, rotazioni, ridimensionamento, prospettiva e simili...

Come si può facilmente indovinare entra qui in gioco una nuova libreria la GLM (OpenGL Math) che, “fortunatamente” avevo già installata e funzionante nell'ambiente di sviluppo del primo minicorso.
Subito però sono iniziate le stranezze: la lezione presentava un esempio banale per mostrare come funzionava la rotazione di un punto di 180° intorno all'asse Z dove, applicando un paio di funzioni al punto di coordinate (X,Y,Z) pari a (1, 0, 0), si sarebbe dovuto ottenere (-1, 0, 0) mentre a me il programma restituiva (0.998497, 0.054804, 0)!!
Ora, quando un programma funziona parzialmente come in questo caso, mi preoccupo più di quando non funziona per nulla: per esperienza, so che in genere si tratta di qualcosa di più insidioso. Eppure in questo caso il programma era banale...
Il malfunzionamento era così evidente che mi è venuta l'idea di controllare i commenti (che di solito non vedo perché uso un modulo aggiuntivo per Firefox per tutelare la mia riservatezza che blocca anche i commenti su Disqus). Immediatamente ho notato un commento su GLM, che non ho neppure letto del tutto, ma che ho subito messo in pratica: semplicemente aggiungendo la direttiva...
#define GLM_FORCE_RADIANS
… si è risolto il problema!
A mio giudizio non ha senso che una libreria si comporti in maniera così inaffidabile ma, come si dice nell'ambiente informatico, «A programma che funziona non si guarda in bocca»!

Poi sono riuscito a far funzionare senza problemi l'esempio con la foto di un gattino che ruotava sul piano XY ma, subito dopo, mi sono ribloccato.

L'esempio successivo infatti avrebbe dovuto ruotare la stessa foto su tre dimensioni, da uno specifico punto di vista e con la prospettiva: in soldoni si trattava semplicemente di aggiungere un altro paio di matrici create con opportune funzioni della OpenGL. Insomma più difficile a dirsi che a farsi. Almeno in teoria...
...in pratica sono però rimasto bloccato tutto il pomeriggio...
Non è che l'esempio non funzionasse del tutto, piuttosto vedevo ruotare una macchia di colore come se il punto di vista si trovasse a pochi millimetri dalla foto...
Ho ricontrollato svariate volte il codice (che non posso copiare e incollare in toto a causa della diversa libreria per la gestione delle finestre) ma non vi vedevo problemi. Poi ho iniziato a cercare di isolare il problema semplificando il codice e, ad esempio, inserendo matrici identiche per capire quale fosse quella che non funzionava. Ma il funzionamento era alquanto stravagante e non mi è riuscito giungere a nessuna conclusione. Ho fatto molti altri esperimenti che non ricordo (da questo punto di vista aiuta essere fantasiosi come me) ma anche le modifiche più banali non mi funzionavano. Poi verso le 18:00 ho iniziato a preparare la cena (acceso il forno per il pollo arrosto e raccolto in giardino erbette aromatiche...).

La pausa mi ha fatto bene: talvolta si inizia a fare modifiche su modifiche senza fermarsi a riflettere con calma. In cucina invece ho avuto modo di pensarci in maniera più distaccata.
Inizialmente avevo deciso di mettermi a studiare la GLM per bene in maniera da capire esattamente cosa non funzionava ma poi mi è venuta un'idea: non sarà un problema di versione?

Dopo cena ho controllato: la versione fornita nel vecchio ambiente di sviluppo era la 0.9.4.0 mentre quella che si trovava in linea era la 0.9.7.0... Insomma la versione che usavo non era proprio la più aggiornata ma neppure qualcosa di estremamente obsoleto, però... hai visto mai?
Così ho scaricato l'ultima versione della GLM (non c'è bisogno di compilarla) e l'ho inserita in una cartella parallela a quella già presente con la versione 0.9.4.0. Da buon pappagallino informatico ho modificato l'archivio CMAKE in maniera da rimpiazzare il nome della vecchia cartella GLM con la nuova e...
…incredibile: ha subito funzionato!!

Nella mia ignoranza mi permetto comunque una critica: se una libreria si comporta in maniera così erratica (senza mai segnalare alcun errore ma fornendo risultati incomprensibili) come questa GLM allora tutti i sorgenti che l'adoperano dovrebbero verificarne la versione: in questa maniera si eviterebbe di far perdere tempo inutilmente a chi, come me, non conosce le sue insidie...

Alla fine della lezione c'erano due esercizi: il primo era facilissimo mentre per il secondo mi manca pochissimo (*1).

Nota (*1): l'esercizio consiste nel far ruotare la foto lungo l'asse X quando si preme la barra dello spazio e farla poi rallentare dolcemente fino a fermarsi. A me ruota ma non rallenta dolcemente: suppongo che la mia formula matematica non sia adeguata...

Settimo giorno
Oggi ho ripreso da dove ero arrivato: ho spidocchiato il mio codice per capire come mai la mia versione del secondo esercizio non funzionava.
Mi concentravo sulla formula matematica ma, a tutte le prove che facevo, sembrava andare bene: alla fine l'errore era banale e da tutt'altra parte...
Semplicemente inizializzavo una variabile all'interno del ciclo principale invece che fuori da esso: un errore da principiante che avrei dovuto individuare dopo pochi secondi mentre invece mi è occorsa circa un'ora! Come dicevo sono arrugginito... molto...

Finalmente ho poi cominciato la quarta lezione su profondità e stencil.
La profondità è banale perché fa tutto la scheda video: basta attivarla con un'apposita funzione e, automaticamente, i poligoni (nel mio caso triangoli) che stanno dietro ad altri non vengono disegnati...
L'argomento stencil è invece molto più complesso e, alla prima lettura della teoria non ci ho capito quasi niente!
Fortunatamente l'esempio di uso era molto chiaro e, basandomi su di esso, e rileggendo poi la teoria, sono riuscito a chiarirmi le idee. In pratica gli stencil sono affini alla profondità ma devono essere interamente gestiti via codice. Garantiscono maggiore flessibilità ma al prezzo di una difficoltà d'uso molto maggiore.

A fine lezione non c'erano i soliti esercizi ma l'autore forniva due collegamenti su come usare gli stencil per generare ombre e per evidenziare i bordi di un oggetto tridimensionale: la prima di queste operazioni mi è parsa decisamente più complessa e le indicazioni fornito dal sito collegato erano troppo vaghe per dare più di un'idea superficiale; invece evidenziare i bordi era decisamente più semplici e sono riuscito a implementare tale tecnica nel mio cubo ruotante. Ecco la prova!