ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

添加镜面反射

2022-06-28 18:03:19  阅读:181  来源: 互联网

标签:反射 color double 镜面反射 claset 添加 var sharp


在有了阴影之后,我们小球看起非常的不错了。

现在我们让球更加的真实吧。

我们的效果如下

 

 

镜面反射

实际上我们一直做的事情光线追踪,只不过是非常简单的。

我们定义的球体是一个可以拥有反射,闪亮程度的物体,所以做到这样子不成问题的。

那么如何去做呢。

实际上我们看图中的反射部分,相当于在球体的其他部分画出来他能看出的球体,反射和阴影而已。正如同我们在一些物体上可以到看到其他的物体,如果仔细看反射的物体又在反射其他,最后相互嵌套。

这个是叫做德罗斯特效应(Droste effect)效应

 

 

 

 

分析

实现这样的效果,实际上挺简单,就是对这个概念需要一定的理解,因为绘制这样效果的一切工具都已经满足了。

当我们的光线追踪函数发出一个射线并接触到一个点时,我们就会绘制出这个点的颜色,光的效果。

实际上这个我们这个点是有可能是反射之后存在的效果。

 

也即是说,我们看到的也许是这个反射后的效果,如果我们想要呈现真实的情况,我们应该继续追踪光线,并绘制出每次追踪点的颜色,光的效果。

 

 什么意思呢,就是此时我发出射线看到P,然后我们应该继续发射射线追踪光L,看看是否是其他点反射过来的。

也就是说我们计算完第一次画布视线的射线所接触到的点后, 应该从这个点发射出一个正好是画布射线镜像的射线,如果这个射线接触到点,那么就绘制这个点,然后嵌套继续运行...

很明显,这是一个递归过程。

为了保证不会卡死运行,我们设置一个递归层数。

 

反射

怎么求呢?实际上我们添加光的镜面反射时已经做好了,我们只需要把这个计算的内容提取出来单独做一个函数就行了啊。

我们第一次从画布的视线射线做镜像,值得注意的时我们对光的所有射线都是反着,这样是被方便计算,毕竟光实际上时存在,只是描述方向变化了,不影响实际效果.

那么我们就实际开始代码吧

 

代码:

 

镜像函数

      Vector3D reflectiveray(Vector3D R, Vector3D N)
        {
            return 2 * N * Vector3D.DotProduct(N, R) - R;
        }

 

改光线追踪的函数,可以运行递归,如果反射效果是0或者递归深度小于0就返回好了,对反射的颜色的,我们让他们除去原有反射之后,混合再一起就行了。

  Color tracrray(Vector3D origin, Vector3D dline, double min, double max, int deepth = 3)
        {
            double closet = double.PositiveInfinity;
            var clp = closestIntersection(origin, dline, min, max);

            if (clp == null)
            {
                return Colors.Black;
            }
            closet = clp.Closet;
            var claset_sharp = clp.Claset_sharp;
            var p = origin + (closet * dline);
            var n = p - claset_sharp.center;
            n = n / n.Length;
            var cl = ComputeLighting(p, n, -dline, claset_sharp.specular);
            //保证颜色上下限正确
            var M = Color.FromRgb((byte)(Math.Min(255, Math.Max(0, cl * claset_sharp.color.R))),
                (byte)(Math.Min(255, Math.Max(0, (cl * claset_sharp.color.G)))),
                (byte)(Math.Min(255, Math.Max(0, (cl * claset_sharp.color.B)))));
            if (claset_sharp.reflective <= 0 || deepth <= 0)
            {
                return M;
            }
            var r = reflectiveray(-dline, n);
            var color = tracrray(p, r, 0.001, double.PositiveInfinity, deepth - 1);
            var k = 1 - claset_sharp.reflective;
            var rgb1 = Math.Min(255, Math.Max(0, M.R * k));
            var rgb2 = Math.Min(255, Math.Max(0, M.G * k));
            var rgb3 = Math.Min(255, Math.Max(0, M.B * k));
            var m2 = Color.Multiply(M, (float)k);
            var m3 = Color.Multiply(color, (float)claset_sharp.reflective);
            var m4 = Color.Add(m2, m3);
            return m4;
        }

 

启动时 默认递归10 其实3次以上就看挺好的了

void Start()
        {
            WriteableBitmap.Lock();
            for (double x = 0 - cw / 2; x < cw / 2; x++)
            {
                for (double y = 0 - ch / 2; y < ch / 2; y++)
                {
                    var D = canvastoviewport(new Point(x, y));
                    var color = tracrray(new Vector3D(), D, 1, double.MaxValue, 10);
                    var p = MidPoint(new Point(x, y));

                    byte[] colorData = { color.B, color.G, color.R, color.A };

                    int stride = (WriteableBitmap.PixelWidth * WriteableBitmap.Format.BitsPerPixel) / 8;
                    WriteableBitmap.WritePixels(new Int32Rect((int)p.X, (int)p.Y, 1, 1), colorData, stride, 0);
                }
            }
            WriteableBitmap.Unlock();

        }

 

最终代码 计算机图形学入门_3D渲染指南: 由C#作为编程语言,WPF作为输出。 计算机图形学入门3D渲染指南 - Gitee.com

 

标签:反射,color,double,镜面反射,claset,添加,var,sharp
来源: https://www.cnblogs.com/T-ARF/p/16420487.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有