3D数学基础与三维渲染

31 篇文章 1 订阅
6 篇文章 2 订阅

博客地址:blog.liujunliang.com.cn

本文使用C# Winform开发工具运用3D数学基础实现三维渲染

主要有三个步骤:顶点的变换、矩阵的变换、模拟光照三维渲染

本文源码地址:下载链接

顶点的变换

首先实现在一个窗口绘制一个三角形,让其各个顶点自动旋转

让其自动旋转需要使用到旋转矩阵

矩阵公式:


矩阵与顶点的变换代码如下

// 单个顶点的矩阵转换
        public Vertex4 Mul(Vertex4 vertex)
        {
            Vertex4 vertex4 = new Vertex4();

            if (this.mColumn == vertex.Width())
            {
                vertex4.mVertexX = this[0, 0] * vertex.mVertexX + this[1, 0] * vertex.mVertexY + this[2, 0] * vertex.mVertexZ + this[3, 0] * vertex.mVertexW;
                vertex4.mVertexY = this[0, 1] * vertex.mVertexX + this[1, 1] * vertex.mVertexY + this[2, 1] * vertex.mVertexZ + this[3, 1] * vertex.mVertexW;
                vertex4.mVertexZ = this[0, 2] * vertex.mVertexX + this[1, 2] * vertex.mVertexY + this[2, 2] * vertex.mVertexZ + this[3, 2] * vertex.mVertexW;
                vertex4.mVertexW = this[0, 3] * vertex.mVertexX + this[1, 3] * vertex.mVertexY + this[2, 3] * vertex.mVertexZ + this[3, 3] * vertex.mVertexW;

                return vertex4;
            }
            else
            {
                Console.WriteLine("顶点转化失败!");
                return null;
            }           
        }

使用Winform工具绘制出来

//画出形状(根据点描出线条)
        public override void Draw(Graphics graphics)
        {
            graphics.DrawLines(new Pen(Color.Black, 2f), this.GetAllPointF().ToArray());
        }

其中GetAllPointF函数是获取顶点的X、Y坐标作为在屏幕的显示坐标

//获取各个点屏幕点
        public List<PointF> GetAllPointF()
        {
            List<PointF> pointFList = new List<PointF>();

            pointFList.Add(GetPointF(this.mCurrentVertexA));
            pointFList.Add(GetPointF(this.mCurrentVertexB));
            pointFList.Add(GetPointF(this.mCurrentVertexC));
            pointFList.Add(pointFList[0]);            

            return pointFList;
        }

最终的效果图如下所示


矩阵的变换

以上效果图显示发现,三角形的显示只是在平面上效果,并没有在3D图像上的透视效果

这时我们将三角形进行空间坐标系->世界坐标系->观察坐标系->投影坐标系中的转变

使用的矩阵是mvp矩阵,也就是说将矩阵转换下

 Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);
            Matrix4X4 mv = m.Mul(viewMatrix);
            Matrix4X4 mvp = mv.Mul(projectionMatrix);

            mShape.Transform(mvp);

两个矩阵的转换公式代码如下

// 矩阵的转换
        public Matrix4X4 Mul(Matrix4X4 matrix)
        {
            Matrix4X4 matrix4x4 = new Matrix4X4();

            if (this.mColumn == matrix.mRow)
            {
                for (int x = 0; x < this.mRow; x++)
                {
                    for (int y = 0; y < matrix.mColumn; y++)
                    {
                        for (int z = 0; z < this.mColumn; z++)
                        {
                            matrix4x4[x, y] += this[x,z] * matrix[z,y];
                        }
                    }
                }

                return matrix4x4;
            }
            else
            {
                Console.WriteLine("矩阵转化失败!");
                return null;
            }
        }

透视效果图如下



模拟光照三维渲染

在计算光照渲染需要知道3D数学知识

博主归纳了两个

向量:u=(u1,u2,u3) v=(v1,v2,v3) 
叉积公式:u x v = (u2v3-v2u3 ,u3v1-v3u1 ,u1v2-u2v1
点积公式:u · v = u1v1+u2v2+u3v33=lul*lvl*COS(U,V)
 
获取光照角度代码如下

//得到三角形的法线
        public override Vertex.Vertex4 GetNormal()
        {
            //左手法则
            Vertex.Vertex4 U = this.mCurrentVertexB - this.mCurrentVertexA;
            Vertex.Vertex4 V = this.mCurrentVertexC - this.mCurrentVertexA;
            this.mNormal = U.Cross(V);

            return this.mNormal;
        }

        //得到灯光角度
        public override float GetLightDot(Vertex.Vertex4 lightingDir)
        {
            float dot = GetNormal().Normalized.Dot(lightingDir.Normalized);
            return Math.Max(0,dot);
        }

将三角形填充并且计算光照后的颜色

//画出形状(根据点描出线条)
        public override void Draw(Graphics graphics)
        {
            graphics.DrawLines(new Pen(Color.Black, 2f), this.GetAllPointF().ToArray());
        
            System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
            path.AddLines(this.GetAllPointF().ToArray());

            int dot = (int)(255 * GetLightDot(new Vertex.Vertex4(0, 0, 250, 1)));
            Color color = Color.FromArgb(dot,dot,dot);
            Brush redBrush = new SolidBrush(color);
            
            graphics.FillPath(redBrush, path);
        }

效果显示如下图



博客地址:blog.liujunliang.com.cn



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值