public override Color Tracing(Ray ray, Sky sky, SamplerBase sampler, int depth = 0) { if (depth > tracingTimes) { return(Color.black); } RayCastHit hit; hit.distance = double.MaxValue; if (sceneData.Raycast(ray, m_Epsilon, out hit)) { hit.depth = depth; if (hit.shader == null) { return(new Color(1, 0, 1)); } return(hit.shader.Render(this, sky, sampler, ray, hit, m_Epsilon)); } else { if (sky != null) { return(sky.RenderColor(ray.direction)); } return(Color.black); } }
/// <summary> /// 根据焦距和透镜半径计算光线 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="sampler"></param> /// <returns></returns> private Ray GetThinLensRayFromPixel(int x, int y, SamplerBase sampler) { if (renderTarget == null) { throw new System.NullReferenceException(); } var sample = sampler.SampleUnitSquare(); double px = (renderTarget.width - 1 - (sample.x + x)) / renderTarget.width * 2 - 1; double py = (sample.y + y) / renderTarget.height * 2 - 1; px *= m_Width; py *= m_Height; double per = focal / near; px = px * per; py = py * per; Vector3 p = position + right * px + up * py + forward * focal; Vector2 disk = sampler.SampleUnitDisk(); Vector3 ori = position + right * disk.x * radius + up * disk.y * radius; Vector3 dir = (p - ori).normalized; return(new Ray(ori, dir)); }
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 override float SampleBRDF(SamplerBase sampler, Vector3 wo, Vector3 wi, Vector3 position, Vector3 normal, float roughness) { double denominator = 4.0 * Math.Max(Vector3.Dot(normal, wi), 0.0) * Math.Max(Vector3.Dot(normal, wo), 0.0) + 0.001; //float nominator = D_GGX((wi + wo).normalized, normal, roughness) * G_SmithGGX(wi, wo, normal, roughness); float nominator = G_SmithGGX(wi, wo, normal, roughness); return(nominator / (float)denominator); }
internal void RenderPixel(int x, int y, SamplerBase sampler, Scene scene) { for (int k = 0; k < sampler.numSamples; k++) { var sample = sampler.Sample(); Ray ray = GetRayFromPixel(x + sample.x, y + sample.y); m_RenderTarget.SetPixel(x, y, scene.tracer.Tracing(ray, scene.sky, sampler)); } }
public RenderJob(int x, int y, SamplerBase sampler, Scene scene, Camera camera) { this.x = x; this.y = y; this.sampler = sampler; this.scene = scene; this.camera = camera; this.resetEvent = new ManualResetEvent(false); }
public override Color Render(Tracer tracer, Sky sky, SamplerBase sampler, Ray ray, RayCastHit hit, double epsilon) { Vector3 refl = Vector3.Reflect(ray.direction, hit.normal); if (sky != null) { return(sky.RenderColor(refl)); } return(Color.white); }
public override Ray GetRay(int x, int y, SamplerBase sampler) { if (useThinLens) { return(GetThinLensRayFromPixel(x, y, sampler)); } var sample = sampler.SampleUnitSquare(); return(GetRayFromPixel(sample.x + x, sample.y + y)); }
public PathTracerRenderJobResult Render(Scene scene, PathTracer renderer, SamplerBase sampler) { //int tileWidth = m_Width - m_TileX; //if (tileWidth > 32) // tileWidth = 32; //int tileHeight = m_Height - m_TileY; //if (tileHeight > 32) // tileHeight = 32; //PathTracerRenderJobResult result = new PathTracerRenderJobResult(m_I, m_J, tileWidth, tileHeight); //for (; m_J < m_Height && m_J - m_TileY < 32;m_J++) //{ // for(; m_I < m_Width && m_I - m_TileX < 32;m_I++) // { // Color col = Color.black; // sampler.ResetSampler(); //重置采样器状态 // while (sampler.NextSample()) // { // Ray ray = scene.camera.GetRay(m_I, m_J, sampler); // col += renderer.PathTracing(ray, sampler); // } // col /= sampler.numSamples; // col.a = 1.0f; // result.SetPixel(m_I, m_J, col); // } // if (m_I >= m_Width || m_I - m_TileX >= 32) // { // m_I = m_TileX; // } //} Color col = Color.black; sampler.ResetSampler(); //重置采样器状态 while (sampler.NextSample()) { Ray ray = scene.camera.GetRay(m_I, m_J, sampler); col += renderer.PathTracing(ray, sampler); } col /= sampler.numSamples; col.a = 1.0f; PathTracerRenderJobResult result = new PathTracerRenderJobResult(m_I, m_J, col); m_I++; if (m_I >= m_Width || m_I - m_TileX >= 32) { m_I = m_TileX; m_J++; } return(result); }
public Job(RenderConfig config, Scene scene, W renderer, ConcurrentQueue <IRenderWork <T, W> > works, ConcurrentQueue <T> results, ManualResetEvent resetEvent) { m_Works = works; m_Results = results; m_ResetEvent = resetEvent; m_Scene = scene; m_Renderer = renderer; m_Sampler = SamplerFactory.Create(config.samplerType, config.numSamples, config.numSets); }
public override Vector3 Sample(SamplerBase sampler) { Vector3 localPoint = SampleLocalPosition(sampler); if (m_IsRotated) { return(m_LocalToWorld.TransformPoint(localPoint)); } else { return(position + localPoint); } }
public Color Shade(Material skyMaterial, SamplerBase sampler, Ray ray) { if (skyMaterial == null) { return(Color.black); } RayCastHit hit = default(RayCastHit); hit.normal = ray.direction; return(skyMaterial.GetEmissive(hit)); }
public override float SampleBRDF(SamplerBase sampler, Vector3 wo, Vector3 wi, Vector3 position, Vector3 normal, float roughness) { double oneMinusCosL = 1.0 - Vector3.Dot(wi, normal); double oneMinusCosLSqr = oneMinusCosL * oneMinusCosL; double oneMinusCosV = 1.0 - Vector3.Dot(wo, normal); double oneMinusCosVSqr = oneMinusCosV * oneMinusCosV; // Roughness是粗糙度,IDotH的意思会在下一篇讲Microfacet模型时提到 double IDotH = Vector3.Dot(wi, (wi + wo).normalized); double F_D90 = 0.5 + 2.0 * IDotH * IDotH * roughness; return((float)((1.0 / Math.PI) * (1.0 + (F_D90 - 1.0) * oneMinusCosLSqr * oneMinusCosLSqr * oneMinusCosL) * (1.0 + (F_D90 - 1.0) * oneMinusCosVSqr * oneMinusCosVSqr * oneMinusCosV))); }
public Color PathTracing(Ray ray, SamplerBase sampler, int depth = 0) { if (scene == null) { return(Color.black); } RayCastHit hit; hit.distance = double.MaxValue; Color color = Color.black; if (scene.sceneData.Raycast(ray, out hit)) { hit.depth = depth; if (hit.material == null) { color = new Color(1, 0, 1); } else { color = m_Shader.Shade(hit.material, sampler, ray, hit); } } else { if (depth > tracingTimes) { color = Color.black; } else if (scene.skyLight != null) { color = m_SkyShader.Shade(scene.skyLight.material, sampler, ray); } } color.FixColor(); #if DEBUG if (isDebugging) { Log.AddLog(LogType.Debugging, $"深度:{depth},射线:{ray},颜色:{color}"); } #endif return(color); }
public override Vector3 Sample(SamplerBase sampler) { throw new NotImplementedException(); }
public abstract Ray GetRay(int x, int y, SamplerBase sampler);
public override float SampleBRDF(SamplerBase sampler, Vector3 wo, Vector3 wi, Vector3 position, Vector3 normal, float roughness) { return((float)(1.0f / Math.PI)); }
public override Vector3 Sample(SamplerBase sampler, Vector3 hitPoint) { return(default(Vector3)); }
public abstract Vector3 Sample(SamplerBase sampler, Vector3 hitPoint);
public override Vector3 Sample(SamplerBase sampler, Vector3 hitPoint) { if (m_Geometry == null) return Vector3.zero; return m_Geometry.Sample(sampler); }
public abstract Color Render(Tracer tracer, Sky sky, SamplerBase sampler, Ray ray, RayCastHit hit, double epsilon);
public override Vector3 Sample(SamplerBase sampler) { return(position + sampler.SampleSphere() * radius); }
public override Vector3 Sample(SamplerBase sampler) { Vector2 pos = sampler.SampleUnitDisk(); return(position + right * (pos.x) + up * (pos.y)); }
public override Vector3 Sample(SamplerBase sampler, Vector3 hitPoint) { return(hitPoint + (sunDirection * -1.0) * kEarthSurfaceToSun + sampler.SampleSphere() * kSunRadius); }
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); }
/// <summary> /// /// </summary> /// <returns></returns> public abstract float SampleBRDF(SamplerBase sampler, Vector3 wo, Vector3 wi, Vector3 position, Vector3 normal, float roughness);
public abstract Vector3 Sample(SamplerBase sampler);
public abstract Color Tracing(Ray ray, Sky sky, SamplerBase sampler, int depth = 0);