예제 #1
0
 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);
 }
예제 #2
0
    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);
        }
    }