16
\$\begingroup\$

I downloaded POV-ray and rendered this shiny metal sphere 90s style:

enter image description here

Your task is to do the same thing, but to do it by implementing the rendering engine yourself in as few bytes as possible. You don't have to replicate this exact image - any image of a reflective sphere above an infinite checkerboard will do, as long as it meets the criteria below.

Rules:

  • The image must depict a reflective sphere hovering above an infinite checkerboard. Both the checkerboard itself and its reflection in the sphere must be shown in the image. It must be visually clear that this is what we're seeing. Beyond this, the details of the geometry, colours, material properties etc. are up to you.

  • There must be some lighting in the scene: parts of the sphere should be darker than other parts, and visually it should be possible to tell roughly where the light is coming from. Beyond that, the details of the lighting model are up to you. (You can invent your own simplified lighting model if you like.) The sphere doesn't have to cast a shadow.

  • The above two criteria - whether it really looks like a shiny sphere above a checkerboard illuminated by a light source - will be judged by the community using voting. Therefore, an answer must have a positive score in order to be eligible to win.

  • The output must be at least 300x300 pixels. It can be displayed on the screen or written to a file, either is fine.

  • Your code should run in less than an hour on a reasonable modern computer. (This is generous - POV-ray renders the above scene practically instantaneously.)

  • No built-in ray tracing functionality may be used - you must implement the renderer yourself.

  • This is , so the positive-scoring entry with the shortest code (in bytes) wins. However, you're also welcome to play the meta-game of getting the most votes by drawing a pretty picture (while keeping the code short of course).

This challenge might seem ridiculously hard, but since the geometry is fixed, the algorithm for rendering such a scene by ray tracing is pretty straightforward. It's really just a case of iterating over each pixel in the output image and evaluating a mathematical expression to see what colour it should be, so I'm optimistic that we'll see some good answers.

\$\endgroup\$
8
  • \$\begingroup\$ I personally dislike the lighting requirement. I think it adds a lot of extra complexity, for very little gain. Just my opinion, though. \$\endgroup\$
    – stokastic
    Commented Oct 8, 2014 at 13:16
  • \$\begingroup\$ You say colours are up to us. Does that include greyscale images? \$\endgroup\$ Commented Oct 8, 2014 at 13:17
  • \$\begingroup\$ @MartinBüttner yes, greyscale images are fine. \$\endgroup\$
    – N. Virgo
    Commented Oct 8, 2014 at 13:26
  • \$\begingroup\$ @stokastic my hope is that it will be a source of creativity, as people come up with radically simplified but just about convincing lighting models that can be specified in a small amount of code. I've added a note in the question that simplified lighting models are OK. \$\endgroup\$
    – N. Virgo
    Commented Oct 8, 2014 at 13:30
  • \$\begingroup\$ It has already been done: fabiensanglard.net/rayTracing_back_of_business_card/index.php Of course this can be made a bit shorter by reducing it to one sphere, removing antialiasing etc. \$\endgroup\$
    – Shujal
    Commented Oct 8, 2014 at 19:26

1 Answer 1

29
\$\begingroup\$

Python 2, 484 468 467 bytes

enter image description here

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

Note: after if I>0: there is a newline followed by a single tab char before t=...

Running the program will create an 800x600 image named s.pgm

Started from a "real" ray tracer formulas (tweaked a bit for golfing).

Rendering takes about 3s on my dead old PC (0.7s with pypy).

\$\endgroup\$
7
  • 5
    \$\begingroup\$ Beautiful image! \$\endgroup\$
    – N. Virgo
    Commented Oct 12, 2014 at 14:03
  • \$\begingroup\$ You can save a few bytes without doing the zlib trick by replacing 0000 with e4 throughout. \$\endgroup\$
    – N. Virgo
    Commented Oct 13, 2014 at 1:18
  • \$\begingroup\$ @Nathaniel:Doh... very big mistake for a code golf :-) Fixed. I've also removed the zlib packing trick because I've to investigate on its legality (the latest version for example when zipped works with standard python but doesn't work with pypy, and that's very strange). \$\endgroup\$
    – 6502
    Commented Oct 13, 2014 at 12:53
  • \$\begingroup\$ Another code golf trick, you can replace a if b else c with (c,a)[b] so long as you don't rely on short-circuiting to avoid e.g. division by zero errors. Also if A:code;return B\nelse:return C you can replace with code;return(C,B)[A]. \$\endgroup\$
    – Claudiu
    Commented Oct 13, 2014 at 17:11
  • \$\begingroup\$ @Claudiu: Thanks for the suggestion. I had to change the parameters a bit to avoid a division by zero. I also used a single loop over the image and that saved a lot. \$\endgroup\$
    – 6502
    Commented Oct 13, 2014 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.