From 337ff82efb6c713cf13ce0cfae407755da77e2d5 Mon Sep 17 00:00:00 2001
From: github-actions Por fortuna, hay algoritmos que son capaces de proporcionar la
constante \(s\) sin necesidad de
calcular la integral. Uno de los más conocidos es
-Metropolis-Hastings, el cual se basa en cadenas de
-Markov de Monte Carlo. Sin embargo, su complejidad hace que se escape
-del ámbito de este trabajo. Se puede encontrar más información en (Pharr, Jakob, and Humphreys 2016, Metropolis
-Light Transport).
En este trabajo nos centraremos en buscar funciones de densidad \(p_X\) que se aproximen a \(f\) lo más fielmente posible, dentro del @@ -4673,6 +4669,18 @@
donde \(1 \le i \le N\), \(t, s \ge 0\).
+Un algoritmo basado en cadenas de Markov muy famoso es el +muestreo de Metrópolis (Pharr, +Jakob, and Humphreys 2016, Metropolis Light Transport). Una +de sus grandes ventajas es que puede generar muestras que sigan la +distribución de valores de una función \(f\). Para hacerlo, no necesita nada más que +evaluar dicha función, sin necesidad de integrarla. Además, en cada +iteración del algoritmo se consiguen muestras usables, a diferencia de +otros método como aceptación-rechazo. Tal es su potencia que ha creado +un área específica en la informática gráfica, denominado Metropolis +light transport.
La implementación estará basada en Vulkan, junto al pequeño framework
-de nvpro-samples, que puede encontrarse en el repositorio (La implementación estará basada en Vulkan, junto al pequeño
+framework de nvpro-samples, que puede encontrarse en
+el repositorio (NVIDIA
2022a). Nuestro trabajo recogerá varias de las
características que se muestran en dicho repositorio. Además,
@@ -5077,20 +5086,21 @@ Como es natural, el tiempo es una limitación enorme para cualquier
programa en tiempo real. Mientras que en un offline renderer
-disponemos de un tiempo muy considerable por frame (desde varios
-segundos hasta horas), en un programa en tiempo real necesitamos que un
-frame salga en 33.3 milisegundos o menos. Este concepto se suele
-denominar frame budget: la cantidad de tiempo que disponemos
-para un frame.
Nota: cuando hablamos del tiempo disponible para un -frame, solemos utilizar milisegundos (ms) o frames por segundo (FPS). -Para que un programa en tiempo real vaya suficientemente fluido, -necesitaremos que el motor corra a un mínimo de 30 FPS (que equivalen a -33.3 ms/frame). Hoy en día, debido al avance del área en campos como los -videosjuegos, el estándar se está convirtiendo en 60 FPS (16.6 -ms/frame). Aún más, en los videojuegos competitivos profesionales se han -asentado los 240 FPS (4.1 ms/frame).
+frame, solemos utilizar milisegundos (ms) o frames por +segundo (FPS). Para que un programa en tiempo real vaya suficientemente +fluido, necesitaremos que el motor corra a un mínimo de 30 FPS (que +equivalen a 33.3 ms/frame). Hoy en día, debido al avance del +área en campos como los videosjuegos, el estándar se está convirtiendo +en 60 FPS (16.6 ms/frame). Aún más, en los videojuegos +competitivos profesionales se han asentado los 240 FPS (4.1 +ms/frame).
Las nociones de los capítulos anteriores no distinguen entre un motor en tiempo real y offline. Como es natural, necesitaremos @@ -5168,7 +5178,7 @@
Una vez hemos cumplido los requisitos de hardware, es hora de escoger -los frameworks de trabajo.
+los frameworks de trabajo.Las API de gráficos están empezando a adaptarse a los requisitos del tiempo real, por lo que cambian frecuentemente. La mayoría adquirieron las directivas necesarias muy recientemente. Aun así, son lo @@ -5223,8 +5233,8 @@
Un proyecto de Vulkan necesita una cantidad de código inicial considerable. Para acelerar este trámite y partir de una base más -sólida, se ha decidido usar un pequeño framework de trabajo de Nvidia -llamado [nvpro-samples] framework de trabajo de +Nvidia llamado [nvpro-samples] (NVIDIA 2022b).
Esta serie de repositorios de Nvidia DesignWorks contienen proyectos @@ -5243,8 +5253,8 @@
vk_raytrace
.
-Estos frameworks contienen asimismo otras utilidades menores. -Destacan GLFW (gestión de ventanas en C++), +
Estos frameworks contienen asimismo otras utilidades
+menores. Destacan GLFW (gestión de ventanas en C++),
imgui (interfaz de usuario) y
tinyobjloader (carga de .obj
y
.mtl
).
engine.h/cpp
. Una de las desventajas
-de seguir un framework “de juguete” es que el acoplamiento es
+de seguir un framework “de juguete” es que el acoplamiento es
considerablemente alto. Más adelante comentaremos los motivos.globals.hpp
.Teniendo en cuenta que utilizamos un framework que no está pensado -para producción y la naturaleza de Vulkan, realizar un diagrama de clase -es muy complicado. Sin embargo, podemos ilustrar las clases más +
Teniendo en cuenta que utilizamos un framework que no está +pensado para producción y la naturaleza de Vulkan, realizar un diagrama +de clase es muy complicado. Sin embargo, podemos ilustrar las clases más importantes de la aplicación: la el motor [28] y la de escenas [29] . En las secciones @@ -5362,18 +5372,18 @@
Ejecuta los siguientes comandos desde la terminal para compilar el proyecto:
-$ git clone --recursive --shallow-submodules https://github.com/Asmilex/Raytracing.git
-$ cd .\Raytracing\application\vulkan_ray_tracing\
-$ mkdir build
-$ cd build
-$ cmake ..
-$ cmake --build .
+git clone --recursive --shallow-submodules https://github.com/Asmilex/Raytracing.git
+cd .\Raytracing\application\vulkan_ray_tracing\
+mkdir build
+cd build
+cmake ..
+cmake --build .
Si todo funciona correctamente, debería generarse un binario en
./application/bin_x64/Debug
llamado
asmiray.exe
. Desde la carpeta en la que deberías
encontrarte tras seguir las instrucciones, puedes conseguir ejecutarlo
con
$ ..\..\bin_x64\Debug\asmiray.exe
+..\..\bin_x64\Debug\asmiray.exe
El principal coste de ray tracing es el cálculo de las intersecciones @@ -5393,12 +5403,13 @@
Se puede repetir esta idea repetidamente, de forma que agrupemos varias bounding boxes. Así, creamos una jerarquía de objetos –como si nodos de un árbol se trataran–. A esta jerarquía es a la que @@ -5546,10 +5557,10 @@
application/vulkan_ray_tracing/src/shaders/raytrace.rchit
.application/vulkan_ray_tracing/src/shaders/raytrace.rmiss
.Existe otro tipo de shader adicional denominado callable shader. Este es un shader que se invoca desde otro shader, a @@ -5639,7 +5650,8 @@
vkCreateRayTracingPipelineKHR
.vkCreateRayTracingPipelineKHR
.
vkGetRayTracingShaderGroupHandlesKHR
.Cada entrada de la SBT contiene un handler y una serie de parámetros -embebidos. A esto se le conoce como Shader Record. -Estos records se clasifican en:
+Cada entrada de la SBT contiene un handler y una serie de +parámetros embebidos. A esto se le conoce como Shader +Record. Estos records se clasifican en:
Una de las partes más difíciles de la SBT es saber cómo se relacionan -record y geometría. Es decir, cuando un rayo impacta en una geometría, -¿a qué record de la SBT llamamos? Esto se determina mediante los -parámetros de la instancia, la llamada a trace rays, y el orden -de la geometría en la BLAS.
+record y geometría. Es decir, cuando un rayo impacta en una +geometría, ¿a qué record de la SBT llamamos? Esto se determina mediante +los parámetros de la instancia, la llamada a trace rays, y el +orden de la geometría en la BLAS.Para conocer a fondo cómo funciona la Shader Binding Table, puedes visitar (Usher 2021, 193) @@ -5700,8 +5713,8 @@
.obj
). Aunque es un sistema
relativamente antiguo y sencillo, se han usado definiciones específicas
-en los materiales para adaptarlo a Physically Based Rendering. Entre los
-parámetros del archivo de materiales .mtl
, destacan:
+en los materiales para adaptarlo a Physically Based Rendering.
+Entre los parámetros del archivo de materiales .mtl
,
+destacan:
\[ \begin{aligned} - h & = 0 + e_1 w = e_1 \\ + h & = 0 + e_1 w = e_1, \\ w & = \frac{f_1 \cos\theta_1}{p_1} \end{aligned} \]
@@ -6070,7 +6084,7 @@Es importante destacar que la acumulación temporal solo es válido cuando la cámara se queda estática. Al cambiar de posición, la información del píxel se ve alterada significativamente, @@ -6130,25 +6144,27 @@
Definimos el número máximo de frames que se pueden acumular:
+los shaders para llevar el recuento del número de frames en las +push constants. +Definimos el número máximo de frames que se pueden +acumular:
// engine.h
class Engine {
//...
int m_maxAcumFrames {100};
}
-Las push constant deberán llevar un registro del frame en el que se -encuentran, así como un número máximo de muestras a acumular para un -pixel:
+Las push constant deberán llevar un registro del frame en el +que se encuentran, así como un número máximo de muestras a acumular para +un pixel:
// host_device.h
struct PushConstantRay {
//...
int frame;
int nb_samples
}
-El número de frame se reseteará cuando la cámara se mueva, la ventana -se reescale, o se produzca algún efecto similar en la aplicación.
+El número de frame se reseteará cuando la cámara se mueva, +la ventana se reescale, o se produzca algún efecto similar en la +aplicación.
Finalmente, en los shaders podemos implementar lo siguiente:
// raytrace.rgen
vec3 pixel_color = vec3(0);
@@ -6263,7 +6279,7 @@ .
Nosotros no nos preocuparemos especialmente por esto. Este no es un
trabajo sobre teoría del color, aunque nos metamos en varias partes en
-ella. El área de tone mapping es extensa y merecería su propio
+ella. El área de tone mapping es extensa y merecería su propio
estudio.
Es importante mencionar que sin acumulación temporal, el código
anterior produciría variaciones significativas para pequeños
@@ -6273,9 +6289,10 @@
5 Análisis de rendimiento
En este capítulo vamos a analizar el resultado final del proyecto. -Estudiaremos cómo se ve el motor, cómo rinde en términos de **frame* -time*, y compararemos las imágenes producidas con otras similares; tanto -producidas por otros motores, como situaciones en la vida real.
+Estudiaremos cómo se ve el motor, cómo rinde en términos de tiempo de +procesado de un frame, y compararemos las imágenes producidas +con otras similares; tanto producidas por otros motores, como +situaciones en la vida real.Una vez se ha compilado el @@ -6353,7 +6370,7 @@
cube_reflective
cube_
reflective
Ten en cuenta que las imágenes de las escenas no son definitivas. -Están sujetas a cambios, pues se podría cambiar el comportamiento de los -shaders.
+Están sujetas a cambios, pues los shaders todavía se encuentran en +desarrollo.A lo largo de este trabajo hemos visto una gran variedad de conceptos @@ -6443,7 +6460,7 @@
Los más simples son los difusos. La caja de Cornell +href="#reflexión-difusa-o-lambertiana">difusos. La caja de Cornell original contiene dos objetos de este tipo:
Para un vistazo más a fondo de la iluminación global, puedes @@ -6707,7 +6724,7 @@
\[ \text{tiempo de renderizado} \approx a + N t \text{ -(milisegundos/*frame*)} +(milisegundos/frame)} \]
Donde \(N \in \mathbb{N}\) es el número de muestras y \(t\) es el tiempo @@ -6766,9 +6783,9 @@
No obstante, el cambio de 10 a 20 no es tan significativo como de 1 a -5. Esto sugiere que debemos usar otras técnicas para reducir la varianza -del estimador. ¡La fuerza bruta no suele ser la solución!
+No obstante, el cambio de 10 a 20 no supone un salto tan grande como +el de 1 a 5. Esto sugiere que debemos usar otras técnicas para reducir +la varianza del estimador. ¡La fuerza bruta no es la solución!
Una de las decisiones que tenemos que tomar en el diseño del @@ -6783,9 +6800,9 @@
En esta figura [52] ocurre algo @@ -6804,10 +6821,11 @@
La naturaleza de la escena afecta en gran medida al resultado. Por mera probabilidad, cuando un rayo rebota dentro de la caja, puede salir disparado hacia muchas direcciones. Destacarían en este caso @@ -6894,32 +6912,33 @@
Utilizando una única muestra, pero un valor de acumulación temporal -de 100 frames máximos, proporciona una imagen sin apenas ruido [59].
+de 100 frames máximos, proporciona una imagen sin apenas ruido +[59].Subiendo los parámetros a 200 frames de acumulación temporal y 10 -muestras, se obtiene una imagen muy buena[Subiendo los parámetros a 200 frames de acumulación temporal +y 10 muestras, se obtiene una imagen muy buena[60].
El tremendo efecto de esta técnica es debido a que actúa como normalización entre imágenes. Interpolando linealmente los resultados de -diferentes frames, con el tiempo se conseguirá una foto de lo que se -debe ver realmente, eliminando así el ruido y las luciérnagas.
+diferentes frames, con el tiempo se conseguirá una foto de lo +que se debe ver realmente, eliminando así el ruido y las +luciérnagas.Como se ha mencionado en la introducción, todas las escenas @@ -7159,10 +7178,10 @@
Se puede observar cómo el tipo de ruido es diferente. En In One Weekend, el ruido se presenta en forma de píxeles blancos, debido a las luciérnagas generadas por el muestreo directo de la fuente de luz. En @@ -7174,8 +7193,8 @@
Por último, subiendo el número de muestras a 1000 conseguimos una @@ -7190,7 +7209,7 @@