3D数学基础与三维渲染

 
 
 
 
 
 
<div id="article_content" class="ar
ticle_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post"> <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/htmledit_views-0a60691e80.css"> <div class="htmledit_views"> <p></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p>本文使用C# Winform开发工具运用3D数学基础实现三维渲染</p><p>主要有三个步骤:顶点的变换、矩阵的变换、模拟光照三维渲染</p><p>本文源码地址:<a href="https://gitee.com/JiBu/YouXiYinQing" target="_blank">下载链接</a></p><h5><span style="background-color:rgb(153,255,153);">顶点的变换</span></h5><p></p><p>首先实现在一个窗口绘制一个三角形,让其各个顶点自动旋转</p><p>让其自动旋转需要使用到旋转矩阵</p><p>矩阵公式:</p><p><img src="https://img-blog.csdn.net/20180103232100638" alt=""><br></p><h5><span style="font-weight:normal;background-color:rgb(255,255,255);">矩阵与顶点的变换代码如下</span></h5><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_1" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_8" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 单个顶点的矩阵转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Vertex4 Mul(Vertex4 vertex)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Vertex4 vertex4 = <span class="keyword">new</span><span> Vertex4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == vertex.Width())  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                vertex4.mVertexX = <span class="keyword">this</span><span>[0, 0] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 0] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 0] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 0] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexY = <span class="keyword">this</span><span>[0, 1] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 1] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 1] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 1] * vertex.mVertexW;  </span></span></li><li class=""><span>                vertex4.mVertexZ = <span class="keyword">this</span><span>[0, 2] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 2] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 2] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 2] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexW = <span class="keyword">this</span><span>[0, 3] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 3] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 3] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 3] * vertex.mVertexW;  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> vertex4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"顶点转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }             </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 单个顶点的矩阵转换 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; } }</pre><br>使用Winform工具绘制出来<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_2" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_9" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_9" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条) public override void Draw(Graphics graphics) { graphics.DrawLines(new Pen(Color.Black, 2f), this.GetAllPointF().ToArray()); }</pre><br>其中GetAllPointF函数是获取顶点的X、Y坐标作为在屏幕的显示坐标<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_3" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_10" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_10" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=10&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//获取各个点屏幕点</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> List<PointF> GetAllPointF()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            List<PointF> pointFList = <span class="keyword">new</span><span> List<PointF>();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexA));  </span></span></li><li class="alt"><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexB));  </span></span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexC));  </span></span></li><li class="alt"><span>            pointFList.Add(pointFList[0]);              </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> pointFList;  </span></span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//获取各个点屏幕点 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; }</pre><br>最终的效果图如下所示<p><img src="https://img-blog.csdn.net/20180103232903703" alt=""><br></p><h5><span style="background-color:rgb(153,255,153);">矩阵的变换</span></h5><p>以上效果图显示发现,三角形的显示只是在平面上效果,并没有在3D图像上的透视效果</p><p>这时我们将三角形进行<span style="color:#cc0000;">空间坐标系->世界坐标系->观察坐标系->投影坐标系</span>中的转变</p><p>使用的矩阵是mvp矩阵,也就是说将矩阵转换下</p><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_4" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_4" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_11" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_11" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=11&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span>Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);  </span></span></li><li class=""><span>           Matrix4X4 mv = m.Mul(viewMatrix);  </span></li><li class="alt"><span>           Matrix4X4 mvp = mv.Mul(projectionMatrix);  </span></li><li class=""><span>  </span></li><li class="alt"><span>           mShape.Transform(mvp);  </span></li></ol></div><pre class="csharp" name="code" style="display: none;"> Matrix4X4 m = rotateMatrix.Mul(scaleMatrix); Matrix4X4 mv = m.Mul(viewMatrix); Matrix4X4 mvp = mv.Mul(projectionMatrix); mShape.Transform(mvp);</pre><br>两个矩阵的转换公式代码如下<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_5" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_5" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_12" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_12" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=12&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 矩阵的转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Matrix4X4 Mul(Matrix4X4 matrix)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Matrix4X4 matrix4x4 = <span class="keyword">new</span><span> Matrix4X4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == matrix.mRow)  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> x = 0; x < </span><span class="keyword">this</span><span>.mRow; x++)  </span></span></li><li class="alt"><span>                {  </span></li><li class=""><span>                    <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> y = 0; y < matrix.mColumn; y++)  </span></span></li><li class="alt"><span>                    {  </span></li><li class=""><span>                        <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> z = 0; z < </span><span class="keyword">this</span><span>.mColumn; z++)  </span></span></li><li class="alt"><span>                        {  </span></li><li class=""><span>                            matrix4x4[x, y] += <span class="keyword">this</span><span>[x,z] * matrix[z,y];  </span></span></li><li class="alt"><span>                        }  </span></li><li class=""><span>                    }  </span></li><li class="alt"><span>                }  </span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> matrix4x4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"矩阵转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 矩阵的转换 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; } }</pre><br><p>透视效果图如下</p><p><img src="https://img-blog.csdn.net/20180103233818125" alt=""><br></p><p><br></p><p></p><h5><span style="background-color:rgb(153,255,153);">模拟光照三维渲染</span></h5><p>在计算光照渲染需要知道3D数学知识</p><p>博主归纳了两个</p><h5><span style="font-weight:normal;"><span style="font-size:10px;"><span style="background-color:rgb(255,204,204);"><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">向量:u=(u1,u2,u3) v=(v1,v2,v3)</span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"> <br></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">叉积公式:u x v = (u2v3-v2u3 ,u3v1-v3u1 ,u1v2-u2v1 </span><span style="line-height:27.2px;"><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;">)<br></span></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">点积公式:u · v = u1v1+u2v2+u3v33=lul*lvl*COS(U,V)</span></span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"><span style="background-color:rgb(255,204,204);"> </span></span></span></span></h5>获取光照角度代码如下<p></p><div class="dp-highlighter bg_php"><div class="bar"><div class="tools"><b>[php]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_6" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_6" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_13" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_13" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=13&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//得到三角形的法线</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> override Vertex.Vertex4 GetNormal()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            <span class="comment">//左手法则</span><span>  </span></span></li><li class="alt"><span>            Vertex.Vertex4 U = this.mCurrentVertexB - this.mCurrentVertexA;  </span></li><li class=""><span>            Vertex.Vertex4 V = this.mCurrentVertexC - this.mCurrentVertexA;  </span></li><li class="alt"><span>            this.mNormal = U.Cross(V);  </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> this.mNormal;  </span></span></li><li class=""><span>        }  </span></li><li class="alt"><span>  </span></li><li class=""><span>        <span class="comment">//得到灯光角度</span><span>  </span></span></li><li class="alt"><span>        <span class="keyword">public</span><span> override float GetLightDot(Vertex.Vertex4 lightingDir)  </span></span></li><li class=""><span>        {  </span></li><li class="alt"><span>            float dot = GetNormal().Normalized.Dot(lightingDir.Normalized);  </span></li><li class=""><span>            <span class="keyword">return</span><span> Math.Max(0,dot);  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="php" name="code" style="display: none;">//得到三角形的法线 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); }</pre><br>将三角形填充并且计算光照后的颜色<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_7" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_7" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_14" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_14" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=14&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>          </span></li><li class=""><span>            System.Drawing.Drawing2D.GraphicsPath path = <span class="keyword">new</span><span> System.Drawing.Drawing2D.GraphicsPath();  </span></span></li><li class="alt"><span>            path.AddLines(<span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">int</span><span> dot = (</span><span class="keyword">int</span><span>)(255 * GetLightDot(</span><span class="keyword">new</span><span> Vertex.Vertex4(0, 0, 250, 1)));  </span></span></li><li class=""><span>            Color color = Color.FromArgb(dot,dot,dot);  </span></li><li class="alt"><span>            Brush redBrush = <span class="keyword">new</span><span> SolidBrush(color);  </span></span></li><li class=""><span>              </span></li><li class="alt"><span>            graphics.FillPath(redBrush, path);  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条) 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); }</pre><br>效果显示如下图<p><img src="https://img-blog.csdn.net/20180103234839357" alt=""><br></p><p><br></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p></p><p><span style="background-color:rgb(153,255,255);">本人也在寻找一份游戏开发实习工作,如果大佬们需要开发人员,请把我带走<img alt="奋斗" src="https://static-blog.csdn.net/xheditor/xheditor_emot/default/struggle.gif"></span></p><p><span style="background-color:rgb(153,255,255);">这是我的简历:<a href="http://resume.liujunliang.com.cn/resume.pdf" target="_blank">resume.liujunliang.com.cn/resume.pdf</a></span></p><p><span style="background-color:rgb(153,255,255);">作品的话可以私聊我哦!</span></p><br> </div> </div> <div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">                     <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/htmledit_views-0a60691e80.css">             <div class="htmledit_views">                 <p></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p>本文使用C# Winform开发工具运用3D数学基础实现三维渲染</p><p>主要有三个步骤:顶点的变换、矩阵的变换、模拟光照三维渲染</p><p>本文源码地址:<a href="https://gitee.com/JiBu/YouXiYinQing" target="_blank">下载链接</a></p><h5><span style="background-color:rgb(153,255,153);">顶点的变换</span></h5><p></p><p>首先实现在一个窗口绘制一个三角形,让其各个顶点自动旋转</p><p>让其自动旋转需要使用到旋转矩阵</p><p>矩阵公式:</p><p><img src="https://img-blog.csdn.net/20180103232100638" alt=""><br></p><h5><span style="font-weight:normal;background-color:rgb(255,255,255);">矩阵与顶点的变换代码如下</span></h5><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_1" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_8" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 单个顶点的矩阵转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Vertex4 Mul(Vertex4 vertex)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Vertex4 vertex4 = <span class="keyword">new</span><span> Vertex4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == vertex.Width())  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                vertex4.mVertexX = <span class="keyword">this</span><span>[0, 0] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 0] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 0] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 0] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexY = <span class="keyword">this</span><span>[0, 1] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 1] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 1] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 1] * vertex.mVertexW;  </span></span></li><li class=""><span>                vertex4.mVertexZ = <span class="keyword">this</span><span>[0, 2] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 2] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 2] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 2] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexW = <span class="keyword">this</span><span>[0, 3] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 3] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 3] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 3] * vertex.mVertexW;  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> vertex4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"顶点转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }             </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 单个顶点的矩阵转换         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;             }                    }</pre><br>使用Winform工具绘制出来<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_2" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_9" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_9" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条)         public override void Draw(Graphics graphics)         {             graphics.DrawLines(new Pen(Color.Black, 2f), this.GetAllPointF().ToArray());         }</pre><br>其中GetAllPointF函数是获取顶点的X、Y坐标作为在屏幕的显示坐标<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_3" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_10" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_10" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=10&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//获取各个点屏幕点</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> List<PointF> GetAllPointF()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            List<PointF> pointFList = <span class="keyword">new</span><span> List<PointF>();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexA));  </span></span></li><li class="alt"><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexB));  </span></span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexC));  </span></span></li><li class="alt"><span>            pointFList.Add(pointFList[0]);              </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> pointFList;  </span></span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//获取各个点屏幕点         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;         }</pre><br>最终的效果图如下所示<p><img src="https://img-blog.csdn.net/20180103232903703" alt=""><br></p><h5><span style="background-color:rgb(153,255,153);">矩阵的变换</span></h5><p>以上效果图显示发现,三角形的显示只是在平面上效果,并没有在3D图像上的透视效果</p><p>这时我们将三角形进行<span style="color:#cc0000;">空间坐标系->世界坐标系->观察坐标系->投影坐标系</span>中的转变</p><p>使用的矩阵是mvp矩阵,也就是说将矩阵转换下</p><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_4" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_4" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_11" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_11" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=11&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span>Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);  </span></span></li><li class=""><span>           Matrix4X4 mv = m.Mul(viewMatrix);  </span></li><li class="alt"><span>           Matrix4X4 mvp = mv.Mul(projectionMatrix);  </span></li><li class=""><span>  </span></li><li class="alt"><span>           mShape.Transform(mvp);  </span></li></ol></div><pre class="csharp" name="code" style="display: none;"> Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);             Matrix4X4 mv = m.Mul(viewMatrix);             Matrix4X4 mvp = mv.Mul(projectionMatrix);             mShape.Transform(mvp);</pre><br>两个矩阵的转换公式代码如下<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_5" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_5" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_12" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_12" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=12&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 矩阵的转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Matrix4X4 Mul(Matrix4X4 matrix)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Matrix4X4 matrix4x4 = <span class="keyword">new</span><span> Matrix4X4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == matrix.mRow)  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> x = 0; x < </span><span class="keyword">this</span><span>.mRow; x++)  </span></span></li><li class="alt"><span>                {  </span></li><li class=""><span>                    <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> y = 0; y < matrix.mColumn; y++)  </span></span></li><li class="alt"><span>                    {  </span></li><li class=""><span>                        <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> z = 0; z < </span><span class="keyword">this</span><span>.mColumn; z++)  </span></span></li><li class="alt"><span>                        {  </span></li><li class=""><span>                            matrix4x4[x, y] += <span class="keyword">this</span><span>[x,z] * matrix[z,y];  </span></span></li><li class="alt"><span>                        }  </span></li><li class=""><span>                    }  </span></li><li class="alt"><span>                }  </span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> matrix4x4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"矩阵转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 矩阵的转换         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;             }         }</pre><br><p>透视效果图如下</p><p><img src="https://img-blog.csdn.net/20180103233818125" alt=""><br></p><p><br></p><p></p><h5><span style="background-color:rgb(153,255,153);">模拟光照三维渲染</span></h5><p>在计算光照渲染需要知道3D数学知识</p><p>博主归纳了两个</p><h5><span style="font-weight:normal;"><span style="font-size:10px;"><span style="background-color:rgb(255,204,204);"><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">向量:u=(u1,u2,u3) v=(v1,v2,v3)</span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"> <br></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">叉积公式:u x v = (u2v3-v2u3 ,u3v1-v3u1 ,u1v2-u2v1 </span><span style="line-height:27.2px;"><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;">)<br></span></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">点积公式:u · v = u1v1+u2v2+u3v33=lul*lvl*COS(U,V)</span></span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"><span style="background-color:rgb(255,204,204);"> </span></span></span></span></h5>获取光照角度代码如下<p></p><div class="dp-highlighter bg_php"><div class="bar"><div class="tools"><b>[php]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_6" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_6" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_13" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_13" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=13&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//得到三角形的法线</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> override Vertex.Vertex4 GetNormal()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            <span class="comment">//左手法则</span><span>  </span></span></li><li class="alt"><span>            Vertex.Vertex4 U = this.mCurrentVertexB - this.mCurrentVertexA;  </span></li><li class=""><span>            Vertex.Vertex4 V = this.mCurrentVertexC - this.mCurrentVertexA;  </span></li><li class="alt"><span>            this.mNormal = U.Cross(V);  </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> this.mNormal;  </span></span></li><li class=""><span>        }  </span></li><li class="alt"><span>  </span></li><li class=""><span>        <span class="comment">//得到灯光角度</span><span>  </span></span></li><li class="alt"><span>        <span class="keyword">public</span><span> override float GetLightDot(Vertex.Vertex4 lightingDir)  </span></span></li><li class=""><span>        {  </span></li><li class="alt"><span>            float dot = GetNormal().Normalized.Dot(lightingDir.Normalized);  </span></li><li class=""><span>            <span class="keyword">return</span><span> Math.Max(0,dot);  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="php" name="code" style="display: none;">//得到三角形的法线         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);         }</pre><br>将三角形填充并且计算光照后的颜色<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_7" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_7" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_14" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_14" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=14&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>          </span></li><li class=""><span>            System.Drawing.Drawing2D.GraphicsPath path = <span class="keyword">new</span><span> System.Drawing.Drawing2D.GraphicsPath();  </span></span></li><li class="alt"><span>            path.AddLines(<span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">int</span><span> dot = (</span><span class="keyword">int</span><span>)(255 * GetLightDot(</span><span class="keyword">new</span><span> Vertex.Vertex4(0, 0, 250, 1)));  </span></span></li><li class=""><span>            Color color = Color.FromArgb(dot,dot,dot);  </span></li><li class="alt"><span>            Brush redBrush = <span class="keyword">new</span><span> SolidBrush(color);  </span></span></li><li class=""><span>              </span></li><li class="alt"><span>            graphics.FillPath(redBrush, path);  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条)         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);         }</pre><br>效果显示如下图<p><img src="https://img-blog.csdn.net/20180103234839357" alt=""><br></p><p><br></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p></p><p><span style="background-color:rgb(153,255,255);">本人也在寻找一份游戏开发实习工作,如果大佬们需要开发人员,请把我带走<img alt="奋斗" src="https://static-blog.csdn.net/xheditor/xheditor_emot/default/struggle.gif"></span></p><p><span style="background-color:rgb(153,255,255);">这是我的简历:<a href="http://resume.liujunliang.com.cn/resume.pdf" target="_blank">resume.liujunliang.com.cn/resume.pdf</a></span></p><p><span style="background-color:rgb(153,255,255);">作品的话可以私聊我哦!</span></p><br>            </div>                 </div>
<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/htmledit_views-0a60691e80.css">
            <div class="htmledit_views">
                <p></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p>本文使用C# Winform开发工具运用3D数学基础实现三维渲染</p><p>主要有三个步骤:顶点的变换、矩阵的变换、模拟光照三维渲染</p><p>本文源码地址:<a href="https://gitee.com/JiBu/YouXiYinQing" target="_blank">下载链接</a></p><h5><span style="background-color:rgb(153,255,153);">顶点的变换</span></h5><p></p><p>首先实现在一个窗口绘制一个三角形,让其各个顶点自动旋转</p><p>让其自动旋转需要使用到旋转矩阵</p><p>矩阵公式:</p><p><img src="https://img-blog.csdn.net/20180103232100638" alt=""><br></p><h5><span style="font-weight:normal;background-color:rgb(255,255,255);">矩阵与顶点的变换代码如下</span></h5><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_1" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_1" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 815px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_8" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 单个顶点的矩阵转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Vertex4 Mul(Vertex4 vertex)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Vertex4 vertex4 = <span class="keyword">new</span><span> Vertex4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == vertex.Width())  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                vertex4.mVertexX = <span class="keyword">this</span><span>[0, 0] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 0] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 0] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 0] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexY = <span class="keyword">this</span><span>[0, 1] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 1] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 1] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 1] * vertex.mVertexW;  </span></span></li><li class=""><span>                vertex4.mVertexZ = <span class="keyword">this</span><span>[0, 2] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 2] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 2] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 2] * vertex.mVertexW;  </span></span></li><li class="alt"><span>                vertex4.mVertexW = <span class="keyword">this</span><span>[0, 3] * vertex.mVertexX + </span><span class="keyword">this</span><span>[1, 3] * vertex.mVertexY + </span><span class="keyword">this</span><span>[2, 3] * vertex.mVertexZ + </span><span class="keyword">this</span><span>[3, 3] * vertex.mVertexW;  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> vertex4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"顶点转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }             </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 单个顶点的矩阵转换
        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;
            }           
        }</pre><br>使用Winform工具绘制出来<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_2" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_2" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1358px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_9" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_9" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条)
        public override void Draw(Graphics graphics)
        {
            graphics.DrawLines(new Pen(Color.Black, 2f), this.GetAllPointF().ToArray());
        }</pre><br>其中GetAllPointF函数是获取顶点的X、Y坐标作为在屏幕的显示坐标<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_3" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_3" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 1559px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_10" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_10" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=10&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//获取各个点屏幕点</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> List<PointF> GetAllPointF()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            List<PointF> pointFList = <span class="keyword">new</span><span> List<PointF>();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexA));  </span></span></li><li class="alt"><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexB));  </span></span></li><li class=""><span>            pointFList.Add(GetPointF(<span class="keyword">this</span><span>.mCurrentVertexC));  </span></span></li><li class="alt"><span>            pointFList.Add(pointFList[0]);              </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> pointFList;  </span></span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//获取各个点屏幕点
        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;
        }</pre><br>最终的效果图如下所示<p><img src="https://img-blog.csdn.net/20180103232903703" alt=""><br></p><h5><span style="background-color:rgb(153,255,153);">矩阵的变换</span></h5><p>以上效果图显示发现,三角形的显示只是在平面上效果,并没有在3D图像上的透视效果</p><p>这时我们将三角形进行<span style="color:#cc0000;">空间坐标系->世界坐标系->观察坐标系->投影坐标系</span>中的转变</p><p>使用的矩阵是mvp矩阵,也就是说将矩阵转换下</p><p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_4" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_4" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2419px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_11" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_11" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=11&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span>Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);  </span></span></li><li class=""><span>           Matrix4X4 mv = m.Mul(viewMatrix);  </span></li><li class="alt"><span>           Matrix4X4 mvp = mv.Mul(projectionMatrix);  </span></li><li class=""><span>  </span></li><li class="alt"><span>           mShape.Transform(mvp);  </span></li></ol></div><pre class="csharp" name="code" style="display: none;"> Matrix4X4 m = rotateMatrix.Mul(scaleMatrix);
            Matrix4X4 mv = m.Mul(viewMatrix);
            Matrix4X4 mvp = mv.Mul(projectionMatrix);

            mShape.Transform(mvp);</pre><br>两个矩阵的转换公式代码如下<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_5" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_5" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 2620px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_12" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_12" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=12&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">// 矩阵的转换</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> Matrix4X4 Mul(Matrix4X4 matrix)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            Matrix4X4 matrix4x4 = <span class="keyword">new</span><span> Matrix4X4();  </span></span></li><li class="alt"><span>  </span></li><li class=""><span>            <span class="keyword">if</span><span> (</span><span class="keyword">this</span><span>.mColumn == matrix.mRow)  </span></span></li><li class="alt"><span>            {  </span></li><li class=""><span>                <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> x = 0; x < </span><span class="keyword">this</span><span>.mRow; x++)  </span></span></li><li class="alt"><span>                {  </span></li><li class=""><span>                    <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> y = 0; y < matrix.mColumn; y++)  </span></span></li><li class="alt"><span>                    {  </span></li><li class=""><span>                        <span class="keyword">for</span><span> (</span><span class="keyword">int</span><span> z = 0; z < </span><span class="keyword">this</span><span>.mColumn; z++)  </span></span></li><li class="alt"><span>                        {  </span></li><li class=""><span>                            matrix4x4[x, y] += <span class="keyword">this</span><span>[x,z] * matrix[z,y];  </span></span></li><li class="alt"><span>                        }  </span></li><li class=""><span>                    }  </span></li><li class="alt"><span>                }  </span></li><li class=""><span>  </span></li><li class="alt"><span>                <span class="keyword">return</span><span> matrix4x4;  </span></span></li><li class=""><span>            }  </span></li><li class="alt"><span>            <span class="keyword">else</span><span>  </span></span></li><li class=""><span>            {  </span></li><li class="alt"><span>                Console.WriteLine(<span class="string">"矩阵转化失败!"</span><span>);  </span></span></li><li class=""><span>                <span class="keyword">return</span><span> </span><span class="keyword">null</span><span>;  </span></span></li><li class="alt"><span>            }  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">// 矩阵的转换
        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;
            }
        }</pre><br><p>透视效果图如下</p><p><img src="https://img-blog.csdn.net/20180103233818125" alt=""><br></p><p><br></p><p></p><h5><span style="background-color:rgb(153,255,153);">模拟光照三维渲染</span></h5><p>在计算光照渲染需要知道3D数学知识</p><p>博主归纳了两个</p><h5><span style="font-weight:normal;"><span style="font-size:10px;"><span style="background-color:rgb(255,204,204);"><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">向量:u=(u1,u2,u3) v=(v1,v2,v3)</span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"> <br></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">叉积公式:u x v = (u2v3-v2u3 ,u3v1-v3u1 ,u1v2-u2v1 </span><span style="line-height:27.2px;"><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;">)<br></span></span><span style="font-family:'zuoyeFont_mathFont', 'Microsoft Yahei', '宋体', sans-serif;line-height:18.6667px;">点积公式:u · v = u1v1+u2v2+u3v33=lul*lvl*COS(U,V)</span></span><span style="font-family:'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', '寰蒋闆呴粦', sans-serif;line-height:27.2px;"><span style="background-color:rgb(255,204,204);"> </span></span></span></span></h5>获取光照角度代码如下<p></p><div class="dp-highlighter bg_php"><div class="bar"><div class="tools"><b>[php]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_6" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_6" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 499px; top: 3896px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_13" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_13" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=13&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//得到三角形的法线</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> override Vertex.Vertex4 GetNormal()  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            <span class="comment">//左手法则</span><span>  </span></span></li><li class="alt"><span>            Vertex.Vertex4 U = this.mCurrentVertexB - this.mCurrentVertexA;  </span></li><li class=""><span>            Vertex.Vertex4 V = this.mCurrentVertexC - this.mCurrentVertexA;  </span></li><li class="alt"><span>            this.mNormal = U.Cross(V);  </span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">return</span><span> this.mNormal;  </span></span></li><li class=""><span>        }  </span></li><li class="alt"><span>  </span></li><li class=""><span>        <span class="comment">//得到灯光角度</span><span>  </span></span></li><li class="alt"><span>        <span class="keyword">public</span><span> override float GetLightDot(Vertex.Vertex4 lightingDir)  </span></span></li><li class=""><span>        {  </span></li><li class="alt"><span>            float dot = GetNormal().Normalized.Dot(lightingDir.Normalized);  </span></li><li class=""><span>            <span class="keyword">return</span><span> Math.Max(0,dot);  </span></span></li><li class="alt"><span>        }  </span></li></ol></div><pre class="php" name="code" style="display: none;">//得到三角形的法线
        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);
        }</pre><br>将三角形填充并且计算光照后的颜色<p></p><div class="dp-highlighter bg_csharp"><div class="bar"><div class="tools"><b>[csharp]</b> <a href="#" class="ViewSource" title="view plain" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><span data-mod="popu_168"> <a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_7" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_7" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&width=16&height=16" wmode="transparent"></div><div style="position: absolute; left: 519px; top: 4313px; width: 16px; height: 16px; z-index: 99;"><embed id="ZeroClipboardMovie_14" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_14" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=14&width=16&height=16" wmode="transparent"></div></span><span data-mod="popu_169"> <a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a></span><a href="#" class="About" title="?" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div></div><ol start="1" class="dp-c"><li class="alt"><span><span class="comment">//画出形状(根据点描出线条)</span><span>  </span></span></li><li class=""><span>        <span class="keyword">public</span><span> </span><span class="keyword">override</span><span> </span><span class="keyword">void</span><span> Draw(Graphics graphics)  </span></span></li><li class="alt"><span>        {  </span></li><li class=""><span>            graphics.DrawLines(<span class="keyword">new</span><span> Pen(Color.Black, 2f), </span><span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class="alt"><span>          </span></li><li class=""><span>            System.Drawing.Drawing2D.GraphicsPath path = <span class="keyword">new</span><span> System.Drawing.Drawing2D.GraphicsPath();  </span></span></li><li class="alt"><span>            path.AddLines(<span class="keyword">this</span><span>.GetAllPointF().ToArray());  </span></span></li><li class=""><span>  </span></li><li class="alt"><span>            <span class="keyword">int</span><span> dot = (</span><span class="keyword">int</span><span>)(255 * GetLightDot(</span><span class="keyword">new</span><span> Vertex.Vertex4(0, 0, 250, 1)));  </span></span></li><li class=""><span>            Color color = Color.FromArgb(dot,dot,dot);  </span></li><li class="alt"><span>            Brush redBrush = <span class="keyword">new</span><span> SolidBrush(color);  </span></span></li><li class=""><span>              </span></li><li class="alt"><span>            graphics.FillPath(redBrush, path);  </span></li><li class=""><span>        }  </span></li></ol></div><pre class="csharp" name="code" style="display: none;">//画出形状(根据点描出线条)
        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);
        }</pre><br>效果显示如下图<p><img src="https://img-blog.csdn.net/20180103234839357" alt=""><br></p><p><br></p><h5>博客地址:<a href="http://blog.csdn.net/qq_33747722" target="_blank">blog.liujunliang.com.cn</a></h5><p></p><p><span style="background-color:rgb(153,255,255);">本人也在寻找一份游戏开发实习工作,如果大佬们需要开发人员,请把我带走<img alt="奋斗" src="https://static-blog.csdn.net/xheditor/xheditor_emot/default/struggle.gif"></span></p><p><span style="background-color:rgb(153,255,255);">这是我的简历:<a href="http://resume.liujunliang.com.cn/resume.pdf" target="_blank">resume.liujunliang.com.cn/resume.pdf</a></span></p><p><span style="background-color:rgb(153,255,255);">作品的话可以私聊我哦!</span></p><br>            </div>
                </div>



猜你喜欢

转载自blog.csdn.net/qq_33629773/article/details/80375655