Bump Mapping - Universidad Central de Venezuela

Anuncio
Displacement Mapping y
aproximaciones
Prof. Rhadamés Carmona
Universidad Central de Venezuela
Última revisión: 08-Oct-2009
Contenido
• Introducción
• Displacement Mapping
• Subdividir y Desplazar, Ray Tracing, Volume
Rendering Slicing
• Bump Mapping, Normal Mapping
• Parallax Mapping, Steep Parallax Mapping
• Otros: Relief Mapping, Interval Mapping, View
Dependent Displacement Mapping…
Displacement Mapping
• Mediante una textura, hace que los vértices
de la geometría se desplace en dirección de su
normal.
• Requiere de un alto nivel de tesselation de los
polígonos para obtener “micropolígonos” cuyo
tamaño se ajuste idealmente a un píxel de la
imagen.
• Se puede utilizar para generar animaciones en
batch, pero no para aplicaciones real time.
Displacement Mapping
• La geometría se desplaza en dirección a la
normal. Por ejemplo, el gris 128 significa
“no desplazamiento”. Valores inferiores a 128
hacen el efecto de hundido. Valores sobre 128
hace el efecto de chichones. Para mejorar la
precisión, se pude utilizar 16 bits y no 8 bits.
Displacement Mapping
Se usa también para crear terrenos con una mapa de alturas y un
plano Tesselado en muchos triángulos. En este caso se le denomina
vertex displacement mapping, y puede ser implementado
trivialmente en el vertex shader.
Displacement Mapping
struct vertex
{
float4 position : POSITION;
float3 normal : NORMAL;
float4 color0 : COLOR0;
float2 texcoord0 : TEXCOORD0;
};
fragment main( vertex IN,
uniform sampler2D displacementTexture : TEXUNIT1,
uniform float4 displacementScaler )
{
fragment OUT;
// Perform a texture look-up for the displacement value.
float4 displacement = tex2D( displacementTexture, IN.texcoord0 );
// Now, use the displacment value to move or displace the current vertex
// along the surface normal. We'll also throw in a scaling factor so we'll
// have better control over the effect.
float4 displacedPosition = float4( IN.normal * (displacement.x *
displacementScaler.x), 0.0 ) + IN.position;
struct fragment
{
float4 position : POSITION;
float4 color0 : COLOR0;
float2 texcoord0 : TEXCOORD0;
};
OUT.position = mul( modelViewProj, displacedPosition );
OUT.color0 = IN.color0;
OUT.texcoord0 = IN.texcoord0;
return OUT;
uniform float4x4 modelViewProj :
state.matrix.mvp;
}
Displacement Mapping
Mapa de bump
Creado con Nurbs
Mapa de Normales
Geometría Desplazada
Displacement Mapping
Mapa sin Suavizar
Mapa Suavizado
Displacement Mapping
• Es un problema tanto obtener un mallado muy fino,
como su procesamiento.
• Aproximaciones
–
–
–
–
–
–
–
–
–
Subdividir y Desplazar
Ray Tracing
Volume Slice Rendering
Parallax Mapping, Steep Parallax Mapping
Bump Mapping
Normal Mapping
Relief Mapping
Interval Mapping
View Dependent Displacement Mapping
Displacement Mapping
• Subdividir y Desplazar: se subdivide cada
triángulo en 4 triángulos recursivamente hasta
llegar a la resolución deseada. Esto podría
realizarse con ayuda del geometric shader. Luego
se aplica el vertex displacement mapping con el
vertex shader.
Displacement Mapping
• Ray Tracing: la idea es intersectar los rayos con
el mapa de alturas “on the fly” sin generar un
mallado intermedio. Esta técnica está
relacionada con Steep Parallax Mapping.
Plano de
referencia
Desplazamiento
máximo
Displacement Mapping
• Volume Rendering Slicing
– Partimos de un plano y un mapa de desp.
– Hacemos un strude del polígono en dirección a su normal
– Por cada slice se dibujan sólo los píxeles con altura >= a la
altura del slice
– Esto se logra con el alpha test, donde el =altura en [0,1]
– Requiere mucho “fill rate” pero poca geometría
Displacement Mapping
• Volume Rendering Slicing
Jan Kautz, Hans-Peter Seidel. “Hardware accelerated displacement
mapping for image based rendering”. No description on Graphics interface
2001. pp. 61-70. Canadian Information Processing Society.
Bump Mapping
• No perturba la geometría. Sólo las normales del objeto.
• Las normales se perturban en función de un mapa de
bump.
• Blinn, en 1978, define la normal perturbada como:
n'  n  Fu (n  Pv)  Fv(n  Pu )
•
•
•
•
•
P(u,v) = (X(u,v), Y(u,v), Z(u,v)) es la ecuación paramétrica de un objeto 3D
dP(u,v)/du = Pu es la derivada parcial de la superficie en (u,v) respecto de u
dP(u,v)/dv = Pv es la derivada parcial de la superficie en (u,v) respecto de v
Fu(u,v)=Fu es la diferencia finita (derivada parcial) del mapa de bump respecto de u
Fv(u,v)=Fv es la diferencia finita (derivada parcial) del mapa de bump respecto de v
n(u, v)  n 
P (u ,v ) P (u ,v )

u
v
P (u ,v ) P (u ,v )

u
v
Bump Mapping
• Si la función de perturbación es una imagen
en escala de grises, entonces:
F (u, v) F (u  1, v)  F (u  1, v)

u
2
F (u, v) F (u, v  1)  F (u, v  1)

v
2
Bump Mapping
• Ejemplo de ecuaciones paramétricas 3D:
0<=u,v<=6.28319
X(u,v)=COS(u)*u*(1.0+COS(v)/2.0)
Y(u,v)=u/2.0*SIN(v)
Z(u,v)=SIN(u)*u*(1.0+COS(v)/2.0)
[0,2], [-, ]
P( ,  )  (rCosSen , rSenSen , rCos )
P( , )
 (  rSenSen , rCosSen ,0)

P( , )
 ( rCosCos , rSenCos , rSen )

Displacement vs. Bump
Displacement Mapping
Bump Mapping
Displacement vs. Bump
Displacement Mapping
Bump Mapping
Normal Mapping
• Para mallados 3D, es más usual utilizar un mapa
de normales.
• La normal de cada punto de la superficie puede
definirse en el espacio tangente.
• Por cada punto de la superficie necesitamos el
vector normal N, y el vector tangente T que va en
dirección a la coordenada s de textura. El vector
binormal o binomial se obtiene en el shader
como B=NxT. Similarmente, se puede obtener N
conociendo a T y B como N=TxB.
Normal Mapping
• Un punto (x,y,z) en coordenadas objetos, tiene
asociado una coordenada de textura (s,t) y un
espacio tangente. Muestreando sobre el normal
map en (s,t) sabemos la normal del objeto en el
espacio tangente. Mediante la matrix TBN,
podemos llevar esta normal al espacio objeto,
donde está la luz. Con la normal y la luz en el
mismo espacio, procedemos a calcular un modelo
de iluminación. Equivalentemente se podría llevar
la luz al espacio tangente para calcular el modelo
de iluminación, pero requiere de la inversa de la
TBN.
Normal Mapping
• Sistemas de coordenadas involucrados en el
normal mapping:
Normal Mapping
• Si el objeto fuese paramétrico, el valor de T
sencillamente sería dP(u,v)/du, el valor de B sería
dP(u,v)/dv, y el gradiente sería el producto cruz
de ambos vectores. Al normalizar el gradiente
obtenemos N.
• Si el objeto es una malla, se calcula N en un
vértice como el promedio de las normales de sus
polígonos adyacentes. Para los fragmentos se
interpola la normal de los vértices con el GPU.
Normal Mapping
• Los vectores T, B que definen el espacio
tangente en un punto (x,y,z) del objeto
corresponden con los vectores (1,0) y (0,1) del
espacio de textura.
• Debido a esta correspondencia, los vectores T
y B pueden ser deducidos mediante la relación
entre vértices en el espacio objeto y sus
coordenadas de textura.
Normal Mapping
• Relación entre es espacio objeto, el espacio tangente y
el espacio de textura.
• Como tenemos unas coordenadas (ui,vi) para cada vértice
del triángulo pi, podemos establecer 3 ecuaciones de la
forma:
pi  ui *T  vi * B
Normal Mapping
Lo cual resulta en las siguientes ecuaciones:
p1  u1 *T  v1 * B
p2  u2 *T  v2 * B
p3  u3 *T  v3 * B
Restando las ecuaciones (2) y (3) con (1):
p2  p1  (u2  u1) *T  (v2  v1) * B
p3  p1  (u3  u1) *T  (v3  v1) * B
Normal Mapping
Multiplico la primera ecuación por (v3-v1) y la segunda por (v2-v1)
( p2  p1) * (v3  v1)  (u2  u1) * (v3  v1) *T  (v2  v1) * (v3  v1) * B
( p3  p1) * (v2  v1)  (u3  u1) * (v2  v1) *T  (v3  v1) * (v2  v1) * B
T 
(v3  v1 ) * ( p2  p1 )  (v2  v1 ) * ( p3  p1 )
(u2  u1 ) * (v3  v1 )  (v2  v1 ) * (u3  u1 )
Multiplico la primera ecuación por (u3-u1) y la segunda por (u2-u1)
( p2  p1) * (u3  u1)  (u2  u1) * (u3  u1) *T  (v2  v1) * (u3  u1) * B
( p3  p1) * (u2  u1)  (u3  u1) * (u2  u1) *T  (v3  v1) * (u2  u1) * B
B
(u3  u1 ) * ( p2  p1 )  (u2  u1 ) * ( p3  p1 )
(v2  v1 ) * (u3  u1 )  (u2  u1 ) * (v3  v1 )
Normal Mapping
Con T y B podemos calcular N=TxB. Con los 3 vectores TBN formamos una
base. Mientras N es  a T y B, T no necesariamente es  a B. Por lo tanto
la matriz TBN no es ortonormal. Mediante la matriz TBN podemos mapear
un vector del espacio tangente (expresado en función de T,B,N) a su
equivalente vector en coordenadas objeto, expresado en términos de los
vectores canónicos (1,0,0), (0,1,0), (0,0,1).
Para calcular el modelo de iluminación de lambert, la luz y la normal
deben estar en le mismo espacio. Nos interesa llevar la luz del espacio
objeto al espacio tangente. Equivalentemente podríamos llevar la normal
del mapa del espacio tangente al espacio objeto. Sin embargo, es más
económico llevar la luz del espacio objeto al espacio tangente puesto que
esa multiplicación matriz-vector se haría una sola vez por triángulo,
mientras que llevar la normal al espacio tangente sería por fragmento (luz
en el infinito). En este caso se necesita la inversa de la TBN. Si la luz es
puntual, entonces ambos enfoques son equivalentes, pues requieren
mapear un vector de un espacio a otro por fragmento.
Normal Mapping
Calculando la inversa de la TBN: una alternativa
es darle la TBN a OpenGL en una matriz (por
ejemplo la matriz de textura) , y el vertex shader
recibirá la inversa ya precalculada. La otra
alternativa es invertir la TBN en el CPU, y darle los
vectores TBN a OpenGL pero correspondiendo a
la matriz inversa.
Normal Mapping
//Vertex program con luz en Inf.
varying vec4 passcolor; //The vertex color passed
varying vec3 LightDir; //The transformed light direction, to pass to the fragment shader
attribute vec3 tangent; //The inverse tangent to the geometry
attribute vec3 binormal; //The inverse binormal to the geometry
uniform vec3 lightdir; //The direction the light is shining
void main()
{
//Put the color in a varying variable
passcolor = gl_Color;
//Put the vertex in the position passed
gl_Position = ftransform();
//Construct a 3x3 matrix from the geometry’s inverse tangent, binormal, and normal
mat3 rotmat = mat3(tangent,binormal,gl_Normal);
//Rotate the light into tangent space
LightDir = rotmat * normalize(lightdir);
//Normalize the light
normalize(LightDir);
//Use the first set of texture coordinates in the fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
}
Normal Mapping
// Fragment program con luz en Inf.
uniform sampler2D BumpTex; //The bump-map
uniform sampler2D DecalTex; //The texture
varying vec4 passcolor; //Receiving the vertex color from the vertex shader
varying vec3 LightDir; //Receiving the transformed light direction
void main()
{
//Get the color of the bump-map
vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy));
//Get the color of the texture
vec3 DecalCol = vec3(texture2D(DecalTex, gl_TexCoord[0].xy));
//Expand the bump-map into a normalized signed vector
BumpNorm = (BumpNorm -0.5) * 2.0;
//Find the dot product between the light direction and the normal
float NdotL = max(dot(BumpNorm, LightDir), 0.0);
//Calculate the final color gl_FragColor
vec3 diffuse = NdotL * passcolor.xyz * DecalCol;
//Set the color of the fragment... If you want specular lighting or other types add it here
gl_FragColor = vec4(diffuse, passcolor.w);
}
Normal Mapping
//Vertex program con luz puntual.
varying vec4 passcolor; //The vertex color passed
attribute vec3 tangent; //The tangent to the geometry
attribute vec3 binormal; //The binormal to the geometry
uniform vec3 lightPos; //The direction the light is shining
void main()
{
//Put the color in a varying variable
passcolor = gl_Color;
//Put the vertex in the position passed
gl_Position = ftransform();
//Use the first set of texture coordinates in the fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
// light direction per vertex. It will be interpolated per fragment
gl_TexCoord[1] = normalize(lightPos – gl_Vertex);
}
Normal Mapping
// Fragment program con luz puntual
uniform sampler2D BumpTex; //The bump-map
uniform sampler2D DecalTex; //The texture
varying vec4 passcolor; //Receiving the vertex color from the vertex shader
uniform vec3 lightPos; //Receiving the light direction
attribute vec3 tangent; //The tangent to the geometry
attribute vec3 binormal; //The binormal to the geometry
void main()
{
//Construct a 3x3 matrix from the geometry’s tangent, binormal, and interpolated normal
mat3 rotmat = mat3(tangent,binormal,gl_Normal);
//Get the color of the bump-map
vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy));
//Get the color of the texture
vec3 DecalCol = vec3(texture2D(DecalTex, gl_TexCoord[0].xy));
//Expand the bump-map into a normalized signed vector
BumpNorm = rotmat* ((BumpNorm -0.5) * 2.0);
//Find the dot product between the light direction and the normal
float NdotL = max(dot(BumpNorm, normalize(gl_TexCoord[1]), 0.0);
//Calculate the final color gl_FragColor
vec3 diffuse = NdotL * passcolor.xyz * DecalCol;
//Set the color of the fragment... If you want specular lighting or other types add it here
gl_FragColor = vec4(diffuse, passcolor.w);
}
Parallax Mapping
• Otros nombres: Virtual Displacement Mapping,
offset mapping
• Desplaza las coordenadas de textura en función
del ángulo de visión en es espacio tangente y el
mapa de alturas en cada punto. En ángulos de
visión empinados, las coordenadas de textura se
desplazan más dando la ilusión de profundidad
por el efecto de paralaje por cambios del punto
de vista.
• Generalmente acompaña a las técnicas de bump
mapping y normal mapping.
Parallax Mapping
Corrección de coordenada de textura en A
Parallax Mapping
• Aplicando un offset a las coordenada de
textura adecuadamente, se produce el efecto
deseado.
• Inputs por fragmento: la coordenada de
textura original T0, el valor de altura h de la
superficie en ese punto (en 0,1), y un vector
de visualización V normalizado del pixel al ojo
en el espacio tangente.
Parallax Mapping
• La altura del mapa es primero llevado al rango
deseado mediante hsb=h.s+b
• El offset es calculado trazando un vector
paralelo al polígono desde el punto de la
superficie directamente sobre P hacia el
vector de ojo
Tn = To + ( hsb ∙ V{x, y} / V{z} )
Parallax Mapping
Normal Mapping
Normal + Parallax Mapping
Steep Parallax Mapping
• Utiliza trazado de rayos, y un mapa de alturas.
La idea es caminar en el rayo, entrar en el
volumen de alturas, y encontrar el punto de
intersección del rayo con el mapa. La
intersección más cercana es la visible
realmente.
• Produce self-oclussion y self-shadowing
Steep Parallax Mapping
Steep Parallax Mapping
float step = 1.0 / n
vec2 dt = E.xy * bumpScale / (n * E.z)
float height = 1.0;
vec2 t = texCoord.xy;
vec4 nb = texture2DLod(NB, t, LOD);
while (nb.a < height) {
height -= step; t += dt;
nb = texture2DLod(NB, t, LOD);
}
// ... Shade using N = nb.rgb
Otros…
• Relief mapping ….
• Interval mapping ….
• Dependent Displacement mapping…
Descargar