Asmilex / Raytracing

Path tracer en tiempo real implementado sobre Vulkan KHR basado en Ray Tracing In One Weekend Series de Peter Shirley. Trabajo de fin de grado para el doble grado en Ingeniería Informática y Matemáticas de la UGR.
https://asmilex.github.io/Raytracing/
Apache License 2.0
8 stars 0 forks source link

[:notebook:] Correcciones finales #54

Closed Asmilex closed 2 years ago

Asmilex commented 2 years ago

Colección de tareas finales necesarias para la entrega.

Notas de Carlos (1 de junio de 2022)

Versión de PDF: 31 de Mayo de 2022, 11:22

(1) Título:

El título del TFG debe ser el que se usó para registrarlo el verano pasado, es el siguiente:

"Métodos de Monte-Carlo para síntesis de imágenes: análisis teórico e implementaciones basadas en path-tracing acelerado por hardware"

Debes cambiarlo donde proceda en la memoria y en el repositorio en github.

(2) Sinopsis, página 1

donde dices "modernas de informática gráfica físicamente realistas basadas en ray tracing en tiempo real", debería decir "modernas de síntesis de imágenes físicamente realistas basadas en Path-Tracing en tiempo real"

(3) A brief overview, página 2

En el párrafo que comienza con "Path tracing" se debe al menos decir que la diferencia fundamental entre Path-Tracing y Ray-Tracing es que el primero calcula Iluminación Global (emplear este término exactamente)

(4) A brief overview, página 3

Nombras "Nvidia DesignWorks’ nvpro-samples framework", incluir referencia a la entrada de la bibliografía con el enlace a la Web del framework.

(5) Nota histórica, página 9

Escribes "En 1986 Kajiya introdujo la denominada rendering equation (Pharr, Jakob, and Humphreys 2016)", aquí citas un artículo de Pharr y otros, pero deberías citar el artículo original de Kajiya, este:

James T. Kajiya. 1986. The rendering equation. In Proceedings of the 13th annual conference on Computer graphics and interactive techniques (SIGGRAPH '86). Association for Computing Machinery, New York, NY, USA, 143–150. https://doi.org/10.1145/15922.15902

(6) Nota histórica, página 9 y siguientes

Aquí, y en otros sitios, usas el término Ray-Tracing cuando yo creo que deberías usar Path-Tracing. Ray-tracing es la técnica que se basa en calcular que se ve en cada pixel, usando rayos, mientras que path-tracing es la extensión de ray-tracing para cálculo de iluminación global. Cuando escribes, por ejemplo "A diferencia del uni- verso, nosotros no podemos permitirnos el lujo de usar un elevado número de fotones, ni hacer rebotar la luz tantas veces como queramos. Nos pasaríamos una eternidad esperando. Y para ver una imagen en nuestra pantalla necesitaremos estar vivos, claro. En la práctica, esto su- puso que no todos los medios pudieron pasarse a ray tracing" te estás refiriendo a la capacidad de path-tracing de calcular iluminación global, pero luego simplemente mencionas ray-tracing, no path-tracing, que es lo correcto aquí IMHO.

(7) Nota histórica, página 10

En esta nota histórical debes al menos citar los primeros artículos sobre implementación de ray-tracing por hardware en GPUs, son estos dos:

Timothy J. Purcell, Ian Buck, William R. Mark, and Pat Hanrahan. 2002. Ray tracing on programmable graphics hardware. ACM Trans. Graph. 21, 3 (July 2002), 703–712. https://doi.org/10.1145/566654.566640

Nathan A. Carr, Jesse D. Hall, and John C. Hart. 2002. The ray engine. In Proceedings of the ACM SIGGRAPH/EUROGRAPHICS conference on Graphics hardware (HWWS '02). Eurographics Association, Goslar, DEU, 37–46. PDF: https://www.csee.umbc.edu/~olano/s2005c37/ch08.pdf

(8) Objetivos del trabajo, págin 10

Usar "los fundamentos del ray-tracing y path-tracing en tiempo real", en lugar de únicamente "ray-tracing".

(9) Sobre esta memoria, página 11

Usar "describen como se reflejan los fotones cuando impactan con una superficie" en lugar de "describen cómo cambian los fotones cuando impactan con una superficie"

(10) Sobre esta memoria, página 12

De nuevo, incluir enlace al repositorio en github de nvidia-pro samples cuando se cita aquí.

(11) 1. Las bases, página 14

Cambiar "origin" por "origen". Decir que el origen 'o' es un punto del espacio (de un espacio afin) y 'd' un vector libre. Usar una notación en las fórmulas para distinguir valores reales (como 't') de vectores o puntos (como 'd' o 'p'), lo usual es usar negrita para los vectores o puntos.

(12) 1. Las bases, página 15

Un párrafo comienza por "cuando un rayo impacta", pero "cuando" debe ir en mayúscula

(13) 1. Las bases, página 16

ídem que el anterior, el párrafo empieza con "como" en minúscula.

(14) 1.2. Intersecciones rayo - objeto, página 16

El primer párrafo empieza en minúscula.

(15) 1.2. Intersecciones rayo - objeto, página 16

Lo de separar un poco el inicio no es exactamente por errores de redondeo, es para evitar que se detecte intersección de un rayo en el origen del mismo, con t==0, esa intersección debe ignorarse, por ejemplo para rayos de sombra. Por tanto, en realidad se buscan intersecciones en el intervalo abierto en 0. La forma de implementar esto numéricamente, con precisión finita, es usar el epsilon del que hablas, pero falta describir este motivo.

(16) 1.2.1 Superficies implícitas, página 17

Debes decir que las superficies definidas de forma implícita se pueden usar para calcular intersecciones rayo-superficie de forma numérica iterativa por lo general, aunque en algunos casos hay expresiones analíticas sencillas (como el plano, o la esfera, por ejemplo)

(16) 1.2.1 Superficies implícitas, página 18

Un párrafo comienza con "consideremos" en minúscula. Además, usas Q_0 y q_0 para un punto conocido del plano, es mejor usar minúsculas (aunque también hay que tener en cuenta la nota número 11 aquí arriba, se deben distinguir puntos y vectores de valores escalares). En la fórmula "F(Q)=(q-q_0)\cdot.." usas Q y q, lo correcto es q. Finalmente, debes añadir que d y n son paralelos, entonces se considera que no hay intersección.

(16) 1.2.2 Superficies paramétricas, página 19

Dices que es "sencillo" encontrar intersecciones rayo-superficie paramétrica, pero en realidad es al revés, es decir, las ecuaciones paramétricas de un superficie, por regla general, no permiten calcular esas intersecciones, y por tanto no se usan directamente en ray-tracing (a no ser que se puedan convertir a implícitas, al respecto hay mucha literatura en matemáticas). Lo que sí es fácil es obtener una malla de triángulos a partir de las ecuaciones paramétricas, y luego calcular intersección rayo-malla usando indexación espacial.

(17) 1.2.3. Intersecciones con esferas, página 21

Donde dices "pegaría con el borde" deberías decir "es tangente a la esfera"

(18) 1.2.3. Intersecciones con esferas, página 24

El primer párrafo de esa página empieza en minúscula. Además, has puesto "cramer" en minúscula, pero es un nombre propio, va en mayúscula.

(19) 2.1.1. Potencia, página 26

En la definición de potencia escribes simplemente que la potencia es "la tasa de producción de energía", pero debes de aclarar que se trata de la cantidad de energía por unidad de tiempo que atraviesa un área o región determinada de una superficie.

(20) 2.1.1. Irradiancia, página 26

donde dice "flujo radiante que recibe una superficie", debes decir "potencia por unidad de área que recibe una región de una superficie o un punto de la misma", y luego, en lugar de "dada un área A", debes decir, "si A es el área de dicha superficie"

(21) 2.1.3 Ángulos sólidos, página 29

Para definir el ángulo sólido, es mucho más fácil no usar un esfera de radio arbitrario 'r', sino una de radio unidad, es lo más común en la literatura. Así, el ángulo sólido de un trozo de esfera de radio unidad es directamente su área. Además, lo usual en la literatura es usar \sigma para significar la medida de ángulo sólido, no 'w', me resulta raro. La frase "Debido a la forma en la que se trabaja con ellos, es costumbre usar 'w' como un vector dirección unitario en la esfera." me parece algo confusa, ya que en la literatura de iluminación global se suele usar 'w' para significar vectores unitarios, es cierto, pero eso no tiene nada que ver con el ángulo sólido, una cosa es la medida de ángulo sólido y otra un vector de longitud unidad. Por eso veo mejor usar otro símbolo para el ángulo sólido. Usar A puede ser confuso, ya se usa para la medida de área. El símbolo \Omega lo usas para subconjuntos de la esfera como dominio de alguna integral. Usar 'w' es confuso, como ya he dicho. Por todo esto, creo que sería bueno usar \sigma, esto es habitual en la literatura sobre iluminación global (Peter Shirley lo usa bastante). Además, para las integrales, el diferencial de ángulo sólido entorno a un vector 'w' se puede poner como d\sigma(w), en lugar de dw, eso hace explícito en la notación cual es la medida de que se está usando en la integral, junto con la variable de integración.

(22) 2.1.3 Ángulos sólidos, página 30 y 31

Hablas sobre como se relacionan los diferenciales de los ángulos \theta y \sigma con en el diferencial de ángulo sólido. En matemáticas esto es una relación o tasa entre funciones de medida aplicadas a regiones de tamaño diferencial (es una generalización del concepto de derivada en teoría de la medida, relacionado con el "Jacobian") y efectivamente puede usarse para hacer cambios de variable en integrales. No se si tiene mucho sentido intentar explicarlo aquí, puedes simplemente introducir la relación entre los diferenciales y ya está (puesto que luego lo usas)

(23) 2.1.5 Radiancia, página 32

Aquí creo que habría que escribir el párrafo que sirve para definir la radiancia, de otra forma el lector no puede hacerse una idea de a qué te refieres. El párrafo es:

"La radiancia L(p,w) es la potencia o flujo radiante que pasa por un punto 'p' y viaja en una dirección 'w', por unidad de área (perpendicular a 'w') entorno a ese punto 'p', y por unidad de ángulo sólido entorno a esa dirección 'w'"

El ejemplo del espejo no es adecuado, creo que aquí debes referirte a un superficie de un cristal que refracta la luz, en ese caso del cristal la luz reflejada hacia un lado es distinta de la luz refractada hacia el otro, si no lo entiendo mal.

Lo de distinguir entre L+ y L- creo que es innecesario, y me resulta muy confuso. Lo importante es distinguir entre radiancia saliente Lo(p,w) (viaja en la dirección de 'w') y entrante L{in}(p,w) (viaja en la dirección contraria a 'w', por definición). Estas radiancias se pueden definir para cualquier 'w' en la esfera, no solo en la semiesfera "por encima" del punto (en el lado de la normal). Por tanto, eso cubre los cuatro casos posibles, es decir, la radiancia saliente y entrante, por la parte superior y por la parte inferior de la superficie.

(24) 2.1.6.1. Una nueva expresión de la irradiancia y el flujo, página 35

Donde dices "Haciendo el mismo juego con el flujo emitido de un cierto objeto al hemisferio" creo que lo adecuado sería "Si integramos esta expresión para todos los puntos de una superficie A, obtenemos la potencia total saliente de esa superficie en todas las direcciones"

Según el libro PBRT (que es el que sigues aquí), en la expresión (2.12) se usa el término \Omega para significar cualquier región (subconjunto) de la esfera S^2, debes aclararlo aquí, como lo tienes no se sabe a que te refieres con \Omega.

(25) 2.2. Dispersión de luz, página 36 y 37.

Lo que denominas "dispersión en superficie" o "surface scatering" incluye la reflexión (reflection), deberías decirlo explícitamente, y quizás sería mejor decir "Dispersión y reflexión de la luz".

(26) 2.2.1. La función de distribución de reflectancia bidireccional (BRDF), página 38

En la igualdad de la reciprocidad, donde pones "f_r(p,w_i,w_o)" debes poner "f_r(p,w_i <-- w_o)", (con una flecha en lugar de una coma) en coherencia con la notación que vienes usando, como lo tienes resulta confuso. Esto ayuda a entender que es la reciprocidad de la brdf (no cambia si se intercambian w_i y w_o).

(27) 2.2.3. La función de distribución de dispersión bidireccional

(BSDF), página 39

En la fórmula 2.14 has usado 'S' para significar la esfera (el dominio de integración), pero en fórmulas anteriores has usado \Omega para significar también la esfera completa (mira, por ejemplo, la fórmula 2.12 de la página 35). Creo que es más "estándar" usar S^2 para la esfera y H^2 u \Omega para la semiesfera. De cualquier forma, debes usar un notación coherente en todo el texto e introducir los símbolos en el primer uso.

(28) 2.2.4. Reflectancia hemisférica, página 40

"Algo" en mayúscula en mitad de una frase. La frase "describe la reflexión total sobre un hemisferio debida a una fuente de luz que proviene desde la dirección w_o :" es incorrecta, debería ser "describe la radiancia saliente en la dirección 'w_o'", supuesto que la radiancia entrante desde cualquier dirección es constante e igual a la unidad.".

(29) 2.3.1. Tipos de dispersión, página 42

El párrafo que describe la diferencia entre reflexión isotrópica y anisotrópica es incorrecto. Los materiales que se ven con el mismo color desde todas las direcciones (es decir L(p,w_o) no depende de 'w_o') son los materiales difusos (ya que w_o no aparece en la expresión de la BRDF difusa). Los materiales isotropicos son aquellos cuya BRDF f_r(p,w_o,w_i) no cambia cuando se rotan ambos vectores 'w_o' y 'w_i' un ángulo cualquiera (el mismo para ambos) entorno a la normal a 'p'. La mayoría de los materiales son isotrópicos. Si la BRDF f_r sí varía ante esa rotación, entonces hablamos de materiales anisotrópicos. Los materiales anisotrópicos típicos son materiales pulidos que tiene surcos pequeños, invisibles a simple vista, como un disco de vinilo o una superficie metálica pulida en una dirección. La anisotropía viene de que el comportamiento de la reflexión depende de la orientación de los surcos en la superficie.

(30) 2.3.2.1. Reflexión especular perfecta, página 42

Aquí aparece (1er párrafo de 2.3.2.1) una cita a la primera entrada de la bibliografía, la cita es a un capítulo de un libro que tiene un ISBN y que está publicado en Open Access. Este tipo de referencias bibliográficas debe ponerse en la bibliografía incluyendo la información del autor y nombre del capítulo, junto con los editores, nombre e ISBN del libro completo, en este caso el autor es del capítulo es Eric Haines, debe quedar así:

Eric Haines. 2021. "Reflection and Refraction Fórmulas", en Adam Marrs, Peter Shirley, and I. Wald, (editores). "Ray tracing gems II.", pp.104-108. Editorial Apress, 2021. ISBN: 978-1-4842-7187-2. DOI: https://doi.org/10.1007/978-1-4842-7185-8

(revisa otras referencias parecidas para adaptarlas a este estándar, he puesto el DOI aunque el enlace a http://www.realtimerendering.com/raytracinggems/rtg2/ también es correcto).

Aquí debes usar la notación que vienes usando para los vectores ('w_o','w_i','w_r' en lugar de 'o', 'i', 'r'), además debes usar el convenio de que los vectores w_o,w_i,w_r apuntan desde el punto 'p' hacia afuera, no al revés, como en la figura 2.5 de Eric Haines. De hecho, esa notación (w_o,w_i y w_r apuntando hacia fuera) es lo que usas a continuación en la siguiente sección (y en muchos más sitios). Ten en cuenta que al cambiar el sentido de i y r la expresión de 'r' cambia de signo (se intercambian los operando de la resta).

La expresión k_r(|i·n|) es un poco confusa, puede interpretarse de dos formas:

  1. k_r es una función que se evalua con |i·n| como argumento,
  2. k_r es un coeficiente que multiplica a |i·n|,

en cualquier de los dos casos, debes aclarar cual de las dos opciones es la que tienes en mente y explicarla: si es una función ¿como y pq ocurre esa dependencia? si es un producto ¿pq se multiplica por i·n?

(30) 2.3.2.2. Reflexión difusa o lamberiana, páginas 42 y 43

En el título pones "lamberiana" en lugar de "lambertiana". El símbolo k_d que usas aquí es muy estándard, pero creo que debe aparecer dividido por \pi en la expresión de la BRDF f_r, de esta forma, el rango de valores de k_d es [0,1] y así k_d coincide con el albedo (fración de energía reflejada de forma difusa), que es lo usual (1/\pi es la constante normalización de esta BRDF, aqui abajo te pongo los coeficientes correspondientes para Phong y Blinn-Phong.

(31) 2.3.2.3. Reflexión especular no perfecta, página 43 y 44.

Aquí introduces el modelo de iluminación local de Phong (o Blinn-Phong) usual para rasterización, que es un modelo sencillo que incluye una componente ambiental, otra difusa, y otra pseudo-especular. Pero eso es un modelo aproximado y en esta parte estás hablando de BRDFs basadas en física y normalizadas, así que creo que debes de incluir las BRDFs de la parte pseudo-especular únicamente, ignorando la parte ambiental (no tiene sentido en este contexto) e ignorando la parte difusa (esa BRDF ya la has introducido). Respecto a las expresiones de la parte pseudo-especular, son correctas, pero si estamos definiendo una BRDF realista y normalizada, deben llevar adicionalmente los factores de normalización, para Phong es (n+2)/(2·pi) y para Blinn-Phong es ((n+2)·(n+4))/(8·pi·(2^(-n/2)+n) (ver: http://www.farbrausch.de/~fg/stuff/phong.pdf)

Aquí incluyes dos trozos de código que evaluan estas BRDFs, pero estos trozos de código aparecen un poco 'fuera de contexto', ya que no aparecen para otras BRDFs y no se dice en que lenguaje de programación están escritos.

(32) 2.3.3.2. Ecuaciones de Fresnel, página 47

Escribes "Generalmente en los ray tracers la polarización se ignora, promediando ...", pero lo correcto sería decir "Generalmente en los ray tracers se simula luz no polarizada, así que se deben promediar ambos valores, es decir, se debe usar el valor 'R' definido así: "

Aquí sería coherente incluir cómo se calcula el vector refractado y poner explícitamente una fórmula que indique como depende la radiancia refractada y la reflejada de la radiancia incidente.

(33) 2.3.5.1. Oren - Nayar, página 48

la referencia al "White furnace test" no tiene mucho sentido, no lo entiendo. Además, sería lógico poner la expresión de la BRDF, como has hecho para todas las demás, así como algún texto que describa las características de esta BRDF (que diferencia tiene con las anteriores?)

(34) 2.3.5.2. GGX, página 48

Sería mejor titularlo "BRDFs basadas en modelos de microfacetas. La BRDF GGX", sería conveniente si tienes tiempo al menos poner la expresión de la BRDF y explicar sus parámetros (la rugosidad principalmente), de otra forma no se justifica incluir esta sección en la memoria.

(35) 2.4. La rendering equation, página 49

Introduces la ecuación (2.19) sin más, habría que explicarla en al menos una frase "la radiancia total saliente de p en la dirección de w_o es L_o(p,w_o), y se obtiene como la suma de la radiancia emitida (L_e), más la reflejada (L_r). A su vez, la radiancia reflejada (L_r) es la integral, para todas las posibles direcciones de entrada, de la radiancia incidente (L_i), multiplicada por la BRDF (f)"

En la ecuación siguiente a la 2.19 has puesto L_o a la izquierda de la igualdad (igual que en 2.19), pero las partes derechas de 2.19 y la siguiente no coinciden. Por tanto, en la ecuación siguiente a la 2.19 debes usar L_r (radiancia reflejada) en lugar de L_o (que es la radiancia total saliente, de acuerdo con 2.19).

En la segunda ecuación de la página 50, de nuevo usas L_o cuando deberías usar L_r.

En la tercera ecuación de la página 50, deberías usar L_o en lugar de L a secas, aunque lo mejor (lo usual) es que la radiancia total saliente sea L a secas (entonces habría que cambiarla en las 5 ecuaciones de las página 49 y 50, no usar L_o en ningún sitio).

La ecuación 2.19 y la tercera ecuación de la página 50 son casi iguales, a diferencia que en la ultima ya no aparece L_i, solamente la radiancia saliente. Sin embargo, dices que la 2.19 es la "rendering equation", aunque luego hablas de la "ecuación de reflexión". Debes aclarar la terminología, quizás querías decir que la ecuación 2.19 es la "reflection equation" ??

(36) 3. Métodos de Monte Carlo, páginas 51 a 81

Respecto a esta sección, no voy a revisarla pues esta parte es la que te ha revisado la co-tutora y creo que no debo interferir en lo que te haya dicho ella, únicamente te comento algo de la sección 3.3.3.2 ya que toca temas directamente relacionados con el rendering y la ecuación de rendering. Además, te hago una sugerencia para añadir algo sobre cadenas de markov para solución de ecuaciones integrales, que es la base matemática del Path-tracing y todas las técnicas asociadas (lo pongo en los siguientes dos puntos).

(37) 3.3.3.2. Next event estimation, o muestreo directo de fuentes de luz.

La radiancia directa y la indirecta no tienen como parámetro 'w_i', por tanto donde pones w_o<-w_i en la última ecuación de la página 71, debes poner simplemente wo. Además, donde dices "Siendo, .... , L{directa} la radiancia proporcionada por las fuentes de luz" sería mejor decir "Siendo, ... L_{directa} la radiancia reflejada debida únicamente a radiancia incidente directamente de las fuentes de luz".

En la segunda ecuación de la página 72, donde pones L_i en la integral, debería ser L_r, la radiancia reflejada (sin la parte emitida, que ya se incluye en la radiancia directa). Igualmente, en el párrafo de debajo, donde dices "Al aparecer la radiancia incidente .. L_i ", debes decir, "Al aparecer la radiancia reflejada, ... L_r "

Por cierto, en la bibliografía citas mis apuntes de RIG, así:

Carlos Ureña. 2021. “Realismo e iluminación global.” 2021. https://lsi2.ugr.es/curena/.

Deberías poner:

Carlos Ureña. 2021. “Apuntes del curso: Realismo e Iluminación Global (Máster en Desarrollo de Software de la Univ. de Granada)” 2021.

me doy cuenta ahora mismo que has ordenado alfabéticamente las citas usando el nombre de pila del 1er autor en muchos casos (como este), esto no es para nada lo usual, debes usar ordenación por el 1er apellido, no el nombre de pila.

(38) (para insertar una nueva sección entre las actuales secciones 3.2 y 3.3 de este documento)

Como te he escrito, los métodos de Monte-Carlo para aproximar la rendering equation son variantes de una técnica general que se conoce con el nombre de "Markov Chain" o "Cadenas de Markov". Las técnicas basadas en Markov Chains sirven en general para aproximar ecuaciones integrales, y la "Rendering Equation" es una variante de un tipo de ecuación integral. En esta memoria hablas de los métodos de Monte-Carlo para aproximar integrales, pero no para aproximar funciones que son soluciones de ecuaciones integrales. Así que creo que habría que insertar una nueva seción donde en general hables de cadenas de markov y de como se pueden usar para solucionar ecuaciones integrales. Esto es la base formal matemática de Path-tracing. Afortunadamente, he encontrado un paper no muy complicado ni muy largo que da las claves de este tema, y en el que tu puedes basar para escribir esta sección. No tienes que entrar a fondo, ni tiene que ser muy largo, simplemente introducir lo que es una Cadena de Markov, una ecuación integral (en concreto una ecuación integral de Fredholm de 2 tipo, "Fredholm Integral Equation of the second kind"), y como se pueden obtener estimadores para la función solución de la ecuación integral. Creo que puede caber todo en un par de páginas. El artículo al que me refiero es este :

R. Farnoosh, M. Ebrahimi, Monte Carlo method for solving Fredholm integral equations of the second kind, Applied Mathematics and Computation, Volume 195, Issue 1, 2008, Pages 309-315, ISSN 0096-3003, https://doi.org/10.1016/j.amc.2007.04.097. (https://www.sciencedirect.com/science/article/pii/S0096300307005541)

En el paper se trata un caso sencillo genérico en el cual la ecuación integral que resuelve tiene como dominio el intervalo [0,1] en R, en lugar del dominio de la función de radiancia (que es el espacio multidimensional de todos los puntos y direcciones). Pero el paper da las ideas clave generales de como se aproxima una función que es solución de una ecuación integral con métodos de Monte-Carlo, usando cadenas o "paths" de puntos del dominio. No entiendo muy bien como este paper se publica como en 2008 como un trabajo original con revisión por pares, ya que lo que dice son cosas conocidas desde los años 60 por lo menos (ver: https://physicstoday.scitation.org/doi/10.1063/1.3022338, año 69, o mejor https://epubs.siam.org/doi/pdf/10.1137/0704029, del 67), pero el caso es que nos viene de perlas.

En el paper, en la ecuación (1):

El paper muestra como construir secuencias de puntos aleatorios en [0,1] para aproximar el producto escalar de 'u' y otra función, al igual que en rendering aproximamos el valor promedio de la radiancia en un pixel (es el producto escalar de la radiancia y la función de pertenencia al pixel). Las secuencia de valores del paper se corresponden con las secuencia de puntos que forman un path en rendering. De todas formas, en esta nueva sección no es necesario que hagas mención a nada de rendering, solo contar como se puede estimar el producto escalar de 'u' y otra función 'h' (en particular, si usamos una delta Dirac en lugar de 'h', se pueden estimar valores puntuales de la función 'u').

Asumo que una vez que los escribas, probablmente quieras que lo vea la co-tutora, ya que forma parte de la parte "matemática" de la memoria. Si tienes cualuquier duda, me escribes.

Notas de Carlos (7 de junio de 2022)

Versión del PDF: descargada el 2 de junio

(39), sección 4, página 82

Donde dices "La implementación estará basada en Vulkan, junto a ...." habría que incluir una referencia al repositorio y carpeta concreta que has usado como base. El repositorio se llama 'nvpro-samples', pero además la carpeta concreta con el ejemplo se llama 'ray_tracing_gltf', si no me equivoco, es esta URL la que se debe incluir:

https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing_gltf

(en la sección 4.1 tienes una cita a "Nvidia 2022a", pero eso tiene la URL del repositorio completo, creo que sería bueno señalar este ejemplo concreto).

(40) secc. 4.1.1, página 82

En la ecuación de esta página cos\theta_i debe aparecer en valor absoluto, al igual que en la ecuación 2.14, ya que estás integrando en la esfera. Donde dices "recordemos que Lo es la radiancia emitida ...", deberías usar "reflejada" en lugar de "emitida", ya que esa integral solo incluye la radiancia reflejada.

(41) secc. 4.1.1, página 83

En la 1a ecuación de esa página, llamas 'L_o' a otra cantidad distinta de la que has usado en la página 82. Lo usual es llamar a esto de la página 83 simplemente "L". Sería conveniente decir que este "L" es la radiancia total saliente (emitida más reflejada) desde p en la dirección de w_o. En esa ecuación, a la izquierda del '=' sobra la flecha y la variable 'w_i'

(42) secc. 4.1.1, página 83

En la fórmula 4.1, inmediatamente después), habría que aclarar o recordar al lector que cosa es la función 'p' del denominador (es la pdf correspondiente a la selección aleatoria de una dirección de salida 'w_j') y que cosa es L_i. Ahora que lo veo, en estas fórmulas estás usando 'p' para dos cosas y puede ser confuso, quizás el punto 'p' podría renombrarse como 'x', es lo usual, y dejar la pdf como 'p'.

(43) secc. 4.1.1, página 83

En la última frase de esa página, donde dices "no será necesario", creo que lo correcto es decir que "no será posible", es decir, para otros tipos de BRDFs, distinta de la difusa, algunas veces no podemos encontrar una forma de hacer muestro por importancia tan simple, en el cual la PDF sea exactamente proporcional a la BRDF.

(44) secc. 4.1.2, página 84

El listado de la página 84 parece más código concreto en algún lenguaje de programación, que pseudo-código, el pseudo-código suele escribirse en estos textos usando el package latex 'algoritmic' o 'algoritmicx', y no debe hacer mención a funciones o tipos de datos que no aparecen explicados en el código o en el texto. En tu caso usas 'hit_info', 'siguiente_direccion' y cosas así. Además, no queda claro en que contexto se ejecuta la función 'pathtrace', que cosa devuelve, etc...Creo que puedes usar directamente o basarte en el pseudo-código de un path-tracer básico que aparece en las transparencia 35 y 36 del archivo 'rig-t3b-monte-carlo-1.pdf' que te envié por mail el pasado 5 de mayo, es un pseudo-código de un path-tracer básico que no hace muestreo directo de fuentes de luz. En este punto se trata simplemente darle al lector una idea de la estructura del algoritmo de path-tracing, sin que todavía hayas introducido nada sobre shaders en ray-tracing (hit, miss shader, etc...).

Una cosa a aclarar en algún sitio es que en la fórmula 4.1 aparece una sumatoria, pero en este código se usa N=1, ya que en path-tracing cuando se genera un camino, cada rayo (distinto del último) solo da lugar a otro rayo, no N de ellos.

En el último párrafo de esa página hablas del "closest hit shader", pero no has introducido antes que cosa es el closest hit shader. Como te he comentado, el pseudo-código no debe usar nada de shaders, lo de los shaders es algo que introduces más tarde, cuando hablas de como ese pseudo-código se implementa en Vulkan ray-tracing.

Puedes introducir aquí código genérico (pseudo-código) y pasar este código concreto a un punto posterior de la memoria donde ya hayas hablado de la estructura de un path-tracer y hayas introducido que cosa son los shaders.

(45) secc 4.1.3, página 85

Este listado y el texto tienen el mismo problema que el de la página anterior, hablas, por ejemplo, de "hit payload" cuándo al lector le falta información para entender qué cosa es esa.

En estas página 84 y 85, hablas de que la versión recursiva es más lenta, supongo que la gestión de la pila en la GPU no es tan eficiente como en la CPU, pero si eso es cierto deberías aclararlo.

(46) sección 4.2, página 87

Dices que un sistema de rendering en tiempo real tiene hasta 16 milisegundos por cuadro, pero en realidad eso corresponde obviamente a 62 cuadros por segundo, pero creo que en realidad un juego o aplicación a 30 fps (33 ms por cuadro) ya va bien.

(47) sección 4.2.1, página 87

Aquí enumeras las tarjetas que dices que son necesarias para hacer ray-tracing en tiempo real, pero en mi opinión esa afirmación debe ser matizada, se puede hacer ray-tracing en tiempo real a 30 fps o 60 fps usando una GPU mucho más antigua que esas, con el ray-tracing implementado en GLSL en el fragment shader (usando el cauce de rasterización), siempre y cuando la complejidad de la escena (en términos de número de triángulos o primitivas) sea baja. Por tanto, yo cambiaría la afirmación "tajante" por otra mas matizada en la que hables simplemente de que con esas GPUs se puede hacer real time ray-tracing es escenarios muy complejos.

(48) sección 4.3, página 90

Como te he comentado antes, creo que, dentro del repositorio 'vk_raytracing_tutorial_KHR' te has basado principalmente en el ejemplo en la carpeta 'ray_tracing_gltf', si eso es cierto, debes referenciar aquí esa carpeta en concreto (si te has basado principalmente en otro ejemplo, indica cual es la carpeta concreta)

(49) sección 4.3.1, página 91

Donde dices "La estructura final del proyecto", creo que lo correcto sería decir "La estructura final de las carpetas del repositorio con el código fuente del proyecto..."

(50) sección 4.5, página 95

La frase "son similares a los grafos de escena en rasterización" no es correcta, en realidad el grafo de escena constituye el modelo de escena tanto en rasterización como en ray-tracing. Lo que pasa es que la indexación espacial en ray-tracing se puede hacer tomando como base el propio grafo de escena, y en este caso no hay grafo de escena sino simplemente una secuencia (un array de objetos)

Donde dices "resulta más eficiente hacer la intersección", deberías indicar se trata de eficiencia en tiempo y explicar brevemente (un párrafo) a qué se debe esto (las cajas englobantes permiten evitar muchas intersecciones rayo-triángulo si el rayo no interseca un volumen que engloba a un conjunto de triángulos, explicarlo).

Sería conveniente citar el artículo de Kay & Kajiya, este:

Timothy L. Kay and James T. Kajiya. 1986. Ray tracing complex scenes. In Proceedings of the 13th annual conference on Computer graphics and interactive techniques (SIGGRAPH '86). Association for Computing Machinery, New York, NY, USA, 269–278. https://doi.org/10.1145/15922.15916

(51) sección 4.5.1, página 96

donde dices "almacenan la geometría de un objeto individual" debería aclarar que se entiende por un "objeto individual" en este contexto, supongo que se refiere a una malla de triángulos almacenada en la GPU usando un buffer de vértices y atributos, si es así hacerlo explícito (creo que es así por lo que leo aquí: https://nvpro-samples.github.io/vk_raytracing_tutorial_KHR/)

(52) sección 4.6.2, página 99

en la explicación de la figura 4.6, se debe indicar para que sirve el "intersection shader", ¿ es el código que se encarga de calcular intersecciones de un rayo con un triángulo ? ¿ o con un grupo de ellos ? (aclararlo). Como te comento a continuación, sería mejor explicar los distintos tipos de shaders (subsección 4.6.2) antes de hablar de la "shader binding table".

(53) sección 4.6.2, página 100

Aquí mencionas los tipos de shaders que todavía no has explicado, esto no es lógico, creo que sería mejor reorganizar para que, en primer lugar, introduzcas los tipos de shaders (sección 4.6.3) y luego hables de la "shader binding table". Esta relacionado con el punto (41), donde también se habla de que no se deben usar conceptos clave, como el de un shader, si no se han explicado antes.

¿ Qué es "Callable group record" ? (no lo explicas, si es un concepto importante, explícalo, en otro caso, si no es importante, quita eso).

No entiendo la frase "En particular, resulta problemático de los índices en los hit groups."

La figura 4.7 no está explicada y no se puede entender, creo que sería conveniente explicarla o bien quitarla, si los enlaces que indicas te parecen suficientes.

(54) sección 4.6.3, página 101

Donde dices "Idealmente, solo se invocan rayos desde aquí", no queda nada claro que cosa es "invocar un rayo".

Donde dices "cuando un rayo impacta con la geometría por primera vez", creo que te refieres a la intersección rayo-objeto más cercana al origen del rato ¿ es así ? (si es así aclararlo).

Creo que no es necesario la frase "pega con el infinito"

Donde hablas de los "callable shader", me da la sensación de que estos shader simplemente contienen funciones que se pueden invocar desde otros shaders ¿ es así ? (si es así, escribirlo explícitamente, más o menos es lo que dices, pero creo que debes mencionar que se trata de llamar a funciones).

(55) sección 4.6.4, página 101

Dices que son necesarios mecanismos para pasar información de un shader a otro, pero hablas entre otras cosas de las "push constants", que permiten pasar parámetros desde la aplicación en la CPU a los shaders en la GPU (no de un shader a otro).

(56) sección 4.7, páginas 103 y 104

no me queda claro cómo se asocian los parámetros a cada objeto del archivo wavefront, es decir, ¿ cada objeto tiene un conjunto de valores para K_a, K_d, K_s, etc.... ? o bien ¿ cada objeto tiene un entero 'illum' y luego hay un catálogo, el cual, para cada entero, se proporcionan los valors de 'K_a', 'K_d', 'K_s', etc....?

Otra cosa: en la tabla de la 103, no se en qué se diferencian el "cristal" de la "refracción" en la última columna (el cristal refracta la luz), y en la columna penúltima, tampoco entiendo la diferencia entre 'Ray traced' y 'Sí'.

En la página 104 aparece la última entrada y pone "sombras arrojadizas" donde debería poner "sombras arrojadas". De todas formas no entiendo muy bien esa entrada ¿que significa "sombras arrojadas" ahí en ese contexto ? (las entradas anteriores de la tabla describen tipos de materiales, pero "sobras arrojadas" no es un tipo de material...)

(57) sección 4.8, página 104

"fuentes de luces" debería ser "fuentes de luz"

(58) sección 4.8, páginas 104 y 105

Dices que se preparó el pipeline para fijar la etapa de los rayos de sombra, pero no se muy bien donde en el texto describes esto (me suena que no está, pero puedo equivocarme), si está ya descrito, incluye una referencia, si no está descrito antes, incluye una explicación de la frase o incluye un texto al respecto donde introduces el "pipeline" de ray-tracing.

(59) sección 4.9, páginas 107 y 108

En esta sección describes dos cosas independientes: por un lado el uso de supersampling antialiasing (SSAA) con jittering (promediar 'nb_samples' muestras por pixel por cada cuadro), y por otro el uso de acumulación temporal (promediar el valor calculado en cada pixel a lo largo de los ultimos cuadros desde que se paró la camara). La primera caja de código de la página 108 tiene, en las líneas 4 a 6, el SSAA, y en las líneas 10 a 22, la acumulación temporal.

El primer párrafo de la página 107 describe el "supersampling antialiasing mediante jittering", al final dices "A este proceso lo llamamos acumulación temporal", pero no es así, por un lado debes nombrar explicitamente lo de "supersampling antialiasing" (es necesario ya que hay otras formas de antialiasing, distintas de supersampling), y por otro lado te falta describir la "acumulación temporal".

Supongo que lo sabes, pero en cualquier caso la acumulación temporal consiste en promediar el color calculado para un pixel a lo largo de varios cuadros, en concreto desde que se paró la cámara, es decir, desde que el color objetivo o real del pixel no ha cambiado por permanecer la cámara en el mismo sitio. La gran ventaja es que de esta forma, cuando la cámara se para, la imagen va mejorando en calidad, ya que con cada nuevo cuadro se promedian más muestras por cada pixel, al tener en cuenta, para cada pixel, no solo las del cuadro actual, sino también las de los otros cuadros (en total usas 'nb_samples*nf', donde nf es el número de cuadro desde que la camara está quieta). Todo esto debe aparecer reflejado explícitamente en tu texto.

Viendo el código de la página 108, veo que cuando 'pcRay.cuadro' vale 0 (en la línea 7 de la caja de abajo), siempre se muestrea el punto central al pixel, es decir, las llamadas a 'sample_pixel' de la línea 5 (de la caja de arriba) van a devolver todas el mismo valor, luego en ese 1er cuadro se está haciendo trabajo repetido sin mejora de calidad. En realidad, siempre puedes usar los valores aleatorios r1 y r2, incluyendo el 1er cuadro.

(60) sección 4.10, páginas 108 a 111

En el 1er párrafo introduces el problema del rango dinámico (no acotado 'a priori', fuera de [0,1]) de los valores que produce el cálculo de iluminación, y luego dices que "esto lo arreglamos con la correción gamma", pero el problema de los valores fuera de rango (mayores que uno) no se soluciona con la correción gamma. Puedes ver esto que digo sin más que pensar que cualquier valor 'x' mayor estricto que uno, al elevarlo a una potencia positiva cualquiera, te va seguir dando un valor mayor que uno (y si es menor antes, también lo será después). Luego si un valor R,G o B es superior a la unidad y debe ser truncado, después de la correción gamma va a seguir siendo superior (o inferior) y debe ser truncado

En realidad estás hablando aquí dos dos cosas distintas: por un lado de como se soluciona el problema de los valores fuera de rango [0,1], y por otro lado de como se mapean los valores RGB al monitor (usando una función no lineal como la correción gamma). Para el primer problema usas simplemente un truncamiento, para el segundo usas la corrección gamma con exponente 1/2.2

En el código entre las páginas 110 y 111 parece que usas la corrección gamma antes de hacer la suma (el 'mix') de la acumulación temporal, creo que esto no es correcto, la corrección gamma se debe hacer al final, cuando ya has calculado el valor RGB del pixel. Obviamente la suma no conmuta con la exponenciación, por eso únicamente se puede hacer la corrección gamma como ultimo paso de cálculo de la imagen.

Yo creo que sería mejor aplicar la corrección gamma después de normalizar (dividir por el máximo valor), en lugar de después de truncar (creo que ya te he hablado de eso), el problema es que en este cuadro de Vulkan quizás calcular ese valor no sea sencillo (habría que mirar todos los pixels de la imagen en cada cuadro), aunque podría hacerse con un compute shader específico que haga ese cálculo (los compute shaders se pueden combinar en un programa de ray-tracing, aquí hay un ejemplo en el cual se usan para ray-tracing: https://nvpro-samples.github.io/vk_mini_path_tracer/#computeshaders/usingcomputeshadersforraytracing, aquí no haría falta usarlos para ray-tracing, simplemente sería para calcular el máximo de una imagen en paralelo). De todas forma entiendo que esto es complicado teniendo en cuenta el tiempo que queda para la entrega.

Por ultimo, sería conveniente usar la misma cámara y la misma escena en las figuras 4.8 y 4.9, ahora mismo las imágenes son diferentes, por ejemplo la esfera de la derecha aparece proyectada mucho más grande en la 4.8 que la 4.9, además los bordes de las sombras no van igual (no me refiero a diferencias de intensidad por diferencias en la corrección gamma, me refiero a que las sombras van por distintos sitios).

(61) sección 5 páginas 112 y siguientes

En esta sección aparecen imágenes (por ejemplo, la 5.1, 5.2, 5.27) las cuales parecen estar iluminadas con una luz de área rectangular del techo, como es habitual en esta escena en la literatura ¿ implica esto que el programa es capaz de hacer path-tracing con fuentes de área ? me ha parecido leer antes que no es así, esto se debe aclarar. Otro ejemplo es la imagen 5.25, en la cual hay una fuente puntual que produce sombras arrojadas, pero es que además la esfera especular proyecta una sombra de borde suave en el suelo que parece estar creada por la fuente de luz en el techo .... perdón, ya caigo: el programa gestiona fuentes de área (en la escena) y fuentes puntuales (o direccionales, en las push-constants), lo que pasa es para las fuentes de área no se hace muestro directo de las fuentes de luz y para las otras sí. Por tanto, en todas las escenas donde aparece la fuente rectangular del techo, se está teniendo en cuenta correctamente la luz de esa fuente, ya que en cada impacto sumas L_e ¿ no es así?. Quizás esto debe ser aclarado en la sección 4.8, página 104.

La verdad es que el muestreo directo de las fuentes de luz se puede extender muy fácilmente a una o unas pocas fuentes de luz de área, sin más que pasar los atributos de esas fuentes de luz como push constants, igual que haces con los otros tipos de fuentes. En ese caso, bastaría con no añadir L_e en los puntos de impacto (excepto los de los rayos primarios). De todas formas entiendo que es un poco tarde para esto.

(62) sección 5.3.1, página 128

Respecto a la dependencia del tiempo medio por cuadro 't' respecto del numero de muestras por pixel 'n', supongo que será de la forma t=an+b, para dos valores a y b que dependen de la escena. Se pueden calcular los valores de 'a' y 'b' para alguna escena, 'a' representa los costes fijos por cuadro y 'b' los costes por path. Si esto es así, la frase donde dices que el coste medio por cuadro es 2 milisegundos es incorrecta (divides t por n), ya que eso solo sería correcto si 'a' es 0 (o casi 0 comparado con 'b'), pero probablemente no lo sea ¿ o si ? (sería interesante medir 'a' y 'b' para alguna escena y aclarar esto)

(63) sección 5.3.1, página 131

El mismo análisis que he hecho en el punto anterior (59) se aplica a la dependencia del tiempo respecto de la profundidad o longitud de los caminos, cuando esta se elige de forma fija.

(64) General

Un cosa que veo en este texto, en general, es que usas palabras del inglés que tienen una traducción fácil y bien establecida a nuestro idioma, este ejemplo está tomado de la página 106 (al final) y 107 (al inicio), escribes:

"Al preparar la pipeline fijamos el stage de los shadow rays"

Pero en mi opinión, se debería escribir:

"Al preparar el cauce fijamos la etapa de los rayos de sombra"

esto se debe revisar en todo el texto y para muchas palabras. Algunas veces no te queda más remedio que usar una palabra en inglés de todas formas, en esos casos creo que queda mejor si las pones en cursiva para reflejar que es una palabra de otro idioma.

Asmilex commented 2 years ago

(21) 2.1.3 Ángulos sólidos, página 29

Para definir el ángulo sólido, es mucho más fácil no usar un esfera de radio arbitrario 'r', sino una de radio unidad, es lo más común en la literatura. Así, el ángulo sólido de un trozo de esfera de radio unidad es directamente su área. Además, lo usual en la literatura es usar \sigma para significar la medida de ángulo sólido, no 'w', me resulta raro. La frase "Debido a la forma en la que se trabaja con ellos, es costumbre usar 'w' como un vector dirección unitario en la esfera." me parece algo confusa, ya que en la literatura de iluminación global se suele usar 'w' para significar vectores unitarios, es cierto, pero eso no tiene nada que ver con el ángulo sólido, una cosa es la medida de ángulo sólido y otra un vector de longitud unidad. Por eso veo mejor usar otro símbolo para el ángulo sólido. Usar A puede ser confuso, ya se usa para la medida de área. El símbolo \Omega lo usas para subconjuntos de la esfera como dominio de alguna integral. Usar 'w' es confuso, como ya he dicho. Por todo esto, creo que sería bueno usar \sigma, esto es habitual en la literatura sobre iluminación global (Peter Shirley lo usa bastante). Además, para las integrales, el diferencial de ángulo sólido entorno a un vector 'w' se puede poner como d\sigma(w), en lugar de dw, eso hace explícito en la notación cual es la medida de que se está usando en la integral, junto con la variable de integración.

Creo que ya sé de dónde me viene este fallo. Para estudiar el tema utilicé el curso de Berkeley. En las diapositivas pasan de hablar de ángulo sólido a citar \omega como vector unitario, por lo que los confundí. En PBR Book nunca asientan la notación para los ángulos sólidos, por lo que me imaginé que sería \omega. Además, en algunas fuentes aparecen como \Omega.

Todas esos pequeños detalles se han combinado creando un buen fallo.

Oops.

Asmilex commented 2 years ago

Por cierto, en la bibliografía citas mis apuntes de RIG, así:

Carlos Ureña. 2021. “Realismo e iluminación global.” 2021. https://lsi2.ugr.es/curena/.

Deberías poner:

Carlos Ureña. 2021. “Apuntes del curso: Realismo e Iluminación Global (Máster en Desarrollo de Software de la Univ. de Granada)” 2021.

me doy cuenta ahora mismo que has ordenado alfabéticamente las citas usando el nombre de pila del 1er autor en muchos casos (como este), esto no es para nada lo usual, debes usar ordenación por el 1er apellido, no el nombre de pila.

Esto se debía a cómo escribía el campo del autor en la bibliografía. En vez de poner

author = {{Carlos Ureña}}

se debería poner

author = {Carlos Ureña}

y en principio se soluciona.

Asmilex commented 2 years ago

(39), sección 4, página 82

Donde dices "La implementación estará basada en Vulkan, junto a ...." habría que incluir una referencia al repositorio y carpeta concreta que has usado como base. El repositorio se llama 'nvpro-samples', pero además la carpeta concreta con el ejemplo se llama 'ray_tracing_gltf', si no me equivoco, es esta URL la que se debe incluir:

https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing_gltf

(en la sección 4.1 tienes una cita a "Nvidia 2022a", pero eso tiene la URL del repositorio completo, creo que sería bueno señalar este ejemplo concreto).

El trabajo en conjunto es una colección de varios tutoriales del repositorio. Es difícil señalar alguno en particular. En conjunto, se han usado

Asmilex commented 2 years ago

(42) secc. 4.1.1, página 83 En la fórmula 4.1, inmediatamente después), habría que aclarar o recordar al lector que cosa es la función 'p' del denominador (es la pdf correspondiente a la selección aleatoria de una dirección de salida 'w_j') y que cosa es L_i. Ahora que lo veo, en estas fórmulas estás usando 'p' para dos cosas y puede ser confuso, quizás el punto 'p' podría renombrarse como 'x', es lo usual, y dejar la pdf como 'p'.

Como llevamos utilizando todo el trabajo $p$ para los puntos, he decidido utilizar $P[\omega]$ para indicar que es una PDF.

Asmilex commented 2 years ago

(44) secc. 4.1.2, página 84

El listado de la página 84 parece más código concreto en algún lenguaje de programación, que pseudo-código, el pseudo-código suele escribirse en estos textos usando el package latex 'algoritmic' o 'algoritmicx', y no debe hacer mención a funciones o tipos de datos que no aparecen explicados en el código o en el texto. En tu caso usas 'hit_info', 'siguiente_direccion' y cosas así. Además, no queda claro en que contexto se ejecuta la función 'pathtrace', que cosa devuelve, etc...Creo que puedes usar directamente o basarte en el pseudo-código de un path-tracer básico que aparece en las transparencia 35 y 36 del archivo 'rig-t3b-monte-carlo-1.pdf' que te envié por mail el pasado 5 de mayo, es un pseudo-código de un path-tracer básico que no hace muestreo directo de fuentes de luz. En este punto se trata simplemente darle al lector una idea de la estructura del algoritmo de path-tracing, sin que todavía hayas introducido nada sobre shaders en ray-tracing (hit, miss shader, etc...).

He añadido el paquete algorithm2e para el PDF. En la web he tenido que dejar el bloque de código debido a limitaciones de Pandoc/mathjax, pero aún así el resultado es similar.

image

Asmilex commented 2 years ago

(54) sección 4.6.3, página 101

Donde hablas de los "callable shader", me da la sensación de que estos shader simplemente contienen funciones que se pueden invocar desde otros shaders ¿ es así ? (si es así, escribirlo explícitamente, más o menos es lo que dices, pero creo que debes mencionar que se trata de llamar a funciones).

Funcionan de forma similar a los punteros a funciones, pero siguen siendo un shader. En esencia son shaders que funcionan como subrutinas, que se invocan desde otros shaders. Creo que no merece más la pena añadir información sobre ellos, así que lo dejaré tal y como está.

Asmilex commented 2 years ago

(56) sección 4.7, páginas 103 y 104

Otra cosa: en la tabla de la 103, no se en qué se diferencian el "cristal" de la "refracción" en la última columna (el cristal refracta la luz), y en la columna penúltima, tampoco entiendo la diferencia entre 'Ray traced' y 'Sí'.

Yo tampoco, pero así aparece en las especificaciones. He buscado y rebuscado, pero no encuentro nada más específico que lo del enlace.

Asmilex commented 2 years ago

(60) sección 4.10, páginas 108 a 111

En el código entre las páginas 110 y 111 parece que usas la corrección gamma antes de hacer la suma (el 'mix') de la acumulación temporal, creo que esto no es correcto, la corrección gamma se debe hacer al final, cuando ya has calculado el valor RGB del pixel. Obviamente la suma no conmuta con la exponenciación, por eso únicamente se puede hacer la corrección gamma como ultimo paso de cálculo de la imagen.

Yo creo que sería mejor aplicar la corrección gamma después de normalizar (dividir por el máximo valor), en lugar de después de truncar (creo que ya te he hablado de eso), el problema es que en este cuadro de Vulkan quizás calcular ese valor no sea sencillo (habría que mirar todos los pixels de la imagen en cada cuadro), aunque podría hacerse con un compute shader específico que haga ese cálculo (los compute shaders se pueden combinar en un programa de ray-tracing, aquí hay un ejemplo en el cual se usan para ray-tracing: https://nvpro-samples.github.io/vk_mini_path_tracer/#computeshaders/usingcomputeshadersforraytracing, aquí no haría falta usarlos para ray-tracing, simplemente sería para calcular el máximo de una imagen en paralelo). De todas forma entiendo que esto es complicado teniendo en cuenta el tiempo que queda para la entrega.

En efecto, eso sería lo más correcto. Como dices esto no es fácil, por eso opté por la implementación actual. Aunque no es la más correcta, me parece que genera un resultado lo suficientemente bueno.

Asmilex commented 2 years ago

(61) sección 5 páginas 112 y siguientes

En esta sección aparecen imágenes (por ejemplo, la 5.1, 5.2, 5.27) las cuales parecen estar iluminadas con una luz de área rectangular del techo, como es habitual en esta escena en la literatura ¿ implica esto que el programa es capaz de hacer path-tracing con fuentes de área ? me ha parecido leer antes que no es así, esto se debe aclarar. Otro ejemplo es la imagen 5.25, en la cual hay una fuente puntual que produce sombras arrojadas, pero es que además la esfera especular proyecta una sombra de borde suave en el suelo que parece estar creada por la fuente de luz en el techo .... perdón, ya caigo: el programa gestiona fuentes de área (en la escena) y fuentes puntuales (o direccionales, en las push-constants), lo que pasa es para las fuentes de área no se hace muestro directo de las fuentes de luz y para las otras sí. Por tanto, en todas las escenas donde aparece la fuente rectangular del techo, se está teniendo en cuenta correctamente la luz de esa fuente, ya que en cada impacto sumas L_e ¿ no es así?. Quizás esto debe ser aclarado en la sección 4.8, página 104.

La verdad es que el muestreo directo de las fuentes de luz se puede extender muy fácilmente a una o unas pocas fuentes de luz de área, sin más que pasar los atributos de esas fuentes de luz como push constants, igual que haces con los otros tipos de fuentes. En ese caso, bastaría con no añadir L_e en los puntos de impacto (excepto los de los rayos primarios). De todas formas entiendo que es un poco tarde para esto.

Básicamente el problema es ese. El programa no conoce los objetos con propiedades emisivas de la escena, por lo que no puede muestrearlos explícitamente. Es el punto central de la conclusión (problemas de la interfaz de luces + carga de los objetos en la escena). Cambiarlo llevaría mucho esfuerzo y a estas alturas es prácticamente imposible.

He decidido estructurar la comparativa entorno a este problema. Me parece muy interesante hacerlo de esta manera. Por una parte, existe el muestreo directo de fuentes de iluminación (está un poco cojo, pero existe). Y por otra, la implementación es primitiva. Esto hace que con pocas muestras el resultado sea malo, porque deshabilito las fuentes de iluminación externas a la escena. Esto hace que la comparativa con In One Weekend se vuelva más curiosa, porque el número de muestras afecta muchísimo más.

No quiero tampoco engañar a nadie, esto es un problema. Y en secciones posteriores hablo de ello. Además, lo introduje en el resumen en inglés:

The images it produces are very noisy and need a considerable amount of samples to become sharp. This is mainly due to the weak light interface that has been implemented, since it doesn’t take into account emissive materials found in the scene. Nevertheless, the combination of how fast it can render a frame and the ability to mix multiple accumulated frames over time manages to overcome this issue.

Voy a explicitarlo en la sección 4.8 como me comentas, porque lo veo muy relevante.

Asmilex commented 2 years ago

(64) General

Un cosa que veo en este texto, en general, es que usas palabras del inglés que tienen una traducción fácil y bien establecida a nuestro idioma, este ejemplo está tomado de la página 106 (al final) y 107 (al inicio), escribes:

"Al preparar la pipeline fijamos el stage de los shadow rays"

Pero en mi opinión, se debería escribir:

"Al preparar el cauce fijamos la etapa de los rayos de sombra"

esto se debe revisar en todo el texto y para muchas palabras. Algunas veces no te queda más remedio que usar una palabra en inglés de todas formas, en esos casos creo que queda mejor si las pones en cursiva para reflejar que es una palabra de otro idioma.~

Sí, es algo que me pasa habitualmente. Estoy tan acostumbrado a leer literatura en inglés, que cuando traduzco esas palabras al español me suenan fatal. Creo que es algo común en la gente de mi generación.

Voy a intentar poner en cursiva todas las palabras inglesas que me encuentre y traducir las que queden bien.