public override void Sample_f(ShadePointInfo pt, float u0, float u1, float u2, out Vector vector, out float radiancePdf, out float pdf1, out BsdfEvent @event) { float c = 1f - Vector.Dot(ref pt.IncomingDirection, ref pt.ShadingNormal); float Re = R0 + (1f - R0) * c * c * c * c * c; float P = .25f + .5f * Re; if ((u2 < P && reflectionSpecularBounce)) {//onlySpecular || vector = MetalBrdf.GlossyReflection(ref pt.IncomingDirection, exponent, ref pt.ShadingNormal, u0, u1); pdf1 = P / Re; @event = BsdfEvent.Specular; radiancePdf = Re; } else { Vector dir = MC.CosineSampleHemisphere(u0, u1); pdf1 = dir.z * MathLab.INVPI; /* Vector v1, v2; * dir = Vector.CoordinateSystem(ref shadeN, out v1, out v2); dir = new Vector( v1.x * dir.x + v2.x * dir.y + shadeN.x * dir.z, v1.y * dir.x + v2.y * dir.y + shadeN.y * dir.z, v1.z * dir.x + v2.z * dir.y + shadeN.z * dir.z);*/ ONB fm = new ONB(ref pt.ShadingNormal); var wi = fm.ToWorld(ref dir);//pt.Frame float dp = Vector.Dot(ref pt.ShadingNormal, ref wi); // Using 0.0001 instead of 0.0 to cut down fireflies if (dp <= 0.0001f) { pdf1 = 0f; } pdf1 /= dp; float iRe = 1f - Re; pdf1 *= (1f - P) / iRe; @event = BsdfEvent.Glossy | BsdfEvent.Diffuse; vector = wi; radiancePdf = iRe; } }