Domanda

Sto cercando di scrivere un semplice raytracer come un progetto hobby ed è tutto lavorare bene ora, tranne che non posso ottenere soft-ombre di lavorare a tutti. La mia idea di soft-ombre è che la sorgente di luce è considerato di avere una posizione e un raggio. Per fare un test ombra su questa luce prendo il punto in cui il raggio primario colpito un oggetto nella scena e gettato un n-quantità di raggi verso la sorgente di luce in cui ogni nuova ray ha una componente casuale ad ogni asse, in cui il componente casuale varia tra raggio di curvatura e raggio.

Se un tale raggio colpisce un oggetto nella scena, ho incrementare un hitcounter (se un raggio colpisce più oggetti, ancora incrementa solo uno). Se lo fa alla sorgente di luce, senza collisioni, aggiungo la distanza del punto di intersezione del raggio primario al centro della sorgente di luce a una variabile.

Quando sono stati prelevati campioni N, a calcolare il rapporto di raggi che sono scontrati e moltiplicare il colore della luce da questo rapporto (così una luce di colore 1000,1000,1000 diventerà 500.500.500 con un rapporto di 0,5, dove metà dei raggi si sono scontrati). Poi a calcolare la distanza media dalla sorgente luminosa dividendo la variabile distanza precedenza dalla quantità di raggi non collisione. Torno che variabile e la funzione termina.

Il problema è: non funziona. Non proprio, almeno. Quello che sembra può essere visto qui . Lo si può vedere una sorta di assomiglia soft-ombre, se si strabismo vero duro.

Non capisco, sto facendo una sorta di difetto fondamentale qui, o è qualcosa di molto piccolo? Sono abbastanza sicuro che il problema è in questo metodo, perché quando ho contare il numero di pixel parzialmente illuminati direttamente prodotti con questo metodo, ci sono solo circa 250, quando ci dovrebbe essere molto di più. E quando si guarda attentamente la foto, si può vedere ci sono alcuni pixel parzialmente illuminati, suggerendo il resto del codice elabora i pixel parzialmente illuminato bene.

Ecco la luce reale per la classe soft-ombre:

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
  }
}
È stato utile?

Soluzione

Prova la generazione di un "rand" diverso per ogni componente di "Loc". Come è, i tuoi punti jittered tutti giacciono su una linea.

Altri suggerimenti

punto minore, ma è questo il miglior utilizzo della classe casuale ..

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

ove ciò non sia ..

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

In realtà genera il punto sulla linea su una linea con la direzione (1, 1, 1). È la sorgente di luce davvero lineare?

Inoltre, riesco a malapena a vedere nulla nel tuo esempio. Potrebbe rendere la fotocamera più vicino alla to-be ombra e non puntando dalla direzione della luce?

Vedi, questo è il motivo per cui vengo a questo sito:)

Ogni asse ha il suo caso ora, e sembra molto meglio. E 'ancora un po' strano guardare, aumentando il numero di campioni aiuta però. Ora sembra questo .

Lo sai un modo più efficiente per ridurre il modello di formazione?

Il più grande aiuto però: non istanziare casuale per ogni campione. E 'seriamente triplicato la mia velocità di rendering con ombre morbide! Non ho mai saputo che a caso è stato così costoso da istanziare. Wow.

Grazie mille.

Nella tua risposta hai chiesto un modo migliore per fare le ombre morbide. Un miglioramento potrebbe essere, invece di randomizzazione tutti i raggi dallo stesso punto, per dare ogni raggio un offset su tutti gli assi per dare efficacemente una piccola finestra separata per randomizzare. Questo dovrebbe tradursi in una distribuzione più uniforme differente. Non so se questo era chiaro ma un altro modo di descrivere è come una griglia che è perpendicolare al raggio ombra. Ogni tessera nella griglia contiene uno dei raggi n ombra ma la posizione nella griglia è casuale. Qui è possibile trovare una parte di un tutorial che spiega come questo può essere utilizzato per le ombre morbide.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top