/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mRepeat; useU = useU - ((int)useU); return((useU * mColor2) + (1 - useU) * mColor1); }
/// <summary> /// Intersects the ray, if intersection is closer than the one inside the record, /// sets the records with intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { float dist = 0f; Vector3 hitPt, n; n = mNormal; // because ray/plane intersection may flip the normal! if (!RayPlaneIntersection(ray, ref n, mD, ref dist)) { return(false); } /* * rectangle behind the ray or there are other closer intersections */ if ((dist < 0) || (dist > record.HitDistance)) { return(false); } hitPt = ray.Origin + (ray.Direction * dist); /* * Now need to decide inside or outside */ if (!InsidePolygon(hitPt)) { return(false); } record.UpdateRecord(dist, hitPt, n, ray, mMaterialIndex, GetResourceIndex()); return(true); }
public bool FindNearest(Ray ray, IntersectionRecord rec, int exceptGeom) { float enterD=0f, exitD=0f; if (!ComputeEntryAndExitSignedDistances(ray, out enterD, out exitD)) return false; if (IsLeafNode()) { bool hit = IntersectWithGeom(ray, rec, exceptGeom); return (hit && (rec.HitDistance >= enterD) && (rec.HitDistance <= exitD) ); } Vector3 enterPos = ray.Origin + enterD * ray.Direction; Vector3 exitPos = ray.Origin + exitD * ray.Direction; bool rightHit = false; bool leftHit = false; if (PositionLeftOfSplit(enterPos)) { leftHit = LeftChild.FindNearest(ray, rec, exceptGeom); if ((!leftHit) && PositionRightOfSplit(exitPos)) rightHit = RightChild.FindNearest(ray, rec, exceptGeom); } else { rightHit = RightChild.FindNearest(ray, rec, exceptGeom); if ((!rightHit) && PositionLeftOfSplit(exitPos)) leftHit = LeftChild.FindNearest(ray, rec, exceptGeom); } return leftHit || rightHit; }
private Vector3 ShadeRec(Vector3 V, RTLight lgt, IntersectionRecord rec) { RTMaterial m = mSceneDatabase.GetMaterial(rec.MaterialIndex); Vector3 r = Vector3.Zero; float percentToUse = 1f; if (mComputeShadow) { percentToUse = lgt.PercentVisible(rec.IntersectPosition, rec.GeomIndex, mSceneDatabase); } if (percentToUse > 0f) { Vector3 L = lgt.GetNormalizedDirection(rec.IntersectPosition); float NdotL = Vector3.Dot(rec.NormalAtIntersect, L); if (NdotL > 0) { Vector3 diffColor = m.GetDiffuse(mSceneDatabase, rec); Vector3 lightColor = percentToUse * lgt.GetColor(rec.IntersectPosition); r += diffColor * NdotL * lightColor; Vector3 R = 2 * NdotL * rec.NormalAtIntersect - L; float VdotR = Vector3.Dot(V, R); if (VdotR > 0) { r += m.GetSpecular(mSceneDatabase, rec) * (float)Math.Pow(VdotR, m.GetN) * lightColor; } } } return(r); }
private Vector3 ShadeRec(Vector3 V, RTLight lgt, IntersectionRecord rec) { RTMaterial m = mSceneDatabase.GetMaterial(rec.MaterialIndex); Vector3 r = Vector3.Zero; float percentToUse = 1f; if (mComputeShadow) percentToUse = lgt.PercentVisible(rec.IntersectPosition, rec.GeomIndex, mSceneDatabase); if (percentToUse > 0f) { Vector3 L = lgt.GetNormalizedDirection(rec.IntersectPosition); float NdotL = Vector3.Dot(rec.NormalAtIntersect, L); if (NdotL > 0) { Vector3 diffColor = m.GetDiffuse(mSceneDatabase, rec); Vector3 lightColor = percentToUse * lgt.GetColor(rec.IntersectPosition); r += diffColor * NdotL * lightColor; Vector3 R = 2 * NdotL * rec.NormalAtIntersect - L; float VdotR = Vector3.Dot(V, R); if (VdotR > 0) r += m.GetSpecular(mSceneDatabase, rec) * (float)Math.Pow(VdotR, m.GetN) * lightColor; } } return r; }
private bool IsBlocked(Vector3 org, Vector3 target, int exceptGeomIndex) { Vector3 d = target - org; float dist = d.Length(); IntersectionRecord rec = new IntersectionRecord(dist); d /= dist; Ray r = Ray.CrateRayFromPtDir(org, d); #if KDTREE mKdTree.ComputeVisibility(r, rec, exceptGeomIndex); return(rec.GeomIndex != RTCore.kInvalidIndex); #else bool blocked = false; int count = 0; while ((!blocked) && (count < mSceneDatabase.GetNumGeom())) { if (count != exceptGeomIndex) { blocked = mSceneDatabase.GetGeom(count).Intersect(r, rec); } count++; } return(blocked); #endif }
/// <summary> /// Intersects the ray with the sphere. If intersection is closer than what is /// in the record, updates the record with new intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { Vector3 v1 = ray.Origin - mCenter; float b = 2f * Vector3.Dot(v1, ray.Direction); float c = v1.LengthSquared() - mRadiusSquared; float root = b * b - 4 * c; if (root < 0f) { return(false); } root = (float)Math.Sqrt(root); float t0 = 0.5f * (-b - root); float t1 = 0.5f * (-b + root); if ((t0 < 0) && (t1 < 0)) { return(false); } float dist; if (t0 < t1) { if (t0 > 0) { dist = t0; } else { dist = t1; } } else { if (t1 > 0) { dist = t1; } else { dist = t0; } } if (dist > record.HitDistance) { return(false); } // intersection found Vector3 pt = ray.Origin + dist * ray.Direction; Vector3 n = pt - mCenter; record.UpdateRecord(dist, pt, n, ray, mMaterialIndex, GetResourceIndex()); return(true); }
/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mDirection.X + v * mDirection.Y; float theta = useU * mThetaRange; float sineV = 0.5f * (((float) Math.Sin(theta)) + 1); return (sineV * mColor1) + (1f - sineV) * mColor2; }
/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mDirection.X + v * mDirection.Y; float theta = useU * mThetaRange; float sineV = 0.5f * (((float)Math.Sin(theta)) + 1); return((sineV * mColor1) + (1f - sineV) * mColor2); }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { Vector3 norm = Vector3.UnitY; if ((u >= 0) && (u <= 1f) && (v >= 0) && (v <= 1f)) { int u0Index = 0, u1Index = 0, v0Index = 0, v1Index = 0; float uIndex, vIndex; float bumpAtu0v0, bumpAtu0v1, bumpAtu1v0, bumpAtu1v1; lock (mTextureImage) { GetIndices(u, mTextureImage.Width, ref u0Index, ref u1Index); GetIndices(v, mTextureImage.Height, ref v0Index, ref v1Index); v0Index = mTextureImage.Height - 1 - v0Index; v1Index = mTextureImage.Height - 1 - v1Index; uIndex = u * mTextureImage.Width; vIndex = mTextureImage.Height - 1 - (v * mTextureImage.Height); bumpAtu0v0 = ColorToVec(mTextureImage.GetPixel(u0Index, v0Index)).Length(); bumpAtu1v0 = ColorToVec(mTextureImage.GetPixel(u1Index, v0Index)).Length(); bumpAtu0v1 = ColorToVec(mTextureImage.GetPixel(u0Index, v1Index)).Length(); bumpAtu1v1 = ColorToVec(mTextureImage.GetPixel(u1Index, v1Index)).Length(); } float du = uIndex - u0Index; float dv = vIndex - v1Index; float bumpAtV0 = du * bumpAtu1v0 + (1 - du) * bumpAtu0v0; float bumpAtV1 = du * bumpAtu1v1 + (1 - du) * bumpAtu0v1; float bumpAtU0 = dv * bumpAtu0v1 + (1 - dv) * bumpAtu0v0; float bumpAtU1 = dv * bumpAtu1v1 + (1 - dv) * bumpAtu1v0; float dDu = mGain * (bumpAtV1 - bumpAtV0); float dDv = mGain * (bumpAtU1 - bumpAtU0); float u0Ref, u1Ref, v0Ref, v1Ref; u0Ref = u0Index * mInvWidth; u1Ref = u1Index * mInvWidth; v0Ref = v0Index * mInvHeight; v1Ref = v1Index * mInvHeight; Vector3 Pu0 = g.GetPosition(u0Ref, v); Vector3 Pu1 = g.GetPosition(u1Ref, v); Vector3 Pv0 = g.GetPosition(u, v0Ref); Vector3 Pv1 = g.GetPosition(u, v1Ref); Vector3 Pu = Pu1 - Pu0; Vector3 Pv = Pv1 - Pv0; Vector3 aDir = Vector3.Normalize(Vector3.Cross(Pu, rec.NormalAtIntersect)); Vector3 bDir = Vector3.Normalize(Vector3.Cross(Pv, rec.NormalAtIntersect)); Vector3 D = (dDv * aDir) - (dDu * bDir); norm = rec.NormalAtIntersect + D; norm.Normalize(); } return(norm); }
/// <summary> /// Diffuse color lookup: if texture mapped, scale the texture value by mKd /// </summary> /// <param name="database"></param> /// <param name="rec"></param> /// <returns></returns> public Vector3 GetDiffuse(SceneDatabase database, IntersectionRecord rec) { Vector3 result = mKd.AttributeValue(); if (mKd.IsTextureMapped()) { result *= mKd.AttributeLookup(database, rec); } return(result); }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { Vector3 norm = Vector3.UnitY; if ((u >= 0) && (u <= 1f) && (v >= 0) && (v <= 1f)) { int u0Index=0, u1Index=0, v0Index=0, v1Index=0; float uIndex, vIndex; float bumpAtu0v0, bumpAtu0v1, bumpAtu1v0, bumpAtu1v1; lock (mTextureImage) { GetIndices(u, mTextureImage.Width, ref u0Index, ref u1Index); GetIndices(v, mTextureImage.Height, ref v0Index, ref v1Index); v0Index = mTextureImage.Height - 1 - v0Index; v1Index = mTextureImage.Height - 1 - v1Index; uIndex = u * mTextureImage.Width; vIndex = mTextureImage.Height - 1 - (v * mTextureImage.Height); bumpAtu0v0 = ColorToVec(mTextureImage.GetPixel(u0Index, v0Index)).Length(); bumpAtu1v0 = ColorToVec(mTextureImage.GetPixel(u1Index, v0Index)).Length(); bumpAtu0v1 = ColorToVec(mTextureImage.GetPixel(u0Index, v1Index)).Length(); bumpAtu1v1 = ColorToVec(mTextureImage.GetPixel(u1Index, v1Index)).Length(); } float du = uIndex - u0Index; float dv = vIndex - v1Index; float bumpAtV0 = du * bumpAtu1v0 + (1 - du) * bumpAtu0v0; float bumpAtV1 = du * bumpAtu1v1 + (1 - du) * bumpAtu0v1; float bumpAtU0 = dv * bumpAtu0v1 + (1 - dv) * bumpAtu0v0; float bumpAtU1 = dv * bumpAtu1v1 + (1 - dv) * bumpAtu1v0; float dDu = mGain * (bumpAtV1 - bumpAtV0); float dDv = mGain * (bumpAtU1 - bumpAtU0); float u0Ref, u1Ref, v0Ref, v1Ref; u0Ref = u0Index * mInvWidth; u1Ref = u1Index * mInvWidth; v0Ref = v0Index * mInvHeight; v1Ref = v1Index * mInvHeight; Vector3 Pu0 = g.GetPosition(u0Ref, v); Vector3 Pu1 = g.GetPosition(u1Ref, v); Vector3 Pv0 = g.GetPosition(u, v0Ref); Vector3 Pv1 = g.GetPosition(u, v1Ref); Vector3 Pu = Pu1 - Pu0; Vector3 Pv = Pv1 - Pv0; Vector3 aDir = Vector3.Normalize(Vector3.Cross(Pu, rec.NormalAtIntersect)); Vector3 bDir = Vector3.Normalize(Vector3.Cross(Pv, rec.NormalAtIntersect)); Vector3 D = (dDv * aDir) - (dDu * bDir); norm = rec.NormalAtIntersect + D; norm.Normalize(); } return norm; }
/// <summary> /// Transparency look up: if mapped, scales Avg(RBG) by transparency /// </summary> /// <param name="database"></param> /// <param name="rec"></param> /// <returns></returns> public float GetTransparency(SceneDatabase database, IntersectionRecord rec) { float result = mTransparency.AttributeValue(); if (mTransparency.IsTextureMapped()) { Vector3 v = mTransparency.AttributeLookup(database, rec); result *= ((v.X + v.Y + v.Z) / 3f); } return(result); }
public Vector3 TextureLookup(IntersectionRecord rec, RTGeometry g) { if (mTexture.NeedUV()) { float u = 0f, v = 0f; g.GetUV(rec.IntersectPosition, rec.HitPtBC, ref u, ref v); return(mTexture.GetTexile(u, v, rec, g)); } else { return(mTexture.GetTexile(rec, g)); } }
public Vector3 TextureLookup(IntersectionRecord rec, RTGeometry g) { if (mTexture.NeedUV()) { float u = 0f, v = 0f; g.GetUV(rec.IntersectPosition, rec.HitPtBC, ref u, ref v); return mTexture.GetTexile(u, v, rec, g); } else { return mTexture.GetTexile(rec, g); } }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float uVal = u * mURepeat; float vVal = v * mVRepeat; int uBit = ((int)uVal) % 2; int vBit = ((int)vVal) % 2; Vector3 c = mColor1; if (uBit == vBit) c = mColor2; return c; }
private void ComputeVisibility(Ray r, IntersectionRecord rec, int exceptGeomIndex) { #if KDTREE mKdTree.ComputeVisibility(r, rec, exceptGeomIndex); #else for (int i = 0; i < mSceneDatabase.GetNumGeom(); i++) { if (i != exceptGeomIndex) { RTGeometry g = mSceneDatabase.GetGeom(i); g.Intersect(r, rec); } } #endif }
private void ComputeVisibility(Ray r, IntersectionRecord rec, int exceptGeomIndex) { #if KDTREE mKdTree.ComputeVisibility(r, rec, exceptGeomIndex); #else for (int i = 0; i < mSceneDatabase.GetNumGeom(); i++) { if (i != exceptGeomIndex) { RTGeometry g = mSceneDatabase.GetGeom(i); g.Intersect(r, rec); } } #endif }
private bool IntersectWithGeom(Ray ray, IntersectionRecord rec, int exceptGeom) { bool hitOnce = false; if (mGeomList != null) { foreach (RTGeometry g in mGeomList) { if ((g.GetResourceIndex() != exceptGeom) && g.Intersect(ray, rec)) { hitOnce = true; } } } return(hitOnce); }
/// <summary> /// (x,y,z) is the visible pt, returns solid texture value at x,y,z /// </summary> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public override Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { float x = rec.IntersectPosition.X; float y = rec.IntersectPosition.Y; float z = rec.IntersectPosition.Z; float n = ComputeTurbulanceNoise(x, y, z); Vector3 v = new Vector3(x, y, z); v.Normalize(); float useU = Vector3.Dot(mDirection, v) + n; float theta = useU * mThetaRange; float sineV = 0.5f * (((float) Math.Sin(theta)) + 1); return (sineV * mColor1) + (1f - sineV) * mColor2; }
/// <summary> /// (x,y,z) is the visible pt, returns solid texture value at x,y,z /// </summary> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public override Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { float x = rec.IntersectPosition.X; float y = rec.IntersectPosition.Y; float z = rec.IntersectPosition.Z; float n = ComputeTurbulanceNoise(x, y, z); Vector3 v = new Vector3(x, y, z); v.Normalize(); float useU = Vector3.Dot(mDirection, v) + n; float theta = useU * mThetaRange; float sineV = 0.5f * (((float)Math.Sin(theta)) + 1); return((sineV * mColor1) + (1f - sineV) * mColor2); }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float uVal = u * mURepeat; float vVal = v * mVRepeat; int uBit = ((int)uVal) % 2; int vBit = ((int)vVal) % 2; Vector3 c = mColor1; if (uBit == vBit) { c = mColor2; } return(c); }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> /// /// only available to Vista and later /// [MethodImpl(MethodImplOptions.Synchronized)] public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { System.Drawing.Color c = System.Drawing.Color.Black; if (null != mTextureImage) { if ((u >= 0) && (u <= 1f) && (v >= 0) && (v <= 1f)) { lock (mTextureImage) { int x = (int)(u * (mTextureImage.Width - 1) + 0.5f); int y = (int)(v * (mTextureImage.Height - 1) + 0.5f); y = mTextureImage.Height - y - 1; c = mTextureImage.GetPixel(x, y); } } } return ColorToVec(c); }
/// <summary> /// UV are values between 0 to 1, maps to texture width/height linearly and returns the /// corresponding textile. /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> /// /// only available to Vista and later /// [MethodImpl(MethodImplOptions.Synchronized)] public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { System.Drawing.Color c = System.Drawing.Color.Black; if (null != mTextureImage) { if ((u >= 0) && (u <= 1f) && (v >= 0) && (v <= 1f)) { lock (mTextureImage) { int x = (int)(u * (mTextureImage.Width - 1) + 0.5f); int y = (int)(v * (mTextureImage.Height - 1) + 0.5f); y = mTextureImage.Height - y - 1; c = mTextureImage.GetPixel(x, y); } } } return(ColorToVec(c)); }
/// <summary> /// Percentage of the light that is visible from the visiblePt /// </summary> /// <param name="visiblePt"></param> /// <param name="exceptGeomIndex">this geometry can never block the light (geomIndex of the visiblePt)</param> /// <param name="database"></param> /// <returns></returns> public virtual float PercentVisible(Vector3 visiblePt, int exceptGeomIndex, SceneDatabase sceneDatabase) { IntersectionRecord rec = new IntersectionRecord(DistanceToLight(visiblePt)); Ray r = Ray.CrateRayFromPtDir(visiblePt, GetNormalizedDirection(visiblePt)); bool blocked = false; int count = 0; while ((!blocked) && (count < sceneDatabase.GetNumGeom())) { if (count != exceptGeomIndex) { blocked = sceneDatabase.GetGeom(count).Intersect(r, rec); } count++; } return(blocked ? 0f : 1f); }
/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mURepeat; useU = useU - ((int)useU); float useV = v * mVRepeat; useV = useV - ((int)useV); Vector3 resultColor = mColor1; if ((useU > kLowBound) && (useU < kUpBound)) { resultColor = GetGridColor(useU); } else if ((useV > kLowBound) && (useV < kUpBound)) { resultColor = GetGridColor(useV); } return resultColor; }
/// <summary> /// Normal vector lookup, if texture mapped, replaces the intersection record's normal vector! /// </summary> /// <param name="database"></param> /// <param name="rec"></param> /// <returns></returns> public Vector3 GetNormal(SceneDatabase database, IntersectionRecord rec) { Vector3 result; if (mNormal.IsTextureMapped()) { result = mNormal.AttributeLookup(database, rec); if (Vector3.Dot(result, rec.NormalAtIntersect) < 0) { result = -result; } rec.SetNormalAtIntersection(result); } else { result = rec.NormalAtIntersect; } return(result); }
public bool FindNearest(Ray ray, IntersectionRecord rec, int exceptGeom) { float enterD = 0f, exitD = 0f; if (!ComputeEntryAndExitSignedDistances(ray, out enterD, out exitD)) { return(false); } if (IsLeafNode()) { bool hit = IntersectWithGeom(ray, rec, exceptGeom); return(hit && (rec.HitDistance >= enterD) && (rec.HitDistance <= exitD) ); } Vector3 enterPos = ray.Origin + enterD * ray.Direction; Vector3 exitPos = ray.Origin + exitD * ray.Direction; bool rightHit = false; bool leftHit = false; if (PositionLeftOfSplit(enterPos)) { leftHit = LeftChild.FindNearest(ray, rec, exceptGeom); if ((!leftHit) && PositionRightOfSplit(exitPos)) { rightHit = RightChild.FindNearest(ray, rec, exceptGeom); } } else { rightHit = RightChild.FindNearest(ray, rec, exceptGeom); if ((!rightHit) && PositionLeftOfSplit(exitPos)) { leftHit = LeftChild.FindNearest(ray, rec, exceptGeom); } } return(leftHit || rightHit); }
/// <summary> /// Samples the depth map, returns the percentage of samples that is closer to the light than the map /// </summary> /// <param name="visiblePt"></param> /// <param name="visibleObj"></param> /// <returns></returns> private float SampleDepthMap(Vector3 visiblePt, int visibleObj) { float samplesTaken = 0f; float count = 0f; // intersect a ray with the depthMap to get the intersection position Ray r = new Ray(visiblePt, mPosition); IntersectionRecord rec = new IntersectionRecord(); if (mDepthMapGeom.Intersect(r, rec)) { float x = 0, y = 0; mDepthMapGeom.GetUV(rec.IntersectPosition, rec.HitPtBC, ref x, ref y); int lowX = (int)(x * mRes) - mFilterRes; int hiX = lowX + mFilterRes; int lowY = (int)(y * mRes) - mFilterRes; int hiY = lowY + mFilterRes; //float distToPt = (visiblePt - mPosition).Length(); // depth map look up for (int i = lowX; i <= hiX; i++) { for (int j = lowY; j <= hiY; j++) { if ((i >= 0) && (j >= 0) && (i < mRes) && (j < mRes)) { samplesTaken += 1f; if (visibleObj == mGeomID[i][j]) { count += 1f; } } } } } return(count /= samplesTaken); }
private void computePixelColor(Ray r, ref Vector3 pixelColor, int channel) { IntersectionRecord rec = new IntersectionRecord(); // what can we see? ComputeVisibility(r, rec, RTCore.kInvalidIndex); Vector3 sampleColor = mBgColor; if (pixelColor != Vector3.Zero) { int a = 5; } // what color should it be? if (rec.GeomIndex != RTCore.kInvalidIndex) { sampleColor = ComputeShading(rec, 0); } if (channel == SINGLE) { pixelColor += sampleColor; } else if (channel == LEFT) { pixelColor += sampleColor * leftLens; } else if (channel == RIGHT) { pixelColor += sampleColor * rightLens; } //throws off the filters // This prevents a yellow background by bringing in the color blue where there are no intersections // if (channel != SINGLE && rec.GeomIndex == RTCore.kInvalidIndex) // pixelColor.Z += sampleColor.Z / 2; }
/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mURepeat; useU = useU - ((int)useU); float useV = v * mVRepeat; useV = useV - ((int)useV); Vector3 resultColor = mColor1; if ((useU > kLowBound) && (useU < kUpBound)) { resultColor = GetGridColor(useU); } else if ((useV > kLowBound) && (useV < kUpBound)) { resultColor = GetGridColor(useV); } return(resultColor); }
private bool IsBlocked(Vector3 org, Vector3 target, int exceptGeomIndex) { Vector3 d = target - org; float dist = d.Length(); IntersectionRecord rec = new IntersectionRecord(dist); d /= dist; Ray r = Ray.CrateRayFromPtDir(org, d); #if KDTREE mKdTree.ComputeVisibility(r, rec, exceptGeomIndex); return (rec.GeomIndex != RTCore.kInvalidIndex); #else bool blocked = false; int count = 0; while ((!blocked) && (count < mSceneDatabase.GetNumGeom())) { if (count != exceptGeomIndex) blocked = mSceneDatabase.GetGeom(count).Intersect(r, rec); count++; } return blocked; #endif }
public void ComputeImage(Object parm) { int startX, startY, endX, endY, threadID; ParseParm(parm, out startX, out startY, out endX, out endY, out threadID); // Console.WriteLine("Start: Thread:" + threadID + " - y(" + startY + " " + endY + ")"); int currentX = startX; int currentY = startY; while (currentY < endY && currentY < ImageHeight) { while (currentX < ImageWidth) { Vector3 pixelColor = Vector3.Zero; float pixelCoverage = 0f; float pixelDepth = 0f; for (int i = 0; i < mImageSpec.NumSamplesPerPixel; i++) { float dx; float dy; lock (this) { dx = (float)mRand.NextDouble(); dy = (float)mRand.NextDouble(); } Vector3 pixelPos = mCamera.GetPixelPosition(currentX + dx, currentY + dy); Ray r; if (!mOrthoRT) { r = new Ray(mCamera.EyePosition, pixelPos); } else { pixelPos -= 10f * mCamera.ViewDirection; r = Ray.CrateRayFromPtDir(pixelPos, mCamera.ViewDirection); } // #if RT_PIXEL_DEBUG if ((currentX == 348) && (currentY == 196)) { int a = 4; } // #endif if (!mAnaglyph) { computePixelColor(r, ref pixelColor, SINGLE); } else { Ray left = new Ray(mCamera.LeftEyePosition, pixelPos); computePixelColor(left, ref pixelColor, LEFT); Ray right = new Ray(mCamera.RightEyePosition, pixelPos); computePixelColor(right, ref pixelColor, RIGHT); } float sampleCoverage = 0f; float sampleDepth = 0f; // what coverage and depth? IntersectionRecord rec = new IntersectionRecord(); ComputeVisibility(r, rec, RTCore.kInvalidIndex); if (rec.GeomIndex != RTCore.kInvalidIndex) { sampleCoverage = 1f; sampleDepth = kUseMaxDepth - rec.HitDistance; } pixelCoverage += sampleCoverage; pixelDepth += sampleDepth; } pixelColor /= (float)mImageSpec.NumSamplesPerPixel; pixelCoverage /= (float)mImageSpec.NumSamplesPerPixel; pixelDepth /= (float)mImageSpec.NumSamplesPerPixel; System.Drawing.Color c = ComputeColor(pixelColor); // convert Vector3 (0-1 float) to Color (0 - 255) System.Drawing.Color p = ComputePixelCoverage(pixelCoverage); float useDepth = pixelDepth / kUseMaxDepth; System.Drawing.Color z = ComputePixelCoverage(useDepth); lock (this) { mResultImage.SetPixel(currentX, currentY, c); mPixelCoverage.SetPixel(currentX, currentY, p); mPixelDepth.SetPixel(currentX, currentY, z); if (mShowPixelInWorld || mDisplayDebugPixels || mDisplayDebugRays) { Vector3 pixelPos = mCamera.GetPixelPosition(currentX, currentY); Ray r = new Ray(mCamera.EyePosition, pixelPos); IntersectionRecord rec = new IntersectionRecord(); Vector3 resultColor = mBgColor; ComputeVisibility(r, rec, RTCore.kInvalidIndex); if (rec.GeomIndex != RTCore.kInvalidIndex) { resultColor = ComputeShading(rec, 0); } mPixelPosition[currentX][currentY] = pixelPos; mPixelHitDistance[currentX][currentY] = rec.HitDistance; mResultImage.SetPixel(currentX, currentY, ComputeColor(resultColor)); } } // next pixel currentX++; } // next scanline currentX = startX; currentY++; lock (this) { if (currentY > mCurrentY) { mCurrentY = currentY; } } } // Console.WriteLine("Start: Thread:" + threadID + " - y(" + startY + " " + endY + ")"); if (threadID != -1) { ThreadNextWorkLoad(threadID); } else { RTRenderingDone(); } }
private bool IntersectWithGeom(Ray ray, IntersectionRecord rec, int exceptGeom) { bool hitOnce = false; if (mGeomList != null) { foreach (RTGeometry g in mGeomList) if ((g.GetResourceIndex() != exceptGeom) && g.Intersect(ray, rec)) hitOnce = true; } return hitOnce; }
/// <summary> /// (x,y,z) is the visible pt, returns solid texture value at x,y,z /// </summary> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public virtual Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { return(Vector3.Zero); }
/// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public override Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { float noise = ComputeFractalNoise(rec.IntersectPosition.X, rec.IntersectPosition.Y, rec.IntersectPosition.Z); return((noise * mColor1) + ((1f - noise) * mColor2)); }
private const float kDepthImageDist = 1f; // depth map image plane distance from the light source private void InitDepthMap(SceneDatabase sceneDatabase) { if (null != mDepthMap) { return; // done } // remember!! mDireciton is L, or a vector from Visible point to the light. // Here we want direction from light source towards the scene Vector3 useDir = -mDirection; // 1. Find a Up direction // guess up direction to be (0, 1, 0), if view direction is also this, // use (1, 0, 0) as view direction Vector3 up = Vector3.UnitY; if (Math.Abs(Vector3.Dot(up, useDir)) > 0.99999) { up = Vector3.UnitX; } // 2. define Orthonormal base Vector3 sideV = Vector3.Cross(up, useDir); up = Vector3.Cross(useDir, sideV); sideV.Normalize(); up.Normalize(); // 3. compute the depth map image plane, // define the image plane to be located at ... a distance of kDepthImageDist away Vector3 ptOnImage = mPosition + kDepthImageDist * useDir; // 4. compute depth map image size float halfImageSize = kDepthImageDist * (float)Math.Tan(mOuterAngle / 2f); // 5. Compute the 4 vertices the defines the depth map Vector3[] v = new Vector3[4]; v[0] = ptOnImage - halfImageSize * up - halfImageSize * sideV; v[1] = ptOnImage - halfImageSize * up + halfImageSize * sideV; v[2] = ptOnImage + halfImageSize * up + halfImageSize * sideV; v[3] = ptOnImage + halfImageSize * up - halfImageSize * sideV; // 6. create a Geometry that represents the map // ** Be caureful **!! // RTRectangle uses v[0] as the origin for texture lookup // we _MUST_ follow the same in order to take advante of GetUV() function! mDepthMapGeom = new RTRectangle(v); // 7. Now allocate memory for the actual map mDepthMap = new float[mRes][]; mGeomID = new int[mRes][]; for (int i = 0; i < mRes; i++) { mDepthMap[i] = new float[mRes]; mGeomID[i] = new int[mRes]; } // now, trace rays through each of the pixels in the depth map and record the depth and geomID float pixelSize = halfImageSize / (0.5f * mRes); Vector3 upPixelVector = pixelSize * up; Vector3 sidePixelVector = pixelSize * sideV; for (int y = 0; y < mRes; y++) { Vector3 yDisp = v[0] + (y + 0.5f) * upPixelVector; for (int x = 0; x < mRes; x++) { Vector3 pixelPos = ((x + 0.5f) * sidePixelVector) + yDisp; Ray r = new Ray(mPosition, pixelPos); IntersectionRecord rec = new IntersectionRecord(); for (int i = 0; i < sceneDatabase.GetNumGeom(); i++) { RTGeometry g = sceneDatabase.GetGeom(i); g.Intersect(r, rec); } mDepthMap[x][y] = rec.HitDistance; // closes intersection distance, any object that is // further away from the light than this distance is in the shadow of this light mGeomID[x][y] = rec.GeomIndex; // this object can never be in shadow, becuase it is the closest to the light! } } }
public bool ComputeVisibility(Ray ray, IntersectionRecord rec, int exceptGeom) { return(mRoot.FindNearest(ray, rec, exceptGeom)); }
private void computePixelColor(Ray r, ref Vector3 pixelColor, int channel) { IntersectionRecord rec = new IntersectionRecord(); // what can we see? ComputeVisibility(r, rec, RTCore.kInvalidIndex); Vector3 sampleColor = mBgColor; if (pixelColor != Vector3.Zero) { int a = 5; } // what color should it be? if (rec.GeomIndex != RTCore.kInvalidIndex) sampleColor = ComputeShading(rec, 0); if (channel == SINGLE) pixelColor += sampleColor; else if (channel == LEFT) pixelColor += sampleColor * leftLens; else if (channel == RIGHT) pixelColor += sampleColor * rightLens; //throws off the filters // This prevents a yellow background by bringing in the color blue where there are no intersections // if (channel != SINGLE && rec.GeomIndex == RTCore.kInvalidIndex) // pixelColor.Z += sampleColor.Z / 2; }
public void ComputeImage(Object parm) { int startX, startY, endX, endY, threadID; ParseParm(parm, out startX, out startY, out endX, out endY, out threadID); // Console.WriteLine("Start: Thread:" + threadID + " - y(" + startY + " " + endY + ")"); int currentX = startX; int currentY = startY; while (currentY < endY && currentY < ImageHeight) { while (currentX < ImageWidth) { Vector3 pixelColor = Vector3.Zero; float pixelCoverage = 0f; float pixelDepth = 0f; for (int i = 0; i < mImageSpec.NumSamplesPerPixel; i++) { float dx; float dy; lock (this) { dx = (float)mRand.NextDouble(); dy = (float)mRand.NextDouble(); } Vector3 pixelPos = mCamera.GetPixelPosition(currentX + dx, currentY + dy); Ray r; if (!mOrthoRT) { r = new Ray(mCamera.EyePosition, pixelPos); } else { pixelPos -= 10f * mCamera.ViewDirection; r = Ray.CrateRayFromPtDir(pixelPos, mCamera.ViewDirection); } // #if RT_PIXEL_DEBUG if ((currentX == 348) && (currentY == 196)) { int a = 4; } // #endif if (!mAnaglyph) { computePixelColor(r, ref pixelColor, SINGLE); } else { Ray left = new Ray(mCamera.LeftEyePosition, pixelPos); computePixelColor(left, ref pixelColor, LEFT); Ray right = new Ray(mCamera.RightEyePosition, pixelPos); computePixelColor(right, ref pixelColor, RIGHT); } float sampleCoverage = 0f; float sampleDepth = 0f; // what coverage and depth? IntersectionRecord rec = new IntersectionRecord(); ComputeVisibility(r, rec, RTCore.kInvalidIndex); if (rec.GeomIndex != RTCore.kInvalidIndex) { sampleCoverage = 1f; sampleDepth = kUseMaxDepth - rec.HitDistance; } pixelCoverage += sampleCoverage; pixelDepth += sampleDepth; } pixelColor /= (float)mImageSpec.NumSamplesPerPixel; pixelCoverage /= (float)mImageSpec.NumSamplesPerPixel; pixelDepth /= (float)mImageSpec.NumSamplesPerPixel; System.Drawing.Color c = ComputeColor(pixelColor); // convert Vector3 (0-1 float) to Color (0 - 255) System.Drawing.Color p = ComputePixelCoverage(pixelCoverage); float useDepth = pixelDepth / kUseMaxDepth; System.Drawing.Color z = ComputePixelCoverage(useDepth); lock (this) { mResultImage.SetPixel(currentX, currentY, c); mPixelCoverage.SetPixel(currentX, currentY, p); mPixelDepth.SetPixel(currentX, currentY, z); if (mShowPixelInWorld || mDisplayDebugPixels || mDisplayDebugRays) { Vector3 pixelPos = mCamera.GetPixelPosition(currentX, currentY); Ray r = new Ray(mCamera.EyePosition, pixelPos); IntersectionRecord rec = new IntersectionRecord(); Vector3 resultColor = mBgColor; ComputeVisibility(r, rec, RTCore.kInvalidIndex); if (rec.GeomIndex != RTCore.kInvalidIndex) { resultColor = ComputeShading(rec, 0); } mPixelPosition[currentX][currentY] = pixelPos; mPixelHitDistance[currentX][currentY] = rec.HitDistance; mResultImage.SetPixel(currentX, currentY, ComputeColor(resultColor)); } } // next pixel currentX++; } // next scanline currentX = startX; currentY++; lock (this) { if (currentY > mCurrentY) mCurrentY = currentY; } } // Console.WriteLine("Start: Thread:" + threadID + " - y(" + startY + " " + endY + ")"); if (threadID != -1) ThreadNextWorkLoad(threadID); else RTRenderingDone(); }
/// <summary> /// /// </summary> private Vector3 ComputeShading(IntersectionRecord rec, int generation) { if (rec.GeomIndex == RTCore.kInvalidIndex) { return(mBgColor); } Vector3 resultColor = Vector3.Zero; Vector3 V = -Vector3.Normalize(rec.RayDirection); RTMaterial m = mSceneDatabase.GetMaterial(rec.MaterialIndex); Vector3 useNormal = m.GetNormal(mSceneDatabase, rec); for (int l = 0; l < mSceneDatabase.GetNumLights(); l++) { RTLight lgt = mSceneDatabase.GetLight(l); resultColor += ShadeRec(V, lgt, rec); } resultColor += mSceneDatabase.GetMaterial(rec.MaterialIndex).GetAmbient(mSceneDatabase, rec); int nextGen = generation + 1; // now take care of reflection float reflectivity = m.GetReflectivity(mSceneDatabase, rec); Vector3 reflColor = Vector3.Zero; if (mComputeReflection && (reflectivity > 0f) && (generation < mGeneration)) { IntersectionRecord refRec = new IntersectionRecord(); Vector3 refDir = Vector3.Reflect(rec.RayDirection, useNormal); Ray refRay = Ray.CrateRayFromPtDir(rec.IntersectPosition, refDir); // Now compute new visibility ComputeVisibility(refRay, refRec, rec.GeomIndex); if (refRec.GeomIndex != RTCore.kInvalidIndex) { reflColor = ComputeShading(refRec, nextGen) * reflectivity; } else { reflColor = mBgColor * reflectivity; } } // now do transparency // // The following code: // 1. only supports refractive index > 1 (from less dense e.g.: air, to more dense: e.g., glass) // 2. cannot go from dense material into less dense material (once enter cannot exit) // 3. once entered: do not know how to go from one transparent object into another transparent object // float transparency = m.GetTransparency(mSceneDatabase, rec); Vector3 transColor = Vector3.Zero; if (mComputeReflection && (transparency > 0f) && (generation < mGeneration)) { float cosThetaI = Vector3.Dot(V, useNormal); float invN = 1f / m.GetRefractiveIndex; float cosThetaT = (float)Math.Sqrt(1 - ((invN * invN) * (1 - (cosThetaI * cosThetaI)))); Vector3 transDir = -((invN * V) + ((cosThetaT - (invN * cosThetaI)) * useNormal)); Ray transRay = Ray.CrateRayFromPtDir(rec.IntersectPosition, transDir); // Now compute new visibility IntersectionRecord transRec = new IntersectionRecord(); ComputeVisibility(transRay, transRec, rec.GeomIndex); // here we assume single layer geometries if (transRec.GeomIndex != RTCore.kInvalidIndex) { transColor = ComputeShading(transRec, nextGen) * transparency; } else { transColor = mBgColor * transparency; } } resultColor = (1 - transparency - reflectivity) * resultColor + transColor + reflColor; return(resultColor); }
/// <summary> /// Returns status of if Ray intersects with this Geom. If so, details of intersection /// is returned in the IntersectionRecord. /// </summary> /// <param name="ray">Incoming ray.</param> /// <param name="record">If intersect, this record has the details.</param> /// <returns>T/F: intersect or not.</returns> public abstract bool Intersect(Ray ray, IntersectionRecord record);
/// <summary> /// </summary> /// <param name="u">value between 0 to 1</param> /// <param name="v">value between 0 to 1</param> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">the geometry</param> /// <returns></returns> public override Vector3 GetTexile(float u, float v, IntersectionRecord rec, RTGeometry g) { float useU = u * mRepeat; useU = useU - ((int)useU); return (useU * mColor2) + (1 - useU) * mColor1; }
/// <summary> /// (x,y,z) is the visible pt, returns solid texture value at x,y,z /// </summary> /// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public virtual Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { return Vector3.Zero; }
/// <summary> /// Intersects the ray, if intersection is closer than the one inside the record, /// sets the records with intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { float dist = 0f; Vector3 hitPt, n; n = mNormal; if (!RayPlaneIntersection(ray, ref n, mD, ref dist)) return false; /* * rectangle behind the ray or there are other closer intersections */ if ((dist < 0) || (dist > record.HitDistance)) return false; hitPt = ray.Origin + (ray.Direction * dist); /* * Now need to decide inside or outside */ float u, v, w; Vector3 v1 = mVertices[1] - hitPt; Vector3 v2 = mVertices[2] - hitPt; float areaPV1V2 = Vector3.Dot(mNormal, Vector3.Cross(v1, v2)); u = areaPV1V2 * mInvArea2; if ((u < 0f) || (u > 1f)) return false; v1 = mVertices[0] - hitPt; float areaPV0V2 = Vector3.Dot(mNormal, Vector3.Cross(v2, v1)); v = areaPV0V2 * mInvArea2; if ((v<0f) || (v>1f)) return false; w = 1 - u - v; if (w<0f) return false; /* * An actual hit */ record.UpdateBC(u, v, w); // now if we have per-vertex normal, use it! if (null != mNormalAtVertices) n = u * mNormalAtVertices[0] + v * mNormalAtVertices[1] + w * mNormalAtVertices[2]; // flip the normal if seeing the back face if (Vector3.Dot(n, ray.Direction) > 0f) n = -n; record.UpdateRecord(dist, hitPt, n, ray, mMaterialIndex, GetResourceIndex()); return true; }
/// <summary> /// Intersects the ray, if intersection is closer than the one inside the record, /// sets the records with intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { float dist = 0f; Vector3 hitPt, n; n = mNormal; if (!RayPlaneIntersection(ray, ref n, mD, ref dist)) { return(false); } /* * rectangle behind the ray or there are other closer intersections */ if ((dist < 0) || (dist > record.HitDistance)) { return(false); } hitPt = ray.Origin + (ray.Direction * dist); /* * Now need to decide inside or outside */ float u, v, w; Vector3 v1 = mVertices[1] - hitPt; Vector3 v2 = mVertices[2] - hitPt; float areaPV1V2 = Vector3.Dot(mNormal, Vector3.Cross(v1, v2)); u = areaPV1V2 * mInvArea2; if ((u < 0f) || (u > 1f)) { return(false); } v1 = mVertices[0] - hitPt; float areaPV0V2 = Vector3.Dot(mNormal, Vector3.Cross(v2, v1)); v = areaPV0V2 * mInvArea2; if ((v < 0f) || (v > 1f)) { return(false); } w = 1 - u - v; if (w < 0f) { return(false); } /* * An actual hit */ record.UpdateBC(u, v, w); // now if we have per-vertex normal, use it! if (null != mNormalAtVertices) { n = u * mNormalAtVertices[0] + v * mNormalAtVertices[1] + w * mNormalAtVertices[2]; } // flip the normal if seeing the back face if (Vector3.Dot(n, ray.Direction) > 0f) { n = -n; } record.UpdateRecord(dist, hitPt, n, ray, mMaterialIndex, GetResourceIndex()); return(true); }
/// <summary> /// Looks up attribute from the texture table! NO ERROR CHECKINGG! If mTextureIndex is invalid, this function will crash!! /// </summary> /// <param name="database"></param> /// <param name="rec"></param> /// <returns></returns> public Vector3 AttributeLookup(SceneDatabase database, IntersectionRecord rec) { return(database.GetTexture(mTextureIndex).TextureLookup(rec, database.GetGeom(rec.GeomIndex))); }
/// <summary> /// Intersects the ray, if intersection is closer than the one inside the record, /// sets the records with intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { float dist= 0f; Vector3 hitPt, n; n = mNormal; // because ray/plane intersection may flip the normal! if (!RayPlaneIntersection(ray, ref n, mD, ref dist)) return false; /* * rectangle behind the ray or there are other closer intersections */ if ((dist < 0) || (dist > record.HitDistance)) return false; hitPt = ray.Origin + (ray.Direction * dist); /* * Now need to decide inside or outside */ if (!InsidePolygon(hitPt)) return false; record.UpdateRecord(dist, hitPt, n, ray, mMaterialIndex, GetResourceIndex()); return true; }
/// <summary> /// Returns status of if Ray intersects with this Geom. If so, details of intersection /// is returned in the IntersectionRecord. /// </summary> /// <param name="ray">Incoming ray.</param> /// <param name="record">If intersect, this record has the details.</param> /// <returns>T/F: intersect or not.</returns> public abstract bool Intersect(Ray ray, IntersectionRecord record);
/// <summary> /// /// </summary> private Vector3 ComputeShading(IntersectionRecord rec, int generation) { if (rec.GeomIndex == RTCore.kInvalidIndex) return mBgColor; Vector3 resultColor = Vector3.Zero; Vector3 V = -Vector3.Normalize(rec.RayDirection); RTMaterial m = mSceneDatabase.GetMaterial(rec.MaterialIndex); Vector3 useNormal = m.GetNormal(mSceneDatabase, rec); for (int l = 0; l < mSceneDatabase.GetNumLights(); l++) { RTLight lgt = mSceneDatabase.GetLight(l); resultColor += ShadeRec(V, lgt, rec); } resultColor += mSceneDatabase.GetMaterial(rec.MaterialIndex).GetAmbient(mSceneDatabase, rec); int nextGen = generation + 1; // now take care of reflection float reflectivity = m.GetReflectivity(mSceneDatabase, rec); Vector3 reflColor = Vector3.Zero; if ( mComputeReflection && (reflectivity > 0f) && (generation < mGeneration) ) { IntersectionRecord refRec = new IntersectionRecord(); Vector3 refDir = Vector3.Reflect(rec.RayDirection, useNormal); Ray refRay = Ray.CrateRayFromPtDir(rec.IntersectPosition, refDir); // Now compute new visibility ComputeVisibility(refRay, refRec, rec.GeomIndex); if (refRec.GeomIndex != RTCore.kInvalidIndex) reflColor = ComputeShading(refRec, nextGen) * reflectivity; else reflColor = mBgColor * reflectivity; } // now do transparency // // The following code: // 1. only supports refractive index > 1 (from less dense e.g.: air, to more dense: e.g., glass) // 2. cannot go from dense material into less dense material (once enter cannot exit) // 3. once entered: do not know how to go from one transparent object into another transparent object // float transparency = m.GetTransparency(mSceneDatabase, rec); Vector3 transColor = Vector3.Zero; if (mComputeReflection && (transparency > 0f) && (generation < mGeneration)) { float cosThetaI = Vector3.Dot(V, useNormal); float invN = 1f / m.GetRefractiveIndex; float cosThetaT = (float)Math.Sqrt(1 - ((invN * invN) * (1 - (cosThetaI * cosThetaI)))); Vector3 transDir = -((invN * V) + ((cosThetaT - (invN * cosThetaI)) * useNormal)); Ray transRay = Ray.CrateRayFromPtDir(rec.IntersectPosition, transDir); // Now compute new visibility IntersectionRecord transRec = new IntersectionRecord(); ComputeVisibility(transRay, transRec, rec.GeomIndex); // here we assume single layer geometries if (transRec.GeomIndex != RTCore.kInvalidIndex) transColor = ComputeShading(transRec, nextGen) * transparency; else transColor = mBgColor * transparency; } resultColor = (1 - transparency - reflectivity) * resultColor + transColor + reflColor; return resultColor; }
/// <summary> /// Intersects the ray with the sphere. If intersection is closer than what is /// in the record, updates the record with new intersection information. /// </summary> /// <param name="ray"></param> /// <param name="record"></param> /// <returns></returns> public override bool Intersect(Ray ray, IntersectionRecord record) { Vector3 v1 = ray.Origin - mCenter; float b = 2f * Vector3.Dot(v1, ray.Direction); float c = v1.LengthSquared() - mRadiusSquared; float root = b * b - 4 * c; if (root < 0f) return false; root = (float) Math.Sqrt(root); float t0 = 0.5f * (-b - root); float t1 = 0.5f * (-b + root); if ((t0 < 0) && (t1 < 0)) return false; float dist; if (t0 < t1) { if (t0 > 0) dist = t0; else dist = t1; } else { if (t1 > 0) dist = t1; else dist = t0; } if (dist > record.HitDistance) return false; // intersection found Vector3 pt = ray.Origin + dist * ray.Direction; Vector3 n = pt - mCenter; record.UpdateRecord(dist, pt, n, ray, mMaterialIndex, GetResourceIndex()); return true; }
public bool ComputeVisibility(Ray ray, IntersectionRecord rec, int exceptGeom) { return mRoot.FindNearest(ray, rec, exceptGeom); }
/// <summary> /// Samples the depth map, returns the percentage of samples that is closer to the light than the map /// </summary> /// <param name="visiblePt"></param> /// <param name="visibleObj"></param> /// <returns></returns> private float SampleDepthMap(Vector3 visiblePt, int visibleObj) { float samplesTaken = 0f; float count = 0f; // intersect a ray with the depthMap to get the intersection position Ray r = new Ray(visiblePt, mPosition); IntersectionRecord rec = new IntersectionRecord(); if (mDepthMapGeom.Intersect(r, rec)) { float x = 0, y = 0; mDepthMapGeom.GetUV(rec.IntersectPosition, rec.HitPtBC, ref x, ref y); int lowX = (int)(x * mRes) - mFilterRes; int hiX = lowX + mFilterRes; int lowY = (int)(y * mRes) - mFilterRes; int hiY = lowY + mFilterRes; //float distToPt = (visiblePt - mPosition).Length(); // depth map look up for (int i = lowX; i <=hiX; i++) { for (int j = lowY; j <=hiY; j++) { if ((i >=0) && (j>=0) && (i < mRes) && (j < mRes)) { samplesTaken += 1f; if (visibleObj == mGeomID[i][j]) count += 1f; } } } } return count /= samplesTaken; }
private int mRes = 128; // depth map resolution is Res x Res #endregion Fields #region Methods private void InitDepthMap(SceneDatabase sceneDatabase) { if (null != mDepthMap) return; // done // remember!! mDireciton is L, or a vector from Visible point to the light. // Here we want direction from light source towards the scene Vector3 useDir = -mDirection; // 1. Find a Up direction // guess up direction to be (0, 1, 0), if view direction is also this, // use (1, 0, 0) as view direction Vector3 up = Vector3.UnitY; if (Math.Abs(Vector3.Dot(up, useDir)) > 0.99999) up = Vector3.UnitX; // 2. define Orthonormal base Vector3 sideV = Vector3.Cross(up, useDir); up = Vector3.Cross(useDir, sideV); sideV.Normalize(); up.Normalize(); // 3. compute the depth map image plane, // define the image plane to be located at ... a distance of kDepthImageDist away Vector3 ptOnImage = mPosition + kDepthImageDist * useDir; // 4. compute depth map image size float halfImageSize = kDepthImageDist * (float)Math.Tan(mOuterAngle/2f); // 5. Compute the 4 vertices the defines the depth map Vector3[] v = new Vector3[4]; v[0] = ptOnImage - halfImageSize * up - halfImageSize * sideV; v[1] = ptOnImage - halfImageSize * up + halfImageSize * sideV; v[2] = ptOnImage + halfImageSize * up + halfImageSize * sideV; v[3] = ptOnImage + halfImageSize * up - halfImageSize * sideV; // 6. create a Geometry that represents the map // ** Be caureful **!! // RTRectangle uses v[0] as the origin for texture lookup // we _MUST_ follow the same in order to take advante of GetUV() function! mDepthMapGeom = new RTRectangle(v); // 7. Now allocate memory for the actual map mDepthMap = new float[mRes][]; mGeomID = new int[mRes][]; for (int i = 0; i<mRes; i++) { mDepthMap[i] = new float[mRes]; mGeomID[i] = new int[mRes]; } // now, trace rays through each of the pixels in the depth map and record the depth and geomID float pixelSize = halfImageSize / (0.5f * mRes); Vector3 upPixelVector = pixelSize * up; Vector3 sidePixelVector = pixelSize * sideV; for (int y = 0; y < mRes; y++) { Vector3 yDisp = v[0] + (y+0.5f) * upPixelVector; for (int x = 0; x < mRes; x++) { Vector3 pixelPos = ((x+0.5f) * sidePixelVector) + yDisp; Ray r = new Ray(mPosition, pixelPos); IntersectionRecord rec = new IntersectionRecord(); for (int i = 0; i < sceneDatabase.GetNumGeom(); i++) { RTGeometry g = sceneDatabase.GetGeom(i); g.Intersect(r, rec); } mDepthMap[x][y] = rec.HitDistance; // closes intersection distance, any object that is // further away from the light than this distance is in the shadow of this light mGeomID[x][y] = rec.GeomIndex; // this object can never be in shadow, becuase it is the closest to the light! } } }
/// <param name="rec">IntersectionRecord to be texture mapped</param> /// <param name="g">The geometry</param> /// <returns></returns> public override Vector3 GetTexile(IntersectionRecord rec, RTGeometry g) { float noise = ComputeFractalNoise(rec.IntersectPosition.X, rec.IntersectPosition.Y, rec.IntersectPosition.Z); return (noise * mColor1) + ((1f - noise) * mColor2); }