<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>
3D数学基础与三维渲染
猜你喜欢
转载自blog.csdn.net/qq_33629773/article/details/80375655
今日推荐
周排行