Perché gli shader devono essere in un file html per il programma webgl?

Ho visto la seguente domanda in cui qualcuno ha chiesto come rimuovere gli shader da html: WebGL – c’è un’alternativa all’incorporamento degli shader in HTML?

Esistono elaborati workaround da caricare in un file contenente lo shader suggerito nelle risposte alla domanda.

Nel tutorial che ho visto, il codice dello shader è incorporato direttamente nell’html. Il codice javascript si riferisce ad esso utilizzando getElementById. Ma è brutto incorporare lo shader direttamente nell’html per molte ragioni. Perché non posso semplicemente riferirmi esternamente usando l’attributo src =?

 

Quanto sopra non funziona, voglio solo sapere perché no. Questo chiaramente ha a che fare con le limitazioni dello script stesso, ma non capisco.

Non è necessario utilizzare i tag per caricare un programma shader. La maggior parte dei tutorial e degli esempi li utilizza come contenitore per memorizzare una stringa nel DOM della pagina Web. Il tipo di script "x-shader/x-fragment" significato per i browser Web, quindi non esegue lo script. Tuttavia, essi memorizzano il contenuto di quel tag come una stringa nel DOM che può essere successivamente accessibile da script "reali". Funziona solo quando il contenuto dello script è nel file HTML. Quando si carica lo script tramite un attributo src, il contenuto non diventa un childcode di testo del tag script e quindi non è ansible accedervi tramite l'albero DOM .

Puoi anche memorizzare il codice sorgente per lo shader come stringa in un file Javascript:

 // myVertextShader.glsl.js var myVertexShaderSrc = "attribute vec3 pos;"+ "void main() {"+ " gl_Position = vec4(pos, 1.0);"+ "}" ; 

Dovresti quindi compilare lo shader in questo modo:

 var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, myVertexShaderSrc); gl.compileShader(vertexShader); gl.attachShader(program, vertexShader); 

Perché gli shader devono essere in un file html per il programma webgl?

Non lo fanno

Puoi mettere shader in javascript esterno. Per esempio

 // --myshader.js-- var myFragmentShader = "void main() {\n" + " gl_FragColor = vec4(1,0,0,1);\n" + "}n\"; 

O un altro formato comune

 // --myshader.js-- var myFragmentShader = [ "void main() {", " gl_FragColor = vec4(1,0,0,1);", "}", ].join("\n"); 

In tutti i browser che supportano WebGL è ansible utilizzare letterali modello

 // --myshader.js-- var myFragmentShader = ` void main() { gl_FragColor = vec4(1,0,0,1); } `; 

Altrimenti puoi metterli in file di testo e caricarli con XMLHTTPRequest

 // --myshader.txt void main() { gl_FragColor = vec4(1,0,0,1); } 

Quindi in JavaScript fai quanto segue

 function loadTextFile(url, callback) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.addEventListener('load', function() { callback(request.responseText); }); request.send(); } loadTextFile("myshader.txt", function(text) { // use text... }); 

La ragione per cui le persone li inseriscono nell’HTML è perché è facile, efficiente e sincrono.

facile : a differenza delle versioni di file JS, non devi circondare ogni riga con virgolette e altri segni di punteggiatura. Anche se ora con es6 non è più un problema. Ogni browser che supporta WebGL supporta stringhe modello es6.

efficiente : a differenza dei file text e js c’è solo una richiesta al server. Ovviamente alcune persone potrebbero eseguire un concatenatore sui loro file js per sistemarne alcune.

sincrono : a differenza dei file di testo, i loro usi sono sincroni. Non è necessario ricorrere a callback o promesse o altrimenti affrontare problemi asincroni di download di file.

Per quanto riguarda il motivo per cui il tuo esempio non funziona, sono sicuro che la ragione è che consentirebbe l’accesso alle risorse di origine incrociata. Il tag stato progettato prima che le persone capissero che l'accesso all'origine incrociata era un problema, quindi non potevano distriggersre gli script di origine incrociata senza rompere un gruppo di siti. Potrebbero rendere tutto più rigoroso.

XMLHttpRequest, ad esempio, non consente l'accesso all'origine incrociata a meno che il server che stai contattando non dia il permesso. Se i tag di script consentono di accedere a quel contenuto, è ansible utilizzare i tag di script per aggirare tale restrizione. In altre parole, invece di creare una richiesta XMLHttpRequest e leggere request.responseText per il risultato, dovresti creare un tag script a livello di programmazione, impostare il suo src sull'URL desiderato e leggere il suo campo di text al termine. Per assicurarti di non poterlo fare, non ti è permesso leggere il campo di text di un tag script che aveva un attributo src

Gli script di linguaggio shader sono solo testo. Il testo può essere afferrato o generato da qualsiasi luogo (che puoi leggere o generare testo). Molti tutorial saltano la parte in cui avviene la magia e le istanze di shader WebGL vengono create dalla stringa ottenuta. Non c’è motivo per cui non si possa fare riferimento agli script esternamente come si propone, ma è necessario un ulteriore JavaScript per caricare i contenuti, non il browser . I tag script sono probabilmente utilizzati nelle esercitazioni principalmente perché se si assegna a un tag script un tipo che il browser non comprende, il browser salta l’esecuzione del contenuto del tag o il recupero dell’origine dello script , in modo che i contenuti e gli attributi del tag possano essere utilizzati comunque tu desideri.

Edit: Beh, devo riprendere alcune cose. Ho deciso di passare attraverso quattro browser (Chrome, Firefox, IE9, Opera) e vedere cosa succede quando hai una linea

  

nel tuo html. Risulta, il browser carica il file in ogni browser che ho provato, quindi ho sbagliato. Tuttavia, ciò non significa che il browser sappia cosa fare con il file oltre a memorizzarlo nella cache. Non so cosa intendi con “Perché non src =” util / fs “funziona ???”. In ogni browser che ho provato,

 alert(document.getElementById('shader-fs').src); 

avvisa il percorso completo del file quando viene fornito un percorso parziale. (Forse questo è il tuo problema? Ti aspetti un percorso parziale quando il browser ti offre un pieno?) Oltre a questo, non sono sicuro di come interpretare il tuo problema.