Ray-trace une sphère brillante

15

J'ai téléchargé POV-ray et rendu ce style de sphère en métal brillant des années 90:

entrez la description de l'image ici

Votre tâche est de faire la même chose, mais de le faire en implémentant vous-même le moteur de rendu en aussi peu d'octets que possible. Vous n'avez pas à reproduire cette image exacte - n'importe quelle image d'une sphère réfléchissante au-dessus d'un damier infini fera l'affaire, tant qu'elle répond aux critères ci-dessous.

Règles:

  • L'image doit représenter une sphère réfléchissante planant au-dessus d'un damier infini. Le damier lui-même et son reflet dans la sphère doivent être représentés sur l'image. Il doit être clair visuellement que c'est ce que nous voyons. Au-delà de cela, les détails de la géométrie, des couleurs, des propriétés des matériaux, etc. sont à vous.

  • Il doit y avoir un certain éclairage dans la scène: les parties de la sphère doivent être plus sombres que les autres parties, et visuellement il devrait être possible de dire approximativement d'où vient la lumière. Au-delà de cela, les détails du modèle d'éclairage sont à vous. (Vous pouvez inventer votre propre modèle d'éclairage simplifié si vous le souhaitez.) La sphère n'a pas à projeter d'ombre.

  • Les deux critères ci-dessus - s'il ressemble vraiment à une sphère brillante au-dessus d'un damier éclairé par une source lumineuse - seront jugés par la communauté à l'aide du vote. Par conséquent, une réponse doit avoir un score positif pour être éligible à gagner.

  • La sortie doit être d'au moins 300x300 pixels. Il peut être affiché à l'écran ou écrit dans un fichier, c'est bien.

  • Votre code devrait fonctionner en moins d'une heure sur un ordinateur moderne raisonnable. (C'est généreux - POV-ray rend la scène ci-dessus presque instantanément.)

  • Aucune fonctionnalité de lancer de rayons intégrée ne peut être utilisée - vous devez implémenter le rendu vous-même.

  • Il s'agit de , donc l'entrée à score positif avec le code le plus court (en octets) l'emporte. Cependant, vous êtes également invité à jouer au méta-jeu pour obtenir le plus de votes en dessinant une jolie image (tout en gardant le code court bien sûr).

Ce défi peut sembler ridiculement difficile, mais comme la géométrie est fixe, l'algorithme de rendu d'une telle scène par lancer de rayons est assez simple. Il s'agit simplement d'itérer sur chaque pixel de l'image de sortie et d'évaluer une expression mathématique pour voir de quelle couleur elle devrait être, alors je suis optimiste que nous verrons de bonnes réponses.

Nathaniel
la source
Personnellement, je n'aime pas les besoins d'éclairage. Je pense que cela ajoute beaucoup de complexité supplémentaire, pour très peu de gain. Mais à mon avis.
stokastic
Vous dites que les couleurs nous appartiennent. Cela inclut-il des images en niveaux de gris?
Martin Ender
@ MartinBüttner oui, les images en niveaux de gris sont très bien.
Nathaniel
@stokastic, j'espère que ce sera une source de créativité, car les gens proposeront des modèles d'éclairage radicalement simplifiés mais à peu près convaincants qui peuvent être spécifiés dans une petite quantité de code. J'ai ajouté une note dans la question que les modèles d'éclairage simplifiés sont OK.
Nathaniel
Cela a déjà été fait: fabiensanglard.net/rayTracing_back_of_business_card/index.php Bien sûr, cela peut être un peu plus court en le réduisant à une sphère, en supprimant l'anticrénelage, etc.
Shujal

Réponses:

28

Python 2, 484 468 467 octets

entrez la description de l'image ici

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)))

Remarque: après if I>0:une nouvelle ligne suivie d'un caractère de tabulation unique avant t=...

L'exécution du programme créera une image 800x600 nommée s.pgm

Commencé à partir d'une "vraie" formule de ray tracer (peaufinée un peu pour le golf).

Le rendu prend environ 3 secondes sur mon vieux PC mort (0,7 seconde avec du gypse).

6502
la source
4
Belle image!
Nathaniel
Vous pouvez enregistrer quelques octets sans faire l'astuce zlib en remplaçant 0000par e4partout.
Nathaniel
@Nathaniel: Doh ... très grosse erreur pour un code golf :-) Correction. J'ai également supprimé l'astuce d'emballage zlib parce que je dois enquêter sur sa légalité (la dernière version par exemple lorsque zippé fonctionne avec python standard mais ne fonctionne pas avec pypy, et c'est très étrange).
6502
Une autre astuce de golf de code, vous pouvez remplacer a if b else cpar (c,a)[b]tant que vous ne comptez pas sur les courts-circuits pour éviter, par exemple, la division par zéro erreur. En outre , if A:code;return B\nelse:return Cvous pouvez remplacer par code;return(C,B)[A].
Claudiu
@Claudiu: Merci pour la suggestion. J'ai dû changer un peu les paramètres pour éviter une division par zéro. J'ai également utilisé une seule boucle sur l'image et cela a permis d'économiser beaucoup.
6502