Ray-trace uma esfera brilhante

15

Eu baixei o POV-ray e renderizei esse estilo brilhante da esfera de metal dos anos 90:

insira a descrição da imagem aqui

Sua tarefa é fazer a mesma coisa, mas implementando o mecanismo de renderização no menor número de bytes possível. Você não precisa replicar esta imagem exata - qualquer imagem de uma esfera reflexiva acima de um tabuleiro de damas infinito funcionará, desde que atenda aos critérios abaixo.

Regras:

  • A imagem deve representar uma esfera reflexiva pairando acima de um tabuleiro de damas infinito. O tabuleiro de damas em si e seu reflexo na esfera devem ser mostrados na imagem. Deve ficar claro visualmente que é isso que estamos vendo. Além disso, os detalhes da geometria, cores, propriedades do material etc. são com você.

  • Deve haver alguma iluminação na cena: partes da esfera devem ser mais escuras do que outras, e visualmente deve ser possível dizer aproximadamente de onde a luz está vindo. Além disso, os detalhes do modelo de iluminação são com você. (Você pode inventar seu próprio modelo de iluminação simplificado, se quiser.) A esfera não precisa projetar uma sombra.

  • Os dois critérios acima - se realmente se parece com uma esfera brilhante acima de um tabuleiro de xadrez iluminado por uma fonte de luz - serão julgados pela comunidade por meio de votação. Portanto, uma resposta deve ter uma pontuação positiva para ser elegível para ganhar.

  • A saída deve ter pelo menos 300 x 300 pixels. Pode ser exibido na tela ou gravado em um arquivo, ou está bom.

  • Seu código deve ser executado em menos de uma hora em um computador moderno razoável. (Isso é generoso - o raio POV renderiza a cena acima praticamente instantaneamente.)

  • Nenhuma funcionalidade integrada de rastreamento de raios pode ser usada - você deve implementar o renderizador por conta própria.

  • Isso é , então a entrada de pontuação positiva com o código mais curto (em bytes) vence. No entanto, você também pode jogar o meta-jogo de obter mais votos desenhando uma figura bonita (mantendo o código curto, é claro).

Esse desafio pode parecer ridiculamente difícil, mas, como a geometria é fixa, o algoritmo para renderizar essa cena pelo traçado de raios é bastante direto. É realmente apenas um caso de iteração sobre cada pixel na imagem de saída e avaliação de uma expressão matemática para ver qual deve ser a cor, por isso estou otimista de que veremos boas respostas.

Nathaniel
fonte
Pessoalmente, não gosto do requisito de iluminação. Eu acho que acrescenta muita complexidade extra, para pouquíssimos ganhos. Apenas minha opinião, no entanto.
stokastic
Você diz que as cores são nossas. Isso inclui imagens em escala de cinza?
Martin Ender
@ MartinBüttner sim, imagens em escala de cinza são boas.
Nathaniel
@stokastic minha esperança é que seja uma fonte de criatividade, pois as pessoas criam modelos de iluminação radicalmente simplificados, mas quase convincentes, que podem ser especificados em uma pequena quantidade de código. Eu adicionei uma observação na pergunta de que modelos de iluminação simplificados são bons.
Nathaniel
Ele já foi feito: fabiensanglard.net/rayTracing_back_of_business_card/index.php Claro que isso pode ser feito um pouco mais curto, reduzindo-o a uma esfera, removendo antialiasing etc.
Shujal

Respostas:

28

Python 2, 484 468 467 bytes

insira a descrição da imagem aqui

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: depois que if I>0:houver uma nova linha seguida por uma única guia antes de t=...

A execução do programa criará uma imagem de 800x600 chamada s.pgm

Começou a partir de uma fórmula "real" de traçador de raios (ajustada um pouco para jogar golfe).

A renderização demora cerca de 3s no meu PC antigo (0,7s com pypy).

6502
fonte
4
Imagem bonita!
Nathaniel #
Você pode salvar alguns bytes sem executar o truque zlib, substituindo-o 0000por e4todo.
Nathaniel #
@ Nathaniel: Doh ... erro muito grande para um código de golfe :-) Corrigido. Também removi o truque de empacotamento do zlib porque tenho que investigar sua legalidade (a versão mais recente, por exemplo, quando compactado funciona com python padrão, mas não funciona com pypy, e isso é muito estranho).
6502
Outro truque de golfe código, você pode substituir a if b else ccom (c,a)[b]contanto que você não confiar em curto-circuito para evitar por exemplo, divisão por zero erros. Também if A:code;return B\nelse:return Cvocê pode substituir com code;return(C,B)[A].
Claudiu 13/10
@ Claudiu: Obrigado pela sugestão. Eu tive que mudar um pouco os parâmetros para evitar uma divisão por zero. Eu também usei um único loop sobre a imagem e isso economizou muito.
6502