2009-07-11 6 views
15

Ho due modelli, A e B, e una luce, L. Vorrei che il modello A proiettasse un'ombra sul modello B. Non voglio preoccuparmi di volumi di ombre o ombre appropriate per il momento, solo un semplice l'ombra del cerchio sarà sufficiente. L'effetto è che il modello A è trattato come una sfera per scopi di fusione dell'ombra.Come posso creare ombre economiche in OpenGL?

Ecco come mi immagino l'algoritmo:

Per ogni triangolo nel modello B, disegnare il triangolo. Proietta un cerchio sul triangolo lungo la linea da L ad A, aumentando le dimensioni del cerchio a seconda di quanto è distante il triangolo. Assicurati che il cerchio sia troncato ai confini del triangolo (usando il buffer degli stencil in qualche modo, immagino).

Sto lavorando con OpenGL e pianura C.

Eventuali indicazioni su alcuni documenti di riferimento posso leggere? O idee di implmentazione?

risposta

9

Penso che sia effettivamente più semplice implementare le ombre corrette perché OpenGL può fare il lavoro per voi.

Ho trovato un codice ombra lavoro con molta documentazione qui: http://www.opengl.org/resources/code/samples/mjktips/TexShadowReflectLight.html

Il codice sopra rende l'oggetto due volte: prima normalmente poi con una matrice speciale. Fa un sacco di cose non correlate come il controllo con mouse e riflessioni. Quindi ecco le parti interessanti.

Questo calcola la matrice ombra:

/* Create a matrix that will project the desired shadow. */ 
void 
shadowMatrix(GLfloat shadowMat[4][4], 
    GLfloat groundplane[4], 
    GLfloat lightpos[4]) 
{ 
    GLfloat dot; 

    /* Find dot product between light position vector and ground plane normal. */ 
    dot = groundplane[X] * lightpos[X] + 
    groundplane[Y] * lightpos[Y] + 
    groundplane[Z] * lightpos[Z] + 
    groundplane[W] * lightpos[W]; 

    shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; 
    shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; 
    shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; 
    shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; 

    shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; 
    shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; 
    shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; 
    shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; 

    shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; 
    shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; 
    shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; 
    shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; 

    shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; 
    shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; 
    shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; 
    shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; 

} 

Non fingo capire questo completamente. lightpos è la posizione della sorgente luminosa. Le prime 3 coordinate del piano terra sono il vettore normale della superficie del terreno. Il quarto è l'offset (quanto dista da 0,0,0).

E questa parte in realtà rende l'ombra:

glPushMatrix(); 
/* Project the shadow. */ 
glMultMatrixf((GLfloat *) floorShadow); 
drawDinosaur(); 
glPopMatrix(); 

Ci sono alcune cose che dovete glEnable/glDisable prima per far funzionare tutto in modo da guardare al link.

+4

Questo "appiattisce" il modello su un piano .. ottimo per proiettare un'ombra su una superficie piana. L'OP vuole rendere l'ombra su un oggetto 3d di forma arbitraria. –

+0

Questo si suppone che faccia questo: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=27 Purtroppo non riesco a compilarlo con gcc. – stribika

+0

Questo metodo sembra buono, ma il costo di disegnare il modello sorgente una volta per ogni faccia in B sembra alto. C'è un modo per ridurre la complessità di questo metodo? – Martin

0

This paper sembra coprire le vostre esigenze, utilizzando OpenGL e accelerazione hardware per creare una mappa delle ombre dettagliata.

Se stavo cercando di realizzare questo, sarei tentato di usare ray casting. Per ogni triangolo in B, crea un vettore dal triangolo alla luce. Se colpisce qualcosa lungo la strada, è in ombra. Sarebbe un po 'lento a meno che non stiate usando una struttura di accelerazione decente e un test rapido a triangolo. Mi piace bounding volume hierarchies; molti programmi li usano anche per il rilevamento delle collisioni.