Пример #1
0
            /// <summary>
            /// Scatter a ray using the BRDF and Impulses
            /// </summary>
            public ScatteredRay Scatter(PositionNormalCoordinate surfel, float3 w)
            {
                float selection   = random();
                float impulseProb = 0;

                foreach (var impulse in GetBRDFImpulses(surfel, w))
                {
                    float pdf = (impulse.Ratio.x + impulse.Ratio.y + impulse.Ratio.z) / 3;

                    if (selection < pdf) // this impulse is choosen
                    {
                        return new ScatteredRay
                               {
                                   Ratio     = impulse.Ratio / abs(dot(surfel.Normal, impulse.Direction)),
                                   Direction = impulse.Direction,
                                   PDF       = pdf
                               }
                    }
                    ;
                    selection   -= pdf;
                    impulseProb += pdf;
                }

                float3 wout = randomHSDirection(surfel.Normal);

                /// BRDF uniform sampling
                return(new ScatteredRay
                {
                    Direction = wout,
                    Ratio = EvalBRDF(surfel, wout, w),
                    PDF = (1 - impulseProb) / (2 * pi)
                });
            }
        }
Пример #2
0
            public float3 EvalBRDF(PositionNormalCoordinate surfel, float3 wout, float3 win)
            {
                float3 diffuse  = Diffuse * (DiffuseMap == null ? float3(1, 1, 1) : DiffuseMap.Sample(TextureSampler, surfel.Coordinates).xyz) / pi;
                float3 H        = normalize(win + wout);
                float3 specular = Specular * pow(max(0, dot(H, surfel.Normal)), SpecularPower) * (SpecularPower + 2) / two_pi;

                return(diffuse * WeightDiffuse / WeightNormalization + specular * WeightGlossy / WeightNormalization);
            }
Пример #3
0
        public float3 EvalBRDF(PositionNormalCoordinate surfel, float3 wout, float3 win)
        {
            float3 diffuse  = Diffuse.Sample(TextureSampler, surfel.Coordinates).xyz / pi;
            float3 H        = normalize(win + wout);
            float3 specular = Specular * pow(max(0, dot(H, surfel.Normal)), SpecularPower) * (SpecularPower + 2) / two_pi;

            return(diffuse * (1 - Glossyness) + specular * Glossyness);
        }
Пример #4
0
            public IEnumerable <Impulse> GetBRDFImpulses(PositionNormalCoordinate surfel, float3 wout)
            {
                if (!any(Specular))
                {
                    yield break; // No specular => Ratio == 0
                }
                float NdotL = dot(surfel.Normal, wout);
                // Check if ray is entering the medium or leaving
                bool entering = NdotL > 0;

                // Invert all data if leaving
                NdotL         = entering ? NdotL : -NdotL;
                surfel.Normal = entering ? surfel.Normal : -surfel.Normal;
                float ratio = entering ? 1.0f / this.RefractionIndex : this.RefractionIndex / 1.0f; // 1.0f air refraction index approx

                // Reflection vector
                float3 R = reflect(wout, surfel.Normal);

                // Refraction vector
                float3 T = refract(wout, surfel.Normal, ratio);

                // Reflection quantity, (1 - F) will be the refracted quantity.
                float F = ComputeFresnel(NdotL, ratio);

                if (!any(T))
                {
                    F = 1;                                // total internal reflection (produced with critical angles)
                }
                if (WeightMirror + WeightFresnel * F > 0) // something is reflected
                {
                    yield return new Impulse
                           {
                               Direction = R,
                               Ratio     = Specular * (WeightMirror + WeightFresnel * F) / WeightNormalization
                           }
                }
                ;

                if (WeightFresnel * (1 - F) > 0) // something to refract
                {
                    yield return new Impulse
                           {
                               Direction = T,
                               Ratio     = Specular * WeightFresnel * (1 - F) / WeightNormalization
                           }
                }
                ;
            }