Si je ne m'abuse, la cible c'est l"animation photoréaliste en temps réel.
Si d'autres techniques que le Ray Tracing parviennent au même résultat avec moins de calcul, pourquoi pas, mais je ne suis pas sûr que ce soit vraiment photoréaliste.
Si je ne m'abuse, la cible c'est l"animation photoréaliste en temps réel.
Si d'autres techniques que le Ray Tracing parviennent au même résultat avec moins de calcul, pourquoi pas, mais je ne suis pas sûr que ce soit vraiment photoréaliste.
Pour faire du raytracing avec le gpu il faudrait que celui-ci soit optimisé pour un algorithme de ce genre :
Code cpp : 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 for (unsigned int i = 0; i < m_instances.size(); i++) { for (unsigned int j = 0; j < m_instances[i]->getVertexArrays().size(); j++) { TransformMatrix& tm = m_instances[i]->getTransforms()[j].get(); for (unsigned int k = 0; k < m_instances[i]->getVertexArrays()[j]->getVertexCount(); k++) { math::Matrix4f texM; math::Matrix4f invTexM; if (m_instances[i]->getMaterial().getTexture() != nullptr) { texM = m_instances[i]->getMaterial().getTexture()->getTextureMatrix(); invTexM = texM.inverse(); } if (m_instances[i]->getVertexArrays()[j]->getPrimitiveType() == sf::TrianglesFan && m_instances[i]->getVertexArrays()[j]->getVertexCount() >= 3 && k < m_instances[i]->getVertexArrays()[j]->getVertexCount() - 2) { math::Vec3f p1 = math::Vec3f((*m_instances[i]->getVertexArrays()[j])[0].position.x,(*m_instances[i]->getVertexArrays()[j])[0].position.y,(*m_instances[i]->getVertexArrays()[j])[0].position.z); math::Vec3f p2 = math::Vec3f((*m_instances[i]->getVertexArrays()[j])[k+1].position.x,(*m_instances[i]->getVertexArrays()[j])[k+1].position.y,(*m_instances[i]->getVertexArrays()[j])[k+1].position.z); math::Vec3f p3 = math::Vec3f((*m_instances[i]->getVertexArrays()[j])[k+2].position.x,(*m_instances[i]->getVertexArrays()[j])[k+2].position.y,(*m_instances[i]->getVertexArrays()[j])[k+2].position.z); p1 = tm.transform(p1); p2 = tm.transform(p2); p3 = tm.transform(p3); math::Vec3f orig = math::Vec3f(view.getPosition().x, view.getPosition().y, view.getViewport().getPosition().z); for (unsigned int x = 0; x < size.x; x++) { for (unsigned int y = 0; y < size.y; y++) { math::Vec3f ext = window.mapPixelToCoords(math::Vec3f(x, y, view.getViewport().getPosition().z + view.getViewport().getSize().z), view); math::Ray ray(orig, ext); math::Vec3f o, point; math::Vec3f r = ray.getOrig() - ray.getExt(); math::Vec3f u = p2 - p1; math::Vec3f v = p3 - p1; math::Vec3f n = u.cross(v); math::Vec3f otr = ray.getOrig() - p1; point.x = n.dot2(otr) / n.dot2(r); point.y = -otr.cross(u).dot2(r) / n.dot2(r); point.z = -v.cross(otr).dot2(r) / n.dot2(r); if (0 <= point.x && 0 <= point.y && point.y <= 1 && 0 <= point.z && point.z <= 1 && point.y + point.z <= 1) { //std::cout<<"intersects"<<std::endl; sf::Color c1 = (*m_instances[i]->getVertexArrays()[j])[0].color; sf::Color c2 = (*m_instances[i]->getVertexArrays()[j])[k+1].color; sf::Color c3 = (*m_instances[i]->getVertexArrays()[j])[k+2].color; math::Vec3f ct1 = texM * math::Vec3f((*m_instances[i]->getVertexArrays()[j])[0].texCoords.x,(*m_instances[i]->getVertexArrays()[j])[0].texCoords.y, 1.f); math::Vec3f ct2 = texM * math::Vec3f((*m_instances[i]->getVertexArrays()[j])[k+1].texCoords.x,(*m_instances[i]->getVertexArrays()[j])[k+1].texCoords.y, 1.f); math::Vec3f ct3 = texM * math::Vec3f((*m_instances[i]->getVertexArrays()[j])[k+2].texCoords.x,(*m_instances[i]->getVertexArrays()[j])[k+2].texCoords.y, 1.f); math::Vec3f z (p1.z, p2.z, p3.z); float bz = z.x * point.x + z.y * point.y + z.z * point.z; float actualZ = depthBuffer[y * size.x + x].z; if (bz >= view.getViewport().getPosition().z && bz <= view.getViewport().getSize().z) { math::Vec3f r = math::Vec3f (c1.r / 255.f, c2.r / 255.f, c3.r / 255.f); math::Vec3f g = math::Vec3f (c1.g / 255.f, c2.g / 255.f, c3.g / 255.f); math::Vec3f b = math::Vec3f (c1.b / 255.f, c2.b / 255.f, c3.b / 255.f); math::Vec3f a = math::Vec3f (c1.a / 255.f, c2.a / 255.f, c3.a / 255.f); std::array<math::Vec3f, 2> colors; colors[0] = math::Vec3f(r.x * point.x + r.y * point.y + r.z * point.z, g.x * point.x + g.y * point.y + g.z * point.z, b.x * point.x + b.y * point.y + b.z * point.z, a.x * point.x + a.y * point.y + a.z * point.z); math::Vec3f finalColor = colors[0]; depthBuffer[y * size.x + x] = math::Vec3f(0, 0, bz, colors[0].w); frameBuffer[(y * size.x + x) * 4] = finalColor.x * 255; frameBuffer[(y * size.x + x) * 4 + 1] = finalColor.y * 255; frameBuffer[(y * size.x + x) * 4 + 2] = finalColor.z * 255; frameBuffer[(y * size.x + x) * 4 + 3] = finalColor.w * 255; } } } } } } } }
M'enfin bon, je ne pense pas que ça soit pour demain!
Ce que tu as écrit là ce n'est pas du raytracing, c'est de la (mauvaise) rastérisation et c'est exactement ce pour quoi le GPU est optimisé depuis vingt ans !
Quant au raytracing les derniers GPU sont au contraire bien adaptés puisqu'ils ils gèrent les sparse octrees directement au niveau matériel (dx 11.1 je crois), qu'ils sont massivement parallèles et que le cohérence spatiale doit déboucher sur une exécution efficace des branchements conditionnels.
Par contre ils ne font pas encore dans le vaudou, ce qui explique qu'ils ne soient toujours pas capables de faire du raytracing en temps réel du fait des besoins colossaux en puissance de calcul.
Raytracing dans les jeux vidéos ? Réponse de Normand comme souvent en programmation : c'est compliqué !
On peut noter une tendance et cela se confirmera peut-être que dans quelques années le rendu des ray/path tracers et rasterizers aura convergé suffisamment pour qu'on puisse passer de l'un à l'autre et avoir un "feeling" similaire sur une scène lambda.
Voilà une scène super simple mais qui utilise des concepts utilisés désormais couramment dans les jeux conçus pour les rasterizers, éclairage direct (avec ombrage "tranché"), ambient occlusion, éclairage à base d'image (pour le terme ambiant), environment map, etc :
Et voici la même scène, mêmes paramètres de matériaux, mêmes valeurs d'éclairage mais cette fois rendue dans un raytracer/path tracer basé sur la physique (Mitsuba) :
Bien entendu si j'introduisais des réflexions miroir et des interreflexions (illumination globale), caustiques, etc très visibles dans la scène, la donne changerait légèrement, mais ces choses seront peut-être mieux gérées dans le futur et font déjà parfois l'objet de solutions ad hoc convaincantes (screen space reflections ou env maps pour les réflexions, voxel gi ou propagation volume ou lightmaps pour les interreflexions, rendus procéduraux pour les caustiques. etc). Le tout en restant très intéractifs voire fluide et avec un rendu pas forcément aussi bruité que avec un path tracer brut.
Au final ce qui importe ce n'est pas tant la méthode qui est utilisée mais celle qui permet d'atteindre l'objectif voulu. Le jeu vidéo va encore privilégier le haut frame rate (30 à 60 fps dans une scène complexe) à une solution théorique plus exacte physiquement. Ça ne veut pas dire non plus que dans le futur le rasterizer aura à faire trop de sacrifices non plus.
Bref chacun voit midi à sa porte comme on dit. La personne qui a un objectif de rendu architectural parfait va privilégier les rendus offlines pour leurs capacités à propager la lumière et exceller avec les surfaces un peu plus complexes (verre, marbre, métaux, etc), pareil pour l'ingénieur automobile qui voudra un rendu "parfait" de la réflection de l'environnement sur la carrosserie simulée d'une future voiture, idem dans les films où l'oeil exercé du spectateur sera plus important que le temps de rendu d'un film (rendu une seule fois et rejoué des millions de fois au format "video").
Le développeur de jeu va voir ce qui lui permet d'atteindre le plus facilement sa cible de 60 fps et si il a le budget en puissance de calcul n'hésitera pas à utiliser des méthodes qui ressemblent à celle du rendu offline (lancers de rayons dans la scène/espace de texture/espace de l'écran ou dans un arbre volumétrique, cf self shadows, ambient occlusion, global illumination). Si cela améliore l'expérience visuelle bien entendu.
Bref, pensez comme un programmeur de jeu. Imaginez que vous avez un problème à résoudre. Exemple parmi tant d'autres, distortion de caméra de l'Oculus Rift.
Vous pourriez (naïvement) vous dire : eh c'est un problème tout simple pour un raytracer, il n'y aucun surcoût à ajouter de la distortion en envoyant les rayons légèrement différemment.. Sauf que votre frame rate de base pour ce même rendu serait super bas. Et que l'Oculus en plus a des impératifs de latence/fluidité beaucoup plus haute que pour un jeu sur écran normal.
Donc même si ça semble moins naturel, il est tout à fait normal de faire le rendu dans une texture et de faire la distortion de cette texture sur l'écran avec un bon vieux rasterizer comme ce qui est fait dans cette image.
Vous aurez la même discussion interne pour tous les autres choix (reflection, ombres..).
Après, on ne vous décourage pas j'espère. Rien ne vous empêche de porter des jeux en raytracing juste pour le fun :
ou de faire des choses très différentes (Euclideon, unlimited details) :
LeGreg
Et il y a une chose qu'on pourrait ajouter : finalement cela fait des années que les jeux utilisent le raytracing et la radiosité, sauf qu'ils l'utilisaient uniquement en pré-calculé, pour générer les lightmaps. La nouveauté c'est que l'on peut désormais appliquer des techniques similaires en temps réel (en trichant beaucoup) pour les lumières dynamiques. et autres.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager