2012-05-23 1 views
5

Ho un'app Android che utilizza OpenGL ES 2.0. Ho bisogno di disegnare 10 linee da una matrice ognuna delle quali è descritta da un punto iniziale e un punto finale. Quindi ci sono 10 linee = 20 punti = 60 valori galleggianti. Nessuno dei punti è collegato in modo che ogni coppia di punti nell'array non sia correlata agli altri, quindi disegno con GL_LINES.Come utilizzare uno shader per colorare le linee disegnate con GL_LINES e OpenGL ES 2.0

li disegnare mettendo i valori in un buffer galleggiante e chiamando un codice helper simili:

public void drawLines(FloatBuffer vertexBuffer, float lineWidth, 
     int numPoints, float colour[]) { 
    GLES20.glLineWidth(lineWidth); 
    drawShape(vertexBuffer, GLES20.GL_LINES, numPoints, colour); 
} 

protected void drawShape(FloatBuffer vertexBuffer, int drawType, 
     int numPoints, float colour[]) { 
    // ... set shader ... 
    GLES20.glDrawArrays(drawType, 0, numPoints); 
} 

I drawLines prende il buffer galleggiante (60 galleggianti), una larghezza di riga, il numero di punti (20) e una matrice di valori di colore a 4 colori. Non ho mostrato il codice di impostazione dello shader ma fondamentalmente espone la variabile di colore al valore uColour uniforme.

Lo shader di frammenti che preleva uColour si collega direttamente all'output.

/* Fragment */ 
precision mediump float; 

uniform vec4 uColour; 
uniform float uTime; 

void main() { 
    gl_FragColor = uColour; 
} 

Il vertex shader:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
} 

Ma ora voglio fare qualcosa di diverso. Voglio che ogni riga nel mio buffer abbia un colore diverso. I colori sono una funzione della posizione della linea nell'array. Voglio ombreggiare la linea di inizio bianca, l'ultimo grigio scuro e le linee tra una gradazione tra i due, ad es. #ffffff, #eeeeee, #dddddd etc.

Ovviamente potrei semplicemente disegnare ogni riga singolarmente inserendo un nuovo valore in uColour ogni volta, ma questo è inefficiente. Non voglio chiamare GL 10 volte quando potrei chiamarlo una volta e modificare il valore di uno shader ogni volta.

Forse potrei dichiarare un valore uniforme chiamato uVertexCount nel mio vertex shader? Prima del sorteggio ho impostato uVertexCount su 0 e per ogni volta che viene chiamato il vertex shader, incremento questo valore. Lo shader di frammenti può determinare l'indice di linea guardando uVertexCount. Potrebbe quindi interpolare un valore per il colore tra un valore iniziale e uno finale o qualche altro mezzo. Ma questo dipende se ogni linea o punto è considerato un primitivo o l'intera serie di linee è un singolo primitivo.

È fattibile? Non so quante volte il vertex shader viene chiamato per framment shader. Le chiamate sono intercalate in un modo come questo per renderlo praticabile, cioè vertice 0, vertice 1, x * frammento, vertice 2, vertice 3, x * frammento ecc.

Qualcuno sa di un codice di esempio ragionevole che potrebbe dimostrare il concetto o indicarmi un altro modo di fare qualcosa di simile?

+0

Perché non usare il colore come un attributo? Aggiungi le informazioni sul colore nel tuo VertexBuffer. – pearcoding

+0

Potrei aggiungerlo come attributo, ma ho ancora bisogno di conoscere l'indice punto/linea nello shader del frammento per sapere quale colore deve essere fuori dall'attributo che dovrei usare. vale a dire se ho passato un array di 10 colori come attributo, come fa il mio frammento shader a sapere quale di questi 10 dovrebbe usare? – locka

+0

non è stato fatto automaticamente ...hai bisogno dell'indice se hai una matrice uniforme, ma non quando hai un attributo. Un attributo è connesso a un solo vertice. Quindi ognuno dei tuoi vertici ha una posizione e un colore. – pearcoding

risposta

6

Aggiungere informazioni sul colore nel Vertexbuffer (Floatbuffer) e utilizzare l'attributo nello shader.

Esempio VertexBuffer:

uniform mat4 uMVPMatrix; 

attribute vec4 vPosition; 
attribute vec3 vColor; 

varying vec3 color; 

void main() { 
    gl_Position = uMVPMatrix * vPosition; 
    color = vColor; 
} 

Esempio fragmentshader:

precision mediump float; 

varying vec3 color; 

void main() { 
    gl_FragColor = color; 
} 
+0

Stai suggerendo di usare glDrawElements invece di glDrawArray qui in qualche modo per spingere vColor nello vector shader? Il colore finisce per essere interpolato o qualcosa da questo o dovrei fornire lo stesso colore al punto iniziale/finale per garantire che il valore variabile non cambi? Cercherò di provarlo stasera per vedere come vado avanti. – locka

+2

Penso di averlo capito ora. Devo associare glVertexAttribPointer/glEnableVertexAttribArray a una matrice di float per i colori. Probabilmente dovrò raddoppiare i colori per ciascuna estremità della linea, ma dovrebbe essere abbastanza semplice. Pubblicherò un aggiornamento quando arrivo da qualche parte con questo. – locka

+0

+1 Sì, questo è il modo giusto: D – pearcoding