public override bool L(SceneData sceneData, Ray ray, out Color color, out Vector3 surfaceNormal) { RayCastHit hit = default(RayCastHit); hit.distance = double.MaxValue; if (sceneData.Raycast(ray, out hit)) { color = Color.black; surfaceNormal = default(Vector3); return(false); } Vector3 hitNormal; if (RayCastSun(ray, out hitNormal)) { double ndl = Vector3.Dot(-1.0 * hitNormal, ray.direction); surfaceNormal = hitNormal; if (ndl < 0) { color = Color.black; return(false); } color = sunIntensity * sunColor; return(true); } color = Color.black; surfaceNormal = default(Vector3); return(false); }
public bool Raycast(Ray ray, out RayCastHit hit) { hit = default(RayCastHit); hit.distance = double.MaxValue; return(RaycastTriangles(ray, ref hit)); }
public override bool L(SceneData sceneData, Ray ray, out Color color, out Vector3 normal) { if (m_Geometry == null || m_Geometry.material == null) { color = Color.black; normal = default(Vector3); return false; } RayCastHit hit = default(RayCastHit); hit.distance = double.MaxValue; if (sceneData.Raycast(ray, out hit)) { if (hit.geometry == m_Geometry && hit.material == m_Geometry.material) { double ndl = Vector3.Dot(-1.0 * hit.normal, ray.direction); normal = hit.normal; if (ndl < 0) { color = Color.black; return false; } color = m_Geometry.material.GetEmissive(hit); return true; } } color = Color.black; normal = default(Vector3); return false; }
public override Vector3 GetWorldNormal(RayCastHit hit) { if (bump != null) { return(RecalucateNormal(hit.normal, hit.tangent, bump.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)))); } return(hit.normal); }
public override float GetRoughness(RayCastHit hit) { if (mroTex != null) { Color mro = mroTex.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)); return(mro.g); } return(roughness); }
public override float GetOcclusion(RayCastHit hit) { if (mroTex != null) { Color mro = mroTex.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)); return(mro.b); } return(1.0f); }
public override float GetMetallic(RayCastHit hit) { if (mroTex != null) { Color mro = mroTex.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)); return(mro.r); } return(metallic); }
public override Color GetEmissive(RayCastHit hit) { Color emissiveColor = emissive; if (emissiveTex != null) { emissiveColor *= emissiveTex.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)); } return(emissiveColor); }
public override Color GetAlbedo(RayCastHit hit) { Color albedoColor = color; if (albedo != null) { albedoColor *= albedo.Sample((float)(hit.texcoord.x * tile.x), (float)(hit.texcoord.y * tile.y)); } return(albedoColor); }
public override bool ShouldCull(Ray ray, RayCastHit hit) { if (!transparentCutOut) { return(false); } if (GetOpacity(hit) < 0.5f) { return(true); } return(false); }
public bool RayCast(Ray ray, ref RayCastHit hit) { if (RayCastGeometry(ray, ref hit)) { //如果射线检测成功,则额外判断一下shader是否允许cull,用于实现材质的alpha裁剪等功能 if (hit.material != null && hit.material.ShouldCull(ray, hit)) { return(false); } return(true); } return(false); }
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 bool RayCast(Ray ray, double epsilon, ref RayCastHit hit) { Vector3 tocenter = ray.origin - this.position; double vala = Vector3.Dot(ray.direction, ray.direction); double valb = Vector3.Dot(tocenter, ray.direction) * 2.0f; double valc = Vector3.Dot(tocenter, tocenter) - radius * radius; double dis = valb * valb - 4.0f * vala * valc; if (dis < 0.0) { return(false); } else { double e = Math.Sqrt(dis); double denom = 2.0f * vala; double t = (-valb - e) / denom; if (t > epsilon && t <= hit.distance) { // if (hit.depth == 0 && m_Material.isLight && LScene.ignoreLight) // return false; hit.distance = t; hit.normal = (tocenter + ray.direction * t) / radius; hit.hit = ray.origin + ray.direction * t; hit.shader = shader; hit.texcoord = default(Vector2); return(true); } t = (-valb + e) / denom; if (t > epsilon && t <= hit.distance) { // if (hit.depth == 0 && m_Material.isLight && LScene.ignoreLight) // return false; hit.distance = t; hit.normal = (tocenter + ray.direction * t) / radius; hit.hit = ray.origin + ray.direction * t; hit.shader = shader; hit.texcoord = default(Vector2); return(true); } } return(false); }
public override Color GetEmissive(RayCastHit hit) { if (environment == null) { return(color * intensity); } float fi = (float)Math.Atan2(hit.normal.x, hit.normal.z); float InvPi = (float)(1.0 / Math.PI); float u = fi * 0.5f * InvPi; float theta = (float)Math.Acos(hit.normal.y); float v = 1.0f - theta * InvPi; return(environment.Sample(u, v) * color * intensity); }
public override bool Raycast(Ray ray, double epsilon, out RayCastHit hit) { hit = default(RayCastHit); hit.distance = double.MaxValue; bool result = false; for (int i = 0; i < m_Geometrys.Count; i++) { if (m_Geometrys[i].RayCast(ray, epsilon, ref hit)) { result = true; } } return(result); }
protected override bool RaycastTriangles(Ray ray, ref RayCastHit hit) { if (m_Geometries == null) { return(false); } if (!m_Bounds.Raycast(ray)) { return(false); } bool result = false; for (int i = 0; i < m_Geometries.Count; i++) { if (m_Geometries[i].RayCast(ray, ref hit)) { result = true; } } return(result); }
public override Color FastRender(Ray ray, RayCastHit hit) { float vdn = (float)Math.Max(0, Vector3.Dot(-1.0 * ray.direction, hit.normal)); return(new Color(vdn, vdn, vdn, 1.0f)); }
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); }
protected abstract bool RaycastTriangles(Ray ray, ref RayCastHit hit);
public virtual float GetMetallic(RayCastHit hit) { return(0.0f); }
protected override bool RayCastGeometry(Ray ray, ref RayCastHit hit) { double t = Vector3.Dot(this.position - ray.origin, this.normal) / Vector3.Dot(ray.direction, this.normal); if (t <= double.Epsilon) { return(false); } if (t > hit.distance) { return(false); } Vector3 p = ray.origin + ray.direction * t; Vector3 d = p - this.position; double ddw = Vector3.Dot(d, this.right); if (ddw < 0.0 || ddw > this.widthSquared) { return(false); } double ddh = Vector3.Dot(d, this.up); if (ddh < 0.0 || ddh > this.heightSquared) { return(false); } hit.distance = t; hit.normal = normal; Vector3 lp = p - this.position; double texcoordx = Vector3.Dot(lp, this.right) / this.right.magnitude; double texcoordy = Vector3.Dot(lp, this.up) / this.up.magnitude; hit.texcoord = new Vector2(texcoordx, texcoordy); hit.normal = this.normal; Vector3 tang = this.right.normalized; hit.tangent = new Vector4(tang.x, tang.y, tang.z, 1.0); hit.material = material; hit.geometry = this; hit.hit = p; double ndv = Vector3.Dot(normal, ray.origin - hit.hit); if (ndv < 0) { if (material != null && !material.ShouldRenderBackFace()) { return(false); } hit.isBackFace = true; hit.normal *= -1; } else { hit.isBackFace = false; } //if (hit.isBackFace) // hit.hit -= hit.normal * 0.00000000000001; //else hit.hit += hit.normal * 0.00000000000001; //hit.distance = Vector3.Distance(hit.hit, ray.origin); return(true); }
protected override bool RayCastGeometry(Ray ray, ref RayCastHit hit) { Vector3 tocenter = ray.origin - this.position; double vala = Vector3.Dot(ray.direction, ray.direction); double valb = Vector3.Dot(tocenter, ray.direction) * 2.0f; double valc = Vector3.Dot(tocenter, tocenter) - radius * radius; double dis = valb * valb - 4.0f * vala * valc; if (dis < 0.0) { return(false); } else { double e = Math.Sqrt(dis); double denom = 2.0f * vala; double t = (-valb - e) / denom; if (t > double.Epsilon && t <= hit.distance) { hit.distance = t; hit.normal = (tocenter + ray.direction * hit.distance) / radius; hit.hit = ray.origin + ray.direction * hit.distance; hit.material = material; hit.geometry = this; hit.texcoord = GetUV(hit.normal); Vector3 tang = Vector3.Cross(new Vector3(0, 1, 0), hit.normal).normalized; hit.tangent = new Vector4(tang.x, tang.y, tang.z, 1.0); double ndv = Vector3.Dot(hit.normal, ray.origin - hit.hit); if (ndv < 0) { if (material != null && !material.ShouldRenderBackFace()) { return(false); } hit.isBackFace = true; hit.normal *= -1; } else { hit.isBackFace = false; } //if (hit.isBackFace) // hit.hit -= hit.normal * 0.00000000000001; //else hit.hit += hit.normal * 0.00000000000001; //hit.distance = Vector3.Distance(hit.hit, ray.origin); return(true); } t = (-valb + e) / denom; if (t > double.Epsilon && t <= hit.distance) { hit.distance = t; hit.normal = (tocenter + ray.direction * hit.distance) / radius; hit.hit = ray.origin + ray.direction * hit.distance; hit.material = material; hit.geometry = this; hit.texcoord = GetUV(hit.normal); Vector3 tang = Vector3.Cross(new Vector3(0, 1, 0), hit.normal).normalized; hit.tangent = new Vector4(tang.x, tang.y, tang.z, 1.0); double ndv = Vector3.Dot(hit.normal, ray.origin - hit.hit); if (ndv < 0) { if (material != null && !material.ShouldRenderBackFace()) { return(false); } hit.isBackFace = true; hit.normal *= -1; } else { hit.isBackFace = false; } //if (hit.isBackFace) // hit.hit -= hit.normal * 0.00000000000001; //else hit.hit += hit.normal * 0.00000000000001; //hit.distance = Vector3.Distance(hit.hit, ray.origin); return(true); } } return(false); }
public override bool RayCast(Ray ray, double epsilon, ref RayCastHit hit) { if (bounds.Raycast(ray) == false) { return(false); } double rt = 0.0f; Vector3 e1 = this.v1 - this.v0; Vector3 e2 = this.v2 - this.v0; double v = 0; double u = 0; Vector3 n = Vector3.Cross(e1, e2); double ndv = Vector3.Dot(ray.direction, n); if (ndv > 0) { return(false); } Vector3 p = Vector3.Cross(ray.direction, e2); double det = Vector3.Dot(e1, p); Vector3 t = default(Vector3); if (det > 0) { t = ray.origin - this.v0; } else { t = this.v0 - ray.origin; det = -det; } if (det < epsilon) { return(false); } u = Vector3.Dot(t, p); if (u < 0.0 || u > det) { return(false); } Vector3 q = Vector3.Cross(t, e1); v = Vector3.Dot(ray.direction, q); if (v < 0.0 || u + v > det) { return(false); } rt = Vector3.Dot(e2, q); double finvdet = 1.0 / det; rt *= finvdet; if (rt < 0.001) { return(false); } if (rt > hit.distance) { return(false); } u *= finvdet; v *= finvdet; hit.hit = ray.origin + ray.direction * rt; hit.texcoord = (1.0f - u - v) * uv0 + u * uv1 + v * uv2;; hit.normal = (1.0f - u - v) * n0 + u * n1 + v * n2; hit.shader = shader; hit.distance = rt; return(true); }
protected override bool RayCastGeometry(Ray ray, ref RayCastHit hit) { double tmin = 0.0; double tmax = hit.distance; Vector3 cubeCenter = m_IsRotated ? Vector3.zero : position; Vector3 min = cubeCenter - scale * 0.5; Vector3 max = cubeCenter + scale * 0.5; Vector3 normal = default(Vector3); Vector3 rayOrigin = m_IsRotated ? m_WorldToLocal.TransformPoint(ray.origin) : ray.origin; Vector3 rayDir = m_IsRotated ? m_WorldToLocal.TransformVector(ray.direction) : ray.direction; int hitFace = 0; for (int i = 0; i < 3; i++) { Vector3 n = new Vector3(i == 0 ? -1 : 0, i == 1 ? -1 : 0, i == 2 ? -1 : 0); if (Math.Abs(rayDir[i]) < double.Epsilon) { if (rayOrigin[i] < min[i] || rayOrigin[i] > max[i]) { return(false); } } else { int hf = i + 1; double ood = 1.0 / rayDir[i]; double t1 = (min[i] - rayOrigin[i]) * ood; double t2 = (max[i] - rayOrigin[i]) * ood; if (t1 > t2) { double t = t2; t2 = t1; t1 = t; n *= -1; hf = i + 4; } if (t1 > tmin) { tmin = t1; normal = n; hitFace = hf; } if (t2 < tmax) { tmax = t2; } if (tmin > tmax) { return(false); } } } //if (tmin > -double.Epsilon && tmin < double.Epsilon) // return false; hit.distance = tmin; hit.material = material; hit.geometry = this; hit.hit = rayOrigin + rayDir * hit.distance; Vector3 tangent = Vector3.zero; if (hitFace == 1) { hit.texcoord = new Vector2((hit.hit.z - cubeCenter.z) / (scale.z * 0.5f) * 0.5f + 0.5f, (hit.hit.y - cubeCenter.y) / (scale.y * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(0, 0, 1); } else if (hitFace == 2) { hit.texcoord = new Vector2(-(hit.hit.x - cubeCenter.x) / (scale.x * 0.5f) * 0.5f - 0.5f, (hit.hit.z - cubeCenter.z) / (scale.z * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(-1, 0, 0); } else if (hitFace == 3) { hit.texcoord = new Vector2(-(hit.hit.x - cubeCenter.x) / (scale.x * 0.5f) * 0.5f - 0.5f, (hit.hit.y - cubeCenter.y) / (scale.y * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(-1, 0, 0); } else if (hitFace == 4) { hit.texcoord = new Vector2(-(hit.hit.z - cubeCenter.z) / (scale.z * 0.5f) * 0.5f - 0.5f, (hit.hit.y - cubeCenter.y) / (scale.y * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(0, 0, -1); } else if (hitFace == 5) { hit.texcoord = new Vector2((hit.hit.x - cubeCenter.x) / (scale.x * 0.5f) * 0.5f + 0.5f, (hit.hit.z - cubeCenter.z) / (scale.z * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(1, 0, 0); } else if (hitFace == 6) { hit.texcoord = new Vector2((hit.hit.x - cubeCenter.x) / (scale.x * 0.5f) * 0.5f + 0.5f, (hit.hit.y - cubeCenter.y) / (scale.y * 0.5f) * 0.5f + 0.5f); tangent = new Vector3(1, 0, 0); } hit.normal = normal; double ndv = Vector3.Dot(normal, rayOrigin - hit.hit); if (ndv < 0) { if (material != null && !material.ShouldRenderBackFace()) { return(false); } hit.isBackFace = true; hit.normal *= -1; } else { hit.isBackFace = false; } //if (hit.isBackFace) // hit.hit -= hit.normal * 0.00000000000001; //else hit.hit += hit.normal * 0.00000000000001; //hit.distance = Vector3.Distance(hit.hit, ray.origin); if (m_IsRotated) { hit.hit = m_LocalToWorld.TransformPoint(hit.hit); hit.normal = m_LocalToWorld.TransformVector(hit.normal); tangent = m_LocalToWorld.TransformVector(tangent); } hit.tangent = new Vector4(tangent.x, tangent.y, tangent.z, 1); return(true); }
public virtual float GetRoughness(RayCastHit hit) { return(1.0f); }
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); }
public abstract bool RayCast(Ray ray, double epsilon, ref RayCastHit hit);
public virtual Color GetAlbedo(RayCastHit hit) { return(Color.white); }
protected abstract bool RayCastGeometry(Ray ray, ref RayCastHit hit);
public abstract bool Raycast(Ray ray, double epsilon, out RayCastHit hit);