문제

나는 취미 프로젝트로 간단한 레이 트레이서를 쓰려고 노력하고 있으며 소프트 섀도우가 전혀 작동하지 않는 것을 제외하고는 모두 잘 작동합니다. 소프트 섀도에 대한 나의 생각은 LightsOrce에 위치와 반경이있는 것으로 간주된다는 것입니다. 이 조명에 대한 그림자 테스트를 수행하려면 1 차 광선이 장면에서 물체를 치고 각각의 새로운 광선이 모든 축에 임의의 구성 요소가있는 Lightsource를 향해 N-Amount를 시전하는 지점을 취합니다. -Radius와 Radius 사이.

그러한 광선이 장면에서 물체를 때리면 hitcounter를 증가시킵니다 (광선이 여러 객체에 닿는 경우 여전히 하나만 증가합니다). 충돌없이 Lightsource에 연결되면 기본 Ray의 교차점의 거리를 LightsOrce의 중심에 변수에 추가합니다.

N 샘플을 채취하면 충돌 한 광선의 비율을 계산하고 빛의 색상 에이 비율을 곱하여 (1000,1000,1000의 색상의 빛은 0.5의 비율로 500,500,500이 될 것입니다. 충돌했다). 그런 다음 이전의 거리 변수를 비 종합 광선의 양으로 나누어 Lightsource까지의 평균 거리는 계산합니다. 나는 그 변수를 반환하고 함수는 종료됩니다.

문제는 다음과 같습니다. 작동하지 않습니다. 적어도. 그것이 어떻게 생겼는지 볼 수 있습니다 여기. 당신이 진짜 끈기를 곁들인 경우 소프트 섀도와 비슷한 것을 볼 수 있습니다.

나는 그것을 얻지 못하고, 나는 여기서 일종의 근본적인 결함을 만들고 있습니까, 아니면 작은 것입니까? 이 방법에서 직접 생성 된 부분 itt 픽셀의 수를 계산할 때 더 많은 것이있을 때 약 250 개에 불과하기 때문에이 방법에 문제가 있다고 확신합니다. 그리고 그림을 자세히 살펴보면 부분적으로 켜진 부분 픽셀이 있음을 알 수 있습니다. 나머지 코드 프로세스는 부분적으로 켜진 픽셀을 잘 알 수 있습니다.

Soft Shadows 클래스의 실제 조명은 다음과 같습니다.

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
  }
}
도움이 되었습니까?

해결책

"loc"의 각 구성 요소마다 다른 "rand"를 생성 해보십시오. 그대로, 당신의 지구 포인트는 모두 한 줄에 있습니다.

다른 팁

사소한 포인트이지만 이것이 임의의 클래스의 가장 잘 사용하는 것입니다 ..

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

이건 ..

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

실제로 방향 (1, 1, 1)이있는 선으로 선의 지점을 생성합니다. LightsOrce가 정말로 선형입니까?

또한, 나는 당신의 예에서 간신히 볼 수 없습니다. 카메라가 그림자에 가까워지고 빛의 방향을 가리키지 않아도 될까요?

참조, 이것이 내가이 사이트에 오는 이유입니다 :)

모든 축에는 이제 자체 무작위가 있으며 훨씬 좋아 보입니다. 여전히 조금 이상한 모습으로 샘플의 수를 늘리는 것이 도움이됩니다. 지금은 모양입니다 이것.

패턴 형식을 줄이는 더 효율적인 방법을 알고 있습니까?

가장 큰 도움 : 모든 샘플에 대해 무작위로 인스턴스화하지는 않습니다. 그것은 부드러운 그림자로 내 렌더링 속도를 심각하게 3 배로 늘 렸습니다! 나는 무작위가 인스턴스화하는 데 너무 많은 비용이 든다는 것을 결코 알지 못했습니다. 우와.

정말 감사합니다.

응답으로 부드러운 그림자를 만들 수있는 개선 된 방법을 요청했습니다. 개선은 동일한 지점에서 모든 광선을 무작위로 무작위 화하는 대신 모든 축에 다른 오프셋을 제공하여 무작위 화 될 수있는 별도의 작은 창을 효과적으로 제공 할 수 있습니다. 이로 인해 더 많은 분포가 발생해야합니다. 그것이 명확했는지는 모르겠지만 그것을 설명하는 또 다른 방법은 그림자 광선에 수직 인 그리드입니다. 그리드의 각 타일에는 n 그림자 광선 중 하나가 포함되어 있지만 그리드의 위치는 무작위입니다. 여기 부드러운 그림자에 어떻게 사용할 수 있는지 설명하는 튜토리얼의 일부를 찾을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top