2013-04-29 26 views
22

È possibile posizionare più trame l'una sull'altra sulla stessa faccia in Three.js in modo che l'alpha blending sia eseguito accelerando GPU in webGL?Trame trasparenti multiple sulla stessa faccia della mesh in Three.js

Le trame sono (o dovrebbero essere) applicate alla stessa faccia in modo che la trama di fondo (trama 1) sia senza canale alfa e le trame di cui sopra siano canalizzate alfa in modo simile alla trama 2 nell'esempio di immagine sottostante.

Questa fusione può essere ottenuta utilizzando HTML5 Canvas come pre-passo, ma poiché le bitmap di trama possono essere enormi, preferisco saltare le operazioni di fusione della tela.

Ho provato creando una copia della mesh e applicando una texture per mesh e reso trasparente un'altra mesh e spostandola un po ', cosa che è andata bene, ma c'è un po' di sfarfallio e perché gli oggetti non possono essere esattamente nella stessa posizione , c'è un po 'di spazio tra le trame che non è l'effetto giusto. Dovrebbero sembrare come se fossero miscelati ad es. Photoshop (come è l'immagine qui sotto).

enter image description here

+2

Si potrebbe provare l'approccio nella risposta [qui] (http://stackoverflow.com/questions/13309289/three-js-geometry-in-top -di-altro/13309722 # 13309722) – WestLangley

+0

Grazie. Sembra essere un buon modo. E possibilmente può gestire anche il rendering di più trame l'una sull'altra. Ma non ancora testato finora. –

risposta

51

Usa ShaderMaterial e impostare entrambe le texture come le uniformi, e poi si fondono all'interno di shader.

Ho fatto questo esempio: http://abstract-algorithm.com/three_sh/ e questo dovrebbe essere abbastanza.

Quindi, fate ShaderMaterial:

var vertShader = document.getElementById('vertex_shh').innerHTML; 
var fragShader = document.getElementById('fragment_shh').innerHTML; 

var attributes = {}; // custom attributes 

var uniforms = { // custom uniforms (your textures) 

    tOne: { type: "t", value: THREE.ImageUtils.loadTexture("cover.png") }, 
    tSec: { type: "t", value: THREE.ImageUtils.loadTexture("grass.jpg") } 

}; 

var material_shh = new THREE.ShaderMaterial({ 

    uniforms: uniforms, 
    attributes: attributes, 
    vertexShader: vertShader, 
    fragmentShader: fragShader 

}); 

e creare rete con quel materiale:

var me = new THREE.Mesh(new THREE.CubeGeometry(80,80,80), material_shh); 

si può mettere più semplice vertex shader:

varying vec2 vUv; 

void main() 
{ 
    vUv = uv; 
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); 
    gl_Position = projectionMatrix * mvPosition; 
} 

E frammento di shader che effettivamente fare la fusione:

#ifdef GL_ES 
precision highp float; 
#endif 

uniform sampler2D tOne; 
uniform sampler2D tSec; 

varying vec2 vUv; 

void main(void) 
{ 
    vec3 c; 
    vec4 Ca = texture2D(tOne, vUv); 
    vec4 Cb = texture2D(tSec, vUv); 
    c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a); // blending equation 
    gl_FragColor= vec4(c, 1.0); 
} 

Se avete bisogno di fondere ancora di più texture, si utilizza stessa equazione per la miscelazione semplicemente più volte.

Quindi, ecco il risultato:

enter image description here

+1

Grazie per la risposta. Devo aspettare 17 ore per assegnare la taglia. –

+0

Questo approccio non si adatta al caso in cui dobbiamo posizionare trame multiple in una posizione specifica. – Tarun

+0

@Tarun Sì, la mappatura UV si occupa di questo. Bene, qualsiasi tipo di manipolazione UV-coordiante-saggia. –