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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Conversion d'un code C de Lightmap : noir et blanc au lieu de nuances de gris


Sujet :

Lazarus Pascal

  1. #1
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut Conversion d'un code C de Lightmap : noir et blanc au lieu de nuances de gris
    Bonjour,

    Je suis en train de convertir un code en C++ sous GTK, qui produit une lightmap depuis une heightmap.

    Mais hélas, je n'obtiens pas le même résultat visuel sous Lazarus que sous le projet originel.

    Voilà ce que je devrais obtenir :

    Nom : Lightmap-cpp.jpeg
Affichages : 542
Taille : 33,4 Ko

    Et ce que j'ai sous Lazarus :

    Nom : lightmap.jpg
Affichages : 535
Taille : 65,6 Ko

    Chez moi, ma lightmap, est blanche et noire, il n'y a pas de niveaux de gris comme dans l'original.

    Voici la routine originelle :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    void on_apercu(GtkWidget* widget, gpointer data)
    {
        int ombrage = (int)gtk_adjustment_get_value(adj_ombrage);
        float angle_rayons = (int)gtk_adjustment_get_value(adj_angle_rayons);
        float hauteur_max_rayons = (int)gtk_adjustment_get_value(adj_hauteur_max_rayons);
        float hauteur_max_heightmap = (float)gtk_adjustment_get_value(adj_hauteur_max_heightmap);
     
        int n_channels;
        int rowstride_lightmap, rowstride_heightmap;
        guchar *pixels_lightmap=NULL, *p_lightmap=NULL;
        guchar *pixels_heightmap=NULL, *p_heightmap=NULL;
        int x, y, width, height = 0;
        float step_z=0.0f;
        float z_origine=0.0f;
        int x_rayon=0;
        float z_rayon=0.0f;
     
        n_channels = gdk_pixbuf_get_n_channels(pixbuf_lightmap);
     
        g_assert(gdk_pixbuf_get_colorspace (pixbuf_lightmap) == GDK_COLORSPACE_RGB);
        g_assert(gdk_pixbuf_get_bits_per_sample (pixbuf_lightmap) == 8);
        g_assert(gdk_pixbuf_get_has_alpha (pixbuf_lightmap) == FALSE);
        g_assert(n_channels == 3);
     
        width = gdk_pixbuf_get_width(pixbuf_lightmap);
        height = gdk_pixbuf_get_height(pixbuf_lightmap);
     
        rowstride_lightmap = gdk_pixbuf_get_rowstride(pixbuf_lightmap);
        pixels_lightmap = gdk_pixbuf_get_pixels(pixbuf_lightmap);
     
        rowstride_heightmap = gdk_pixbuf_get_rowstride(pixbuf_heightmap);
        pixels_heightmap = gdk_pixbuf_get_pixels(pixbuf_heightmap);
     
        // Au départ, tout est dans l'ombre...
        for(y=0 ; y<height ; y++)
            for(x=0 ; x<width ; x++)
            {
                p_lightmap = pixels_lightmap + y * rowstride_lightmap + x * n_channels;
                p_lightmap[0] = ombrage;
                p_lightmap[1] = ombrage;
                p_lightmap[2] = ombrage;
            }
     
        // Puis vint la lumière !!
     
        // On calcule de combien on doit incrémenter en z à chaque nouveau rayon
        step_z = fabs(1/tan(angle_rayons));
     
        // On lance les rayons dans le sens horizontal (en voyant de haut), de la gauche vers la droite.
        // On fait donc ça pour toutes les lignes (d'où la boucle en y).
        for(y=0 ; y<height ; y++)
        {
            // On parcourt en montant (i.e. suivant l'axe des Z) pour lancer des rayons à chacune
            // de ces hauteurs
            for(z_origine=0.0f ; z_origine<hauteur_max_rayons ; z_origine+=step_z)
            {
                // Lancer du rayon !
                for(z_rayon=z_origine, x_rayon=0 ;
                    x_rayon < width;
                    z_rayon-=step_z, x_rayon++)
                {
                    // Si la hauteur du pixel en cours est supérieure ou égale à z_rayon,
                    // c'est qu'on a touché
                    // qqch, alors on le colorie en blanc et on passe au rayon d'après
     
                    // On pointe sur le point (x_rayon, y)
                    p_heightmap = pixels_heightmap + y * rowstride_heightmap + x_rayon * n_channels;
                    p_lightmap = pixels_lightmap + y * rowstride_lightmap + x_rayon * n_channels;
     
                    if((float)(p_heightmap[0]/255.0f)*hauteur_max_heightmap >= z_rayon)
                    {
                        p_lightmap[0] = p_lightmap[1] = p_lightmap[2] = 255;
                        break;
                    }
                }
            }
        }
     
        gtk_image_set_from_pixbuf(GTK_IMAGE(image_lightmap), pixbuf_lightmap);
        redimensionner_image(image_lightmap);
    }

    Et ma conversion en Pascal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    Procedure TForm1.bouton_apercuClick(Sender: TObject);
    var
       x, y, x_rayon: integer;
       z_step, z_origine, z_rayon: single;
       Pixel, Final: PRGBTriple;
    Begin
        // Calcul du pas en z pour chaque rayon.
        z_step := abs(1 / tan(spin_angle_rayons.Value));
     
        image_lightmap.Picture.Bitmap.BeginUpdate;
     
        // Lancement des rayons dans le sens horizontal et de gauche a droite.
        for y := 0 to image_lightmap.Picture.Bitmap.Height - 1 do
        begin
             // Pointeurs sur les 2 même lignes des 2 bitmaps.
             Final := PRGBTriple(image_heightmap.Picture.Bitmap.RawImage.GetLineStart(y));
             Pixel := PRGBTriple(image_lightmap.Picture.Bitmap.RawImage.GetLineStart(y));
     
             // Par defaut tout a la valeur de l'ombre défini dans l'UI.
             for x := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
             begin
                  Pixel[x].rgbtRed   := spin_ombrage.Value;
                  Pixel[x].rgbtGreen := spin_ombrage.Value;
                  Pixel[x].rgbtBlue  := spin_ombrage.Value;
             End;
     
             // Lancements des rayons pour chaque hauteur en remontant suivant l'axe z
             z_origine := 0.0;
     
             while z_origine < spin_hauteur_max_rayons.Value do
             begin
                  // Lancement de rayon.
                  z_rayon := z_origine;
     
                  for x_rayon := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
                  begin
                       // Si la hauteur (rouge pour l'exmple) du pixel est supérieur ou égale a la valeur
                       // du z_rayon alors on le colorie en blanc et on passe au rayoin lancé suivant.
                       if ((Final[x_rayon].rgbtRed / 255) * spin_hauteur_max_heightmap.Value) >= z_rayon then
                       begin
                            Pixel[x_rayon].rgbtRed   := 255;
                            Pixel[x_rayon].rgbtGreen := 255;
                            Pixel[x_rayon].rgbtBlue  := 255;
     
                            break;
                       End;
     
                       z_rayon := z_rayon - z_step;
                  end;
     
                  z_origine := z_origine + z_step;
             end;
        end;
     
        image_lightmap.Picture.Bitmap.EndUpdate;
    end;
    À votre avis, où ai-je loupé un truc ?

  2. #2
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 328
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 328
    Points : 4 145
    Points
    4 145
    Par défaut All inclusive ?
    Bonjour,

    Quand on regarde les deux codes, il est difficile de voir une différence : les deux affectent soit un gris (ombrage) soit un blanc. Il ne devrait donc pas y avoir de nuances autres.

    Mais le code d'origine a une fonction "redimensionner_image(image_lightmap);" qui présuppose un filtre d'interpolation. Si celui-ci est plus pondéré que celui du redimensionnement appelé dans le code Lazarus (apparemment de type plus proche voisin) il va créer un flou qui va faire apparaître des niveaux de gris qui ne proviennent pas directement du traitement initial.

    La solution est d'appliquer explicitement un filtre d'interpolation au redimensionnement et de ne pas laisser, par exemple, la fonction stretch de décider de la méthode d'interpolation.

    Bon courage.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    Salut

    il faut que tu regardes si l'image est bien en triplet RGB.
    Vérifie si l'image est pf24bit ou pf32bit, le résultat ne sera forcement pas le même.
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  4. #4
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    J’ai créé explicitement mes bitmaps en 24bits, et l’auteur du code originel aussi.

    Merci de vos retours...

    Petite question annexe: à votre avis normalement une lightmap doit être seulement noire et blanche ou en nuance de gris ?

  5. #5
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 328
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 328
    Points : 4 145
    Points
    4 145
    Par défaut Niveaux
    Bonjour,

    En toute rigueur, la réflexion devrait dépendre de l'angle d'incidence et ne pas être systématiquement blanche. Ils ont triché en appliquant un filtre au redimensionnement pour avoir une solution plus performante (en temps sinon en qualité).

    Passer en 32 bits est une bonne solution pour accélérer le traitement (alignement d'adresse et possibilité d'écrire PInteger(p)^ := $00FFFFFF au lieu de 3 affectations de 255). En revanche je ne crois pas que cela change le fait que le code n'affecte que deux couleurs (un gris caractérisant la lumière diffuse et un blanc en cas de réflexion).

    Pour se rapprocher de ce qu'ils ont fait, on peut trouver sur Developpez.com le message de Jurassic Pork du 13/04/2016 à 05h14 qui répond à "Redimensionnement d'une image et perte de qualité" en montrant comment utiliser les filtres de redimensionnement.

    Bonne chance.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  6. #6
    Expert confirmé
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Points : 4 346
    Points
    4 346
    Billets dans le blog
    2
    Par défaut
    Salut Guesset a raison la génération renvois que 2 couleurs Blanc ou Gris. Et effectivement ce dégradé est dût au redimensionnement.
    Peux tu nous faire un petit zip du projet ?. Je n'ai pas beaucoup de temps libre en ce moment, mais je pourrais jeter un oeil entre deux.

    A+
    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  7. #7
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Sans PB, je posterai le zip demain matin...

  8. #8
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Voici le zip contenant les sources de mon petit programme pour ceux que cela intéresse...
    Fichiers attachés Fichiers attachés

  9. #9
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 328
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 328
    Points : 4 145
    Points
    4 145
    Par défaut
    Bonjour,

    J'ai du reprendre le code car sous windows (nobody's perfect) il compilait mais sans rien afficher (une option qui doit se balader quelque part).

    Les angles étaient en radiants, il fallait donc une conversion (les valeurs par défaut n'éclairent pas les sommets les plus à droite).

    Comme les boucles sont assez longues, j'en ai sorti un maximum de calculs.

    Pour avoir quelques niveaux de gris (un peu colorés), je propose de doser la luminosité en fonction du nombre d'impacts (linéairement ou exponentiellement) mais c'est un pis-aller.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    type
       // Quad.......................................//
       TxRGB   = packed record                       // Idem TRGB mais étendu à 4 octets
          case integer of                            // composantes.
             0 : (Color      : TRGBQuad);
             1 : (B, G, R, z : Byte);                // Ordre z R G B différent de TColor
             2 : (int        : Integer);
             3 : (rgb        : TRGBTriple;  z3 : byte);
             end;
       PxRGB   = ^TxRGB;   
    // . . .
    //__________________________________________________________________________________________________
    procedure TMainForm.DoLightmap(aSrc, aDst: TBitmap; aVO: integer; aAR, aHR, aHP: Single);
    var
       pSrcX, pSrcY        : PByte;
       pDstX, pDstY        : PxRGB;
       ClrOmbre, ClrLight  : TxRGB;
       dXSrc, dYSrc, dYDst : Integer;
       x, y, W, H, dZ, Zo, Zr, HR : Integer;
    begin
       dXSrc := aSrc.RawImage.Description.BitsPerPixel >> 3;
       W := aDst.Width;
       H := aDst.Height;
       ClrLight.int := Integer($FF4F4F4F);
       ClrOmbre.int := -1;
       ClrOmbre.R := aVo;
       ClrOmbre.G := aVo - (aVo >> 3);
       ClrOmbre.B := aVo - (aVo >> 2);
       // Calcul du pas en z pour chaque rayon.......//
       dZ := round( 65280.0*cotan(DegToRad(aAR))/aHP);
       HR := round((65280.0*aHR)/aHP);
       aDst.BeginUpdate(False);
       dYSrc := aSrc.RawImage.Description.BytesPerLine;
       dYDst := aDst.RawImage.Description.BytesPerLine >> 2;     // Nbr de points par ligne (4 o/point)
       pSrcY := PByte(aSrc.RawImage.GetLineStart(0));            // Pointeurs sur mêmes lignes des bmps
       pDstY := PxRGB(aDst.RawImage.GetLineStart(0));
       FillDWord(pDstY^, aDst.RawImage.DataSize >> 2, DWORD(ClrOmbre));
       // Lancement des rayons dans le sens horizontal et de gauche a droite.
       for y := 0 to H - 1 do begin
          // Lancements des rayons pour chaque hauteur en remontant suivant l'axe z
          Zo := 0;
          while Zo < HR do begin                     // Lancement de rayon.
             Zr    := Zo;
             pSrcX := pSrcY;
             pDstX := pDstY;
             for x := 0 to W -1 do begin
                if Integer(pSrcX^) << 8 >= Zr then begin
                   //pDstX^ := ClrLight;             // Blanc (mettre ClrLight.int à -1)
                   asm                               // Linéaire selon nb_impacts
                      mov       r8,   pDstX          // (mettre ClrLight.int à $FF4F4F4F)
                      movd      xmm2, ClrLight
                      movd      xmm1, [r8]
                      paddusb   xmm2, xmm1
                      movd      [r8], xmm2
                   end;
         //          asm                               // Exponentielle  (mettre ClrLight.int à -1)
         //             mov       r8,  pDstX           // en 1 - e^(-nb_impacts)
         //             pxor      xmm0, xmm0
         //             movd      xmm2, ClrLight
         //             movd      xmm1, [r8]
         //             punpcklbw xmm2, xmm0           // xmm2 = ClrLight en 16 bits
         //             punpcklbw xmm1, xmm0           // xmm1 = pDstXo^ en 16 bits
         //             psubw     xmm2, xmm1           // xmm2 = ClrLight-pDstXo^        (par composante)
         //             psraw     xmm2, 2              // xmm3 =(ClrLight-pDstXo^)/2^n   (par composante)
         //             paddw     xmm1, xmm2           // xmm1 = ClrLight+(pDstXo^-ClrLight)/16 (par comp)
         //             packuswb  xmm1, xmm0
         //             movd      [r8], xmm1
    					//end;
    					break;
                end;
                inc(pSrcX, dXSrc);
                inc(pDstX);
                Zr -= dZ;
             end;
             Zo += dZ;
          end;
          inc(pSrcY, dYSrc);
          inc(pDstY, dYDst);
       end;
       aDst.EndUpdate(True);
    end;
    Resultat :
    Nom : light-2019-09-28-13h34mn23.png
Affichages : 452
Taille : 71,8 Ko

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  10. #10
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Impressionnant tes modifs.

    Par contre, pourrais-tu proposer le code pascal à la place de l’ASM ?

    Est-ce que le code ASM peut-être remplacé par : pDstX^ := ClrLight; ?

    Si je le fait il m'affiche des trucs bizarre, est pas du tout le même résultat que toi.

    Par contre si je garde le bout de code en assembleur, j'ai ceci a la compilation:
    Nom : erreurcompilation.jpg
Affichages : 447
Taille : 77,9 Ko

  11. #11
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Bon, j'ai compris que tu travaillais en 32 bit donc j'ai modifié le bitmap de sortie en conséquence mais, je trouve que le résultat coté couleurs est bizarre chez moi, pourtant je suis sous Windows 10, en utilsant ce code pDstX^ := ClrLight; :
    Nom : Test512.jpg
Affichages : 384
Taille : 120,5 Ko

  12. #12
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 328
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 328
    Points : 4 145
    Points
    4 145
    Par défaut Variantes
    Bonsoir,

    Pour utiliser les variantes, (comme indiqué en commentaire), il faut initialiser ClrLight.int := -1 (<=> $FFFFFFFF soit ClrLight.Z=255, ClrLight.R=255, ClrLight.G=255, ClrLight.B=255) . Sinon c'est un peu sombre car le mode linéaire somme les contributions assez faibles apportées par un ClrLight pas si Light.

    C'est compilé en 64 bits (d'où les codes asm avec r8 par exemple).

    L'assembleur peut bien sûr être réécrit en Pascal mais, paradoxalement, ce serait avec plus de lignes (les XMM sont parfaits pour traiter en // les composantes couleurs). Et plus lent. De plus, la programmation de la saturation (faire en sorte qu'un octet ne subisse pas de troncature ie. 250+8 -> 255 et non 2 ou 3-8 -> 0 et non 251) est assez lourde à écrire.

    J'ai limité l'amplitude des angles entre 1 et 89° pour éviter zéro et infini. Au dessus de 80 ça devient assez lent (89° de l'ordre de 10 secondes. Je me demande si un double parcours des x pour chercher un angle < à l'angle des rayons ne serait pas plus rapide (H*W(W-1)/2 opérations en moyenne). De plus, la hauteur Yo à Xo = 0 du rayon qui passe par le point X et le sommet le plus haut vu de X donnerait une information d'éclairement (plus Yo est bas plus le sommet est éclairé). A voir. Si j'ai du courage...

    Les sources complètes et l'exécutable (sous Windows ) intéressent quelqu'un ?

    Bonne nuit.
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  13. #13
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    L’intérêt Du code full pascal est qu’il est compilable sur d’autre processeur qu’Intel (exemple PI3)

    pourrais-tu préciser exactement où mettre les modifs pour le -1 ?

    sinon, je veux bien des sources.

  14. #14
    Expert confirmé

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 328
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 328
    Points : 4 145
    Points
    4 145
    Par défaut Sources
    Bonjour

    Ligne 24 : -1 correspond à du blanc (et opaque si z est la transparence).

    Source et exécutable (64 bits) : LightMap.7z

    Je ne travaille que sur des machines 64 bits à base d'Intel ou compatible (AMD) aussi, égoïstement, la portabilité du code (assembleur y compris) ne se pose pas trop.

    Sinon le mode linéaire est assez aisé à programmer : en cas d'impact, pour chaque composante, par exemple la rouge pDstX^.R, on ajoute un delta (ClrLight.R) mais en vérifiant avant que 255 - pDstX^.R est > ClrLight.R) sinon on met pDstX^.R à 255.

    Le mode exponentiel est de type : à chaque impact, pour chaque composante par exemple la rouge, pDstX^.R += a*(ClrLight.R) -pDstX^.R) div 256 avec a/256 compris entre 0 et 1. Avant de faire cette incrémentation il faut à nouveau vérifier que 255 - pDstX^.R est > a*(ClrLight.R) -pDstX^.R) div 256 sinon on met pDstX^.R à 255.

    J'ai ajouté quelques facilités (barre de progression, actualisation automatique si souhaité, vue à taiille 100% si on clique sur l'une des image, date à la seconde près en lieu et place du random)

    Salutations
    Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)

  15. #15
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Merci pour ton apport à mon problème

    je vais tester tes modifs demain...

  16. #16
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    J'ai dézippé ton fichier et lancé le programme qui s'y trouve et sans avoir rien modifié dans le paramétrage, voila que que j'ai :
    Nom : light-2019-09-30-09h00mn31.png
Affichages : 401
Taille : 50,2 Ko

  17. #17
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    J'ai rajouté une fonction interne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       function ControlCouleur(AC, AX: Byte):Byte; inline;
       begin
         if (255 - AC) > AX then
           Result := AC + AX
         else
           Result := 255;
       End;
    Et a la place de l'ASM, j'ai mis ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
             begin
                if Integer(pSrcX^) << 8 >= Zr then
                begin
                  pDstX^.R := ControlCouleur(pDstX^.R, ClrLight.R);
                  pDstX^.G := ControlCouleur(pDstX^.G, ClrLight.G);
                  pDstX^.B := ControlCouleur(pDstX^.B, ClrLight.B);
     
                  ClrLight.int := Integer($FF4F4F4F);
                  break;
                End;
                inc(pSrcX, dXSrc);
                inc(pDstX);
                Zr -= dZ;
             end;
    Grace a cette modif, j’obtiens ceci:
    Nom : V2.png
Affichages : 406
Taille : 255,1 Ko

    Par contre je ne comprend pas pourquoi cela n'est pas en nuance de gris mais cela tire sur le jaune ?

    Pour le mode exponentiel, d’où vient le "a" ?

  18. #18
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 726
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 726
    Points : 15 126
    Points
    15 126
    Par défaut
    Salut,
    Citation Envoyé par der§en Voir le message
    Par contre je ne comprends pas pourquoi cela n'est pas en nuances de gris mais cela tire sur le jaune ?
    Dans DoLightMap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       ClrOmbre.R := aVo;
    // 2 lignes dessous = original, mais l'ombre est jaune foncé (127 96 64)
    //   ClrOmbre.G := aVo - (aVo >> 2);
    //   ClrOmbre.B := aVo - (aVo >> 1);
    // donc
       ClrOmbre.G := aVo;
       ClrOmbre.B := aVo;
    Nom : progombregrise.png
Affichages : 402
Taille : 175,3 Ko

    Il me reste le problème classique des codes Windows avec Scanline à porter sous Linux, mais je n'aurai pas le temps, j'ai d'autres trucs sur le gaz…
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  19. #19
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    THX Jipété

    Dernière petite interrogation, c'est a propos de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ClrLight.int := Integer($FF4F4F4F);
    Pourquoi ces valeurs de "4F" pour les composants (et pas "FF") ?

  20. #20
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 763
    Points : 959
    Points
    959
    Par défaut
    Petites modifications au source proposé par Guesset !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       // Quad
       TxRGB   = packed record  
          case integer of            
             0 : (B, G, R, A : Byte);
             1 : (BGRA : Cardinal);  
          end;
       PxRGB   = ^TxRGB;
    Et la routine principale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    procedure TMainForm.DoLightmap(aSrc, aDst: TBitmap; aVO: integer; aAR, aHR, aHP: Single);
    var
       pSrcX, pSrcY        : PByte;
       pDstX, pDstY        : PxRGB;
       ClrOmbre, ClrLight  : TxRGB;
       dXSrc, dYSrc, dYDst : Integer;
       x, y, W, H, dZ, Zo, Zr, HR : Integer;
     
       function ControlCouleur(const AC, AX: Byte): Byte; inline;
       begin
         if (255 - AC) > AX then
           Result := AC + AX
         else
           Result := 255;
       End;
     
    begin
       dXSrc := aSrc.RawImage.Description.BitsPerPixel div 8;
     
       W := aDst.Width;
       H := aDst.Height;
     
       ClrOmbre.R := aVo;
       ClrOmbre.G := aVo;
       ClrOmbre.B := aVo;
       ClrOmbre.A := 255;
     
       ClrLight.BGRA := ClrOmbre.BGRA;
     
       // Calcul du pas en z pour chaque rayon
       dZ := round( 65280.0*cotan(DegToRad(aAR))/aHP);
       HR := round((65280.0*aHR)/aHP);
     
       aDst.BeginUpdate(False);
     
       dYSrc := aSrc.RawImage.Description.BytesPerLine;
       dYDst := aDst.RawImage.Description.BytesPerLine div 4;    // Nbr de points par ligne (4 octets/point)
       pSrcY := PByte(aSrc.RawImage.GetLineStart(0));            // Pointeurs sur mêmes lignes des bmps
       pDstY := PxRGB(aDst.RawImage.GetLineStart(0));
     
       FillDWord(pDstY^, aDst.RawImage.DataSize div 4, DWORD(ClrOmbre));
     
       // Lancement des rayons dans le sens horizontal et de gauche a droite.
       Bar.Max := H - 1;
     
       for y := 0 to H - 1 do
       begin
          Bar.Position := y;
          // Lancements des rayons pour chaque hauteur en remontant suivant l'axe z
          Zo := 0;
          while Zo < HR do
          begin                     // Lancement de rayon.
             Zr    := Zo;
             pSrcX := pSrcY;
             pDstX := pDstY;
     
             for x := 0 to W -1 do
             begin
                if Integer(pSrcX^) << 8 >= Zr then
                begin
                  pDstX^.R := ControlCouleur(pDstX^.R, ClrLight.R);
                  pDstX^.G := ControlCouleur(pDstX^.G, ClrLight.G);
                  pDstX^.B := ControlCouleur(pDstX^.B, ClrLight.B);
                  pDstX^.A := 255;
     
                  ClrLight.BGRA := clrOmbre.BGRA;
                  break;
                End;
     
                inc(pSrcX, dXSrc);
                inc(pDstX);
     
                Zr -= dZ;
             end;
     
             Zo += dZ;
          end;
     
          inc(pSrcY, dYSrc);
          inc(pDstY, dYDst);
       end;
     
       aDst.EndUpdate(True);
     
       Bar.Position := 0;
    end;
    Chez moi, le résultat est intéressant...

Discussions similaires

  1. [AC-2016] Impression Noir et blanc au lieu de couleurs pour certains Formulaires
    Par Philippe Tulliez dans le forum IHM
    Réponses: 0
    Dernier message: 29/08/2019, 14h06
  2. Code pour imprimer en noir et blanc
    Par ami19 dans le forum VBA Access
    Réponses: 1
    Dernier message: 17/10/2018, 08h16
  3. Conversion d'un code javascript en php
    Par jazz3210 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 2
    Dernier message: 07/02/2009, 20h48
  4. Conversion d"un code javascript en php
    Par jazz3210 dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 07/02/2009, 20h05
  5. Problème de conversion d'un code de AS2 en AS3
    Par platondog dans le forum ActionScript 3
    Réponses: 4
    Dernier message: 20/11/2008, 01h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo