Pages

[OpenGL 3.x] Ray Tracing GPU : Caméra sujet

jeudi 27 mars 2014




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:


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

good.png

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

fail2.png

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

fail.png

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











Images attachées










Aucun commentaire:

Enregistrer un commentaire