Color GetLightPathColor(Vector3 pos, Vector3 dir, float length) { RayTrace.Ray ray = new RayTrace.Ray(pos, dir, length); RayTrace.Intersect(ref ray); if (ray.geomID == RayTrace.Invalid) { return(Color.white); } else { SimpleModel model = scene.models[(int)ray.geomID]; SimpleMesh mesh = model.mesh; int t0 = mesh.triangles[ray.primID * 3 + 0]; int t1 = mesh.triangles[ray.primID * 3 + 1]; int t2 = mesh.triangles[ray.primID * 3 + 2]; Vector2 uv = RayTraceTool.Lerp(mesh.uv[t0], mesh.uv[t1], mesh.uv[t2], ray.u, ray.v); Vector3 hitPos = ray.pos + ray.dir * ray.length; Color texColor = model.material.PointSample(uv); if (texColor.a < 0.99f) { Color aheadColor = GetLightPathColor(hitPos, dir * 0.01f, length - ray.length); Color blendColor = (aheadColor * (1 - texColor.a)) + (texColor * texColor.a); return(blendColor); } } return(Color.black); }
public void Render() { //RayTraceTool.GetRandomDirs_BlinnPhong_Importance2(Vector3.up, new Vector3(1, 0.1f, 0).normalized, 0.7f, 1000); //return; updateProgress(0); Camera cam = GetComponent <Camera>(); if (cam) { Vector3 left = Vector3.Cross(cam.transform.forward, cam.transform.up); Vector3 up = Vector3.Cross(left, cam.transform.forward); float lengthY = Mathf.Tan(Mathf.Deg2Rad * cam.fieldOfView / 2) * 2; float lengthX = lengthY * width / height; int waitNum = width * height; int curIndex = 0; SimpleTexture targetTexture = new SimpleTexture(width, height); float startTime = Time.realtimeSinceStartup; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int x = i - width / 2; int y = height / 2 - j; Color color = Color.black; int splitPixel = antiAliasing ? 3 : 1; for (int ax = 0; ax < splitPixel; ax++) { for (int ay = 0; ay < splitPixel; ay++) { float fx = (lengthX * (x + ax / (float)splitPixel)) / width; float fy = (lengthY * (y + ay / (float)splitPixel)) / height; Vector3 temp = cam.transform.position + cam.transform.forward + left * fx + up * fy; Vector3 tempDir = Vector3.Normalize(temp - cam.transform.position); int subSampleNum = sampleNum / (splitPixel * splitPixel); color += TraceColor(cam.transform.position, tempDir, subSampleNum, 3); } } color /= splitPixel * splitPixel; color.a = 1; targetTexture.SetColor(width - i - 1, height - j - 1, RayTraceTool.LinearToGammaSpace(color)); curIndex += 1; } if (updateProgress(curIndex / (float)waitNum)) { break; } } //TaskPipeLine.Flush(); Debug.Log("render time : " + (Time.realtimeSinceStartup - startTime)); texture.SetPixels(targetTexture.colors); texture.Apply(true); } }
public SimpleMaterial(Material mat) { unityTexture = mat.mainTexture as Texture2D; if (mat.mainTexture != null) { Int64 key = mat.mainTexture.GetNativeTexturePtr().ToInt64(); if (!textures.TryGetValue(key, out texture)) { texture = new SimpleTexture(mat.mainTexture as Texture2D); textures[key] = texture; } } else { texture = new SimpleTexture(null); } if (mat.HasProperty("_Color")) { this.color = RayTraceTool.GammaToLinearSpace(mat.color); } if (mat.HasProperty("_Glossiness")) { glossiness = mat.GetFloat("_Glossiness"); } if (mat.HasProperty("_Metallic")) { metallic = mat.GetFloat("_Metallic"); } if (mat.HasProperty("_Cutoff")) { renderMode = RenderMode.Alphablend; } else if (mat.shader.name.ToLower().Contains("standard")) { if (mat.HasProperty("_Mode")) { if (mat.GetInt("_Mode") == 0) { renderMode = RenderMode.Opaque; } } } else if (mat.shader.name.ToLower().Contains("multiply")) { renderMode = RenderMode.Multiply; } else if (mat.shader.name.ToLower().Contains("transparent")) { renderMode = RenderMode.Alphablend; } }
public override Color LinearSample(Vector2 uv) { Color rlt = Color.black; for (int i = 0; i < alphamapLayers; i++) { float alpha = RayTraceTool.BilinearInterpolation(alphamaps[i], alphamapWidth, alphamapHeight, new Vector2(uv.y, uv.x)); if (alpha > 0.004f) { rlt += RayTraceTool.LinearSample(textures[i].colors, textures[i].width, textures[i].height, Vector2.Scale(uv, textures[i].scale)) * alpha; } } return(rlt); }
public SimpleTexture(Texture2D texture) { if (texture != null) { string assetPath = UnityEditor.AssetDatabase.GetAssetPath(texture); var tImporter = UnityEditor.AssetImporter.GetAtPath(assetPath) as UnityEditor.TextureImporter; if (tImporter == null || !tImporter.isReadable) { RenderTexture rt = new RenderTexture(texture.width, texture.height, 0); RenderTexture.active = rt; Graphics.Blit(texture, rt); texture = new Texture2D(texture.width, texture.height); texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); texture.Apply(); RenderTexture.active = null; if (bFirst) { bFirst = false; RayTraceRenderer.Instance.previewTexture = texture; } } } if (texture) { width = texture.width; height = texture.height; colors = texture.GetPixels(); for (int i = 0; i < colors.Length; i++) { colors[i] = RayTraceTool.GammaToLinearSpace(colors[i]); } } if (colors == null || colors.Length == 0) { width = 1; height = 1; colors = new Color[1]; colors[0] = Color.white; } }
Color TraceColor(Vector3 startPos, Vector3 rayDir, int sample, int depth) { if (depth <= 0) { return(Color.black); } RayTrace.Ray ray = new RayTrace.Ray(startPos, rayDir, 1000); RayTrace.Intersect(ref ray); if (ray.geomID == RayTrace.Invalid) { return(skyColor); } else { SimpleModel model = scene.models[(int)ray.geomID]; SimpleMesh mesh = model.mesh; int t0 = mesh.triangles[ray.primID * 3 + 0]; int t1 = mesh.triangles[ray.primID * 3 + 1]; int t2 = mesh.triangles[ray.primID * 3 + 2]; Vector2 uv = RayTraceTool.Lerp(mesh.uv[t0], mesh.uv[t1], mesh.uv[t2], ray.u, ray.v); Color texColor = model.material.LinearSample(uv); if (!ignoreMaterialColor) { texColor *= model.material.GetColor(); } if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Opaque) { texColor.a = 1; } Vector3 hitPos = ray.pos + ray.dir * ray.length; Vector3 hitNormal = RayTraceTool.Lerp(mesh.normals[t0], mesh.normals[t1], mesh.normals[t2], ray.u, ray.v); hitNormal = (model.rst.rot * hitNormal); float transFactor = 1 - texColor.a; float glossiness = model.material.glossiness; float reflectFactor = Mathf.Lerp(0.2f * glossiness, 1f, model.material.metallic); if (reflectFactor > 0.01f) { reflectFactor = Fresnel_Schlick(Vector3.Dot(-rayDir, hitNormal), reflectFactor); } float grayscale = texColor.grayscale; float diffuseFactor = Mathf.Clamp01(1 - transFactor - reflectFactor); int transSample = (int)(sample * grayscale * transFactor); int reflectSample = (int)(sample * reflectFactor); int diffuseSample = (int)(sample * grayscale * diffuseFactor); Color finaleColor = Color.black; Color reflectColor = Color.black; { Color finalLightColor = Color.black;// GetAllLightsColor(model, hitPos, hitNormal) * (reflectFactor + scene.lights.Length);//光源直接贡献 if (reflectSample > 0) { Vector3 reflectDir = Vector3.Reflect(rayDir, hitNormal); Vector3[] dirs = RayTraceTool.GetRandomDirs_BlinnPhong_Importance2(hitNormal, reflectDir, glossiness, reflectSample); for (int i = 0; i < reflectSample; i++) { finalLightColor += TraceColor(hitPos + hitNormal * 0.01f, dirs[i], 1, depth - 1);//间接光贡献 } finalLightColor /= (reflectSample); } reflectColor = Color.Lerp(Color.white, texColor, model.material.metallic) * finalLightColor; } Color diffuseColor = Color.black; { Color finalLightColor = GetAllLightsColor(model, hitPos, hitNormal) * (diffuseSample + scene.lights.Length);//光源直接贡献 if (diffuseSample > 0) { Vector3 reflectDir = Vector3.Reflect(rayDir, hitNormal); Vector3[] dirs = RayTraceTool.GetRandomDirs_RoundProj(hitNormal, diffuseSample); for (int i = 0; i < diffuseSample; i++) { finalLightColor += TraceColor(hitPos + hitNormal * 0.01f, dirs[i], 1, depth - 1);//间接光贡献 } } finalLightColor /= (diffuseSample + scene.lights.Length); diffuseColor = texColor * finalLightColor; } //Color reflectColor = Color.black; //if(reflectFactor > 0.01f){ // Vector3 refDir = Vector3.Reflect(rayDir,hitNormal); // Color finalLightColor = TraceColor(hitPos + refDir * 0.01f, refDir,reflectSample ,depth - 1); // reflectColor = finalLightColor; //} finaleColor = reflectColor * reflectFactor + diffuseColor * diffuseFactor; if (texColor.a < 0.99f) { Color transColor = TraceColor(hitPos + rayDir * 0.01f, rayDir, transSample, depth); if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Alphablend) { finaleColor = finaleColor * texColor.a + transColor * (1 - texColor.a); } else if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Multiply) { finaleColor = finaleColor * transColor; } else if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Additive) { finaleColor = finaleColor + transColor; } } return(finaleColor); } }
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; }
public override Color LinearSample(Vector2 uv) { return(RayTraceTool.LinearSample(texture.colors, texture.width, texture.height, uv)); }