PREVIOUS article

DevLog #034: il problema dei riflessi [26/01/2020]

NEXT article

DevLog #036: il problema delle tende [16/02/2020]
DevLog #035: Il problema delle collezioni linkate come librerie esterne [02/02/2020]

Quando abbiamo iniziato a comporre la scena ritengo che siamo stati saggi e lungimiranti decidendo di realizzare quasi tutti gli asset in file separati per importarli come librerie esterne in un unico file dedicato alla scena completa. In teoria questo approccio ci è sembrato (e ci sembra tuttora) valido e vincente, sono convinto che dovrebbe essere la strada giusta per permettere di avere una scena finale complessa tuttavia gestibile come file leggero. Mantenendo tutti gli asset in file separati e consentendo le modifiche ad ogni singolo asset tramite intervento ad un file specifico da parte di chiunque, anche eventuali collaboratori, consente di avere la scena finale automaticamente aggiornata.
In verità invece in quest'ultima fase progettuale, ora che siamo alla ricerca del perfezionamento estetico della scena per realizzare il nostro tanto desiderato teaser, ci stiamo scontrando contro una serie di piccoli problemi il primo tra tutti quello di non poter intervenire direttamente sui materiali degli asset importati.
Infatti quando in Blender si importa un asset come libreria esterna, sebbene l'oggetto in questione risulti ben visibile e maneggiabile e sia possibile applicare anche una serie di trasformazioni base come posizione rotazione e scala,  tuttavia non è possibile intervenire sui dati dell'oggetto e nemmeno sui dati relativi agli shader applicati. Per farlo bisogna andare a modificare l'oggetto direttamente nella libreria esterna.
Questo problema si collega ad un altro già citato in un devlog precedente, trascurato fino a questo momento, ma recentemente salito alla ribalta è diventato prioritario in questi ultimi giorni: alcuni asset hanno un aspetto differente quando renderizzati nella scena finale rispetto a quando renderizzati nel loro file di origine. Per qualche motivo misterioso cambiano drasticamente aspetto nonostante tutti i nostri sforzi di creare le stesse condizioni al contorno di illuminazione, setup, impostazioni di rendering tra il file di origine ed il file della scena finale.
Continuare a saltare avanti ed indietro dal file origine al file della scena finale e fare continue prove di rendering non è sostenibile, non nella nostra situazione in cui la sola scena finale praticamente sfrutta il 100% delle risorse di sistema disponibili e ogni render comunque comporta del tempo per essere calcolato.
Sebbene non abbiamo speso troppo tempo fino ad oggi a sviscerare questo tipo di problematiche, più volte ed a più riprese ci siamo trovati a discutere di possibili e eventuali soluzioni al problema ed una delle soluzioni che ci sembrava più semplice (forse non la più veloce, né la più ottimizzata) è di ricreare la scena completa “appendendo” tutti gli asset invece di importarli come libreria esterna. Per chi non lo sapesse Blender consente di attingere ad altri file .blend come se fossero delle librerie esterne e ciò è possibile in due modi:

  1. utilizzando un link al file sorgente
  2. utilizzando un append

In caso di link l'oggetto rimane di fatto collegato esternamente dal file sorgente nella scena attuale, ma non è editabile nella scena attuale. Il vantaggio di questo approccio è che la scena rimane più leggera e l'oggetto viene effettivamente computato solo in fase di rendering. Il lato negativo è che non si può editare il modello importato e per farlo bisogna intervenire nel file di origine.
Con il secondo approccio, usare la tecnica di append, l'oggetto sorgente viene copiato interamente all'interno della scena attuale ed ogni collegamento con il file di origine viene perso. Il vantaggio di questo approccio è che l'oggetto è interamente editabile. Il contro ovviamente è che la scena si appesantisce di ulteriore oggetto.
Se dovessimo decidere di ricreare la scena completa utilizzando append e quindi importando tutti gli asset, ci troveremo con una scena discretamente impegnativa. Anzi a dirla tutta ho qualche dubbio che il mio pc sia in grado di reggerla... Tuttavia non ho modo di stimare a priori il carico, giusto?
Diciamo che prevedo un ulteriore possibile ottimizzazione in questo senso perché non ho la più pallida idea di come Blender, gestisca internamente gli oggetti linkati come librerie esterne, ma mi sono chiesto più volte cosa succede se vado a importare con link più oggetti che hanno lo stesso identico shader? Blender è in grado di riconoscere lo stesso shader ed ottimizzarne calcoli e sfruttamento della memoria? Non credo che spenderò del tempo per approfondire questa questione, magari in futuro, in ogni caso se qualcuno fosse al corrente di questo dettaglio avrei piacere di saperlo e vi prego di contattarmi tranquillamente su uno qualsiasi dei canali social per farmelo sapere.
In ogni caso siccome so che alcuni materiali sono stati utilizzati più volte in diversi asset come ad esempio il vetro, intravedo una possibilità di pulire e ottimizzare ulteriormente la scena.
Diciamo quindi che abbiamo deciso di intraprendere questa strada ossia, quella di ottenere la scena completa, così come ce l'abbiamo in questo momento, ma con tutti gli asset importati con append invece che tramite link.
Una delle cose più incredibili è stato scoprire che non esiste (o perlomeno io non sono riuscito a trovare) un modo semplice per convertire gli oggetti linkati in oggetti locali.
Ho letto e riletto più volte il manuale, ho cercato in lungo e in largo sui vari social, ho trovato in realtà diverse persone con le mie stesse domande tuttavia ho trovato sempre e solo un'unica risposta. Evidentemente non soddisfacente né per me, né per tutti gli altri con cui ho condiviso la domanda.
A quanto pare il metodo suggerito sia dal manuale sia da diversi utenti per convertire un oggetto linkato in un oggetto locale è di utilizzare un'apposita funzione disponibile nel menu contestuale dell’outliner (o nel menu della 3D view) con l'oggetto selezionato: utilizzare una funzione chiamata Make Local.
Stando al manuale make local dovrebbe essere esattamente quello che ci serve, dovrebbe convertire un oggetto importato tramite link in una entità istanziata localmente e quindi editabile.
Tuttavia svariate prove che ho condotto agendo sulle collezioni nella scena non hanno portato a nulla... make local lanciato in qualsivoglia modo su qualsiasi degli asset importati non risulta in un errore, ma apparentemente non succede nulla. Non si percepiscono cambiamenti effettivi nella scena.

Ricomponiamo la scena da capo

Abbiamo deciso di intraprendere la strada di ricreare un'altra volta da capo la scena completa, questa volta importando tutti gli asset con append invece di link. Il lavoro doveva essere apparentemente laborioso e noioso ma non particolarmente complicato, tuttavia come ogni volta ho sottovalutato terribilmente la situazione.
Il problema di fondo che è emerso una volta iniziato il lavoro è relativo all'organizzazione dei dati dei file asset.
Tutti i nostri asset per questioni di pulizia e scelta organizzativa, sono stati raccolti all'interno del loro file in una collezione dedicata per una facile condivisione e riutilizzo nella scena completa. Fino ad ora avevamo importato ogni asset tramite link collegando direttamente la collezione contenente l'asse in questione.
Il problema si pone nel momento in cui l'asset non è composto da un singolo oggetto ma da diversi elementi, motivo per cui aveva senso strutturare tutto in collezioni e non importare tutto direttamente.
Il problema di fondo è che importando con append una collezione mi sono trovato immediatamente in difficoltà per quanto riguarda le trasformazioni base, infatti mentre con una collezione importata tramite link è sufficiente selezionare e trasformare un empty che rappresenta la libreria esterna, per quanto riguarda invece le collezioni “appese” non sono trasformabili in quanto collezioni ma bisogna andare a selezionare di volta in volta tutti gli oggetti contenuti.
Per quanto questa singola operazione di selezione di tutti gli oggetti contenuti nella collezione non sia niente di complicato ed è facilmente ottenibile con il menù contestuale dell’outliner, in realtà se si pensa di ripeterla per decine e decine di volte risulta indubbiamente frustrante ed è una grossa perdita di tempo. Consideriamo che la scena finale in questo momento è composta da diverse centinaia di asset, per un totale di migliaia di oggetti.
Ammetto di avere sottovalutato questo aspetto agli inizi, quando abbiamo deciso e regolamentato in qualche modo la realizzazione degli asset. Ammetto di non aver compreso a fondo le collezioni ipotizzando di poterle usare come se fossero degli oggetti raggruppati (alla stregua di oggetti le collezioni stesse).
Dato che abbiamo lavorato sino a questo momento importando asset tramite link come librerie esterne non ci siamo mai resi conto di come sarebbe stato il flusso di lavoro importando oggetti veri e propri con append. Di conseguenza è venuto spontaneo voler fare una seconda review degli aspetti importanti della struttura/organizzazione degli asset man mano che venivano integrati nella scena.
È cominciata quindi in parallelo alla realizzazione della nuova scena completa anche un'altra review complessiva di tutti gli asset e questa volta molto più a basso livello della precedente, infatti in questo giro di revisione si è preso in considerazione una serie di altri fattori come la verifica di tutti gli oggetti che compongono l’asset, l'eventuale correzione dei nomi utilizzati e soprattutto uno degli oggetti in questione è stato eletto a “elemento base” e tutti gli altri oggetti di scena sono stati imparentati con esso. Col senno di poi probabilmente sarebbe stato meglio inserire un empty per ogni asset e imparentare tutti gli oggetti/componenti dell'asset con l’empty per avere una maggior similitudine con l'approccio dei link esterni. Ma è una cosa che è sempre possibile correggere in seguito, quindi un po' alla volta siamo andati avanti a ricomporre la scena, imparentare gli oggetti, riposizionarli, in qualche caso correggere qualche svista (fattore di scala, asimmetrie, trasformazioni non applicate, ecc.ecc.).
È facile immaginare che una review invasiva di questo tipo abbia richiesto più tempo di quello che mi fossi prefissato. Tuttavia in qualche modo siamo arrivati in fondo. La prima cosa che ho fatto a review e ricomposizione ultimate è stato rimettermi al lavoro sui render di prova per verificare che fosse tutto ok.
Il risultato che ho potuto constatare era abbastanza simile ai render precedenti sebbene ci fossero diverse problematiche su cui intervenire, infatti era già stato accennato tempo fa in un devlog, il problema relativo alla resa degli shader differente nei file degli asset piuttosto che nella scena finale.
Il problema era stato risolto correggendo gli shader nei file sorgenti per ottenere una buona resa nel file finale, tuttavia ora ci si trova nella situazione opposta:  questi shader una volta importati nella scena hanno una resa completamente differente. Quindi ho dovuto risistemare per l'ennesima volta tutti questi shader per ripristinarne l'aspetto esteriore.
Una volta sistemati gli shader problematici sono tornato a lavorare sul tema principale quello che ha dato origine a tutta la review e la ricomposizione della scena: il problema dei riflessi. Per cui per ogni asset importato che lo richiedesse sono andato ad aggiungere e regolare una reflection cubemap specifica.
In prima battuta ho voluto esagerare e sono andato ad inserire una reflection cubemap per praticamente qualsiasi oggetto vagamente riflettente presente nella scena, tuttavia i render successivi hanno evidenziato come non solo questo fosse inutilmente pesante per il bake e per il carico di sistema, ma in alcuni casi fosse anche peggiorativo per la qualità finale.
Prendiamo ad esempio la zona del fornello con le pentole e la caffettiera... Dopo aver inserito le cubemap per ogni oggetto presente sul fornello (fornello compreso) le riflessioni sono diventate indubbiamente più realistiche, tuttavia si sono create una serie di zone scure, di macchie nei riflessi decisamente sgradevoli.

 


Con diversi tweak alla regolazione di screen space reflection ed appesantendo non poco il calcolo, sono riuscito a migliorare leggermente la situazione tuttavia le zone scure permangono e complessivamente non sono gradevoli. Se rimuovo le cubemap dalla zona del fornello e confronto il render posso notare immediatamente come complessivamente la scena risulti più gradevole sebbene osservando nel dettaglio le singole riflessioni risultano essere meno realistiche.

 


Tutte queste prove confermano la decisione iniziale di inserire le reflection cubemap solo ed esclusivamente per gli oggetti che manifestano palesemente dei problemi o dei difetti nelle riflessioni mentre lasceremo un'unica cubemap globale per generare le riflessioni approssimative su tutti gli oggetti di scena che non richiedano particolari accorgimenti.

 


EDIT:

Ne approfitto per aggiornare questo articolo con alcune informazioni che ho appena scoperto mio malgrado. Abbiamo parlato in questo articolo di come sembrava non esserci un modo per convertire le collezioni importate come link esterni in un file in oggetti locali e di come non sembrava funzionare correttamente la funzione make local pensata proprio a questo scopo. Ci sono voluti circa quattro giorni o per essere più precisi quattro sere di lavoro per ricreare la scena completa partendo da zero, importando con append tutti gli asset e come nelle migliori storie allo scadere dell'ultima sera quando ormai la scena era completa, per qualche motivo che ignoro mi è venuto in mente di andare a cercare sul sito developer.blender.org, ossia il sito dove si può entrare in contatto con gli sviluppatori segnalando bug o problemi relativi a Blender e sono andato a cercare se qualcuno avesse già segnalato il baco relativo alla funzione make local. Ebbene sono finito su questa discussione. A quanto pare un utente ha segnalato lo stesso identico comportamento che ho riscontrato io: l'impossibilità di utilizzare make local per convertire in oggetti locali le collezioni linkate esternamente. Uno degli sviluppatori ha risposto in maniera tanto brusca quanto semplice, mettendo in evidenza un fatto probabilmente ovvio (ma non per me o per chi ha segnalato il problema), che le collezioni non sono oggetti di scena. Cosa intendo? Molto semplicemente se selezionate una collezione nell’outliner di fatto non viene selezionato nulla nella 3D viewport. Una collezione non è qualcosa di tangibile visibile nella viewport, è semplicemente un contenitore per organizzare i dati all'interno del file Blender. Tornando alla discussione, lo sviluppatore fa semplicemente notare come la funzione make local sia in realtà corretta e che il problema sia solo che deve essere usata su un oggetto collegato esternamente e non su una collezione in quanto “non-oggetto”.
Questa cosa inizialmente non l'ho capita, ci ho dovuto ragionare su un po' e fare degli esperimenti e sono giunto a queste conclusioni:

  1. se andate a verificare direttamente in Blender cosa succede quando importate tramite link una collezione esterna noterete che viene inserito nella scena un empty
  2. se andate a vedere le informazioni di questo empty noterete che istanzia una collezione e la collezione contiene in realtà il collegamento al file esterno (alla collezione nel file esterno)
  3. se fate la prova di collegare tramite link esterno un oggetto e non una collezione vedrete la differenza: se provate ad applicare la funzione make local sull'oggetto linkato esternamente sembra funzionare correttamente

A questo punto per pura curiosità, dopo aver capito che le collezioni non sono oggetti ma istanze, ho fatto una semplice ricerca con “F3” nelle funzioni disponibili in Blender cercando la parola chiave “istanze”... e ho scoperto che esiste una funzione chiamata make instances real.
Ho provato a lanciarla su tutte le collezioni del vecchio file della scena completa, quello con tutti gli asset importati tramite link a collezioni esterne, ed ecco che come per magia tutte le mie collezioni si sono tramutate negli oggetti contenuti. A quel punto è bastato selezionare gli oggetti e usare make local per avere tutto trasformato in oggetti o entità importate nella scena e non più collegamenti esterni.
Non ho ancora metabolizzato il fatto di aver scoperto che si poteva fare quello che cercavo di fare dopo ormai aver speso 4 giorni per rifare tutto da capo in altro modo... E rimane il fatto che sono fortemente sorpreso di aver scoperto che esiste questo metodo nonostante abbia cercato in lungo e in largo per la rete e abbia trovato in tutti i principali canali di discussione la domanda ma non la risposta. E per inciso nemmeno nella discussione su developer.blender.org lo sviluppatore ha fornito la soluzione all'utente, gli ha solo detto che è corretto che make local non funzione sulle collezioni ma nessuno ha scritto che con le collezioni si poteva fare.
Cose che capitano, suppongo...