Ray-trace una esfera brillante

15

Descargué POV-ray y rendericé este brillante estilo de esfera de metal de los años 90:

ingrese la descripción de la imagen aquí

Su tarea es hacer lo mismo, pero hacerlo implementando el motor de representación usted mismo en la menor cantidad de bytes posible. No tiene que replicar esta imagen exacta; cualquier imagen de una esfera reflectante sobre un tablero de ajedrez infinito funcionará, siempre que cumpla con los criterios a continuación.

Reglas:

  • La imagen debe representar una esfera reflectante que se cierne sobre un tablero de ajedrez infinito. Tanto el tablero de ajedrez como su reflejo en la esfera deben mostrarse en la imagen. Debe quedar claro visualmente que esto es lo que estamos viendo. Más allá de esto, los detalles de la geometría, los colores, las propiedades del material, etc., dependen de usted.

  • Debe haber algo de iluminación en la escena: las partes de la esfera deberían ser más oscuras que otras, y visualmente debería ser posible decir aproximadamente de dónde proviene la luz. Más allá de eso, los detalles del modelo de iluminación dependen de usted. (Puede inventar su propio modelo de iluminación simplificado si lo desea). La esfera no tiene que proyectar una sombra.

  • Los dos criterios anteriores, si realmente se ve como una esfera brillante sobre un tablero de ajedrez iluminado por una fuente de luz, serán juzgados por la comunidad mediante la votación. Por lo tanto, una respuesta debe tener una puntuación positiva para poder ganar.

  • La salida debe ser de al menos 300x300 píxeles. Puede mostrarse en la pantalla o escribirse en un archivo, o está bien.

  • Su código debería ejecutarse en menos de una hora en una computadora moderna razonable. (Esto es generoso: POV-ray hace que la escena anterior sea prácticamente instantánea).

  • No se puede utilizar la funcionalidad de trazado de rayos incorporada; debe implementar el renderizador usted mismo.

  • Este es el , por lo que gana la entrada de puntuación positiva con el código más corto (en bytes). Sin embargo, también puedes jugar al metajuego de obtener la mayor cantidad de votos dibujando una imagen bonita (manteniendo el código corto, por supuesto).

Este desafío puede parecer ridículamente difícil, pero dado que la geometría es fija, el algoritmo para renderizar tal escena mediante el trazado de rayos es bastante sencillo. Realmente es solo un caso de iterar sobre cada píxel en la imagen de salida y evaluar una expresión matemática para ver de qué color debería ser, así que soy optimista de que veremos algunas buenas respuestas.

Nathaniel
fuente
Personalmente no me gusta el requisito de iluminación. Creo que agrega mucha complejidad adicional, con muy poca ganancia. Solo mi opinión, sin embargo.
stokastic
Dices que los colores dependen de nosotros. ¿Eso incluye imágenes en escala de grises?
Martin Ender
@ MartinBüttner sí, las imágenes en escala de grises están bien.
Nathaniel
@stokastic, espero que sea una fuente de creatividad, ya que la gente presenta modelos de iluminación radicalmente simplificados pero convincentes que se pueden especificar en una pequeña cantidad de código. He agregado una nota en la pregunta de que los modelos de iluminación simplificados están bien.
Nathaniel
Ya se ha hecho: fabiensanglard.net/rayTracing_back_of_business_card/index.php Por supuesto, esto se puede acortar un poco reduciéndolo a una esfera, eliminando el antialiasing, etc.
Shujal

Respuestas:

28

Python 2, 484 468 467 bytes

ingrese la descripción de la imagen aquí

i=int;u=249.3
def Q(A,B):
 a=A*A+B*B+9e4;b=B*u+36e4;I=b*b-a*128e4
 if I>0:
    t=(-b+I**.5)/(5e2*a);F,G,H=A*t,B*t,u*t;J,K,M=F,G+.6,H+2.4;L=a**-.5;k=2*(A*J+B*K+u*M)*L;C,D,E=A*L-k*J,B*L-k*K,u*L-k*M;L=(C*C+D*D+E*E)**-.5;t=(-4e2-G)/D;return(D*D*L*L*u,((i(F+t*C)/200+i(H+t*E)/200)&1)*(u*D*L))[D>0]
 else:return(u*B*B/a,((i(-2e2/B*A)/200+i(-6e4/B)/100)&1)*u*B/a**.5)[B>0]
open("s.pgm","wb").write("P5 800 600 255 "+"".join(chr(i(Q(j%800-4e2,j/800-u)))for j in range(480000)))

Nota: después de que if I>0:haya una nueva línea seguida de un carácter de pestaña única antes t=...

La ejecución del programa creará una imagen de 800x600 llamada s.pgm

Comenzó con fórmulas de trazado de rayos "reales" (modificadas un poco para jugar al golf).

El renderizado toma alrededor de 3 segundos en mi vieja PC muerta (0.7 segundos con pypy).

6502
fuente
44
¡Hermosa imagen!
Nathaniel
Puede guardar unos pocos bytes sin hacer el truco zlib reemplazándolo 0000con e4todo.
Nathaniel
@Nathaniel: Doh ... gran error para un código de golf :-) Corregido. También eliminé el truco de empaquetado de zlib porque tengo que investigar su legalidad (la última versión, por ejemplo, cuando está comprimido funciona con python estándar pero no con pypy, y eso es muy extraño).
6502
Otro truco código de golf, usted puede reemplazar a if b else ccon (c,a)[b]siempre que no se basan en cortocircuito para evitar por ejemplo, la división por cero errores. También if A:code;return B\nelse:return Cpuedes reemplazar con code;return(C,B)[A].
Claudiu
@Claudiu: Gracias por la sugerencia. Tuve que cambiar un poco los parámetros para evitar una división por cero. También usé un solo bucle sobre la imagen y eso ahorró mucho.
6502