Pergunta

Eu estou tentando escrever uma raytracer simples como um hobby e está tudo funcionando bem agora, só que eu não consigo soft-sombras de trabalhar em conjunto. Minha idéia de soft-sombras é que o lightsource é considerada como tendo um local e um raio. Para fazer um teste de sombra sobre esta luz Eu tiro o ponto onde o raio primário atingiu um objeto na cena e lançou um n-quantidade de raios para o lightsource onde cada nova ray tem um componente aleatório para cada eixo, onde os varia componente aleatório entre -radius e raio.

Se tal raio atinge um objeto na cena, eu incrementar um hitcounter (se um raio atinge vários objetos, ainda apenas incrementos com um). Se torna-se ao lightsource sem colisões, acrescento a distância do ponto de intersecção do raio principal para o centro da lightsource a uma variável.

Quando n amostras foram tomadas, I calcular o rácio de raios que colidem e multiplicar a cor da luz por esta razão (assim uma luz com cor 1000,1000,1000 se tornará 500500500 com uma proporção de 0,5, onde metade dos raios colidiram). Então eu calcular a distância média para o lightsource dividindo a variável distância de mais cedo pela quantidade de raios não colidir. Eu voltar a variável e as saídas de função.

O problema é: ele não funciona. Não é bem assim, pelo menos. O que parece que pode ser visto aqui . Você pode ver que tipo de se assemelha soft-sombras, se você é vesgo duro real.

Eu não entendo, eu estou fazendo algum tipo de falha fundamental aqui, ou é algo minúsculo? Estou bastante certo de que o problema é neste método, porque quando eu contar o número de pixels parcialmente iluminados produzidos diretamente por este método, existem apenas cerca de 250, quando deve haver muito mais. E quando você olhar atentamente para a foto, você pode ver que há alguns pixels parcialmente iluminados, sugerindo que o resto do código processa os pixels parcialmente iluminados apenas multa.

Aqui está a luz real para a classe soft-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
  }
}
Foi útil?

Solução

Tente gerar uma "rand" diferente para cada componente de "loc". Como é, os seus pontos Jittered tudo mentira em uma linha.

Outras dicas

ponto menor, mas é este o melhor uso da classe aleatório ..

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

caso de não ser ..

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

Você realmente gerar o ponto na linha em uma linha com a direção (1, 1, 1). É o lightsource realmente linear?

Além disso, eu mal posso ver nada no seu exemplo. você poderia fazer sua câmera mais perto do a-ser sombra e não apontando na direção da luz?

Veja, é por isso que eu venho a este site:)

Cada eixo tem a sua própria aleatório agora, e parece muito melhor. Ainda é um pouco estranho à procura, aumentando o número de amostras ajuda embora. Agora parece que este .

Você sabe uma maneira mais eficiente para reduzir a formação de padrão?

A maior ajuda embora: não instanciar aleatória para cada amostra. Ele triplicou seriamente a minha velocidade de renderização com sombras suaves! Eu nunca soube que a Random era tão caro para instanciar. Wow.

Muito obrigado.

Na sua resposta, você pediu um modo melhorado para tornar sombras suaves. Uma melhoria poderia ser, em vez de randomizing todos os raios do mesmo ponto, para dar a cada ray um deslocamento em todos os eixos para diferentes efetivamente dar-lhes uma pequena janela separada para embaralhar. Isso deve resultar em uma distribuição mais uniforme. Eu não sei se isso era clara, mas uma outra maneira de descrevê-lo é como uma grade que é perpendicular ao raio sombra. Cada telha na grade contém um dos raios n sombra mas a localização na grade é aleatória. Aqui pode encontrar uma parte de um tutorial que descreve como isso pode ser usado para sombras suaves.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top