Monday, May 18, 2009

occlusion: ¿raytrace o point clouds?

Actualizando algunos shaders, llegue de nuevo al tema del occlusion. Hasta este momento, no habia considerado la posibilidad de usarlo en base a point clouds por dos razones:
  • Hay una diferencia visual entre el generado con raytrace.
  • El proceso de generar el point cloud solamente para calcular occlusion no significaba un ahorro de tiempo.
Ahora, viendo el resultado de ambos métodos llegue a la conclusión de que:
  • Todos los cuadros de la pasada de occlusion van a ser calculados con el mismo método, por lo que no habrá variación en el render final (si 50 cuadros se calcularan con point clouds y 50 con raytracing de una secuencia de 100, es lógico que tendriamos un problema).
  • Si estoy calculando el indirectdiffuse, es necesario generar el point cloud. Y si ya hay un point cloud, ¿porque no utilizarlo para sacar el occlusion también?
Bueno, ahora los renders:
En el render de la izquierda, estoy usando raytracing. El código es

surface
ambocc(
float maxhitdist = 10;

float bias = .005;

float num_samples = 256;

float angle = 90;

)
{
float is_matte;

attribute("user:delight_is_matte", is_matte);
if (is_matte == 0)
{

normal Nf = faceforward( normalize(N), I);
uniform float adaptive = num_samples >= 256 ? 1 : 0;

float a = 1 - occlusion (P,
vector(Nf), num_samples, "adaptive", adaptive,
"angle", radians(angle),
"maxdist", maxhitdist, "bias", bias);
Ci = a;

}

else

Ci = Cs;

Oi = Os;
Ci *= Oi;

}
Usando los valores declarados en el shader, aun tenemos algo de grano y el caracteristico borde blanco en superficies (que puede arreglarse como se explica aqui http://www.3delight.com/en/modules/PunBB/viewtopic.php?id=1411) . El tiempo de render de ese still fue de 223 segundos (3.7 minutos aprox).


Ahora, usando point clouds, obtenemos el render de la izquierda. Tenemos menos contraste que en el render anterior. El código es (usando renderman codes porque aun no lo hago sl):

float radius = 90
float occ_bias = 0.001
string ptc_file = "myptc.ptc"
float aoMaxSolidAngle = 0.010
output color result_BT

extern normal N;
extern point P;
extern vector I;

normal n = normalize(N);
color result_OCC = color (1);

result_OCC = 1 - occlusion( P, n,
"filename", ptc_file, "pointbased", 1,
"coneangle", radians (radius),
"maxdist", 20,
"maxsolidangle", aoMaxSolidAngle,
"bias", occ_bias, "clamp", 1, "hitsides", "front" );

result_BT = result_OCC;
Los valores que hay que usar son los definidos en "Shading Parameters". Y lo que pueden ver es que no tenemos grano (el contraste se puede controlar en compuesto haciendo "clamp", 0). Otra forma de acercarnos mas al render de arriba, es haciendo maxdist mas grande. En el ejemplo con raytracing maxdist = 10, y usando point clouds maxdist = 20. Posiblemente aumentando la distancia, podamos acercarnos mas. De nuevo, como todo esto se maneja sin variación, el compuesto no debe tener mucha bronca.

El tiempo de render de la imagen de arriba es de 152 segundos (2.5 minutos aprox). Eso es casi 1 minuto de diferencia!!. Entre las ventajas de usar este método, aparte del minuto de diferencia, esta la posibilidad de calcular occlusion + displacement de forma rapida.

Creo que la mejor manera de ver si esto se rompe, es utilizandolo en un proyecto real. Por lo pronto, cualquier shader puede integrar la opcion de calcular occlusion usando point clouds si es que tenemos presente el archivo (sobre todo si estamos calculando indirectdiffuse) y agregando una opcion para que el usuario lo use o no.

Ya les dire despues si se rompe o no ;)

edit: En el render de point cloud, tambien hay algo raro en las esquinas superiores. Esto es porque cuando exporte el archivo usando bake3d(), la camara no tenia visible toda la geometria. Esto es importante ;)

No comments: