Bonjour à vous tous :-).

Voilà, je m'intérèsse depuis très peu de temps au ray tracing.
J'ai réussis (ou presque) à faire une fonction permettant de calculer les intersections avec une quadrique telle qu'une sphère, ou une hyperboloïde à une nappe en passant par un plan et d'autres encore.

Bref, voilà, après avoir fait tout ça, j'ai voulu rajouter une caméra, chose très difficile à faire pour moi ^_^. Après moult recherches, j'ai trouver un truc pas mal, et effectivement tout fonctionne (dans le cas du plan ou de la sphère en tout cas), mais quand j'ai voulu rajouter mon hyperboloïde, misère... Mauvais affichage...
Donc deux possibilités, soit je me suis trompé dans ma fonction de résolution de l'équation (possible, mais je ne pense pas), soit je me suis trompé pour la caméra et c'est pas impossible..., bien que ça me semble bizarre que ça ne marche pas pour l'hyperboloïde et que ça fonctionne avec les sphères / plans...

Les "vexteurs" pos, dir, up correspondent à ceux que l'on rentre dans la fonction lookAt (gluLookAt pour les OpenGL 2.1) avec le vecteur up : up(0.0, 1.0, 0.0);

Ceci est un code en GLSL, mais je pense qu'il n'est pas trop complexe à comprendre quand même.

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#version 330 core
 
precision highp float;
 
uniform int numberQuadric;
 
struct QuadricData
{
    // ax^2 + by^2 + cz^2 + 2dxy + 2exz + 2fyz + gx + hy + iz + j = 0
    float a, b, c, d, e, f, g, h, i, j;
 
    // Intervalle
    float xMin, xMax, yMin, yMax, zMin, zMax;
 
    // Couleur
    float rColor, gColor, bColor;
 
    float useless;
};
 
uniform Camera
{
    float xPos, yPos, zPos;
    float xDir, yDir, zDir;
    float xUp, yUp, zUp;
    float cotanHalfFovY;
    int width, height;
}camera;
 
uniform Quadric
{
    QuadricData q[500];
}quadric;
 
 
out vec4 color;
 
// Si inférieur, c'est 0
float minZero = 0.001;
 
float computeDistQuadric(in vec3 ro, in vec3 rd, in QuadricData q, out vec3 pointIntersect)
{
    /* Equation d'une quadric :ax² + bx² + cx² + 2dxy + 2exz + 2fyz + gx + hy + iz + j = 0
        (x, y, z) = ro + dist*rd;
        Objectif : Calculer la distance dist
    */
    /* On se ramène à une équation en a*dist^2 + b*dist + c */
    // a = partie en dist^2
    float a = q.a * rd.x * rd.x + q.b * rd.y * rd.y + q.c * rd.z * rd.z + 2 * q.d * rd.x * rd.y + 2 * q.e * rd.x * rd.z + 2 * q.f * rd.y * rd.z;
 
    // b Partie en dist
    float b = 2 * (q.a * rd.x * ro.x + q.b * rd.y * ro.y + q.c * rd.z * ro.z + q.d * (rd.x * ro.y + rd.y * ro.x) + q.e * (rd.x * ro.z + rd.z + ro.x) + q.f * (rd.y * ro.z + rd.z * ro.y)) + q.g * rd.x + q.h * rd.y + q.i * rd.z;
 
    // c Partie Constante
    float c = q.a * ro.x * ro.x + q.b * ro.y * ro.y + q.c * ro.z * ro.z + 2 * q.d * ro.x * ro.y + 2 * q.e * ro.x * ro.z + 2 * q.f * ro.y * ro.z + q.g * ro.x + q.h * ro.y + q.i * ro.z + q.j;
 
    if(abs(a) < minZero)
        return -c / b;
 
    float delta = b * b - 4.0 * a * c;
 
    // Il n'y a pas d'intersection
    if(delta < 0.0)
        return -1.0;
 
    // On récupère les distances
    float disc = sqrt(delta);
    float dist1 = (-b - disc) / (2.0 * a);
    float dist2 = (-b + disc) / (2.0 * a);
 
    // On récupère la bonne distance
    float goodDistance;
 
    // Les intersections sont derrières
    if(dist1 < 0.0 && dist2 < 0.0)
        return -1.0;
 
    if(dist1 > 0.0)
        goodDistance = dist1;
 
    // Distance 2 plus petites que la première
    if((dist2 > 0.0 && dist1 > 0.0) && dist2 < dist1)
        goodDistance = dist2;
 
    if(dist2 > 0.0 && dist1 < 0.0)
        goodDistance = dist2;
 
    pointIntersect = ro + goodDistance * rd;
 
    // Test l'interval
    if(pointIntersect.x < q.xMin || pointIntersect.x > q.xMax ||
       pointIntersect.y < q.yMin || pointIntersect.y > q.yMax ||
       pointIntersect.z < q.zMin || pointIntersect.z > q.zMax)
        return -1.0;
 
    return goodDistance;
}
 
void intersect(in vec3 ro, in vec3 rd)
{
    color = vec4(0.0);
    float lessDist = 100000.0;
    int i;
    vec3 pointIntersect;
 
    float dist;
 
    for(i = 0; i < numberQuadric; ++i)
    {
        dist = computeDistQuadric(ro, rd, quadric.q[i], pointIntersect);
 
        // Si la distance d'intersection est plus petite que l'ancienne (z-Buffer)
        if(dist > 0.0 && dist < lessDist)
        {
            color = vec4(quadric.q[i].rColor, quadric.q[i].gColor, quadric.q[i].bColor, 1.0);
            lessDist = dist; // On met à jour la nouvelle distance
        }
    }
}
 
void main(void)
{
    float i = (gl_FragCoord.x / camera.width) * 2.0 - 1.0;
    float j = (gl_FragCoord.y / camera.height) * 2.0 - 1.0;
 
    vec3 ro = vec3(camera.xPos, camera.yPos, camera.zPos);
    vec3 dir = vec3(camera.xDir, camera.yDir, camera.zDir);
    vec3 up = vec3(camera.xUp, camera.yUp, camera.zUp);
    vec3 right = cross(dir, up);
 
    // On recalcule le up pour avoir les 3 axes de telle sorte qu'elle forme une base orthonormal
    up = cross(right, dir);
 
    vec3 rd = normalize(camera.cotanHalfFovY * dir + i * right + j * up);
 
    intersect(ro, rd);
}
Voilà le côté parfait de l'hyperboloïde

Nom : good.png
Affichages : 214
Taille : 2,8 Ko

Là on commence à voir le bug : On ne voit pas l'arrière de l'hyperbole alors que dans ce mode de vue, on devrait

Nom : fail2.png
Affichages : 168
Taille : 3,4 Ko

Et le dernier, on voit bien le gros problème ^_^

Nom : fail.png
Affichages : 175
Taille : 3,8 Ko

Merci de votre aide à tous et à toutes :-)

EDIT : Erreur trouvé, excusez moi pour le dérangements...