private Vector3 SampleLocalPosition(SamplerBase sampler) { double rand = sampler.GetRandom(); double areaRand = rand * (m_Area0 * 2.0 + m_Area1 * 2.0 + m_Area2 * 2.0); Vector2 sample = sampler.SampleUnitSquare(); if (areaRand < m_Area0) { return(new Vector3(-scale.x * 0.5 + scale.x * sample.x, -scale.y * 0.5 + scale.y * sample.y, -scale.z * 0.5)); } else if (areaRand >= m_Area0 && areaRand < m_Area0 * 2.0) { return(new Vector3(-scale.x * 0.5 + scale.x * sample.x, -scale.y * 0.5 + scale.y * sample.y, scale.z * 0.5)); } else if (areaRand >= m_Area0 * 2.0 && areaRand < m_Area0 * 2.0 + m_Area1) { return(new Vector3(-scale.x * 0.5, -scale.y * 0.5 + scale.y * sample.x, -scale.z * 0.5 + scale.z * sample.y)); } else if (areaRand >= m_Area0 * 2.0 + m_Area1 && areaRand < m_Area0 * 2.0 + m_Area1 * 2.0) { return(new Vector3(scale.x * 0.5, -scale.y * 0.5 + scale.y * sample.x, -scale.z * 0.5 + scale.z * sample.y)); } else if (areaRand >= m_Area0 * 2.0 + m_Area1 * 2.0 && areaRand < m_Area0 * 2.0 + m_Area1 * 2.0 + m_Area2) { return(new Vector3(-scale.x * 0.5 + scale.x * sample.x, -scale.y * 0.5, -scale.z * 0.5 + scale.z * sample.y)); } else { return(new Vector3(-scale.x * 0.5 + scale.x * sample.x, scale.y * 0.5, -scale.z * 0.5 + scale.z * sample.y)); } }
public Color Shade(Material material, SamplerBase sampler, Ray ray, RayCastHit hit) { if (hit.depth > m_PathTracer.tracingTimes) { if (material.IsEmissive() && m_PathTracer.sampleDirectLight && ray.isDiffuseRay) { return(Color.black); } return(material.GetEmissive(hit)); } if (material.IsEmissive()) { if (m_PathTracer.sampleDirectLight && hit.depth != 0 && ray.isDiffuseRay) { return(Color.black); } return(material.GetEmissive(hit)); } float refractive = material.GetRefractive(hit); float metallic = material.GetMetallic(hit); float roughness = material.GetRoughness(hit); float opacity = material.GetOpacity(hit); Color albedo = material.GetAlbedo(hit); Vector3 worldNormal = material.GetWorldNormal(hit); float ndv = (float)Math.Max(0.0f, Vector3.Dot(worldNormal, -1.0 * ray.direction)); if (hit.isBackFace) { refractive = 1.0f / refractive; } float F0 = (1.0f - refractive) / (1.0f + refractive); F0 = F0 * F0; if (F0 > 0.04f) { F0 = 0.04f; } Color F0Col = Color.Lerp(new Color(F0, F0, F0), albedo, metallic); Color fresnel = Fresnel.FresnelSchlick(ndv, F0Col, roughness); float fl = fresnel.Average(); ShadingType shadingType = ShadingType.Reflect; double russianRoulette = sampler.GetRandom(); if (fl > russianRoulette) { shadingType = ShadingType.Reflect; } else if (fl + (1.0f - fl) * (1.0f - opacity) > russianRoulette) { shadingType = ShadingType.Refract; } else { shadingType = ShadingType.Diffuse; } if (shadingType == ShadingType.Diffuse) { if (1.0f - metallic < float.Epsilon) { return(Color.black); } if (albedo.IsCloseToZero()) { return(Color.black); } Vector3 sp = sampler.SampleHemiSphere(); Vector3 wi = Vector3.ONB(worldNormal, sp); float pdf = (float)(sp.z / Math.PI); double ndl = Vector3.Dot(worldNormal, wi); if (ndl <= 0.0) { return(Color.black); } float brdf = (roughness < float.Epsilon ? m_LambertaianBRDF : m_DisneyDiffuseBRDF).SampleBRDF(sampler, ray.direction * -1.0, wi, hit.hit, worldNormal, roughness); if (brdf < float.Epsilon) { return(Color.black); } Ray diffuseRay = new Ray(hit.hit, wi, true); Color L = m_PathTracer.PathTracing(diffuseRay, sampler, hit.depth + 1); return(albedo * L * brdf * (1.0f - metallic) * (float)ndl / pdf); } if (shadingType == ShadingType.Reflect) { if (albedo.IsCloseToZero()) { return(Color.black); } Vector3 sp = sampler.SampleHemiSphere(roughness); Vector3 spnormal = Vector3.ONB(worldNormal, sp); Vector3 wo = ray.direction * -1.0; Vector3 wi = Vector3.Reflect(wo, spnormal); float pdf = (float)(sp.z / Math.PI); double ndl = Vector3.Dot(worldNormal, wi); if (ndl <= 0.0) { return(Color.black); } float brdf = m_CookTorranceBRDF.SampleBRDF(sampler, wo, wi, hit.hit, worldNormal, roughness); if (brdf < float.Epsilon) { return(Color.black); } Ray specularRay = new Ray(hit.hit, wi, false); Color L = m_PathTracer.PathTracing(specularRay, sampler, hit.depth + 1); return(Color.Lerp(Color.white, fresnel, metallic) * L * brdf * (float)ndl / pdf); } if (shadingType == ShadingType.Refract) { } return(Color.black); //MaterialProperty property; //property.worldNormal = material.GetWorldNormal(hit); //property.opacity = material.GetOpacity(hit); //property.metallic = material.GetMetallic(hit); //property.roughness = material.GetRoughness(hit); //property.albedo = material.GetAlbedo(hit); //if (m_PathTracer.sampleDirectLight) // result += ShadeDirectLights(property, sampler, ray, hit); //result += material.GetOcclusion(hit) * ShadeAmbientLight(property, sampler, ray, hit); //return result + material.GetEmissive(hit); }