![Page 1: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/1.jpg)
Jose María Buades Rubio
Sombras y ReflejosSombras y Reflejosen Tiempo Realen Tiempo Real
Implementación mediante OpenGL
Uso del stencil buffer
![Page 2: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/2.jpg)
IntroducciónIntroducción
• Renderizar polígonos con texturasZ-Buffer mostrará la salida correcta
• La limitación de los efectos viene dada por el hardware
• Dos efectos que mejoran la calidad gráfica son las sombras y los reflejos
![Page 3: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/3.jpg)
Stencil TestStencil Test
• Mejoran la calidad de las sombras y reflejos
• Stenciling es un test extra por pixel y un conjunto de operaciones muy parecidas al z-buffer
• Añade planos de bits adicionales para cada pixel, ademas de los bits de color y profundidad
![Page 4: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/4.jpg)
Stencil Test IIStencil Test II
• Es una manera de “marcar” pixeles en una renderización para controlar su actualización en renderizaciones siguientes
• Algunas tarjetas gráficas como RivaTNT soporta stencil buffer de 8-bits
• Tanto DirectX y OpenGL soportan Stencil Buffer
![Page 5: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/5.jpg)
Secuencia de operacionesSecuencia de operaciones
Pixel Ownership
TestScissor Test Alpha Test
Stencil TestDepth Test
Blending Dithering Logic Op
![Page 6: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/6.jpg)
Per-pixel Stencil TestingPer-pixel Stencil Testing
• Inicialización mediante GLUT & OpenGL
glutInitDisplayString(“stencil>=1 rgb depth double”)
glutCreateWindow(“Stencil Buffer Example”)
• El valor stencil de un pixel es un entero sin signo (unsigned int)
![Page 7: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/7.jpg)
Per-pixel Stencil Testing IIPer-pixel Stencil Testing II
• Como borrar el stencil bufferglClearStencil(0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
• Activar y desactivar el testglEnable(GL_STENCIL_TEST)
glDisable(GL_STENCIL_TEST)
![Page 8: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/8.jpg)
Per-pixel Stencil Testing IIIPer-pixel Stencil Testing III
• El stencil test compara el valor del pixel del stencil buffer con un valor de referencia
• Permite las siguientes comparaciones:never, alwaysless than, less than or equalgreater than, greater than or equalequal, not equal
![Page 9: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/9.jpg)
Per-pixel Stencil Testing IVPer-pixel Stencil Testing IV
• Es más potente que el buffer de profundidad, antes de comparar realiza una operación AND, tanto del valor de referencia como del valor del buffer, con un valor que sirve como máscara
glStencilFunc( GL_EQUAL, // función de comparación0x1, // valor de referencia0xff); // máscara
![Page 10: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/10.jpg)
Per-pixel Stencil Testing VPer-pixel Stencil Testing V
• Si el pixel no pasa el test de profundidad es rechazado, en cambio si pasa reemplaza el valor del z-buffer. El stencil test es más complicado:– NO pasa el stencil test
– Pasa stencil test y NO el test de profundidad
– Pasa stencil test y el test de profundidad
![Page 11: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/11.jpg)
Per-pixel Stencil Testing VPer-pixel Stencil Testing V
• Para cada caso tenemos seis operaciones posibles:
GL_KEEP, GL_REPLACE, GL_INVERT,
GL_INCREMENT, GL_DECREMENT, GL_ZERO
• Antes de escribir se aplica una máscaraglStencilOp( GL_KEEP, // stencil fail
GL_DECR, // stencil pass, depth failGL_INCR); // stencil pass, depth pass
glStencilMask(0xff);
![Page 12: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/12.jpg)
Per-pixel Stencil Testing VIPer-pixel Stencil Testing VI
State Description Initial Value State Update State Query TokenCommand
Stencilling enable GL_FALSE glEnable GL_STENCIL_TESTglDisable
Stencil function GL_ALWAYS glStencilFunc GL_STENCIL_FUNC
Stencil compare mask All 1’s glStencilFunc GL_STENCIL_VALUE_MASK
Stencil reference value 0 glStencilFunc GL_STENCIL_REF
Stencil fail operation GL_KEEP glStencilOp GL_STENCIL_FAIL
Stencil depth fail operation GL_KEEP glStencilOp GL_STENCIL_PASS_DEPTH_PASS
Stencil depth pass operation GL_KEEP glStencilOp GL_STENCIL_PASS_DEPTH_PASS
Stencil write mask All 1’s glStencilMask GL_STENCIL_WRITEMASK
Stencil buffer clear value 0 glClearStencil GL_STENCIL_CLEAR_VALUE
![Page 13: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/13.jpg)
Reflejos Planos sin Stencil Reflejos Planos sin Stencil
• Tiene una serie de limitaciones:
El objeto reflejado sale por fuera de la superficie reflectante
Desde detrás del espejo se ve el objeto reflejado
No permite reflejos infinitos, esta limitado a un número n de reflejos
![Page 14: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/14.jpg)
AlgoritmoAlgoritmo
1. Cargar la matriz de modelizaciónglMatrixMode(GL_MODELVIEW);glLoadIdentity();glLookAt(eye[0], eye[1], eye[2],
center[0], center[1], center[2],up[0], up[1], up[2]);
2. Introducir en la pila la matriz de modelizaciónglPushMatrix();
3. Aplicar la matriz de reflejo (plano z = 0)glScalef(1.0, 1.0, -1.0);
4. Si usamos recorte de caras traseras, debemos realizar el contrario, eliminación de caras delanteras
glCullFace(GL_FRONT);
5. Renderizar la escena, pero solo los objetos que estan en el lado reflectante del espejo
![Page 15: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/15.jpg)
Algoritmo (continuación)Algoritmo (continuación)
6. Restaurar los valores antes del espejoglCullFace(GL_BACK);glPopMatrix();
7. Renderizar el espejo (por ejemplo si es marmol)glEnable(GL_BLEND);glBlendFunc(GL_ONE, GL_ONE); // aditivorederizarEspejoConTextura();glDisble(GL_BLEND);
Incluso si el espejo no esta renderizado como una superficie semitransparente es importante renderizarlo para actualizar el z-buffer y evitar que aparezcan objetos que estan detrás del objeto
glColorMask(0, 0, 0, 0);renderizarEspejoConPoligonos()glColorMask(1, 1, 1, 1);
8. Finalmente renderizar la escena no reflejada
![Page 16: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/16.jpg)
ResultadosResultados
![Page 17: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/17.jpg)
Reflejos Planos con StencilReflejos Planos con Stencil
• Técnica más perfeccionada
• Permite tener espejos de tamaño limitado
• Podemos situar la cámara al otro lado del espejo
![Page 18: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/18.jpg)
AlgoritmoAlgoritmo
Renderizar la escena, excepto los espejos, con z-buffer pero sin stencil test
glClearStencil(0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);glEnable(GL_DEPTH_TEST);glDisable(GL_STENCIL_TEST);DrawScene();
Para cada espejo realizar los siguientes pasos:
1. Configurar para que escriba 1 en el stencil buffer cuando pasa el buffer de profundidad, deshabilitar escribir en el buffer de color. Entonces renderizar el espejo
glEnable(GL_STENCIL_TEST);glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);glStencilFunc(GL_ALWAYS, 1, ~0);glColorMask(0, 0, 0, 0);RenderizarPoligonoEspejo();
![Page 19: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/19.jpg)
Algoritmo (continuación)Algoritmo (continuación)
2. Con el buffer de color deshabilitado poner en el z-buffer el valor de profundidad máxima para los pixeles que corresponden al espejo
glDepthRange(1, 1); glDepthFunv(GL_ALWAYS);glStencilFunc(GL_EQUAL, 1, ~0);glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);RenderizarPoligonoEspejo();
3. Restaurar el test de profundidad, la mascara de color y el rango de profundidad a los valores estándar
glDepthFunc(GL_LESS);glColorMask(1, 1, 1, 1);glDepthRange(0, 1);
Ahora tenemos marcados como 1 en el stencil buffer los pixeles que corresponden al espejo y con la máxima profundidad en el z-buffer
![Page 20: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/20.jpg)
Algoritmo (continuación)Algoritmo (continuación)
4. Para evitar renderizar polígonos ubicados detrás del espejo definiremos un plano de clipping
GLfloat matrix[4][4];GLdouble clipPlane[4];glPushMatrix();
CalcularPlanoCorteEspejo(clipPlane);glClipPlane(GL_CLIP_PLANE0, clipPlane);CalcularMatrizEspejo(&matrix[0][0]);glMultMatrix(&matrix[0][0]);glCullFace(GL_FRONT);DrawScene();DibujarOtrosEspejosComoSuperficiesGrises();glCullFace(GL_BACK);glDisable(GL_CLIP_PLANE0);
glPopMatrix();
Ahora esta correctamente rederizado el reflejo del espejo
![Page 21: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/21.jpg)
Algoritmo (continuación)Algoritmo (continuación)
5. Ahora reseteamos el valor del stencil buffer a 0 para que no se confundan con otros espejos, ademas actualizamos el z-buffer para que tenga como profundidad la del espejo y no la del objeto reflejado
glColorMask(0, 0, 0, 0);glStencilop(GL_KEEP, GL_KEEP, GL_ZERO);glDepthFunc(GL_ALWAYS);RenderizarPoligonoEspejo();glDepthFunc(GL_LESS);glColorMask(1, 1, 1, 1);
![Page 22: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/22.jpg)
Sombras Planas sin Sombras Planas sin StencilStencil
• Los modelos de iluminación locales soportados por OpenGL y Direct3D no provocan sombras
• Proyectando un polígono sombre el plano a sombrear es una técnica para provocar el efecto sombra
![Page 23: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/23.jpg)
AlgoritmoAlgoritmo
1. Cargar la matriz de modelizaciónglMatrixMode(GL_MODELVIEW);glLoadIdentity();glLookAt(eye[0], eye[1], eye[2],
center[0], center[1], center[2],up[0], up[1], up[2]);
2. Dada la luz y la ecuación del plano donde se proyecta, y asumiendo que el objeto esta entre la luz y el plano, habilitar la luz y renderizar el objeto y el plano
GLfloat lightPosition[4] = {LX, LY, LZ, 1.0};GLfloat groundPlaneEquation[4] = {A, B, C, D};glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);glEnable(GL_LIGHT0);glEnable(GL_LIGHTING);DibujarObjeto();DibujarPlano();
![Page 24: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/24.jpg)
Algoritmo (continuación)Algoritmo (continuación)
3. Meter en la pila la matriz de modelizaciónglPushMatrix();
4. Construir la matriz de proyección, multiplicar la matriz de modelización por la matriz de proyección de la sombra
GLfloat matrix[4][4];ShadowMatrix(&matrix[0][0], lightPosition,
groundPlaneEquation);glMultMatrix(&matrix[0][0]);
5. A menos que lo remediemos la sombra y el plano donde se proyecta son coplanares. Esto causa problemas en el Z-Buffer, a veces la sombra esta más cerca, a veces igual y otras veces más alejado, esto es debido a imprecisiones en el cálculo numérico
glEnable(GL_POLYGON_OFFSET_FILL);glPolygonOffset(1.0, 2.0);
Esto provoca que este dos unidades más cerca
![Page 25: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/25.jpg)
Algoritmo (continuación)Algoritmo (continuación)
6. Deshabilitar la iluminación, poner el color gris oscuro y dibujar el objeto de nuevo
glDisable(GL_LIGHTING);glColor3f(0.25, 0.25, 0.25);DibujarObjeto();
7. Volver al estado anteriorglDisable(GL_POLYGON_OFFSET);glPopMatrix();
![Page 26: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/26.jpg)
ResultadosResultados
![Page 27: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/27.jpg)
Sombras Planas con Sombras Planas con StencilStencil
• Evita problema de doble transparencia
• Impide que la sombra salga del polígono sobre el cual se quiere calcular la sombra
![Page 28: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/28.jpg)
AlgoritmoAlgoritmo
1. Cargar la matriz de modelizaciónglMatrixMode(GL_MODELVIEW);glLoadIdentity();glLookAt(eye[0], eye[1], eye[2],
center[0], center[1], center[2],up[0], up[1], up[2]);
2. Dada la luz y la ecuación del plano donde se proyecta, y asumiendo que el objeto esta entre la luz y el plano, habilitar la luz y renderizar el objeto y el plano
GLfloat lightPosition[4] = {LX, LY, LZ, 1.0};GLfloat groundPlaneEquation[4] = {A, B, C, D};glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);glEnable(GL_LIGHT0);glEnable(GL_LIGHTING);DibujarObjeto();DibujarPlano();
![Page 29: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/29.jpg)
Algoritmo (continuación)Algoritmo (continuación)
3. Meter en la pila la matriz de modelizaciónglPushMatrix();
4. Construir la matriz de proyección, multiplicar la matriz de modelización por la matriz de proyección de la sombra
GLfloat matrix[4][4];ShadowMatrix(&matrix[0][0], lightPosition,
groundPlaneEquation);glMultMatrix(&matrix[0][0]);
5. Asignar un valor distinto de cero al stencil bufferglEnable(GL_STENCIL_BUFFER);glStencilFunc(GL_ALWAYS, valor, ~0);glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);DibujarPlanoASombrear();glDisable(GL_STENCIL_TEST);
![Page 30: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/30.jpg)
Algoritmo (continuación)Algoritmo (continuación)
6. Deshabilitar la iluminaciónglDisable(GL_LIGHTING);glEnable(GL_BLEND);glBlendFunc(GL_DST_COLOR, GL_ZERO); glColor3f(0.5, 0.5, 0.5);glDisable(GL_DEPTH_TEST);
Solo debemos actualizar los pixeles marcados con valorglEnable(GL_STENCIL_TEST);glStencilFunc(GL_EQUAL, valor, ~0);glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);DibujarObjeto();
7. Restaurar los valoresglDisable(GL_BLEND);glDisable(GL_STENCIL_TEST);glEnable(GL_DEPTH_TEST); glPopMatrix();
![Page 31: Jose María Buades Rubio Sombras y Reflejos en Tiempo Real Implementación mediante OpenGL Uso del stencil buffer](https://reader035.vdocumento.com/reader035/viewer/2022062511/54e09a0e4a79595b298b5863/html5/thumbnails/31.jpg)
Programa DemoPrograma Demo
Dinoshade