Exemplo n.º 1
0
    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;
            }
        }
    }
Exemplo n.º 2
0
    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;
            }
        }
    }
Exemplo n.º 3
0
    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);
    }