private void ReflectFunc(Ray ray, RaycastHit hit, MicrofacetModel BRDF, int depth, float multi, ref Color slightColor, ref Color dlightColor) { //反射 var V = -ray.direction; var N = hit.normal; var dirs = BRDF.ReflectDirections(N, V, reflectCount); float countInv = 1.0f / dirs.Count; foreach (var reflectDir in dirs) { var L = reflectDir; Ray refRay = new Ray(hit.point + N * 0.001f, reflectDir); //if (FixNLV(ref N, L, V) == false) continue; var s = BRDF.getSIntensity(N, L, V); var d = BRDF.getDIntensity(); Color reflectColor = Color.black; RaycastHit reflecthit; if (RayTracing(refRay, out reflectColor, out reflecthit, depth + 1, multi * Math.Max(s, d))) { float intensity = countInv; reflectColor *= intensity; //高光计算 slightColor += reflectColor * s; //漫反射计算 dlightColor += reflectColor * d; } } }
private void Lighting(Ray ray, RaycastHit hit, MicrofacetModel BRDF, ref Color slightColor, ref Color dlightColor) { foreach (var light in lights) { switch (light.type) { case LightType.Spot: { } break; case LightType.Directional: break; case LightType.Point: { var L = light.transform.position - hit.point; var len = L.magnitude; L.Normalize(); //点到光源之间被遮挡,阴影特效 if (len > light.range || Physics.Raycast(hit.point + hit.normal * 0.001f, L, len)) { break; } var N = hit.normal; var V = -ray.direction; //在碰撞点上面的光强 var intensity = light.intensity; intensity *= (float)(Math.Pow(1 - len / light.range, 2)); //光根据距离衰减 intensity *= Math.Max(0, Vector3.Dot(N, L)); //光投影到面的衰减 //if (FixNLV(ref N, L, V) == false) continue; //高光计算 slightColor += light.color * intensity * BRDF.getSIntensity(N, L, V); //漫反射计算 dlightColor += light.color * intensity * BRDF.getDIntensity(); //在半球上进行均匀漫反射 d*1/(2*pi) } break; case LightType.Area: break; default: break; } } }
bool RayTracing(Ray ray, out Color desColor, out RaycastHit hit, int depth = 0, float multi = 1) { desColor = Color.black; hit = new RaycastHit(); if (depth >= maxDepth) { return(false); } if (multi < 0.001) { return(false); } if (Physics.Raycast(ray, out hit)) { //是否在物体内部发生碰撞 bool isOutside = Vector3.Dot(hit.normal, -ray.direction) > 0; //双向反射分布模型 var BRDF = new MicrofacetModel(); //表面颜色 Color textureColor = Color.white; var meshRenderer = hit.transform.GetComponent <MeshRenderer>(); int mode = 0; if (meshRenderer && meshRenderer.material) { var material = meshRenderer.material; textureColor = material.color; var texture = material.mainTexture as Texture2D; if (texture) { textureColor *= texture.GetPixelBilinear(hit.textureCoord.x, hit.textureCoord.y); } //0不透明,3透明 mode = material.GetInt("_Mode"); float Metallic = material.GetFloat("_Metallic"); //金属 float Smoothness = material.GetFloat("_Glossiness"); //高光分布 BRDF.S = Metallic; BRDF.m = 1 - Smoothness; } Color slightColor = Color.black; Color dlightColor = Color.black; Color refractColor = Color.black; Lighting(ray, hit, BRDF, ref slightColor, ref dlightColor); //递归追踪,看似光源的一种 bool isRefract = false; if (isReflect) { if (mode == 3 && refractiveIndices > 0.01f) { Vector3 refractV; float ni_over_nt = refractiveIndices; var N = hit.normal; var V = -ray.direction; if (isOutside) { ni_over_nt = 1 / ni_over_nt; } else { N = -N; } if (Refract(V, N, ni_over_nt, out refractV)) { var F = (float)BRDF.Fresnel_Reflection(N, V); RaycastHit refractInfo; var m = multi * (1f - F); var rayRefract = new Ray(hit.point + refractV * 0.0001f, refractV); RayTracing(rayRefract, out refractColor, out refractInfo, depth + 1, m); isRefract = true; refractColor *= 1 - F; } } if (!isOutside) { hit.normal = -hit.normal; } ReflectFunc(ray, hit, BRDF, depth, multi, ref slightColor, ref dlightColor); } var faceColor = textureColor; desColor = faceColor * dlightColor + slightColor; if (isRefract) { desColor += faceColor * refractColor;//漫反射 } //按照距离衰减 if (depth != 0) { float intensity = 1; float len = (hit.point - ray.origin).magnitude; if (len >= 100) { intensity = 0; } intensity *= (float)(Math.Pow(1 - len / 100, 2));//光根据距离衰减 //intensity *= Math.Max(0, Vector3.Dot(hit.normal, -ray.direction));//光投影到面的衰减 desColor *= intensity; } desColor.a = 1; return(true); } return(false); }