2013-03-27 18 views
22

Ho iniziato con il renderer WebGL di ThreeJS dopo aver eseguito un WebGL "regolare" senza librerie aggiuntive + shader GLSL. Sto cercando di scrivere shader personalizzati ora nel mio programma ThreeJS e ho notato che ThreeJS si occupa di molte cose standard come le matrici di proiezione e di modello/vista. Il mio semplice vertex shader ora assomiglia a questo:Attributi shader predefiniti ThreeJS/uniformi

// All of these seem to be predefined: 
// vec3 position; 
// mat4 projectionMatrix; 
// mat4 modelViewMatrix; 
// mat3 normalMatrix; 
// vec3 normal; 

// I added this 
varying vec3 vNormal; 

void main() { 
    vNormal = normalMatrix * vec3(normal); 
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
} 

La mia domanda è: quale di altre caratteristiche variabili (sto supponendo che siano uniformi) sono predefiniti per il vertex shader e frammenti che potrei usare? ThreeJS aiuta con i vettori della luce/il colore della luce ad esempio (ovviamente supponendo che abbia aggiunto una o più luci alla mia scena ThreeJS)?

aggiornamento (9 ott 2014): Questa domanda è stata sempre un bel po 'di vista, e l'utente Killah ha detto che le risposte esistenti non hanno portato ad una soluzione più con la versione corrente di Three.js. Ho aggiunto e accettato la mia risposta, vedi sotto.

+0

Bella domanda, '+ 1' –

risposta

4

Questa domanda è stato sempre un bel paio di punti di vista, e l'utente Killah ha detto che le risposte esistenti non hanno portato ad una soluzione più con la versione corrente di tre .js. Per questo ho cercato di risolvere il problema ancora una volta, e mi piacerebbe delineare un paio di opzioni che ho trovato:

  • Il modo più semplice e veloce (anche se non molto elegante) è quello di mettere solo un caso errore nel tuo shader. Si verificherà un errore della console con l'intero codice dello shader, incluso tutto ciò che aggiunge three.js.

  • La soluzione migliore è generare l'origine dello shader da cui è stato compilato, ovvero THREE.WebGLShader (a partire dalla versione corrente di three.js, r68). Ho fatto una copia e incolla veloce che dovrebbe generare tutte le fonti shader prima che vengano compilate.

    Aggiungere questo dopo aver incluso Three.js e prima il proprio codice:

    THREE.WebGLShader = (function() { 
        var addLineNumbers = function (string) { 
         var lines = string.split('\n'); 
         for (var i = 0; i < lines.length; i ++) { 
          lines[ i ] = (i + 1) + ': ' + lines[ i ]; 
         } 
         return lines.join('\n'); 
        }; 
        return function (gl, type, string) { 
         var shader = gl.createShader(type); 
         console.log(string); 
         gl.shaderSource(shader, string); 
         gl.compileShader(shader); 
         if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) { 
          console.error('THREE.WebGLShader: Shader couldn\'t compile.'); 
         } 
         if (gl.getShaderInfoLog(shader) !== '') { 
          console.warn('THREE.WebGLShader: gl.getShaderInfoLog()', gl.getShaderInfoLog(shader)); 
          console.warn(addLineNumbers(string)); 
         } 
         return shader; 
        }; 
    })(); 
    

    Si noti che questo frammento è solo copiato (e leggermente cambiato) dalle fonti Three.js e deve essere rimosso prima realtà usando il codice. Solo per il debug!

  • C'è un'altra opzione che è meno invasiva: è possibile controllare la vostra ShaderMaterial dopo aver creato e rendendo almeno una volta, in questo modo:

    var material = new THREE.ShaderMaterial({ 
        uniforms: { 
         uColorMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_colors.png') }, 
         uSpecularMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_spec.png') }, 
         uNormalMap: { type: 't', value: THREE.ImageUtils.loadTexture('./img/_normal.png') } 
        }, 
        vertexShader: document.getElementById('vShader').innerText, 
        fragmentShader: document.getElementById('fShader').innerText 
    }); 
    

    Poi, dopo rendere l'oggetto almeno una volta :

    console.log(material.program.attributes); 
    console.log(material.program.uniforms); 
    

Spero che questo aiuti tutti! Sentiti libero di aggiungere i tuoi commenti se conosci più e/o modi migliori per ottenere il tuo codice shader.

11

Le uniformi che puoi usare negli ombreggiatori dipendono da come hai impostato il materiale: hai attivato le luci? colori al vertice? scuoiando? ...

Three JS crea un programma che dipende in gran parte da alcune definizioni (#ifdef nel codice) che vengono iniettate nella parte superiore del programma a seconda dei parametri di cui sopra.

Ho trovato il modo migliore per sapere cosa sta succedendo è stampare gli shader generati da tre JS: come già sai GLSL, capirai facilmente che cosa significa il codice e quali uniformi puoi usare. Cercare buildProgram su tre fonti JS, poi (R57):

var glFragmentShader = getShader("fragment", prefix_fragment + fragmentShader); 
var glVertexShader = getShader("vertex", prefix_vertex + vertexShader); 

Dopo quelle linee, aggiungere:

console.log("fragment shader:", prefix_fragment + fragmentShader); 
console.log("vertex shader:", prefix_vertex + vertexShader); 

E sarete in grado di vedere il contenuto dei shaders.

[EDIT] Rileggendo la tua domanda, mi rendo conto ho risposto un po 'fuori, come si creano i propri shader ...

Si può avere uno sguardo a linee 6463 e 6490 di WebGLRenderer (https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L6463): si vedrà uniformi/attributi standard che tre JS iniettano nei tuoi shader. Puoi dare un'occhiata al Wiki dove hai una voce a riguardo (https://github.com/mrdoob/three.js/wiki - Quali attributi/uniformi/variazioni predefiniti sono disponibili negli shader personalizzati?) Ma ti indirizza alle linee che ho delineato sopra.

+0

Grazie per la risposta, le persone su così sono davvero utili :) La sorgente righe sottolineato ha risposto alla mia domanda. Roba buona! –

+0

Il collegamento al codice è obsoleto, le linee sono cambiate da quando è stata data la risposta. – Killah

+0

@Killah cercherò e aggiornerò questa domanda con un'altra risposta. Grazie per l'heads-up –

19

Per uniformi, la risposta breve è il seguente:

Nel vertex shader

"uniform mat4 modelMatrix;", 
"uniform mat4 modelViewMatrix;", 
"uniform mat4 projectionMatrix;", 
"uniform mat4 viewMatrix;", 
"uniform mat3 normalMatrix;", 
"uniform vec3 cameraPosition;", 

e nel frammento Shader

"uniform mat4 viewMatrix;", 
"uniform vec3 cameraPosition;", 

Per la risposta completa, coinvolgendo uniformi e attributi , gli shader personalizzati hanno le variabili stringa prefixVertex e prefixFragment precompilate.

var vertexGlsl = prefixVertex + vertexShader; 
var fragmentGlsl = prefixFragment + fragmentShader; 

var glVertexShader = THREE.WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl); 
var glFragmentShader = THREE.WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl); 

I prefixVertex e prefixFragment definizioni di variabili possono essere trovati in WebGLProgram.js o nella versione non-minified di three.js.

EDIT: aggiornato per Three.js r.73

+0

Grazie per la risposta! –

+0

Mi dispiace, l'ultima sezione della tua (molto utile) risposta mi confonde. Cosa fanno esattamente queste definizioni di variabili? Elencate 'var glVertexShader = new THREE.WebGLShader (_gl, _gl.VERTEX_SHADER, prefix_vertex + vertexShader);' ma non sono sicuro di quando avremmo bisogno di questi. – Startec

Problemi correlati