Pregunta

Estoy tratando de escribir un trazador de rayos simple como un proyecto de pasatiempo y es todo funcionando bien ahora, excepto que no puedo conseguir suaves sombras que funcionan en absoluto. Mi idea de suaves sombras es que la fuente de luz se considera que tiene un lugar y un radio. Para hacer una prueba de sombra en esta luz tomo el punto en el que el rayo principal chocó contra un objeto en la escena y lanzó un n-cantidad de rayos hacia la fuente de luz, donde cada nuevo rayo tiene un componente aleatorio a cada eje, en el que el componente aleatorio varía entre -radius y el radio.

Si un rayo tales golpea un objeto en la escena, incrementar un hitcounter (si un rayo golpea varios objetos, todavía solamente incrementa con una). Si lo hace a la fuente de luz y sin colisiones, agrego la distancia de Punto intersección del rayo principal del centro de la fuente de luz a una variable.

Cuando se han tomado N muestras, calculo la proporción de rayos que han colisionado y multiplicar el color de la luz por esta relación (por lo que una luz con el color 1000,1000,1000 se convertirá en 500 500 500 con una relación de 0,5, en donde la mitad de los rayos han chocado). Entonces calcular la distancia promedio a la fuente de luz dividiendo la variable distancia de antes por la cantidad de rayos no chocar. Vuelvo esa variable y se cierra la función.

El problema es: no funciona. No del todo al menos. Lo que parece que se puede ver aquí . Se puede ver que se asemeja a una especie de suaves sombras, si usted escudriña muy duro.

No entiendo, estoy haciendo algún tipo de defecto fundamental aquí, o es algo pequeño? Estoy bastante seguro de que el problema es en este método, porque cuando cuente el número de píxeles parcialmente iluminados producidos directamente por este método, sólo hay alrededor de 250, cuando debería ser mucho más. Y cuando se mira de cerca la imagen, se puede ver que hay algunos píxeles parcialmente iluminados, lo que sugiere que el resto del código procesa los píxeles parcialmente iluminadas bien.

Aquí está la luz real para la clase suave sombras:

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
  }
}
¿Fue útil?

Solución

Trate de generar una "rand" diferente para cada componente de "loc". Como es, sus puntos con fluctuación todos se encuentran en una línea.

Otros consejos

punto menor, pero es este el mejor uso de la clase al azar ..

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

si esto no fuera ..

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

En realidad se genera el punto de la línea en una línea con la dirección (1, 1, 1). Es realmente la fuente de luz lineal?

Además, apenas puedo ver nada en su ejemplo. Podría hacer la cámara más cerca de la a-ser la sombra y no se apunta desde la dirección de la luz?

Vea, es por eso que vengo a este sitio:)

Cada eje tiene su propio aleatoria ahora, y se ve mucho mejor. Es todavía un poco de aspecto extraño, aumentando el número de muestras de ayuda sin embargo. Ahora parece que rel="nofollow este .

¿Sabe usted una forma más eficiente para reducir el patrón de formación?

La ayuda más grande sin embargo: no crear instancias aleatoria para cada muestra. En serio, tres veces la velocidad de renderizado con sombras suaves! No sabía que era tan costosa aleatoria para crear una instancia. Wow.

Muchas gracias.

En su respuesta usted pidió una forma mejorada para hacer sombras suaves. Una mejora podría ser, en lugar de la aleatorización de todos los rayos desde el mismo punto, para dar a cada rayo de un desplazamiento diferente en todos los ejes para darles forma efectiva una pequeña ventana separada para seleccionar al azar. Esto debería dar lugar a una distribución más uniforme. No sé si eso era clara, pero otra forma de describirlo es como una rejilla que es perpendicular al rayo sombra. Cada baldosa en la cuadrícula contiene uno de los rayos n sombra pero la ubicación en la cuadrícula es aleatoria. Aquí se puede encontrar una parte de un tutorial que describe cómo se puede utilizar para sombras suaves.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top