stringtranslate.com

Modelo de reflexión de Blinn-Phong

El modelo de reflexión de Blinn-Phong , también llamado modelo de reflexión de Phong modificado, es una modificación desarrollada por Jim Blinn del modelo de reflexión de Phong . [1]

Blinn-Phong es un modelo de sombreado utilizado en el canal de función fija de OpenGL y Direct3D (antes de Direct3D 10 y OpenGL 3.1) y se lleva a cabo en cada vértice a medida que pasa por el canal de gráficos ; Los valores de píxeles entre los vértices se interpolan mediante el sombreado Gouraud de forma predeterminada, en lugar del sombreado Phong, que es más costoso desde el punto de vista computacional . [2]

Descripción

Vectores para calcular el sombreado de Phong y Blinn-Phong

En el sombreado Phong, se debe recalcular continuamente el producto escalar entre un espectador ( V ) y el haz de una fuente de luz ( L ) reflejado ( R ) sobre una superficie.

Si, en cambio, se calcula un vector intermedio entre los vectores del espectador y de la fuente de luz,

se puede reemplazar con , donde es la superficie normalizada normal. En la ecuación anterior, y son vectores normalizados y es una solución de la ecuación donde está la matriz de Householder que refleja un punto en el hiperplano que contiene el origen y tiene la normal

Este producto escalar representa el coseno de un ángulo que es la mitad del ángulo representado por el producto escalar de Phong si V , L , N y R se encuentran todos en el mismo plano. Esta relación entre los ángulos sigue siendo aproximadamente cierta cuando los vectores no se encuentran en el mismo plano, especialmente cuando los ángulos son pequeños. Por lo tanto , el ángulo entre N y H a veces se denomina ángulo intermedio.

Considerando que es probable que el ángulo entre el vector intermedio y la normal de la superficie sea menor que el ángulo entre R y V utilizado en el modelo de Phong (a menos que la superficie se vea desde un ángulo muy pronunciado para el cual es probable que sea mayor), y dado que Phong está usando un exponente, se puede establecer de manera que se acerque más a la expresión anterior.

Para superficies iluminadas frontalmente (reflejos especulares en las superficies que miran al espectador), se obtendrán reflejos especulares que coinciden muy estrechamente con los reflejos Phong correspondientes. Sin embargo, mientras que las reflexiones de Phong son siempre redondas en una superficie plana, las reflexiones de Blinn-Phong se vuelven elípticas cuando la superficie se ve desde un ángulo pronunciado. Esto se puede comparar con el caso en el que el sol se refleja en el mar cerca del horizonte, o en el que una farola lejana se refleja en el pavimento mojado, donde el reflejo siempre estará mucho más extendido verticalmente que horizontalmente. [3]

Comparación visual: las luces Blinn-Phong son más grandes que Phong con el mismo exponente, pero al reducir el exponente, pueden volverse casi equivalentes.

Además, si bien puede verse como una aproximación al modelo de Phong, produce modelos más precisos de funciones de distribución de reflectancia bidireccionales determinadas empíricamente que Phong para muchos tipos de superficies. [4]

Eficiencia

Blinn-Phong será más rápido que Phong en el caso en que el espectador y la luz sean tratados como muy remotos, como acercándose o en el infinito. Este es el caso de las luces direccionales y las cámaras ortográficas/isométricas. En este caso, el vector intermedio es independiente de la posición y la curvatura de la superficie simplemente porque el vector intermedio depende de la dirección hacia la posición del espectador y la dirección hacia la posición de la luz, que convergen individualmente a esta distancia remota, por lo que se puede pensar en el vector intermedio. de constante en este caso. por lo tanto, se puede calcular una vez para cada luz y luego usarse para todo el cuadro, o incluso mientras la luz y el punto de vista permanecen en la misma posición relativa. No ocurre lo mismo con el método de Phong de utilizar el vector de reflexión que depende de la curvatura de la superficie y debe recalcularse para cada píxel de la imagen (o para cada vértice del modelo en el caso de iluminación de vértice). En escenas 3D con cámaras en perspectiva esta optimización no es posible.

Ejemplos de código

Ejemplo de código de lenguaje de sombreado de alto nivel

Este ejemplo de lenguaje de sombreado de alto nivel es un método para determinar la luz difusa y especular de una luz puntual. Se pasan por la estructura luminosa, la posición en el espacio de la superficie, el vector de dirección de visión y la normal de la superficie. Se devuelve una estructura de iluminación;

Lo siguiente también debe limitar ciertos productos escalares a cero en el caso de respuestas negativas. Sin eso, la luz que se aleja de la cámara se trata de la misma manera que la luz que se dirige hacia ella. Para el cálculo especular, un "halo" de luz incorrecto que se refleja en los bordes de un objeto y se aleja de la cámara puede parecer tan brillante como la luz que se refleja directamente hacia la cámara.

estructura Iluminación { float3 Difusa ; float3 Especular ; };     estructura PointLight { posición float3 ; float3 color difuso ; potencia difusa flotante ; float3 color especular ; potencia especular flotante ; };      Iluminación GetPointLight ( luz PointLight , float3 pos3D , float3 viewDir , float3 normal ) { Iluminación OUT ; if ( luz.difusaPotencia > 0 ) { float3 lightDir = luz .posición - pos3D ; //Posición 3D en el espacio de la superficie float distancia = longitud ( lightDir ); Dirluz = Dirluz / distancia ; // = normalizar(lightDir); distancia = distancia * distancia ;                              //Intensidad de la luz difusa. Saturar para mantenerse dentro del rango 0-1. float NdotL = punto ( normal , lightDir ); flotar intensidad difusa = saturar ( NdotL );       // Calcular la luz difusa teniendo en cuenta el color de la luz, la potencia y la atenuación OUT . Difusa = intensidad difusa * luz . color difuso * luz . potencia difusa / distancia ;        // Calcula el medio vector entre el vector de luz y el vector de vista. float3 H = normalizar ( lightDir + viewDir );     //Intensidad de la luz especular float NdotH = dot ( normal , H ); float intensidad especular = pow ( saturar ( NdotH ), dureza especular );        //Resumir el factor de luz especular OUT . Especular = intensidad especular * luz . Color especular * luz . potencia especular / distancia ; } regresar FUERA ; }          

Ejemplo de código de lenguaje de sombreado OpenGL

Este ejemplo en OpenGL Shading Language consta de dos archivos de código o sombreadores . El primero es el llamado sombreador de vértices e implementa el sombreado Phong , que se utiliza para interpolar la superficie normal entre los vértices. El segundo sombreador es el llamado sombreador de fragmentos e implementa el modelo de sombreado Blinn-Phong para determinar la luz difusa y especular de una fuente de luz puntual.

Sombreador de vértices

Este sombreador de vértices implementa el sombreado Phong :

atributo vec3 posición de entrada ; atributo vec3 entradaNormal ;    proyección mat4 uniforme , modelview , normalMat ;    variable vec3 normalInterp ; variable vec3 vertPos ;    void main () { gl_Position = proyección * modelview * vec4 ( entradaPosition , 1.0 ); vec4 vertPos4 = vista de modelo * vec4 ( posición de entrada , 1.0 ); vertPos = vec3 ( vertPos4 ) / vertPos4 . w ; normalInterp = vec3 ( normalMat * vec4 ( entradaNormal , 0.0 )); }                            

Sombreador de fragmentos

Este sombreador de fragmentos implementa el modelo de sombreado Blinn-Phong [5] y la corrección gamma :

flotador medio de precisión ;  en vec3 normalInterp ; en vec3 vertPos ;    modo int uniforme ;  const vec3 lightPos = vec3 ( 1.0 , 1.0 , 1.0 ); const vec3 colorluz = vec3 ( 1.0 , 1.0 , 1.0 ); potencia de luz flotante constante = 40,0 ; const vec3 colorambiente = vec3 ( 0.1 , 0.0 , 0.0 ); const vec3 difusoColor = vec3 ( 0.5 , 0.0 , 0.0 ); const vec3 specColor = vec3 ( 1.0 , 1.0 , 1.0 ); brillo constante del flotador = 16,0 ; pantalla flotante constanteGamma = 2.2 ; // Supongamos que el monitor está calibrado en el espacio de color sRGB                                           vacío principal () {   vec3 normal = normalizar ( normalInterp ); vec3 lightDir = lightPos - vertPos ; distancia flotante = longitud ( lightDir ); distancia = distancia * distancia ; lightDir = normalizar ( lightDir );                      float lambertian = max ( punto ( lightDir , normal ), 0.0 ); flotador especular = 0,0 ;          si ( lambertiano > 0.0 ) {     vec3 viewDir = normalizar ( -vertPos ) ;    // este es blinn phong vec3 halfDir = normalize ( lightDir + viewDir ); float specAngle = max ( punto ( halfDir , normal ), 0.0 ); especular = pow ( specAngle , brillo ); // esto es phong (para comparación) if ( mode == 2 ) { vec3 reflectDir = reflect ( -lightDir , normal ) ; specAngle = max ( punto ( reflectDir , viewDir ), 0.0 ); // tenga en cuenta que el exponente es diferente aquí especular = pow ( specAngle , shininess / 4.0 ); } } vec3 colorLinear = colorambiente + colordifuso * lambertian * colorluz * potencialuz / distancia + specColor * especular * colorluz * potencialuz / distancia ; // aplicar corrección gamma (se supone que ambientColor, difuseColor y specColor // han sido linealizados, es decir, no tienen corrección gamma) vec3 colorGammaCorrected = pow ( colorLinear , vec3 ( 1.0 / screenGamma )); // usa el color con corrección gamma en el fragmento gl_FragColor = vec4 ( colorGammaCorrected , 1.0 ); }                                                                              

Se supone que los colores ambientColor , difuseColor y specColor no deben tener corrección gamma . Si son colores obtenidos de archivos de imagen con corrección gamma ( JPEG , PNG , etc.), es necesario linealizarlos antes de trabajar con ellos, lo cual se hace escalando los valores del canal al rango [0, 1] y elevándolos a el valor gamma de la imagen, que para imágenes en el espacio de color sRGB se puede suponer que es aproximadamente 2,2 (aunque para este espacio de color específico, una relación de potencia simple es solo una aproximación de la transformación real ). Las API de gráficos modernas tienen la capacidad de realizar esta corrección gamma automáticamente cuando se muestrea una textura o se escribe en un framebuffer . [6]

Ver también

Referencias

  1. ^ James F. Blinn (1977). "Modelos de reflexión de la luz para imágenes sintetizadas por computadora". Actas de la cuarta conferencia anual sobre gráficos por computadora y técnicas interactivas . págs. 192-198. CiteSeerX  10.1.1.131.7741 . doi : 10.1145/563858.563893. ISBN 9781450373555. S2CID  8043767.
  2. ^ Shreiner, Dave; El grupo de trabajo Khronos OpenGL ARB (2010). "Las matemáticas de la iluminación". Guía de programación OpenGL: la guía oficial para aprender OpenGL, versiones 3.0 y 3.1 (7ª ed.). Pearson Education, Inc. págs. 240–245. ISBN 978-0-321-55262-4.
  3. ^ Krus, Kristofer (2014), Modelo de olas y modelo de embarcación para simulación del estado del mar, Universidad de Linköping , p. 97
  4. ^ Ngan, Addy; Durand, Fredo; Matusik, Wojciech (2004). "Validación experimental de modelos analíticos BRDF". ACM SIGGRAPH 2004 Bocetos sobre - SIGGRAPH '04 . Prensa ACM. pag. 90. doi :10.1145/1186223.1186336. ISBN 1-59593-836-2. S2CID  9259363 . Consultado el 23 de abril de 2019 .
  5. ^ "Ejemplo de WebGL: sombreado de Phong / Blinn Phong". www.mathematik.uni-marburg.de . Consultado el 13 de septiembre de 2019 .
  6. ^ Framebuffer khronos.org