﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Gattaca-随笔分类-DirectX</title><link>http://www.cppblog.com/kava12/category/4297.html</link><description>标题是记忆非常深刻的一部电影，《太空梦》，很好的励志片。自己一个人在电视上看的，那种感觉现在还记得。</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 18:51:53 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 18:51:53 GMT</pubDate><ttl>60</ttl><item><title>第2章 - 调色板, 游戏概念, 双缓冲区等等（2）</title><link>http://www.cppblog.com/kava12/archive/2007/05/21/24523.html</link><dc:creator>Gattaca</dc:creator><author>Gattaca</author><pubDate>Mon, 21 May 2007 03:33:00 GMT</pubDate><guid>http://www.cppblog.com/kava12/archive/2007/05/21/24523.html</guid><wfw:comment>http://www.cppblog.com/kava12/comments/24523.html</wfw:comment><comments>http://www.cppblog.com/kava12/archive/2007/05/21/24523.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kava12/comments/commentRss/24523.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kava12/services/trackbacks/24523.html</trackback:ping><description><![CDATA[<p>注：原文地址：<a href="http://scorpioncity.com/dj2.html">http://scorpioncity.com/dj2.html<br></a><br></p>
<h1>3、一些你写程序时必须知道的概念</h1>
<p>&nbsp;</p>
<h2>3.1 位图和子图形&nbsp;</h2>
<p>位图是一副图片在计算机里被当作一个像素值的数组来存储。这是个相当蹩脚的解释。基本上可以是计算机上的任何图片，通常是一块由像素组成的矩形。子图形是个和位图一样的东西，但是通常这个子图形相关的位图有透明区域（对于子图形的精确定义在程序员之间也是相当不同的）。子图形是游戏里一个相当重要的组成，有着超过一百万次的使用。例如，你的鼠标光标就是一个合格的子图形，DOOM里的怪物也是子图形。面向你的那边被编程为有透明区域的平面图片（有点绕）。记住子图形总是面对你，但并不是说怪兽总是面对你。不管怎样，对位图和子图形的解释应该足够了，我想。</p>
<h2>3.2 双缓冲区和页翻转&nbsp;</h2>
<p>如果你的游戏直接绘图到当前显示器，当游戏直接绘图到屏幕时用户将注意到非常明显的闪烁。解决方案是准备两个图像缓冲区，一个&#8220;前缓冲区&#8221;，一个&#8220;后缓冲区&#8221;。前缓冲区是用户看到的那个，后缓冲区不是。你把所有的操作画到后缓冲区，当完成绘制完屏幕的所有部分后，你复制后缓冲区的所有内容到前缓冲区。这就是双缓冲区，事实上现在有好几种双缓冲区模式。<br>通常有两种方法来执行后缓冲区到前缓冲区的传输：复制或者页翻转。</p>
<p>复制：后缓冲区的内容简单的复制到前缓冲区。后缓冲区可以在系统内存或者其他显存表面（这个不会翻译了，应该是显卡内存吧）；<br>页翻转：使用这种技巧，就不需要实际的复制操作。两个缓冲区都必须在显存中。为你游戏的每个框架轮流使用这两个表面来绘图。你总是绘图到当前不可见的那个缓冲区，在框架绘制完成后，你指示硬件去把这个绘制好的缓冲区当成可见的，因此在每个框架中前缓冲区现在都是后缓冲区了。</p>
<p>这个技巧会带来一个问题&#8220;Tearing&#8221;。显示器按照刷新频率重画屏幕上的图片，通常大约每秒70次（70Hz）。一般的，按照从上到下的顺序。这时问题出现了，当你使用上面的任何一种技巧指示硬件开始画另一个东西时，显示器只画了一半的图像。当你这么做时，下半截的屏幕使用的是新图像，而上半截屏幕还是老图像。这个效果就叫做&#8220;Tearing&#8221;，或者&#8220;切断&#8221;。有个已有的解决方案，无论如何，你的页面翻转有可能与屏幕刷新的结束很好的配合起来。（fixme：我想DirectDraw以及替你处理这个了，检查一下）。</p>
<h1>4、 剪切和DirectDraw剪切器</h1>
<p>&nbsp;</p>
<p>剪切是一种技术，指预防绘图操作超出到屏幕外边或者超出一个矩形区域比如窗口。如果不执行这个，通常的结果用最好的词来描述就是一团糟（这句是瞎译的）。在DirectDraw里，例如，当使用窗口模式时，window会给DirectDraw一个它想要的正确的屏幕区域。无论如何，一个行为良好的DirectDraw程序应该只画属于自己的窗口。DriectX有一个对象叫做剪切器可以被加到DirectDraw表面来预防画到窗口外面。<br></p>
<h1>5、DirectDraw表面</h1>
<p>&nbsp;</p>
<p>DirectDraw使用&#8220;表面&#8221;去访问一段内存，无论是系统内存还是显存，内存段通常用来存储位图，纹理图，子图形，屏幕或窗口的当前内容。<br>DirectDraw也支持&#8220;覆盖&#8221;，一个特殊类型的子图形，一个&#8220;覆盖&#8221;通常是屏幕上将被覆盖的包含透明位图的内存段。例如，一个赛车游戏可能对驾驶区域和窗口边框使用覆盖。<br>在有些情况下DirectDraw表面使用的内存可能被丢弃，因为DirectDraw和GDI共享资源。你的程序需要规律的检查看这个是否发生，如果被丢弃那就要恢复表面。<br></p>
<h1>6、DirectX返回值和错误检查</h1>
<p>&nbsp;</p>
<p>所有的DirectX函数返回HRESULT作为错误码。自从DirectX对象基于COM体系后，正确的方法检查DirectX函数失败是使用宏 SUCCEEDED() 和 FAILED() ,用HRESULT做参数。并不是检查一个if就够了，例如，有的DirectDraw函数返回HRESULT等于DD_OK，但COM对象可能会有多种表示正确的返回值，你的代码有可能还会正确工作，但是这个是错误的方法。</p>
<p>有些事情需要引起注意，有写DirectX函数执行成功后会返回失败码。例如，当你仅询问数据大小的时候，IDirectPlay::GetPlayerData将返回DPERR_BUFFERTOOSMALL。This behaviour isn't documented either, which is incredibly frustrating. There aren't many of these, but be on the lookout.<br></p>
<h1>7、DirectX调试</h1>
<br>当你安装DirectX SDK是有个选择安装零售版库还是调试版的。调试版会诊断信息OutputDebugString到你的调试器，这个会很有用。无论如何，这个会降低很多速度。如果你只是想玩游戏，那就选择零售版的库，如果你主要做游戏开发，而且你有足够快的机器，安装调试版本。
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/kava12/aggbug/24523.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kava12/" target="_blank">Gattaca</a> 2007-05-21 11:33 <a href="http://www.cppblog.com/kava12/archive/2007/05/21/24523.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>第2章 - 调色板, 游戏概念, 双缓冲区等等</title><link>http://www.cppblog.com/kava12/archive/2007/05/18/24336.html</link><dc:creator>Gattaca</dc:creator><author>Gattaca</author><pubDate>Fri, 18 May 2007 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/kava12/archive/2007/05/18/24336.html</guid><wfw:comment>http://www.cppblog.com/kava12/comments/24336.html</wfw:comment><comments>http://www.cppblog.com/kava12/archive/2007/05/18/24336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kava12/comments/commentRss/24336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kava12/services/trackbacks/24336.html</trackback:ping><description><![CDATA[<p>注：原文地址：<a href="http://scorpioncity.com/dj2.html">http://scorpioncity.com/dj2.html<br></a></p>
<h1><br>1、图像模式</h1>
<p>&nbsp;</p>
按照用多少位来存储屏幕上的一个像素，有好多种屏幕模式。使用更多的位，就能显示更多的颜色，但会占用更多的显存。<br>
<ul>
    <li>1、2、4、8位 &#8220;indexed&#8221;模式（8位就是通常所说的"256色"）；
    <li>16位（64K色）&#8220;high-color&#8221; 模式；
    <li>24位（16.7M色）&#8220;真彩色&#8221;模式；
    <li>32位 RGBA 模式，前三个字节和24位真彩色模式一样，第4个字节用做&#8220;alpha-channel&#8221;，即透明度。 </li>
</ul>
这些模式都是可用的。下面说一下分辨率：<br>
<ul>
    <li>320x200
    <li>320x240
    <li>640x400
    <li>640x480
    <li>800x600
    <li>1024x768
    <li>1280x1024
    <li>1600x1200 </li>
</ul>
现在比较常用的是640x480<span style="FONT-SIZE: 10pt; COLOR: green">（好像年代比较久远了这篇文章，我觉得1024x768应该比较常用吧）</span>。<br>显示器通常是3/4的纵横比，所以沿着高的那个边拥有的像素点应该是宽的那个的3/4，这样像素点的长宽比就是1，所以像素点就是正方形，也就是说100个像素在一个方向上的物理长度和另一个方向上的相当。但是320x200不是这样子滴，实际上它的像素点是稍显瘦高一点的。<br><br>
<h1>2、颜色原理</h1>
<br>有好多种表示颜色的方法，即&#8220;颜色模型&#8221;，比较常见的一个是&#8220;RGB&#8221;，几乎所有可见的颜色都可以用红、绿、蓝三种颜色按照各种比例组合生成。通常会用三个字节来存储颜色，每位表示一个主色的强度，从0到255。比如纯的亮红色就是#ff0000,紫色是#ff00ff,灰色是#969696,等等。<br>下面是一些可以用来表示颜色的c代码：
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">struct&nbsp;SColor<br><img id=Codehighlighter1_14_49_Open_Image onclick="this.style.display='none'; Codehighlighter1_14_49_Open_Text.style.display='none'; Codehighlighter1_14_49_Closed_Image.style.display='inline'; Codehighlighter1_14_49_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_14_49_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_14_49_Closed_Text.style.display='none'; Codehighlighter1_14_49_Open_Image.style.display='inline'; Codehighlighter1_14_49_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_14_49_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_14_49_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;r;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;g;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>SColor&nbsp;make_rgb(&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;r,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;g,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b&nbsp;)<br><img id=Codehighlighter1_92_171_Open_Image onclick="this.style.display='none'; Codehighlighter1_92_171_Open_Text.style.display='none'; Codehighlighter1_92_171_Closed_Image.style.display='inline'; Codehighlighter1_92_171_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_92_171_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_92_171_Closed_Text.style.display='none'; Codehighlighter1_92_171_Open_Image.style.display='inline'; Codehighlighter1_92_171_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_92_171_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_92_171_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;SColor&nbsp;ret;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ret.r&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;r;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ret.g&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;g;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ret.b&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;b;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;ret;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>或者你可能用一个无符号32位整型来储存RGB颜色，0-7位存蓝色，8-15位绿色等等。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">typedef&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;rgb_color;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#define&nbsp;MAKE_RGB(r,g,b)&nbsp;(&nbsp;((r)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">16</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;((g)&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;(b)&nbsp;)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>当然还有其他的颜色模型，比如HSV（Hue 色调, Saturation 饱和度, Luminance 亮度），但我不打算涉及它。</p>
<p>
<h2>2.1 High-color和true-color模式</h2>
<br><br>在这两种模式下，屏幕像素按照他们相应的RGB值存储到显存里。比如，如果屏幕左上角的像素点是绿色，那么在true-color模式下，显存里前三个字节就是0,255,0。而在high-color模式下，对应的RGB值分别用5、6、5位来存储，即前5位红色，接下来6位绿色，然后5位蓝色，所以在这个模式下显存对应的就是两个字节，二进制表示就是 00000111 11100000。
<p>&nbsp;</p>
<h2>2.2 基于调色板或者indexed模式</h2>
<br>Indexed模式使用一个&#8220;look up table&#8221;（LUT)的原理，即颜色查看表，通常这种模式使用8位图像模式，即256色，屏幕上的每个像素都用一个字节来表示，所以每次只能显示256 种颜色，所以这256种颜色就按照每种3个字节存到LUT里，显卡每次就按照LUT里的值确定要显示的颜色。<br>用Indexed模式创建一个程序是非常痛苦的，尤其是搞图像艺术的，但使用Indexed模式还是有一些优势的:
<p>&nbsp;&nbsp;&nbsp; * 需要很少的内存<br>&nbsp;&nbsp;&nbsp; * 运行会更快，因为需要传输的字节变少了<br>&nbsp;&nbsp;&nbsp; * 一些有趣的&#8220;调色板动画&#8221;技巧，在其他模式下很难完成的在Indexed模式下简直太容易了。你可以只改变LUT里的值去改变屏幕颜色，而不需要改变内存里每个像素对应的值。例如，一个淡出效果可以改变LUT里的RGB值到0来实现。<br>&nbsp;&nbsp;&nbsp; * 当你有一个纹理需要很多内存的时候，有些3D加速器支持Indexed模式的纹理。</p>
<p>
<h2>2.3 ModeX</h2>
<br>ModeX是一个特殊的 VGA 256色模式，这种模式下显存的内容会按照一个稍微复杂点planar(二维)格式。这个模式下的分辨率可以非常高，DirectDraw知道如何写 ModeX表面，但是windows GDI并不会，所以当你混合这两种不同类型表面的时候要小心。当设置DirectDraw全屏模式时可以选择是否允许DirectDraw创建ModeX 表面。这些日子里你可能想避开ModeX。
<p>&nbsp;</p>
<p>
<h2>2.4 Pitch/Stride</h2>
<br>虽然屏幕分辨率可能是640x480x32,但这并不是说每行像素会占用640x4个字节的显存。因为速度上的原因，显卡存储的这些表面宽度经常比他们逻辑上要宽。例如，最大支持1024x768的显卡可能会把所有从320x200到1024x768的模式内部实现为1024x768模式，所以表面的右边会留下空白<span style="FONT-SIZE: 10pt; COLOR: green">（呵呵，默认左对齐）</span>，这个分配给表面实际的宽度就称为表面的Pitch（或者Stride），知道表面的Pitch是非常重要的，不管它是一个2D DirectDraw 表面还是纹理贴图，可以使用 DirectDraw 查询表面的Pitch。<br><br>
<h1>3、一些游戏概念你需要知道<br><br></h1>
<p>下班了，以后继续。。。</p>
<img src ="http://www.cppblog.com/kava12/aggbug/24336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kava12/" target="_blank">Gattaca</a> 2007-05-18 16:18 <a href="http://www.cppblog.com/kava12/archive/2007/05/18/24336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>