Un materiale renderizzato con shader personalizzati. Uno shader è un piccolo programma scritto in [link:https://www.khronos.org/files/opengles_shading_language.pdf GLSL] che viene eseguito sulla GPU. Potresti voler utilizzare uno shader personalizzato se hai bisogno di:
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {
// ...
}
#pragma unroll_loop_end
const material = new THREE.ShaderMaterial( {
uniforms: {
time: { value: 1.0 },
resolution: { value: new THREE.Vector2() }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
[example:webgl_buffergeometry_custom_attributes_particles webgl / buffergeometry / custom / attributes / particles]
[example:webgl_buffergeometry_selective_draw webgl / buffergeometry / selective / draw]
[example:webgl_custom_attributes webgl / custom / attributes]
[example:webgl_custom_attributes_lines webgl / custom / attributes / lines]
[example:webgl_custom_attributes_points webgl / custom / attributes / points]
[example:webgl_custom_attributes_points2 webgl / custom / attributes / points2]
[example:webgl_custom_attributes_points3 webgl / custom / attributes / points3]
[example:webgl_depth_texture webgl / depth / texture]
[example:webgl_gpgpu_birds webgl / gpgpu / birds]
[example:webgl_gpgpu_protoplanet webgl / gpgpu / protoplanet]
[example:webgl_gpgpu_water webgl / gpgpu / water]
[example:webgl_interactive_points webgl / interactive / points]
[example:webgl_video_kinect webgl / video / kinect]
[example:webgl_lights_hemisphere webgl / lights / hemisphere]
[example:webgl_marchingcubes webgl / marchingcubes]
[example:webgl_materials_envmaps webgl / materials / envmaps]
[example:webgl_materials_lightmap webgl / materials / lightmap]
[example:webgl_materials_wireframe webgl / materials / wireframe]
[example:webgl_modifier_tessellation webgl / modifier / tessellation]
[example:webgl_postprocessing_dof2 webgl / postprocessing / dof2]
[example:webgl_postprocessing_godrays webgl / postprocessing / godrays]
Si possono specificare due differenti tipi di shader per ogni materiale:
Ci sono tre tipi di variabili negli shader: uniforms (uniformi), attributes (attributi), e varyings (variazioni):
Si noti che `all'interno` dello shader stesso, uniforms e attributes agiscono come costanti; si può solo modificare i loro valori passando valori diversi ai buffer dal codice JavaScript.
Il [page:WebGLRenderer] fornisce da impostazione predefinita molti attributi e uniformi agli shader; le definizioni di queste variabili vengono anteposte al codice `fragmentShader` e `vertexShader` dal [page:WebGLProgram] quando lo shader viene compilato; non è necessario che li dichiari tu stesso. Vedi [page:WebGLProgram] per il dettaglio di queste variabili.
Alcune di queste uniformi o attributi (per esempio quelli relativi all'illuminazione, alla nebbia, etc.) richiedono l'impostazione delle proprietà sul materiale affinché [page:WebGLRenderer] possa copiare i valori appropriati alla GPU - assicurati di impostare questi flag se vuoi utilizzare queste funzionalità nel tuo shader.
Se non vuoi che [page:WebGLProgram] aggiungera niente al tuo codice shader, puoi usare [page:RawShaderMaterial] invece di questa classe.
Sia gli attributi personalizzati che le uniformi personalizzate devono essere dichiarate nel tuo codice shader GLSL (all'interno di `vertexShader` e/o `fragmentShader`). Le uniformi personalizzate devono essere definite in `entrambe` le proprietà `uniforms` del tuo `ShaderMaterial`, mentre qualsiasi attributo personalizzato deve essere definito tramite le istanze di [page:BufferAttribute]. Si noti che è necessario dichiarare le variazioni solo all'interno del codice shader (non all'iterno del materiale).
Per dichiarare un attributo personalizzato, fare riferimento alla pagina [page:BufferGeometry] per una panoramica, e la pagina [page:BufferAttribute] per uno sguardo dettagliato alle API `BufferAttribute`.
Quando crei i tuoi attributi, ogni array tipizzato che crei per contenere i dati del tuo attributo deve essere multiplo della dimensione del tuo tipo di dati. Per esempio, se il tuo attributo è di tipo [page:Vector3 THREE.Vector3], e hai 3000 vertici nel tuo [page:BufferGeometry], il valore del tuo array tipizzato deve essere creato con una lunghezza di 3000 * 3, o 9000 (un valore per componente). Di seguito viene mostrata una tabella delle dimensioni di ciascun tipo di dati come riferimento:
Tipo GLSL | Tipo JavaScript | Dimensione |
---|---|---|
float | [page:Number] | 1 |
vec2 | [page:Vector2 THREE.Vector2] | 2 |
vec3 | [page:Vector3 THREE.Vector3] | 3 |
vec3 | [page:Color THREE.Color] | 3 |
vec4 | [page:Vector4 THREE.Vector4] | 4 |
Si noti che i buffer degli attributi `non` vengono aggiornati automaticamente quando i loro valori cambiano. Per aggiornare gli attributi personalizzati, imposta il flag `needsUpdate` a true sul [page:BufferAttribute] della geometria (vedi [page:BufferGeometry] per maggiori dettagli).
Per dichiarare una [page:Uniform] personalizzata, utilizzare la proprietà `uniforms`:
uniforms: {
time: { value: 1.0 },
resolution: { value: new THREE.Vector2() }
}
Si consiglia di aggiornare i valori di [page:Uniform] personalizzati in base all'[page:Object3D object] e alla [page:Camera telecamera] in [page:Object3D.onBeforeRender] poiché il [page:Material Materiale] può essere condiviso tra le [page:Mesh mesh], la [page:Matrix4 matrixWorld] della [page:Scene scena] e la [page:Camera telecamera] viene aggiornata in [page:WebGLRenderer.render], e alcuni effetti eseguono il rendering di una scena con le proprie [page:Camera telecamere] private.
[page:Object parameters] - (opzionale) un oggetto con una o più proprietà che definiscono l'aspetto del materiale. Qualsiasi proprietà del materiale (inclusa qualsiasi proprietà ereditata da [page:Material]) può essere passata qui.
Vedi la classe base [page:Material] per le proprietà comuni.
Definisce se questo materiale supporta il clipping; true per consetire al renderer di passare l'uniforme di clippingPlanes. L'impostazione predefinita è `false`.
Quando la geometria renderizzata non include questi attributi ma il materiale sì,
questi valori predefiniti verranno passati agli shader. Ciò evita errori quando mancano i dati del buffer.
this.defaultAttributeValues = {
'color': [ 1, 1, 1 ],
'uv': [ 0, 0 ],
'uv2': [ 0, 0 ]
};
Definisce le costanti personalizzate utilizzando le direttive `#define` nel codice GLSL sia per
il vertex shader che il fragment shader; ogni coppia chiave/valore produce un'altra direttiva:
defines: {
FOO: 15,
BAR: true
}
restituisce le linee
#define FOO 15
#define BAR true
nel codice GLSL.
Un oggetto con le seguenti proprietà:
this.extensions = {
derivatives: false, // impostato per utilizzare le direttive
fragDepth: false, // impostato per utilizzare i valori di profondità del frammento
drawBuffers: false, // impostato per utilizzare i buffer di disegno
shaderTextureLOD: false // impostato per utilizzare la texture dello shader LOD
};
Definisce se il colore del materiale è influenzato dalle impostazioni globali della nebbia. true per passare le uniformi allo shader. Il valore predefinito è `false`.
Codice GLSL del fragment shader. Questo è il codice effettivo per lo shader. Nell'esempio sopra, il codice `vertexShader` e `fragmentShader` viene estratto dal DOM; potrebbe essere passato come stringa direttamente o caricato tramite AJAX.
Definisce la versione GLSL del codice dello shader personalizzato. Rilevante solo per WebGL 2 per definire se specificare o meno GLSL 3.0. I valori validi sono `THREE.GLSL1` o `THREE.GLSL3`. Il valore predefinito è `null`.
Se impostato, questo chiama [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation gl.bindAttribLocation] per associare un indice di vertice generico a una variabile di attributo. Il valore predefinito è `undefined`.
Flag di sola lettura per verificare se l'oggetto passato è di tipo [name].
Definisce se questo materiale utilizza l'illuminazione; true per trasmettere dati uniformi relativi all'illuminazione a questo shader. L'impostazione predefinita è `false`.
Controlla lo spessore del wireframe. Il valore predefinito è `1`.
A causa delle limitazioni del [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf profilo OpenGL Core]
con il renderer [page:WebGLRenderer WebGL] sulla maggior parte delle piattaforme,
la larghezza di riga sarà sempre 1 indipendentemente dal valore impostato.
Definisce se il materiale viene renderizzato con un'ombreggiatura piatta. Il valore predefinito è `false`.
Un oggetto della forma:
{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }
specificando le uniformi da passare al codice dello shader; la chiave è il nome della uniform, il valore è la definizione del modulo
{ value: 1.0 }
dove `value` è il valore della uniforme. I nomi devono corrispondere al nome della uniforme,
come definito nel codice GLSL. Si noti che le uniformi vengono aggiornate su ogni frame,
quindi l'aggiornamento del valore della uniforme aggiornerà immediatamente il valore disponinbile per il codice GLSL.
Può essere utilizzata per forzare un aggiornamento della uniform durante la modifica delle uniformi in [page:Object3D.onBeforeRender](). Il valore predefinito è `false`.
Definisce se viene utilizzata la colorazione dei vertici. Il valore predefinito è `false`.
Il codice GLSL del vertex shader. Questo è il codice effettivo per lo shader. Nell'esempio sopra, il codice `vertexShader` e `fragmentShader` viene estratto dal DOM; potrebbe essere passato come stringa direttamente o caricato tramite AJAX.
Rendering della geometria come wireframe (utilizzando GL_LINES instead of GL_TRIANGLES). Il valore predefinito è `false` (cioè renderizzazione come poligoni piatti).
Controlla lo spessore del wireframe. Il valore predefinito è `1`.
A causa delle limitazioni del [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf profilo OpenGL Core]
con il renderer [page:WebGLRenderer WebGL] sulla maggior parte delle piattaforme,
la larghezza di riga sarà sempre 1 indipendentemente dal valore impostato.
Vedi la classe base [page:Material] per i metodi comuni.
Genera una copia superficiale di questo materiale. Si noti che il vertexShader e il fragmentShader sono copiati `per riferimento`, così come le definizioni degli `attributi`; questo significa che i cloni del materiale condivideranno lo stesso [page:WebGLProgram] compilato. Tuttavia, le uniform vengono copiate in base al `valore`, il che consente di avere diversi set di uniformi per diverse copie del materiale.
[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]