Esempio n. 1
0
    public override bool Hit(RayTrace.Ray ray, float t_min, float t_max, ref HitRecord rec)
    {
        var   oc = ray.origin - center;
        float a  = Vector3.Dot(ray.direction, ray.direction);
        float b  = 2f * Vector3.Dot(oc, ray.direction);
        float c  = Vector3.Dot(oc, oc) - radius * radius;

        float discriminant = b * b - 4 * a * c;

        if (discriminant > 0)
        {
            float temp = (-b - Mathf.Sqrt(discriminant)) / a * 0.5f;
            if (temp < t_max && temp > t_min)
            {
                rec.t        = temp;
                rec.p        = ray.GetPoint(rec.t);
                rec.normal   = (rec.p - center).normalized;
                rec.material = material;
                return(true);
            }

            temp = (-b + Mathf.Sqrt(discriminant)) / a * 0.5f;
            if (temp < t_max && temp > t_min)
            {
                rec.t        = temp;
                rec.p        = ray.GetPoint(rec.t);
                rec.normal   = (rec.p - center).normalized;
                rec.material = material;
                return(true);
            }
        }

        return(false);
    }
 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);
 }
Esempio n. 3
0
    static bool IsRayCastSphere(Ray ray, Vector3 sphereOrigin, float radiu)
    {
        Vector3 oc = ray.direction - sphereOrigin;
        float   a  = Vector3.Dot(ray.direction, ray.direction);
        float   b  = 2f * Vector3.Dot(ray.direction, oc);
        float   c  = Vector3.Dot(oc, oc) - radiu * radiu;

        float delta = b * b - 4 * a * c;

        return(delta > 0);
    }
Esempio n. 4
0
    static Color GetSkyColorFronRay(Ray ray)
    {
        if (IsRayCastSphere(ray, new Vector3(0f, 0f, -1f), .5f))
        {
            return(Color.red);
        }

        float y = (ray.direction.y + 1) / 2;

        return((1 - y) * new Color(1, 1, 1) + new Color(0.5f, 0.7f, 1.0f));
    }
Esempio n. 5
0
    static Color GetColorForTestNormal(Ray ray)
    {
        float t = HitSphereForTestNormal(new Vector3(0, 0, -1), 0.5f, ray);

        if (t > 0)
        {
            Vector3 normal = Vector3.Normalize(ray.GetPoint(t) - new Vector3(0, 0, -1));
            return(0.5f * new Color(normal.x + 1, normal.y + 1, normal.z + 1, 2f));
        }
        t = 0.5f * ray.normalDirection.y + 1f;
        return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1));
    }
Esempio n. 6
0
    private static Color GetColorFromScene(Ray ray, HitableList hitableList)
    {
        HitRecord record = new HitRecord();

        if (hitableList.Hit(ray, 0f, float.MaxValue, ref record))
        {
            return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 1f));
        }

        float t = (ray.direction.y + 1) * .5f;

        return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f));
    }
Esempio n. 7
0
    private static Color GetColorForTestDiffusing(Ray ray, HitableList hitableList)
    {
        HitRecord record = new HitRecord();

        if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record))
        {
            Vector3 target = record.p + record.normal + GetRandomDir();
            return(0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList));
        }

        float t = (ray.direction.y + 1) * .5f;

        return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f));
    }
Esempio n. 8
0
    public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord hit)
    {
        HitRecord tempRecord = new HitRecord();
        bool      hitted     = false;
        float     closest    = t_max;

        for (int i = 0; i < this.hitLists.Count; i++)
        {
            if (this.hitLists[i].Hit(ray, t_min, closest, ref tempRecord))
            {
                hit     = tempRecord;
                closest = tempRecord.t;
                hitted  = true;
            }
        }

        return(hitted);
    }
Esempio n. 9
0
    static float HitSphereForTestNormal(Vector3 center, float radius, Ray ray)
    {
        var   oc = ray.origin - center;
        float a  = Vector3.Dot(ray.direction, ray.direction);
        float b  = 2f * Vector3.Dot(oc, ray.direction);
        float c  = Vector3.Dot(oc, oc) - radius * radius;
        //实际上是判断这个方程有没有根,如果有2个根就是击中
        float discriminant = b * b - 4 * a * c;

        if (discriminant < 0)
        {
            return(-1);
        }
        else
        {
            //返回距离最近的那个根
            return((-b - Mathf.Sqrt(discriminant)) / (2f * a));
        }
    }
Esempio n. 10
0
    public static Color[] MakeColors()
    {
        int WIDTH  = CreatPNG.WIDTH;
        int HEIGHT = CreatPNG.HEIGHT;
        int total  = WIDTH * HEIGHT;

        Color[] colors = new Color[total];


        Vector3 origin         = Vector3.zero;
        Vector3 horizontal     = new Vector3(4, 0, 0);
        Vector3 vertical       = new Vector3(0, 2, 0);
        Vector3 leftDownCorner = new Vector3(-2, -1, -1);

        HitableList hitableList = new HitableList();

        hitableList.AddHitable(new HitableSphere(new Vector3(0, 0, -1), 0.5f, null));
        hitableList.AddHitable(new HitableSphere(new Vector3(0, -100.5f, -1), 100f, null));
        for (int i = HEIGHT - 1; i >= 0; i--)
        {
            for (int j = 0; j < WIDTH; j++)
            {
                Ray ray = new Ray(origin,
                                  leftDownCorner + horizontal * ((j + Random.Range(0, 1)) / (float)WIDTH) +
                                  vertical * ((i + Random.Range(0, 1)) / (float)HEIGHT));
                Color newColor = Color.black;
                for (int k = 0; k < SAMPLETIMES; k++)
                {
                    newColor += GetColorForTestDiffusing(ray, hitableList);
                }
                colors[j + i * WIDTH]   = newColor / SAMPLETIMES;
                colors[j + i * WIDTH].a = 1;
                Color temp = colors[j + i * WIDTH];
                colors[j + i * WIDTH] = new Color(Mathf.Pow(temp.r, 1 / 2.2f), Mathf.Pow(temp.g, 1 / 2.2f), Mathf.Pow(temp.b, 1 / 2.2f));
            }
        }

        return(colors);
    }
Esempio n. 11
0
 public abstract bool Hit(Ray ray, float t_min, float t_max, ref HitRecord hit);
Esempio n. 12
0
 public static extern void Intersect(ref RayTrace.Ray ray);
Esempio n. 13
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);
        }
    }