Example #1
0
        public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord record)
        {
            //平面的隐式方程  p·n = d
            //射线方程 p = o + t·dir
            //代入有 t = (d - o·n)/(dir·n)
            //考虑到只有射向平面才叫相交(射出不算),所以必须满足 Vec.dot(dir, normal) < 0

            float dir_dot_normal = Vec3.dot(ray.Direction, normal);

            if (dir_dot_normal < 0)
            {
                float t = (d - Vec3.dot(ray.Origin, normal)) / dir_dot_normal;
                if (t > t_min && t < t_max)
                {
                    if (record == null)
                    {
                        record = new HitRecord();
                    }
                    record.t         = t;
                    record.hit_point = ray.GetPoint(t);
                    record.normal    = normal;
                    record.material  = material;
                    return(true);
                }
            }
            return(false);
        }
Example #2
0
        public override Ray GetScatteredRay(Ray ray_in, HitRecord record)
        {
            //镜面反射...
            Vec3 scattered_dir = ray_in.Direction - 2 * Vec3.dot(ray_in.Direction, record.normal) * record.normal;

            return(new Ray(record.hit_point, scattered_dir, ray_in.DeltaTime));
        }
Example #3
0
        public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth)
        {
            //Phong公式: L = Kd * I * max(0, n·l) + Ks * I * max(0, n·h)^p
            // Kd是散射系数, n是表面法向量,l是光源方向(从相交点指向光源), Ks是高光系数,h是v+l的单位向量,v是视线反方向(从相交点只想视点), I是光强(光在这一点的颜色)
            Vec3  l       = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize());
            float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l));

            Vec3  h       = (-view_ray.Direction + l).normalize();
            float n_dot_h = Math.Max(0, Vec3.dot(record.normal, h));

            Vec3 I = Vec3.one;

            Vec3 dif = diffuse * n_dot_l;

            Vec3 spe = specular * (float)Math.Pow(n_dot_h, phong_exp);

            spe *= _smoothstep(0, 0.12f, n_dot_l);//为了解决背光面高光的问题,如果n_dot_l<0直接spe=0会有颜色间断层,需要做插值处理

            Vec3 L = Vec3.product(I, dif + spe);

            //上面有两个bug/疑问
            //(1)背光面也能出现高光,因为公式里n·l<0并不影响 Ks * I * max(0, n·h)^p的值;
            //(2)求出来的L超过(1,1,1)范围了.---暂时强行映射到[0,1]
            //上面两个问题估计都是要改diffuse和specular来处理
            //目前先特殊处理下,以后看看大佬们怎么搞的
            return(L);
        }
Example #4
0
        public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth)
        {
            Vec3 l = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize());

            float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l));

            Vec3 I = Vec3.one;

            Vec3 dif = diffuse * n_dot_l;

            Vec3 L = Vec3.product(I, dif);

            return(L);
        }
Example #5
0
        public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord record)
        {
            //运动的球先求出time时刻球心位置
            Vec3 _center = GetCenter(ray.DeltaTime);

            //ray == o+t*d; o 是射线原点,t是参数,d是方向
            //(p - c)^2 = radius^2;p是球面上一点,c是球心,radius是球半径
            //交点就是把射线方程代入球面方程化为一元二次方程求参数t
            Vec3  p_sub_c = ray.Origin - _center;
            float A       = Vec3.dot(ray.Direction, ray.Direction);
            float B       = Vec3.dot(p_sub_c, ray.Direction);//(b^2)/4
            float C       = Vec3.dot(p_sub_c, p_sub_c) - radius * radius;

            float b_square_sub_four_a_c_div_four = B * B - A * C;//(b^2 - 4ac)/4

            //方程组有解
            if (b_square_sub_four_a_c_div_four > 0)
            {
                float temp = (-B - (float)Math.Sqrt(b_square_sub_four_a_c_div_four)) / A;// (-b-sqrt(4ac))/2a 分子分母同时除以2就可以得到这个式子,这里的 b=2B
                if (temp > t_min && temp < t_max)
                {
                    if (record == null)
                    {
                        record = new HitRecord();
                    }
                    record.t         = temp;
                    record.hit_point = ray.GetPoint(temp);
                    record.normal    = (record.hit_point - _center).normalize();//球心与球面上一点为法向量方向
                    record.material  = material;
                    return(true);
                }

                temp = (-B + (float)Math.Sqrt(b_square_sub_four_a_c_div_four)) / A;
                if (temp > t_min && temp < t_max)
                {
                    if (record == null)
                    {
                        record = new HitRecord();
                    }
                    record.t         = temp;
                    record.hit_point = ray.GetPoint(temp);
                    record.normal    = (record.hit_point - _center).normalize();//球心与球面上一点为法向量方向
                    record.material  = material;
                    return(true);
                }
            }
            return(false);
        }
Example #6
0
        public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth)
        {
            Vec3 l = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize());

            float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l));

            Vec3 I = Vec3.one;

            Vec3 color = texture == null ? diffuse : texture.GetColorValue(0, 0, record.hit_point);//这里还要改的,下面的material也是,感觉material用来定义反射之类的物理计算公式。颜色映射还是交给texture吧

            Vec3 dif = color * n_dot_l;

            Vec3 L = Vec3.product(I, dif);

            return(L);
        }
Example #7
0
        private float PerlinInterp(Vec3[][][] c, float u, float v, float w)
        {
            float uu    = u * u * (3 - 2 * u);
            float vv    = v * v * (3 - 2 * v);
            float ww    = w * w * (3 - 2 * w);
            float accum = 0;

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    for (int k = 0; k < 2; k++)
                    {
                        Vec3 weight_v = new Vec3(u - i, v - j, w - k);
                        accum +=
                            (i * uu + (1 - i) * (1 - uu)) *
                            (j * vv + (1 - j) * (1 - vv)) *
                            (k * ww + (1 - k) * (1 - ww)) *
                            Vec3.dot(c[i][j][k], weight_v);
                    }
                }
            }
            return(accum);
        }