public static Vector3 random_cosine_direction() { float r1 = Random48.Get(); float r2 = Random48.Get(); float z = Mathf.Sqrt(1 - r2); float phi = 2 * 3.141592f * r1; float x = Mathf.Cos(phi) * Mathf.Sqrt(r2); float y = Mathf.Sin(phi) * Mathf.Sqrt(r2); return(new Vector3(x, y, z)); }
public Vector3 generate(Vector3 origin) { if (Random48.Get() < 0.5) { return(random(origin)); } else { return(random(origin)); } }
bool refractcal(Ray MyRay, RaycastHit MyRayHit, ref Ray scattered, float reffactor, bool forceRefract) { Vector3 out_normal = Vector3.zero; Vector3 reflected = reflect(MyRay.direction, MyRayHit.normal); float realfactor = 1.5f; Vector3 refracted = Vector3.zero; float reflectp = 0f; float cosine = 0f; if (Vector3.Dot(MyRay.direction, MyRayHit.normal) > 0) { out_normal = -MyRayHit.normal; realfactor = reffactor; cosine = reffactor * Vector3.Dot(MyRay.direction, MyRayHit.normal) / MyRay.direction.magnitude; } else { out_normal = MyRayHit.normal; realfactor = 1.0f / reffactor; cosine = -Vector3.Dot(MyRay.direction, MyRayHit.normal) / MyRay.direction.magnitude; } if (refract(MyRay.direction, out_normal, realfactor, ref refracted)) { float r = (1f - reffactor) / (1f + reffactor); r = r * r; reflectp = r + (1 - r) * Mathf.Pow((1 - cosine), 5); if (forceRefract) { scattered = new Ray(MyRayHit.point, refracted); return(true); } } else { if (forceRefract) { scattered = new Ray(MyRayHit.point, refracted); return(true); } scattered = new Ray(MyRayHit.point, reflected); reflectp = 1.0f; } if (Random48.Get() < reflectp) { scattered = new Ray(MyRayHit.point, reflected); return(false); } else { scattered = new Ray(MyRayHit.point, refracted); return(true); } }
// Start is called before the first frame update void Start() { query = new KDQuery(); VPLVector = new Vector3[InitVPLCount]; VPLPoints = new Vector3[InitVPLCount]; SpotAngle = GetComponent <Light>().spotAngle; if (type == "Point Light") { Vector3 org = this.transform.position; RaycastHit hit; parent = new GameObject(); for (int i = 0; i < InitVPLCount; i++) { float Rx = Random48.Get(); float Ry = Random48.Get(); float Rz = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount, 3); Rz = halton(seedCount++, 4); seedCount = seedCount % (maxSeed * 3); Vector3 tempDir = new Vector3(Rx * 2.0f - 1.0f, Ry * 2.0f - 1.0f, Rz * 2.0f - 1.0f); //tempDir.Normalize(); //tempDir -= new Vector3(0.5f,0.5f,0.5f); VPLVector[i] = (tempDir); Vector3 B = tempDir; Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * B.z; if (Physics.Raycast(org, dir, out hit, 1000)) { VPLPoints[i] = (hit.point); } GameObject temp = new GameObject(); temp.transform.parent = parent.transform; temp.transform.position = VPLPoints[i]; temp.AddComponent <Light>(); temp.GetComponent <Light>().shadows = LightShadows.Hard; temp.GetComponent <Light>().shadowBias = 0; temp.GetComponent <Light>().shadowNormalBias = 0; temp.GetComponent <Light>().shadowNearPlane = 0.2f; Vector3 CubeUV = convert_xyz_to_cube_uv(B); if (CubeUV.x == 0.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 1.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 2.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 3.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 4.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 5.0f) { temp.GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } VPL.Add(temp); } } else { int PassCount = 0; Vector3 org = this.transform.position; RaycastHit hit; Texture2D tempTex = new Texture2D(1024, 1024); RenderTexture.active = rendertexture; tempTex.ReadPixels(new UnityEngine.Rect(0, 0, 1024, 1024), 0, 0); parent = new GameObject(); Debug.DrawLine(transform.position + transform.forward * 10, this.transform.position); while (PassCount != InitVPLCount) { //float Rx = ((float)Random.Range(0, 1024)) / 1024.0f; //float Ry = ((float)Random.Range(0, 1024)) / 1024.0f; float Rx = Random48.Get(); float Ry = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount++, 3); seedCount = seedCount % (maxSeed * 2); if (Mathf.Sqrt((Rx - 0.5f) * (Rx - 0.5f) + (Ry - 0.5f) * (Ry - 0.5f)) <= radius) { Vector3 B = new Vector2(Rx, Ry); B.x -= 0.5f; B.y -= 0.5f; VPLVector[PassCount] = B; // float l = Vector3.Dot(B, B); float z; z = -Mathf.Tan((Fov / 2.0f) / 180.0f * 3.1415926f); Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * z; if (Physics.Raycast(org, dir, out hit, 1000)) { Vector3 p; p.x = B.x * 1024.0f; p.y = B.y * 1024.0f; GameObject temp = new GameObject(); temp.transform.parent = parent.transform; temp.transform.position = hit.point; temp.AddComponent <Light>(); temp.GetComponent <Light>().color = (tempTex.GetPixel((int)p.x, (int)p.y)); temp.GetComponent <Light>().shadows = LightShadows.Hard; VPL.Add(temp); VPLPoints[PassCount] = hit.point; PassCount++; } else { continue; } } } int a = 1; tree = new KDTree(VPLPoints, 16); } }
// Update is called once per frame void Update() { //VPL.Clear(); //VPLPoints.Clear(); //VPLVector.Clear(); if (type == "Point Light") { Vector3 org = this.transform.position; RaycastHit hit; for (int i = 0; i < InitVPLCount; i++) { Vector3 checkdir = (VPLPoints[i] - org).normalized; float checkdistance = (VPLPoints[i] - org).magnitude; if (Physics.Raycast(org, checkdir, out hit, checkdistance)) { float Rx = Random48.Get(); float Ry = Random48.Get(); float Rz = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount, 3); Rz = halton(seedCount++, 4); seedCount = seedCount % (maxSeed * 3); Vector3 tempDir = new Vector3(Rx * 2.0f - 1.0f, Ry * 2.0f - 1.0f, Rz * 2.0f - 1.0f); tempDir.Normalize(); //tempDir -= new Vector3(0.5f, 0.5f, 0.5f); VPLVector[i] = tempDir; Vector3 B = VPLVector[i]; Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * B.z; if (Physics.Raycast(org, dir, out hit, 1000)) { VPLPoints[i] = (hit.point); VPL[i].GetComponent <Transform>().LookAt(hit.normal); } VPL[i].transform.position = VPLPoints[i]; Vector3 CubeUV = convert_xyz_to_cube_uv(B); if (CubeUV.x == 0.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 1.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeX, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 2.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 3.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeY, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 4.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.PositiveZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } if (CubeUV.x == 5.0f) { VPL[i].GetComponent <Light>().color = MyCubeMap.GetPixel(CubemapFace.NegativeZ, (int)(CubeUV.y * 1024.0), (int)(CubeUV.z * 1024.0)); } } } } else { Vector3 org = this.transform.position; RaycastHit hit; Texture2D tempTex = new Texture2D(1024, 1024); RenderTexture.active = rendertexture; tempTex.ReadPixels(new UnityEngine.Rect(0, 0, 1024, 1024), 0, 0); Vector3 temp = (this.transform.right + this.transform.up + this.transform.forward); Debug.DrawLine(transform.position + transform.forward * 10, this.transform.position); for (int i = 0; i < InitVPLCount; i++) { Vector3 checkdir = (VPL[i].transform.position - org).normalized; float checkdistance = (VPL[i].transform.position - org).magnitude; float checkAngle = Vector3.Angle(checkdir, transform.forward); if (Physics.Raycast(org, checkdir, out hit, checkdistance) || checkAngle > (SpotAngle / 2.0f)) { float Rx = Random48.Get(); float Ry = Random48.Get(); Rx = halton(seedCount, 2); Ry = halton(seedCount++, 3); seedCount = seedCount % (maxSeed * 2); if (Mathf.Sqrt((Rx - 0.5f) * (Rx - 0.5f) + (Ry - 0.5f) * (Ry - 0.5f)) <= radius) { Vector3 B = new Vector3(Rx, Ry, 0); B.x -= 0.5f; B.y -= 0.5f; // float l = Vector3.Dot(B, B); VPLVector[i] = B; float z; z = -Mathf.Tan((Fov / 2.0f) / 180.0f * 3.1415926f); Vector3 dir = this.transform.right * B.x + this.transform.up * B.y - this.transform.forward * z; if (Physics.Raycast(org, dir, out hit, 1000)) { Vector3 p; p.x = B.x * 1024.0f; p.y = B.y * 1024.0f; VPL[i].transform.position = hit.point; tree.Points[i] = hit.point; VPL[i].GetComponent <Transform>().LookAt(hit.normal); VPL[i].GetComponent <Light>().color = (tempTex.GetPixel((int)p.x, (int)p.y)); } } } } tree.Rebuild(); int count = 0; Dictionary <int, bool> lightflag = new Dictionary <int, bool>(); for (int i = 0; i < InitVPLCount; i++) { if (!lightflag.ContainsKey(i)) { count++; VPL[i].GetComponent <Light>().enabled = true; lightflag[i] = true; var resultIndices = new List <int>(); query.Radius(tree, tree.Points[i], Radius, resultIndices); for (int j = 0; j < resultIndices.Count; j++) { if (resultIndices[j] != i) { VPL[resultIndices[j]].GetComponent <Light>().enabled = false; lightflag[resultIndices[j]] = true; } } } } VPL_Num = count.ToString(); Destroy(tempTex); } if (Input.GetKeyDown(KeyCode.D)) { DEB = !DEB; CANV.SetActive(DEB); } if (Input.GetKeyDown(KeyCode.E)) { SDEB = !SDEB; CANV2.SetActive(SDEB); } if (DEB == true) { Vector3 TP = this.GetComponent <Transform>().position; for (int i = 0; i < InitVPLCount; i++) { Debug.DrawLine(TP, VPL[i].GetComponent <Transform>().position); } if (Input.GetKeyDown(KeyCode.W)) { NowSeeLight++; NowSeeLight = NowSeeLight % InitVPLCount; MainCam.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; MainCam.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; //C.transform.parent = VPL[NowSeeLight].transform; C.transform.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; C.transform.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; } if (Input.GetKeyDown(KeyCode.S)) { NowSeeLight--; if (NowSeeLight < 0) { NowSeeLight += InitVPLCount; } NowSeeLight = NowSeeLight % InitVPLCount; MainCam.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; MainCam.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; //C.transform.parent = VPL[NowSeeLight].transform; C.transform.GetComponent <Transform>().rotation = VPL[NowSeeLight].GetComponent <Transform>().rotation; C.transform.GetComponent <Transform>().position = VPL[NowSeeLight].GetComponent <Transform>().position; } } }
Color RHit(Ray Input, int BoundTime) { RaycastHit MYRayHit; Color color = Color.black; //if (BoundTime >= texture_boundtime) //{ // Vector3 Ldir = ThisLight.GetComponent<Transform>().position - Input.origin; // Ray NRay = new Ray(Input.origin, Ldir.normalized); // if (Physics.Raycast(NRay, out MYRayHit, 2000f)) // { // if (MYRayHit.collider.tag == "Light")//done // { // return Color.white * 4; // } // } // return Color.black; //} if (Physics.Raycast(Input, out MYRayHit, 2000f) && (BoundTime < texture_boundtime)) { Renderer renderer = MYRayHit.collider.GetComponent <MeshRenderer>(); Ray scattered = new Ray(); Color attenuation = Color.black; Color emitted = Color.black; float scatter_pdf = 1f; float pdf_val = 1f; float coef = 1f; if (MYRayHit.collider.tag == "Light")//done { return(Color.white * 3); } else if (MYRayHit.collider.tag == "lambertian") { emitted = new Color(0.15f, 0.15f, 0.15f); //Vector3 scatter_direction = MYRayHit.normal + new Vector3(Random.Range(-1, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized; //scattered = new Ray(MYRayHit.point, scatter_direction); getPixelColor(MYRayHit, ref attenuation); attenuation *= renderer.material.color; Vector3[] onb = new Vector3[3]; build_onb(MYRayHit.normal, ref onb); Vector3 cos_pdf = cos_pdf_generate(onb); Vector3 light_pdf = lights.generate(MYRayHit.point); Vector3 scatter_dir = (Random.Range(0f, 1f) < 0.5f) ? cos_pdf : light_pdf; scattered = new Ray(MYRayHit.point, scatter_dir.normalized); float cos = Vector3.Dot(scatter_dir.normalized, onb[2]); float cos_value = (cos > 0) ? (cos / 3.141592f) : 0; float light_value = lights.pdf_value(Input, MYRayHit.point, scatter_dir.normalized); pdf_val = 0.5f * cos_value + 0.5f * light_value; scatter_pdf = (cos < 0) ? 0 : (Vector3.Dot(MYRayHit.normal, scatter_dir.normalized) / 3.141592f); coef = scatter_pdf / pdf_val; if (coef > 1.2) { coef = 1.2f; } //scatter_pdf *= 1.2f; } else if (MYRayHit.collider.tag == "metal") { float fuzz = 0.01f; emitted = Color.black; Vector3 reflected = Vector3.Reflect(Input.direction.normalized, MYRayHit.normal); scattered = new Ray(MYRayHit.point, reflected + fuzz * Random48.random_cosine_direction()); Vector3 outNor = MYRayHit.normal; getPixelNormal(MYRayHit, ref outNor); Vector3 reflectedn = Vector3.Reflect(Input.direction.normalized, outNor); scattered = new Ray(MYRayHit.point, reflected + fuzz * new Vector3(Random.Range(-1, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized); getPixelColor(MYRayHit, ref attenuation); attenuation *= renderer.material.color; if (Vector3.Dot(scattered.direction, MYRayHit.normal) > 0) { } else { return(Color.black); } } else if (MYRayHit.collider.tag == "dielectric") { Vector3 out_normal = Vector3.zero; Vector3 reflected = reflect(Input.direction, MYRayHit.normal); float reffactor = 1.5f; float realfactor = 1.5f; attenuation = Color.white; Vector3 refracted = Vector3.zero; float reflectp = 0f; float cosine = 0f; if (Vector3.Dot(Input.direction, MYRayHit.normal) > 0) { out_normal = -MYRayHit.normal; realfactor = reffactor; cosine = reffactor * Vector3.Dot(Input.direction, MYRayHit.normal) / Input.direction.magnitude; } else { out_normal = MYRayHit.normal; realfactor = 1.0f / reffactor; cosine = -Vector3.Dot(Input.direction, MYRayHit.normal) / Input.direction.magnitude; } if (refract(Input.direction, out_normal, realfactor, ref refracted)) { float r = (1f - reffactor) / (1f + reffactor); r = r * r; reflectp = r + (1 - r) * Mathf.Pow((1 - cosine), 5); } else { //scattered = new Ray(MYRayHit.point, reflected); reflectp = 1.0f; } if (Random48.Get() < reflectp) { scattered = new Ray(MYRayHit.point, reflected); } else { scattered = new Ray(MYRayHit.point, refracted); } emitted = Color.black; } return(emitted + attenuation * RHit(scattered, ++BoundTime) * coef); } else { return(Color.black); } }
void RayCastPass(Ray INPUT, int texture_x, int texture_y, int texture_sample) { RaycastHit MYRayHit; if (Physics.Raycast(INPUT, out MYRayHit, 2000f)) { Renderer renderer = MYRayHit.collider.GetComponent <MeshRenderer>(); if (MYRayHit.collider.tag == "Light")//done { HitPoint_position[texture_x, texture_y, texture_sample] = MYRayHit.point; } else if (MYRayHit.collider.tag == "lambertian") { HitPoint_position[texture_x, texture_y, texture_sample] = MYRayHit.point; } else if (MYRayHit.collider.tag == "metal") { float fuzz = 0.05f; Vector3 reflected = Vector3.Reflect(INPUT.direction.normalized, MYRayHit.normal); Ray scattered = new Ray(MYRayHit.point, reflected + fuzz * new Vector3(Random.Range(-1, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized); if (Vector3.Dot(scattered.direction, MYRayHit.normal) > 0) { RayCastPass(scattered, texture_x, texture_y, texture_sample); } } else if (MYRayHit.collider.tag == "dielectric") { Vector3 out_normal = Vector3.zero; Ray scattered = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 1)); Vector3 reflected = reflect(INPUT.direction, MYRayHit.normal); float reffactor = 1.5f; float realfactor = 1.5f; Vector3 refracted = Vector3.zero; float reflectp = 0f; float cosine = 0f; if (Vector3.Dot(INPUT.direction, MYRayHit.normal) > 0) { out_normal = -MYRayHit.normal; realfactor = reffactor; cosine = reffactor * Vector3.Dot(INPUT.direction, MYRayHit.normal) / INPUT.direction.magnitude; } else { out_normal = MYRayHit.normal; realfactor = 1.0f / reffactor; cosine = -Vector3.Dot(INPUT.direction, MYRayHit.normal) / INPUT.direction.magnitude; } if (refract(INPUT.direction, out_normal, realfactor, ref refracted)) { float r = (1f - reffactor) / (1f + reffactor); r = r * r; reflectp = r + (1 - r) * Mathf.Pow((1 - cosine), 5); } else { scattered = new Ray(MYRayHit.point, reflected); reflectp = 1.0f; } if (Random48.Get() < reflectp) { scattered = new Ray(MYRayHit.point, reflected); } else { scattered = new Ray(MYRayHit.point, refracted); } RayCastPass(scattered, texture_x, texture_y, texture_sample); } } }