Web Analytics

sqlraytracer

⭐ 282 stars French by chunky

Un traceur de rayons en pur SQL

Tout le monde écrit un traceur de rayons tôt ou tard. Voici le mien.

Exemples de résultats

Utilisation

sh create.sh

``postgres_connection.sh` contient l’hôte/base de données/utilisateur/mot de passe/etc. Il n’y a pas de besoins exotiques autres que « postgres, comme la version 10 et plus ou quelque chose du genre »

Pour ce que ça vaut, j’ai créé le mien ainsi sur mon bureau Ubuntu :

sudo su - postgres
createuser --pwprompt raytracer
createdb -O raytracer raytracer

Leviers pour le développement et le rendu

Lors du développement, évidemment un temps de rendu de quelques minutes est un temps de cycle assez long. Il y a plusieurs leviers que vous pouvez actionner pour accélérer les choses et réduire la qualité. Ils se trouvent sur "camera" et "img" dans setup.sql :

samples\_per\_px* - C'est le nombre de rayons/sous-échantillons par pixel.

max\_ray\_depth* - Le nombre maximal de rebonds de rayons
  • Pour les scènes simples, cela ne dépasse généralement pas 5 rebonds environ
res\_x et res\_y* - Résolution finale de l'image
  • Plus petit est plus rapide
Le CTE principal contient beaucoup d'éléments inutiles pour la sortie finale. C'est pour que je puisse examiner les rayons rebondissant dans la scène avec :
SELECT * FROM rays WHERE img_x=100 AND img_y=250

Il existe un script pour obtenir une vue rapide et approximative d'une scène avec gnuplot ; le script `show_scene.sh` doit générer un dossier de sorties.

Base de données

Ceci est implémenté en SQL pur. Il ne fait rien comme CREATE FUNCTION ou autres éléments non portables, sauf pour le trigger pour faire de l'animation, ce qui évidemment ne compte pas.

En même temps, il y a quelques fonctionnalités SQL pas tout à fait courantes dont il a besoin :

Donc bien que j'aie commencé à développer cela dans SQLite, j'ai fini par m'appuyer sur PostgreSQL. Au moment où j'écris ceci, ça fonctionne sous postgres et n'a pas été testé ailleurs.

Éléments d'implémentation intéressants

Telle qu'elle est, je me suis retrouvé à résoudre certains problèmes de façon intéressante.

JOIN LATERAL

JOIN LATERAL est une façon de faire une sous-requête corrélée dans un JOIN, au lieu de juste dans une clause WHERE. Je l'utilise comme moyen de remonter des calculs et d'en faire beaucoup une seule fois et, dans certains cas, d'éviter une duplication excessive.

Diffusion diffuse

Cela nécessite d'échantillonner une sphère uniforme. Je génère beaucoup d'échantillons aléatoires à l'avance [échantillonnage avec rejet -> mise à l'échelle des points sur la surface de la sphère], et je les numérote.

Trouver une façon de joindre chaque rayon à une seule ligne aléatoire parmi ces diffusions précalculées était étrange ; on ne peut pas simplement joindre à RANDOM() parce que chaque rayon serait joint à la même diffusion aléatoire. On ne peut pas non plus sélectionner avec un calcul typique sur une normale car cela mène à des bandes dans l'image. Donc, à la place, je sors quelques décimales tardives d'une dimension d'une normale, puis je rejoins dessus. C'est « aléatoire » mais aussi suffisamment unique par rayon.

CTE récursifs

Le lancer de rayons suit très naturellement le fonctionnement des CTE récursifs. Une des choses que j'ai rencontrées était une façon propre d'identifier quel rayon est celui à prendre en compte. L'utilisation d'une fonction fenêtrée ordonnant par l'interception (t) a bien marché. À chaque itération, cette requête intersecte un rayon avec tout ce qui est devant lui et effectue tous les calculs associés, mais ensuite dans la clause WHERE rejette tout sauf la chose que le rayon a réellement touchée.

Aussi, il y a quelque chose de vraiment beau dans la simplicité du cœur du rollup final [édité pour la clarté] :


 SELECT img_x, img_y,
         SUM(POW(color_mult * ray_col_r/samples_per_px, gamma)) col_r,
         SUM(POW(color_mult * ray_col_g/samples_per_px, gamma)) col_g,
         SUM(POW(color_mult * ray_col_b/samples_per_px, gamma)) col_b
    FROM rays
    GROUP BY img_y, img_x

Scènes, matériaux, etc.

Parce que c'est en SQL, je peux stocker plusieurs scènes dans la base de données. Celle qui est réellement rendue est sélectionnée dans la table "camera".

Se tenir sur les épaules des géants

Deux ans avant que j'écrive ceci, "Le traceur de rayons MySQL le plus avancé du marché actuellement" a circulé sur les réseaux sociaux : https://www.pouet.net/prod.php?which=83222

J'avais quelques idées en tête que je voulais faire différemment [pire ?] :

J'ai demandé l'avis de Claude

"Pourquoi quelqu'un écrirait-il quelque chose comme ça en premier lieu ?"

C'est un exemple fascinant de SQL en tant que langage de programmation général poussé à l'extrême. Quelqu'un a écrit un traceur de rayons complet en SQL PostgreSQL, ce qui est à la fois impressionnant et... discutable.
[...]
Cela ressemble soit à un brillant projet de thèse d'un étudiant en informatique, à l'expérience d'un ingénieur senior pendant un week-end, ou à quelqu'un piégé dans un environnement strictement limité aux bases de données qui a refusé d'abandonner ses rêves de lancer de rayons.
C'est l'équivalent en programmation de construire une voiture de course en Lego - techniquement impressionnant, mais vous ne devriez probablement pas vraiment la conduire.

Je ne sais pas si je suis flatté ou offensé.

Références

La plupart de ceci est construit en suivant la série "Ray Tracing in One Weekend" : https://raytracing.github.io/ , puis en tenant compte de la manière délibérément obtuse dont je le code.

Gary

``

--- Tranlated By Open Ai Tx | Last indexed: 2026-03-25 ---