//http://www.klayge.org/?p=3006 public static Vector3[] GetRandomDirs_BlinnPhong_Importance(Vector3 faceNormal, Vector3 reflectDir, float smoothness, int num) { Vector3[] rlt = new Vector3[num]; float reflectAngle = Mathf.Acos(Vector3.Dot(reflectDir, faceNormal)); //镜面反射线与法线夹角 float mainAngle = reflectAngle * smoothness; //粗糙反射线平均方向与法线夹角 Vector3 axisTemp = Mathf.Abs(Vector3.Dot(faceNormal, Vector3.up)) > 0.9f ? Vector3.left : Vector3.up; Vector3 axis0 = Vector3.Cross(faceNormal, axisTemp);//任意垂直于faceNormal的方向 Vector3 axis2 = -Vector3.Cross(reflectDir, faceNormal); if (axis2.sqrMagnitude == 0) { axis2 = axis0; } float shininess = Mathf.Pow(8192, smoothness); Quaternion finalRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), faceNormal); for (int i = 0; i < num; i++) { float angle0 = Mathf.Acos(Mathf.Pow(1 - HaltonTool.Halton2(i, 0f, 1f) * (shininess + 1) / (shininess + 2), 1 / (shininess + 1))); angle0 *= Mathf.PI * 0.5f;//看起来上面公式的结果范围是0~1,所以加上这个修正一下,不知道原因 Vector3 dir0 = Quaternion.AngleAxis(angle0 * Mathf.Rad2Deg, axis0) * faceNormal; Vector3 dir1 = Quaternion.AngleAxis(HaltonTool.Halton3(i, 0f, 360f), faceNormal) * dir0; Vector3 dir2 = Quaternion.AngleAxis(mainAngle * Mathf.Rad2Deg, axis2) * dir1; rlt[i] = dir2; //Debug.DrawLine(dir2 + Vector3.up * 5, dir2 + Vector3.up * 5 + dir2 * 0.02f, Color.red, 10000); } return(rlt); }
//尝试瞎凑的公式 public static Vector3[] GetRandomDirs_BRDF(Vector3 faceNormal, Vector3 reflectDir, float smoothness, int num) { Vector3[] rlt = new Vector3[num]; //Vector3 mainOutDir = Vector3.Lerp(faceNormal, reflectDir, smoothness).normalized; float reflectAngle = Mathf.Acos(Vector3.Dot(reflectDir, faceNormal)); //镜面反射线与法线夹角 float mainAngle = reflectAngle * smoothness; //粗糙反射线平均方向与法线夹角 float distributionAngle = (Mathf.PI * 0.5f * (1 - smoothness)); Vector3 axisTemp = Mathf.Abs(Vector3.Dot(faceNormal, Vector3.up)) > 0.9f ? Vector3.left : Vector3.up; Vector3 axis0 = Vector3.Cross(faceNormal, axisTemp);//任意垂直于faceNormal的方向 Vector3 axis2 = -Vector3.Cross(reflectDir, faceNormal); if (axis2.sqrMagnitude == 0) { axis2 = axis0; } Quaternion finalRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), faceNormal); for (int i = 0; i < num; i++) { float angle0 = Mathf.Asin(Mathf.Sqrt(HaltonTool.Halton2(i, 0f, 1f))) * distributionAngle / (Mathf.PI / 2); Vector3 dir0 = Quaternion.AngleAxis(angle0 * Mathf.Rad2Deg, axis0) * faceNormal; Vector3 dir1 = Quaternion.AngleAxis(HaltonTool.Halton3(i, 0f, 360f), faceNormal) * dir0; Vector3 dir2 = Quaternion.AngleAxis(mainAngle * Mathf.Rad2Deg, axis2) * dir1; rlt[i] = dir2; //Debug.DrawLine(dir2 + Vector3.up * 5, dir2 + Vector3.up * 5 + dir2 * 0.02f, Color.red, 10000); } return(rlt); }
public static Vector3[] GetRandomDirs(Vector3 faceNormal, int num) { Vector3[] rlt = new Vector3[num]; Vector3 axisTemp = Mathf.Abs(Vector3.Dot(faceNormal, Vector3.up)) > 0.9f ? Vector3.left : Vector3.up; Vector3 axis0 = Vector3.Cross(faceNormal, axisTemp); for (int i = 0; i < num; i++) { float angle0 = Mathf.Acos(HaltonTool.Halton2(i, 0f, 1f)) * Mathf.Rad2Deg; Vector3 dir = Quaternion.AngleAxis(angle0, axis0) * faceNormal; Quaternion finalRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), faceNormal); dir = finalRot * dir; //Debug.DrawLine(dir + Vector3.up * 5, dir + Vector3.up * 5 + dir * 0.02f, Color.red, 10000); rlt[i] = dir; } return(rlt); }
public static Vector3[] GetRandomDirs_RoundProj(Vector3 faceNormal, int num) { Vector3[] rlt = new Vector3[num]; Vector3 axisTemp = Mathf.Abs(Vector3.Dot(faceNormal, Vector3.up)) > 0.9f ? Vector3.left : Vector3.up; Vector3 axis0 = Vector3.Cross(faceNormal, axisTemp); Quaternion finalRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), faceNormal); for (int i = 0; i < num; i++) { float lenght0 = Mathf.Sqrt(HaltonTool.Halton2(i, 0f, 1f)); //float lenght0 = Mathf.Sin(Mathf.PI * 0.5f * Mathf.Sqrt(HaltonTool.Halton2(i, 0f, 1f))); Vector3 pos0 = axis0 * lenght0; Vector3 pos1 = Quaternion.AngleAxis(HaltonTool.Halton3(i, 0f, 360f), faceNormal) * pos0; Vector3 dir = pos1 + faceNormal * (Mathf.Sqrt(1 - lenght0 * lenght0)); //Debug.DrawLine(dir + Vector3.up * 5, dir + Vector3.up * 5 + faceNormal * 0.02f, Color.red, 10000); dir = finalRot * dir; rlt[i] = dir; } return(rlt); }
//http://www.klayge.org/?p=3006 public static Vector3[] GetRandomDirs_BlinnPhong_Importance2(Vector3 faceNormal, Vector3 reflectDir, float smoothness, int num) { Vector3[] rlt = new Vector3[num]; Vector3 w = Vector3.Lerp(faceNormal, reflectDir, smoothness).normalized; Vector3 u = Vector3.Cross(new Vector3(w.y, w.z, w.x), w); Vector3 v = Vector3.Cross(w, u); float shininess = Mathf.Pow(8192, smoothness); for (int i = 0; i < num; i++) { float a = Mathf.Acos(Mathf.Pow(1 - HaltonTool.Halton2(i, 0f, 1f) * (shininess + 1) / (shininess + 2), 1 / (shininess + 1))); a *= Mathf.PI * 0.5f;//看起来上面公式的结果范围是0~1,所以加上这个修正一下,不知道原因 float phi = HaltonTool.Halton3(i, 0f, Mathf.PI * 2); rlt[i] = (u * Mathf.Cos(phi) + v * Mathf.Sin(phi)) * Mathf.Sin(a) + w * Mathf.Cos(a); //Debug.DrawLine(rlt[i] + Vector3.up * 5, rlt[i] + Vector3.up * 5 + rlt[i] * 0.02f, Color.red, 10000); } return(rlt); }
public void Init() { Instance = this; updateProgress(0); HaltonTool.InitHaltonSequence(); Debug.Log("Start Time : " + Time.realtimeSinceStartup); scene = new SimpleScene(); RayTrace.Init(); SimpleMaterial.textures.Clear(); scene.lights = GameObject.FindObjectsOfType <Light>(); Camera cam = GetComponent <Camera>(); if (cam) { MeshRenderer[] renderers = GameObject.FindObjectsOfType <MeshRenderer>(); foreach (MeshRenderer r in renderers) { bool isLayerVisible = ((1 << r.gameObject.layer) & cam.cullingMask) != 0; if (r.isVisible && isLayerVisible) { MeshFilter filter = r.gameObject.GetComponent <MeshFilter>(); if (filter && filter.sharedMesh) { for (int i = 0; i < filter.sharedMesh.subMeshCount; i++) { Mesh mesh = filter.sharedMesh; int[] triangles = filter.sharedMesh.GetTriangles(i); RayTrace.AddMesh(filter.gameObject.transform, mesh.vertexCount, triangles.Length, mesh.vertices, triangles, 1); SimpleModel model = new SimpleModel(r.gameObject.transform, filter.sharedMesh, i, r.sharedMaterials[i]); model.lights = RayTraceTool.GetActivityLights(r, scene); scene.models.Add(model); } } } } Terrain[] terrains = GameObject.FindObjectsOfType <Terrain>(); foreach (Terrain terrain in terrains) { bool isLayerVisible = ((1 << terrain.gameObject.layer) & cam.cullingMask) != 0; if (terrain.gameObject.activeInHierarchy && isLayerVisible) { int w = terrain.terrainData.heightmapWidth; int h = terrain.terrainData.heightmapHeight; float realWidth = terrain.terrainData.size.x * (1 + 1f / w); float realHeight = terrain.terrainData.size.z * (1 + 1f / h); float[,] heights = terrain.terrainData.GetHeights(0, 0, w, h); Vector3[] vertices = new Vector3[w * h]; Vector2[] uvs = new Vector2[vertices.Length]; Vector3[] normals = new Vector3[vertices.Length]; int[] triangles = new int[(w - 1) * (h - 1) * 2 * 3]; for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { Vector3 pos = new Vector3(i * realWidth / w, heights[j, i] * terrain.terrainData.size.y, j * realHeight / h); vertices[j * w + i] = pos; uvs[j * w + i] = new Vector2(i / (float)w, j / (float)h); normals[j * w + i] = terrain.terrainData.GetInterpolatedNormal(i / (float)w, j / (float)h); } } for (int i = 0; i < w - 1; i++) { for (int j = 0; j < h - 1; j++) { int index = (j * (w - 1) + i) * 6; triangles[index + 0] = (i + 0) + (j + 0) * w; triangles[index + 1] = (i + 1) + (j + 1) * w; triangles[index + 2] = (i + 1) + (j + 0) * w; triangles[index + 3] = (i + 0) + (j + 0) * w; triangles[index + 4] = (i + 0) + (j + 1) * w; triangles[index + 5] = (i + 1) + (j + 1) * w; } } RayTrace.AddMesh(terrain.transform, vertices.Length, triangles.Length, vertices, triangles, 1); SimpleModel model = new SimpleModel(); model.mesh = new SimpleMesh(triangles, uvs, vertices, normals); model.material = new SimpleTerrainMaterial(terrain.terrainData); model.rst = new RayTrace.RST(terrain.transform.rotation, terrain.transform.lossyScale, terrain.transform.position); model.lights.AddRange(scene.lights); scene.models.Add(model); } } } RayTrace.Commit(); texture = new Texture2D(width, height, TextureFormat.ARGB32, true); //viewResult.sharedMaterial.mainTexture = texture; }