|
"¿Cómo se comparan en velocidad las diferentes clases de objetos CSG? ¿Cómo puedo acelerarlas? "
Hay mucha desinformación acerca de la velocidad de los CSG. Un alegato común dice que "fusión -merge- es siempre más lenta que la unión -union-". Esto no es cierto. La fusión es a veces más lenta que la unión, pero en otros casos, es aún más rápida. Por ejemplo, considere el código siguiente:
global_settings { max_trace_level 40 }
camera { location -z*8 look_at 0 angle 35 }
light_source { <100,100,-100> 1 }
merge
{ #declare Ind=0;
#while(Ind<20)
sphere { z*Ind,2 pigment { rgbt .9 } }
#declare Ind=Ind+1;
#end
}
Aqui hay 20 esferas semitransparentes fusionadas. El renderizado de prueba tomó 64 segundos. Sustituyendo 'merge' con 'union', requiere 352 segundos de renderizado. (5.5 veces más). La diferencia de velocidad es notable.
Entonces ¿por qué es 'merge' mucho más rápida que 'union' en este caso? Bien, la respuesta es probablemente que el nùmero de superficies visibles juega un rol muy importante en la velocidad del renderizado. Cuando las esferas se unen, hay 18 superficies internas, mientras que cuando se fusionan, esas superficies internas desaparecen. POV-Ray debe calcular luz y sombra para cada una de esas superficies y eso es lo que lo hace tan lento. Cuando las esferas se fusionan, no hay necesidad de ejecutar cálculos de luz y sombra para esas 18 superficies.
Entonces es 'merge' siempre más rápido que 'union'? No. Si tiene objetos completamente transparentes, entonces 'merge' es ligeramente más lento que 'union', y en ese caso se debiera usar siempre 'union'. No tiene sentido usar 'merge' con objetos no-trasnparentes.
Otro alegato común es el de que "la diferencia es muy lenta; mucho más lenta que la unión ". También esto se puede probar como una falsa declaración. Considere el ejemplo siguiente:
camera { location -z*12 look_at 0 angle 35 }
light_source { <100,100,-100> 1 }
difference
{ sphere { 0,2 }
sphere { <-1,0,-1>,2 }
sphere { <1,0,-1>,2 }
pigment { rgb <1,0,0> }
}
Esta escena tomó 42 segundos para renderizar, mientras que sustituyendo la 'difference' con una 'union' tomó 59 segundos (1.4 veces más).
El asunto crucial aqui es el tamaño de las superficies en pantalla. A mayor tamaño, renderizado más lento (porque POV-Ray tiene que hacer más cálculos de luz y sombra).
Pero la segunda declaración está mucho más cerca de la verdad que la primera: las diferencias son muy a menudo más lentas para renderizar, especialmente cuando los objetos miembros de la diferencia son mucho más grandes que el objeto CSG resultante. Esto es porque la acotacion automática de POV-Ray no es perfecta. Unas pocas palabras acerca de la acotación.
Suponga que tiene cientos de objetos (como esferas o cualquier cosa) formando un objeto CSG más grande, pero este objeto es más que pequeño en la pantalla (como una casita por ejemplo). Sería verdaderamente lento evaluar cada una de las intersecciones rayo/objeto para cada pixel de la pantalla. Esto se acelera limitando el objeto CSG con una forma de acotación (como una caja). Las intersecciones rayo/objeto son evaluadas primero para esta caja, y es evaluada luego para los objetos dentro de la caja solamente si alcanza la caja. Esto acelera el renderizado considerablemente puesto que las evaluaciones son ejecutadas solamente en el área de la pantalla donde se localiza el objeto CSG y en ninguna otra parte.
Puesto que es muy fácil calcular automáticamente una caja de acotación, POV-Ray lo hace y asi usted no lo tiene que hacer.
Pero esta actoación automática no es perfecta. Hay situaciones en las que una acotación automática perfecta es muy difícil de calcular. Tal es el caso de las operaciones diferencia e intersección CSG. POV-Ray hace lo que puede, pero algunas veces hace un trabajo deficiente. Se puede ver apreciar especialmente cuando el objeto CSG resultante es muy pequeño comparado con los objetos miembros de la operación CSG. Por ejemplo:
intersection
{ sphere { <-1000,0,0>,1001 }
sphere { <1000,0,0>,1001 }
}
(Esto es lo mismo que hacer una diferencia con la segunda esfera invertida)
En este ejemplo los objetos miembros de la operación se extiendesn desde <-2001,-1001,-1001> hasta <2001,1001,1001> aunque el objeto CSG resultante es un objeto pequeño con forma de lente que es solamente 2 unidades de ancho en la dirección x y quizás 10 o 20 o algo así en las dirección y en la z. Como se puede ver, es muy difícil calcular las dimensiones reales del objeto (pero no imposible).
En este tipo de casos POV-Ray hace una caja de acotación grandísima, la cual resulta inútil. Usted debería acotar esta clase de objetos a mano (especialmente cuando tenga muchos objetos miembros). Esto puede hacerse con el indicador bounded_by.
Aqui hay un ejemplo:
camera { location -z*80 look_at 0 angle 35 }
light_source { <100,200,-150> 1 }
#declare test =
difference
{ union
{ cylinder {<-2, -20, 0>, <-2, 20, 0>, 1}
cylinder {<2, -20, 0>, <2, 20, 0>, 1}
}
box {<-10, 1, -10>, <10, 30, 10>}
box {<-10, -1, -10>, <10, -30, 10>}
pigment {rgb <1, .5, .5>}
bounded_by { box {<-3.1, -1.1, -1.1>, <3.1, 1.1, 1.1>} }
}
#declare copy = 0;
#while (copy < 40)
object {test translate -20*x translate copy*x}
#declare copy = copy + 3;
#end
Esto tomó 51 segundos para renderizar. El haber comentado la línea del 'bounded_by', incrementaría el tiempo de renderizado a 231 segundos (4.5 veces más lento).
|