Question

Je suis en train d'écrire simple raytraceur comme un projet passe-temps et tout fonctionne bien maintenant, sauf que je ne peux pas-ombres douces pour travailler du tout. Mon idée de-ombres douces est que le lightsource est considéré comme ayant un emplacement et un rayon. Pour faire un test d'ombre sur cette lumière que je prends le point où le rayon primaire a frappé un objet dans la scène et jeta un n-quantité de rayons vers la source de lumière où chaque nouveau rayon a une composante aléatoire à chaque axe, où la composante aléatoire varie entre un rayon de touche et le rayon.

Si un tel rayon frappe un objet sur la scène, j'incrémenter un hitcounter (si un rayon frappe plusieurs objets, il incrémente encore avec un seul). Si elle fait la lightsource sans collision, ajouter la distance du point d'intersection de rayon primaire au centre de la lightsource à une variable.

Si N échantillons ont été prises, je calcule le rapport des rayons qui sont entrés en collision et se multiplier la couleur de la lumière par ce rapport (pour une lumière de couleur 1000,1000,1000 deviendra 500.500.500 avec un ratio de 0,5, où la moitié des rayons sont entrés en collision). Ensuite, je calcule la distance moyenne en divisant la lightsource la variable de distance plus tôt par la quantité de rayons non entrant en collision. Je retourne cette variable et la sortie de fonction.

Le problème est le suivant: il ne fonctionne pas. Pas tout à fait au moins. À quoi il ressemble peut être vu . Vous pouvez le voir ressemble sorte de ombres douces, si vous strabisme vraiment dur.

Je ne comprends pas, que je fais une sorte de défaut fondamental ici, ou est-ce quelque chose de minuscule? Je suis assez sûr que le problème est dans cette méthode, parce que quand je compte le nombre de pixels partiellement éclairés produits directement par cette méthode, il y a seulement environ 250, quand il devrait y avoir beaucoup plus. Et quand vous regardez attentivement l'image, vous pouvez voir il y a quelques pixels partiellement éclairés, ce qui suggère le reste du code traite les pixels partiellement éclairés très bien.

Voici la lumière réelle pour la classe-ombres douces:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyFirstRayTracer
{
  public class AreaLight : ILight
  {
    private const int _radius = 5;
    private const int _samples = 16;
    public Color Color { get; set; }
    public Vector Location { get; set; }
    #region ILight Members

    public float GetLightingInformation(Vector point, ISceneObject[] scene, out Color color)
    {
      int intersectCount = 0;
      float distance = -1;
      for(int i = 0; i < _samples; i++)
      {
    bool intersects = false;
    float rand = 0;
    rand = _radius - (float)(new Random().NextDouble()*(2*_radius));
    foreach (ISceneObject obj in scene)
    {
      Vector iPoint;

      Vector loc = new Vector(Location.X + rand, Location.Y + rand, Location.Z + rand);

      if (!obj.Intersect(new Ray(point, loc), out iPoint))
      {
        distance += (Location - point).SqLength;

      }
      else
      {
        intersects = true;
        distance -= (Location - point).SqLength;
      }
    }
    if (intersects)
      intersectCount++;
      }
      float factor = 1-((float)intersectCount/_samples);

      color = new Color(factor*Color.R, factor*Color.G, factor*Color.B);

      return (float)Math.Sqrt(distance / (_samples - intersectCount));
    }


    #endregion
  }
}
Était-ce utile?

La solution

Essayez générer un autre « rand » pour chaque composante de « loc ». Comme il est, vos points se trouvent tous sur gigue une ligne.

Autres conseils

point mineur, mais est-ce la meilleure utilisation de la classe aléatoire ..

 for(int i = 0; i < _samples; i++)
      {
        bool intersects = false;
        float rand = 0;
        rand = _radius - (float)(new Random().NextDouble()*(2*_radius));

si cela ne pas être ..

    var rnd = new Random()    
    for(int i = 0; i < _samples; i++)
              {
                bool intersects = false;
                float rand = 0;
                rand = _radius - (float)(rnd.NextDouble()*(2*_radius));

Vous générez en fait le point sur la ligne sur une ligne avec la direction (1, 1, 1). Est-ce vraiment la lightsource linéaire?

De plus, je peux à peine voir quoi que ce soit dans votre exemple. Pourriez-vous faire votre appareil photo plus près de l'être à l'ombre et ne pointe pas de la direction de la lumière?

Voir, c'est pourquoi je viens sur ce site:)

Chaque axe a son propre maintenant au hasard, et il semble beaucoup mieux. Il est encore un peu bizarre à la recherche, en augmentant le nombre d'échantillons aide bien. Il ressemble maintenant cette .

Connaissez-vous un moyen plus efficace pour réduire la formation de motif?

La plus grande aide que: non instanciation aléatoire pour chaque échantillon. Il a sérieusement triplé ma vitesse de rendu avec des ombres douces! Je ne savais pas que au hasard était si cher à instancier. Wow.

Merci beaucoup.

Dans votre réponse vous avez demandé un meilleur moyen de faire des ombres douces. Une amélioration pourrait être, au lieu de tous les rayons randomiser du même point, pour donner à chaque rayon un décalage différent sur tous les axes de leur donner effectivement une petite fenêtre séparée randomiser. Cela devrait se traduire par une distribution plus uniforme. Je ne sais pas si cela était clair, mais une autre façon de le décrire est comme une grille qui est perpendiculaire au rayon d'ombre. Chaque tuile dans la grille contient l'un des rayons d'ombre n mais l'emplacement de la grille est aléatoire. vous pouvez trouver une partie d'un tutoriel qui explique comment cela peut être utilisé pour les ombres douces.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top