2013-01-04 6 views
6

Sto lavorando a un'applicazione di scrittura a mano su iOS. Ho trovato il progetto di esempio "GLPaint" dalla documentazione di iOS, implementato da OpenGL ES, e ho apportato qualche modifica su di esso.Come evitare la sovrapposizione della trasparenza usando OpenGL?

Tracciamento dei punti di contatto e calcolo delle curve tra i punti e disegno solo le immagini delle particelle per far sembrare che il dito sia il punto di passaggio.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData); // burshData is from CGImage, it is 

// vertexBuffer is generated based on the calculated points, it's just a sequence of point where need to draw image. 
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer); 
glDrawArrays(GL_POINTS, 0, vertexCount); 

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
[context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

Quello che ho ottenuto è una linea solida che sembra abbastanza buona. Ma ora voglio disegnare l'evidenziazione semitrasparente invece della linea continua. Quindi sostituisco l'immagine delle particelle con una trasparenza del 50% senza modificare il codice.

Result of 50% transparency particle image

Result of 50% transparency particle image

c'è qualcosa di sbagliato con la miscela.

What I need

What I need

I disegnare tre punti tramite l'immagine di particella semitrasparenza, e l'area di intersezione dovrebbe tenere trasparenza del 50%.

Qual è la soluzione?

+1

Il problema è che è necessario eliminare il superamento, che _per il caso generale_ non è possibile con "solo fusione". È possibile utilizzare il buffer di profondità (con test alfa) ma ciò non sarà propriamente l'antialias. Se vuoi che questo sia correttamente antialiasing, non è banale ragionare, almeno non nel caso generale. Dovresti prima eseguire il rendering su un framebuffer extra e compilarlo in un secondo passaggio. – Damon

+0

Grazie per la risposta. Sono un principiante di OpenGL, non sono ancora chiaro riguardo la maggior parte delle concezioni in OpenGL. Penso che l'antialias non sia il problema. Potresti specificare il codice con maggiori dettagli? –

risposta

6

Im forse due anni più tardi rispondere a questa domanda, ma spero che aiuta chi viene qui in cerca di una soluzione a questo problema, come è successo a me.

È necessario assegnare a ciascun cirillo un valore z diverso. Non importa quanto grande o piccola sia questa differenza, abbiamo solo bisogno che non siano strettamente uguali.

Innanzitutto, si disabilita la scrittura nel buffer dei colori glColorMask(false,false,false,false) e quindi si disegnano normalmente i cerchi. Il buffer Z verrà aggiornato come desiderato, ma non verrà ancora disegnato alcun cerchio.

Quindi, si attiva la scrittura nel buffer dei colori (glColorMask(true,true,true,true)) e si imposta depthfunc su LEQUAL (glDepthFunc(GL_LEQUAL)). Solo i pixel circolari più vicini supereranno il test di profondità (impostandolo su LEQUAL invece che EQUAL si occuperà di alcuni rari ma possibili errori di approssimazione in virgola mobile). Abilitare la fusione e disegnarli di nuovo produrrà l'immagine che si desidera, senza sovrapposizioni di trasparenza.

+0

Davvero grazie per la tua risposta. Un'altra domanda. Cosa intendi con "assegnare un valore z diverso". È la terza dimensione della coordinata o il valore del buffer z? Scusate se questa domanda ha poco senso, sono un novizio di opengl. –

+0

Entrambi allo stesso tempo! All'interno degli ombreggiatori, le coordinate X e Y controllano la posizione sullo schermo di ciascun vertice (da -1 a 1) e la coordinata Z controlla la profondità (da 0 a 1, essendo 0 più vicino). Questa profondità è quella confrontata con il buffer Z - se il buffer Z in quel pixel ha un valore minore significa che c'è già un pixel disegnato più vicino alla telecamera, quindi il frammento viene scartato. Quindi, se ogni cerchio ha una coordinata Z diversa, solo un frammento per pixel non verrà scartato (il più vicino alla telecamera), quindi la fusione avrà successo. – Ivelate

+0

Potrebbe essere confuso perché la maggior parte delle volte applichiamo una trasformazione di coordinate all'interno dello shader del vertice usando le matrici di trasformazione. Quindi, hai un X, Y, Z iniziale per un vertice e questo viene trasformato in un'altra posizione per allinearlo alla telecamera o qualsiasi altra cosa, quindi la vera Z usata dallo shader potrebbe non essere la Z originale del tuo vertice. È leggermente complicato spiegare se sei nuovo in OpenGL, quindi ti consiglio vivamente di leggere questo tutorial (fino alla parte "Depth and stencil"), https://open.gl/, che mi ha aiutato molto quando stavo iniziando. Non esitate a chiedermi di più se ne avete bisogno! – Ivelate