Author Topic: Raymarching - besoin d'explications  (Read 23236 times)

0 Members and 1 Guest are viewing this topic.

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #30 on: 29 November 2010 à 22:26:30 »
Bon, ben j'ai trouvé. Vous allez vraiment être atterrés...
Voilà le code d'origine :
Code: [Select]
float sphereDist(vec3 pos, vec3 center, float radius)
{
return length(center - pos) - radius;
}

et comme ça ça marche beaucoup mieux :
Code: [Select]
float sphereDist(vec3 pos, vec3 center, float radius)
{
return abs(length(center - pos) - radius);
}

Voilà, je suis un sacré boulet ;)

Offline Patapom

  • Base
    • View Profile
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #31 on: 29 November 2010 à 22:49:18 »
Bon, ben j'ai trouvé. Vous allez vraiment être atterrés...
Voilà le code d'origine :
Code: [Select]
float sphereDist(vec3 pos, vec3 center, float radius)
{
return length(center - pos) - radius;
}

et comme ça ça marche beaucoup mieux :
Code: [Select]
float sphereDist(vec3 pos, vec3 center, float radius)
{
return abs(length(center - pos) - radius);
}

Voilà, je suis un sacré boulet ;)

Heu non, je trouve pas que t'es un boulet. La première formule était la bonne : il te faut des distances négatives quand t'es à l'intérieur de la sphère hein !
Ton problème se trouve ailleurs.
.  Pom  .

nystep

  • Guest
Re : Raymarching - besoin d'explications
« Reply #32 on: 30 November 2010 à 08:08:27 »
comme dit patapom la première formule est la bonne, mais sinon tu fais bien la valeur absolue de ta normale après l'avoir normalisée pour l'afficher ou bien... ;)

abs(normalize(n)) genre? :) sinon oui si elle est négative il la clampe à zéro et ça fait du noir ;)

nystep

  • Guest
Re : Raymarching - besoin d'explications
« Reply #33 on: 30 November 2010 à 08:11:20 »
   cc = dot(n, eye);

eye est une position, ce n'est pas un vecteur... il faut construire le vecteur et le normaliser, sinon ton lighting lambertien ne risque pas d'être correct ;)

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #34 on: 30 November 2010 à 09:08:12 »
Ouaip mais pour eye j'ai mis en dur vec3(0, 0, 1) donc je pense que c'est normalisé ;)


Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #35 on: 30 November 2010 à 09:15:22 »
Heu non, je trouve pas que t'es un boulet. La première formule était la bonne : il te faut des distances négatives quand t'es à l'intérieur de la sphère hein !
Ton problème se trouve ailleurs.

Zut alors j'étais dans ma sphère noire. Donc je me suis perdu dans mon système de coordonnées. Si je commence à pas comprendre à ce point là déjà dès le début, je suis mal barré ;)

Offline Patapom

  • Base
    • View Profile
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #36 on: 30 November 2010 à 14:01:15 »
Normalement le gradient est partout non nul avec tes 2 sphères, sauf sur le plan équidistant entre les 2 sphères... Je comprends même pas comment tu peux avoir du noir.
Tu peux reposter la dernière version du code entier steuplé ? Je le testerai chez moi.
.  Pom  .

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #37 on: 30 November 2010 à 14:22:22 »
Ok je te poste ça ce soir après nettoyage ;)

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #38 on: 30 November 2010 à 20:29:52 »
Euuuuh, je vais avoir l'air stupide mais je crois que mon problème a disparu. Sans doute que j'avais commencé d'une très mauvaise manière et qu'à force de suivre tes conseils j'ai résolu le problème sans m'en rendre compte (j'avais reculé la sphère concernée pour ne plus voir la sphère noire).

Enfin, je poste quand même ici le shader si jamais tu trouves des choses à y redire je suis preneur ;)
Le vertex shader bien cracra (oui oui la position de la caméra est en dur) :
Code: [Select]
varying vec3 eye, dir;

void main()
{
gl_Position = gl_Vertex;

eye = vec3(0, 0, 1);
dir = vec3(gl_Vertex) - eye;
}

Et le code du pixel shader :
Code: [Select]
varying vec3 eye, dir;

float maxDist = 10.0;
int maxNbStep = 64;
float eps = 0.005;
float n_eps = 0.00001;

float sphereDist(vec3 pos, vec3 center, float radius)
{
return length(center - pos) - radius;
}

float distanceFunc(vec3 pos)
{
return
min( sphereDist(pos, vec3(0.1, 0.5, -1.3), 0.2),
min(
sphereDist(pos, vec3(0, -0.5, -0.5), 0.5),
sphereDist(pos, vec3(-0.3, 0.2, -0.8), 0.3)
));
}

vec3 grad(vec3 pos)
{
return normalize(
vec3(
distanceFunc(pos + vec3(n_eps, 0, 0)) - distanceFunc(pos - vec3(n_eps, 0, 0)),
distanceFunc(pos + vec3(0, n_eps, 0)) - distanceFunc(pos - vec3(0, n_eps, 0)),
distanceFunc(pos + vec3(0, 0, n_eps)) - distanceFunc(pos - vec3(0, 0, n_eps))
)
);
}


void main()
{
int steps;
float d;
vec4 c = vec4(1, 0, 0, 1);
vec3 dn = normalize(dir);
vec3 dt = dn;
float last_dist = 0.0;
float stepped = 0.0;
float cc;

for(steps = 0; steps < maxNbStep; steps++)
{
if(stepped > maxDist) break;

dt = dn * stepped;
d = distanceFunc(dt);
if(d < eps)
{
vec3 n = grad(dt);
cc = dot(n, eye);
gl_FragColor = vec4(cc, cc, cc, 1);
return;
}
stepped += d;
}
gl_FragColor = c;
}

Il faut savoir que je n'ai qu'une GeForce 7300 Go, et avec ces trois pauvres sphères, j'atteins les performances magnifiques de... 3fps...

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #39 on: 30 November 2010 à 20:33:54 »
Une question qui me taraude, concernant le premier step du rayon : faut-il prendre en compte la distance déjà parcourue de la caméra à l'écran ? J'ai fait quelques essais pas concluants, donc je me demande si la question est pertinente...

Ah et il n'y a pas de notion de fov dans mon shader parce que j'ai créé une fenêtre carrée pour pas m'embêter avec ça ;)

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #40 on: 01 December 2010 à 22:21:48 »
Bon ben j'ai un petit peu avancé je suis bien content, j'ai un truc qui ressemble à des metaballs :D (voir capture)
La formule de distance que j'utilise est celle-ci :
Code: [Select]
float distanceFunc(vec3 pos)
{
float r = 0.28;
float s1 = sphereDist(pos, vec3(0.3, 0.2, -0.8), r);
float s2 = sphereDist(pos, vec3(-0.3, 0.2, -0.8), r);
float s0 = (s1 * s2) * r;
return s0;
}

Je me doute bien que ça ne doit pas être la vraie formule des metaballs, mais le résultat y ressemble :) (au fait c'est quoi la vraie fonction de distance pour les metaballs ? :D)

nystep

  • Guest
Re : Raymarching - besoin d'explications
« Reply #41 on: 03 December 2010 à 17:45:59 »
j'avoue que tu me bluffes pour ce coup là!

non ce n'est pas la vraie formule, mais pourtant tu arrives bien à avoir une liaison correcte entre tes "sphères".
voici la fonction typique, tu peux remplacer 1 par la taille que tu souhaites donner aux "sphères" aussi:

f(x,y,z) = 1 / (1 + (x − x0)2 + (y − y0)2 + (z − z0)2)

cette fonction est donc égale à 1 au centre de la métaball, et elle tend vers 0 à l'infini
ce n'est donc pas une distance, mais en ajoutant diverses balles comme ça tu obtiendras l'effet de metaball bien connu.
il faut choisir tout de même un seuil entre 0 et 1... 0.2 devrait bien marcher.

pour évaluer la distance (approximativement) à la racine d'une fonction f:

0.5 * f(x) * log(f(x)) / f'(x) marche assez bien comme évaluateur... (seulement pour la distance extérieure quand f(x) > 0 à cause du logarithme)...

j'ai jamais essayé sur des fonctions dans le cas général, mais ça a l'air de bien marcher pour le mandelbulb...
« Last Edit: 03 December 2010 à 18:02:26 by nystep »

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #42 on: 03 December 2010 à 20:27:37 »
Merci bien Nystep !

J'avais trouvé une formule similaire la même formule sous cette forme : f(p) = R / length(centre - p)
Mais je n'arrivais pas à en déduire une fonction de distance. Parce que cette formule donne en fait l'énergie à un point  p dans le champ de la metaball, et nous il nous faut la distance à une "courbe de niveau de ce champ" en fait (je crois que ça je l'ai bien intégré ;)).

Enfin bref, je vais m'empresser de tester ta formule :D

Pour ma formule, je suis tombé dessus assez par hasard, mais elle ne me satisfait pas, elle est assez compliquée à maîtriser. Et puis ce que j'ai réussi à produire ne ressemble pas vraiment à des metaballs, même s'il y a continuité ;)
« Last Edit: 03 December 2010 à 20:30:03 by flure »

Offline flure

  • Base
    • Pouet.net
    • View Profile
  • Ancienneté: 1998
  • Groupe: PoPsY TeAm
  • Rôle: Codeur Linux
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #43 on: 04 December 2010 à 18:48:20 »
Bon je continue avec mes aventures en raymarching.
J'essaye maintenant de faire des ombres projetées, et évidemment j'ai quelques petits soucis.
Comme vous le voyez sans doute, j'ai une ombre projetée correcte de ma sphère, mais j'ai plein d'artifacts sur les murs (et sur la sphère aussi d'ailleurs). On dirait que des zones qui ne devraient pas être ombrées le sont quand même.

Pour calculer si un pixel doit être ombré, je raymarche depuis la light vers la position que je veux ombrer. Si lors du raymarching je touche une surface avant d'arriver à la position, c'est donc qu'il doit être ombré. Je pense que mon problème est un problème de précision : quand le rayon de lumière est rasant par rapport à une surface, il détecte parfois un hit alors qu'il ne devrait pas. Je me trompe ?

Pour info voici la fonction qui me permet de savoir si on doit ombrer ou pas :
Code: [Select]
bool isLit(vec3 pos, vec3 light)
{
vec3 dt = light;
float l = length(light - pos);
vec3 r = normalize(pos - light);
float stepped = 0.0;
float d = MAX_DIST;

while((d > EPSILON) && (stepped < MAX_DIST))
{
dt = light + r * stepped;
d = distanceFunc(dt);
if(d < EPSILON) break;
stepped += d;
}

return abs(l - stepped) <= EPSILON;
}

La light est positionnée dans le coin supérieur droit de la box.

Voilà donc je pense qu'il faut que je trouve un moyen d'améliorer la précision de mes intersections évidemment. Mais si je diminue mon epsilon je me retrouve avec du noise, donc il va falloir que je trouve autre chose. Je vais sans doute creuser de ce côté : http://sizecoding.blogspot.com/2008/08/isosurfaces-in-glsl.html

Offline Patapom

  • Base
    • View Profile
    • www.patapom.com
  • Ancienneté: 1988
  • Groupe: Bomb!
  • Rôle: Coder
  • Ville: Lyon
Re : Raymarching - besoin d'explications
« Reply #44 on: 04 December 2010 à 20:10:04 »
On dirait plutôt que tu as l'erreur typique du mec qui fait du ray-tracing pour la première fois ! ;D

Tu retournes à ton adolescence : tu as ce qu'on appelle "de l'acnée". Z-acnea...
En gros, quand tu lances ton rayon depuis le point à éclairer jusqu'à la light, tu pars trop près du mur et il trouve une intersection immédiatement. Aux erreurs de précision près, d'où un changement brutal de l'éclairage d'un pixel à l'autre : t'as du noise.

Essaye de faire :

pos += epsilon * normal

pour offseter ta position de départ en dehors du mur lors du premier step. Ca devrait résoudre ton problème...
.  Pom  .