IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Raytracer minimaliste en Haskell : Affichage d'une sphère


précédentsommairesuivant

I. Introduction

Cet article est le premier d'une série consacré à la réalisation d'un raytracer en haskell. Il s'agit d'un tutoriel pas à pas suivant la construction d'une application, où chacune des fonctionnalités est d'abord commentée puis implémentée. Certains points relatifs au langage seront commentés pour plus de clarté, notamment les fonctions les plus complexes. Une archive contenant l'ensemble du code produit au long de l'article, prêt à compiler, vous est fournie ici.

Ce code compile avec GHC 7.6.3. Si vous avez des difficultés pour compiler le code avec une version antérieur, il est possible que votre version d'Haskell requière le module Control.Monad.Instances.

II. Génération d'une image

II-0. Avant-propos

Nous travaillerons dans un répertoire /src. Pour compiler, vous pourrez utiliser ghc avec la ligne de commande :

 
Sélectionnez
ghc -O -prof -rtsopts -fprof-auto --make Main

GHC compilera tous les fichiers .hs et cherchera l'entry-point dans le fichier Main.hs.

Les options -prof, -rtsopts et -fprof-auto servent au profiling, c'est-à-dire quand nous souhaiterons mesurer les performances de notre programme. L'option -O active les optimisations du compilateur, ce qui peut réduire le temps d'exécution de façon importante.

II-1. Production d'un fichier et initialisation de DevIl

On va d'abord mettre en place le nécessaire pour produire une image, puis l'on se concentrera sur le principe du raytracing, et son implémentation en haskell.

Commençons par le nécessaire en matière d'IO. Notre programme enregistrera l'image raytracée dans le fichier "image.png". Puisque ce fichier peut déjà exister, on va prendre la peine de le déplacer.

Main.hs
Sélectionnez
module Main (
  main,
  ) where

import System.Directory

main = do
  ilInit
  exists <- doesFileExists "image.png"
  if exists
    then renameFile "image.png" "image_back.png"
    else return ()
  return () -- Ici viendra le code de l'enregistrement de l'image

La ligne ilInit permet d'initialiser la bibliothèque. La seconde ligne « décapsule » un booléen, nous informe de l'existence ou non du fichier. Par la suite, s'il existe, on le déplace. Dans le cas contraire, on retourne une valeur monadique qui sera ignorée.

II-2. Production d'une image

Comment enregistrer une image ? Cela se fait en deux temps. D'abord, produire un tableau de données, ensuite, l'écrire au format d'image voulue. On doit produire un tableau tridimensionnel, où les deux premières dimensions sont largeur et hauteur, puis la troisième les couleurs. Dans notre cas, il y a trois couleurs : Rouge, Vert et Bleu suivies de la Transparence (0 signifie transparent et 255 opaque).

On veut donc un tableau de type UArray (Int, Int, Int) Word8, où un Word8 correspond à la plage de valeurs 0-255, avec 0 signifiant l'absence de couleur et 255 la saturation maximale.

On rajoute donc les lignes suivantes dans les imports :

Main.hs
Sélectionnez
import Codec.Image.DevIL
import Data.Array.Base

Puis on construit notre tableau, accompagné de quelques constantes :

Main.hs
Sélectionnez
tableData :: Int -> Int -> UArray (Int,Int,Int) Word8
tableData width height = listArray ((0,0,0), (height-1, width-1, 3)) $ repeat (111 :: Word8)

La troisième ligne construit un tableau tridimensionnel, avec des coordonnées comprises entre (0,0,0) (couleur rouge du pixel en bas à gauche) et (height-1, width-1, 2) (couleur bleue du pixel en haut à droite). La dernière instruction produit la liste infinie [111, 111, 111, …] dans laquelle les valeurs seront piochées.

Enregistrons maintenant cette image :

Main.hs
Sélectionnez
--Remplaçons la dernière ligne
  return ()
--Par
  writeImage "image.png" (tableData 800 600)

Nous avons alors une magnifique image grise, de 800 par 600.


précédentsommairesuivant

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 Zenol. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.