精华内容
下载资源
问答
  • 仅供参考,仅有部分页面: 免责声明:本站所有文章和图片均来自用户分享和网络收集,文章和图片版权归原作者及原出处所有,仅供学习与参考,请勿用于商业用途,如果损害了您的权利,请联系网站客服处理。
  • 转载于:https://www.cnblogs.com/miliam-12/p/11404586.html

     

    转载于:https://www.cnblogs.com/miliam-12/p/11404586.html

    展开全文
  • google chart 使用攻略demo

    千次阅读 2012-03-21 16:48:18
    http://psychopyko.com/tutorial/how-to-use-google-charts/ How to use Google Charts API with 6 examples ...Few months ago I had a good look into Google Charts API and it was great! If you are not

    http://psychopyko.com/tutorial/how-to-use-google-charts/


    How to use Google Charts API with 6 examples

    Few months ago I had a good look into Google Charts API and it was great! If you are not aware, Google Charts API basically allows you to create pretty graphs simply by using an URL with correct parameters specified. It is fairly flexible, with many things you can change and customise - which is where it becomes bit complicated. It is quite easy to generate a chart, but it wasn't as easy to generate the exact chart I needed. So below are 6 examples charts with explanations and tips that will hopefully help you understand Google Charts better.

    A few notes before I start

    1. The data/labels for all the graphs here have no meaning at all - just examples that I have come up with.
    2. I'll explain each parameter probably only once (since they are generally the same across all graphs). If something is different or special I'll explain it again.
    3. If you have any other tips/hints please share :)

    Tip 0 (yes a tip before examples!)
    Use this tutorial with Google's own Developer's Guide. Google's guide is quite good, but just confusing at times. I won't be going through every little bit since Google's guide outlines a fair bit, especially the technical syntax.

    Example 1: Pie Chart

    http://chart.apis.google.com/chart?
    cht=p3&chs=450x200&chd=t:73,13,10,3,1&
    chco=80C65A,224499,FF0000&
    chl=Chocolate|Puff+Pastry|Cookies|Muffins|Gelato

    There are 3 parameters that ALL charts MUST have, and they are cht, chs, chd.

    1. Chart Type (cht): Specifies the type of graph you have (pie, vertical bar etc)
    2. Chart Size (chs): Specifies the pixel dimensions of your graph (width*height)
    3. Chart Data (chd): The data that you want to display in your chart

    1. Chart Type (cht) is quite straight forward - select the chart type you want, and put in the corresponding code which can be found from Google'sDeveloper's Guide.

    2. Chart Size (chs) is a tad more complicated but not much more (just needs a bit of trial and error). You specify the size of your graph in pixels:chs=<width>x<height>. Other than the maximum limit, the hardest thing is how big to make your graph? My tips are:

    Tip 1: Give a rough estimate, generate the graph then press 'ctrl+a'. This will highlight the graph boundary so now you can adjust the size accordingly.
    Tip 2: For pie charts, a rule of thumb is: w=2.5h for 3D charts and w=2h for 2D charts.

    3. Chart Data (chd) is probably the most complicated as each chart has a slightly different syntax for data (see below examples and Google'sDeveloper's Guide). For pie charts you need to make sure that the sum of your data points is 100 - ie. calculate the percentages and use the percentages as your data points.

    Now onto the optional parameters - ones that allow you to customise the look of your chart and make the look pretty:)

    Chart Colour (chco) uses the Hex representation (RRGGBB) to specify the colour of your chart. What colour you pick is really up to you. For pie charts you can just put in one colour and all the segments will be shades of that colour. Or you can put in more and the segments will be a gradient from the first colour listed to the last colour listed.

    Tip 3: If you have a fair few segments in your pie chart, I find listing 3 colours works well. It creates a relatively nice gradient and makes it easier to distinguish between the segments.

    Chart Labels (chl) specifies the labels for your data. It is optional, but you probably want to include them, so your chart will makes sense! With pie chart, it makes sense that the number of segments you have is the number of labels. So if you had 6 bits of data, you'll have 6 labels. However, unlike chd where values are comma separated, pie chart labels are separated by a vertical bar '|'.

    Tip 4: If you want a space in your labels use '+' where you needed spaces. eg. Puff+Pastry

    Example 2: Horizontal Bar Chart

    http://chart.apis.google.com/chart?
    cht=bhg&chs=550x230&chd=t:100,50,115,80&
    chxt=x,y&chxl=1:|Python|Java|Ruby|.NET&
    chxr=0,0,120&chds=0,120&
    chco=4D89F9&
    chbh=35,0,15&
    chg=8.33,0,5,5

    Chart Axis Type (chxt) specifies the different axis that will be displayed on the chart. There are4 types (x,y,t,b) and can be repeated (eg. you can have 2 x-axes). These axes are referenced by their index numer (that is the order you have specified them in). Counting starts at 0. So in the example, x-axis is #0, and y-axis is #1.

    Chart Axis Label (chxl) specifies the label you want for the axis/axes. Thesyntax is generally quite straightforward with the axis number coming first followed by a colon':' and then the label names. There is just one small 'exception' (bug?) that I have discovered. For horizontal charts you need to "flip" the axis label and the data you provide. So if your data is chd=t:1,2,3,4 your axis label will have to bechxl=1:|Four|Three|Two|One. Again, this only happens for horizontal charts and I'm not quite sure why.

    Note (not quite a tip): Just to re-iterate, for horizontal charts you need to "flip" (or reverse) the axis labels and data you provide for them to match. So the first label will match the last data, second label match the second last data etc. Note in the example, Python is the first label, but it has value 80 - the last data point.(Strangely enough, this doesn't happen for vertical charts)

    Chart Axis Range (chxr) specifies the start/end range of the axis. The first number specifies the axis, second and third number specifies the start and end of the range respectively. In most cases, you will probably want your range to be slightly more than your maximum data value. (eg. in the above the maximum value is 115, so I have set the range to be between 0 and 120)

    Chart Data Scale (chds) specifies how your data will be scaled. My general rule of thumb is unless you want to do some special scaling (eg. compare percentages of the values instead of showing the actual value) you will scale according to your range. Whatever you have set the min/max of your range (chxr) will be the min/max of your scale (chds).

    In order to display your chart correctly, you will need to use both, Chart Axis Range (chxr)and Chart Data Scale (chds). By default the range and scale is 0,100 - but chances are you won't always want your axis to have a maximum of 100. Without correctly specifying these two parameters, your chart will still appear, but it will essentially be incorrect.

    Tip 5: chxr and chds will generally be a pair and have the same values. The min/max specified inchxr will also be the min/max for chds.
    Tip 6: If you want to display the data percentage-wise, the chxr and chds will differ. chxr will have range 0-100, andchds will be 0-max data point. For the example above, if the graph were to show the percentages of each bar the 4th line will be replaced with:chxr=0,0,100&chds=0,115&

    Chart Bar Size (chbh) specifies the width of the bar and also the spacing between bars (and groups of bars). The first number (mandatory) specifies the width of the bar. The second and third are optional and they specify the spacing between bars in a group and between groups. In this example, the bars have width of 35, and each group (separated by commas inchd) is separated by width 15. As each group only has one data point, changing the middle value will make no difference (to have more than one data point for each group, you need to use vertical bars '|' - see examples below).

    Chart Grid lines (chg) draws the lines behind the bars, making it easier to read the chart. Although optional, I think these really are the icing on the cake for the charts. Thesyntax chg=<verticalGridLines>,<horizontalGridLines>,<lineSize>,<gapSize> itself is easy, but getting the grid lines to draw correctly is harder. Of the four values, the last two are optional and determine what the line will look like when drawn. It really depends on personal preference and the type of chart drawn, but I find using 5 for each gives a nice dashed line. The first values is for vertical grid lines and the second is for horizontal grid lines.

    Getting the grid lines to draw at the intervals you want (eg. every 10 units) is the tricky bit. Google by default assumes your axis range is 0-100 which isn't always the case, so some basic maths is needed. IF your axis was 0-100, then to have vertical grid lines every 10 units is simple: chg=10,0,5,5. But in the example the range is 0-120 so the grid lines will display incorrectly if you simply put in chg=10,0,5,5. To get the lines to show correctly for range 0-120, you need to 'scale' the grid line value. Luckily it is quite simple: 100/120*10 which gives you 8.333..., thereforechg=8.33,0,5,5. The formula is basically 100/MaxRange*IntervalAmount. Also, if the result is not a whole number, give the value to two decimal places, otherwise the grid lines will be slightly off.

    Tip 7: To calculate the value to correctly draw your grid lines, use the formula:100/MaxRange*IntervalAmount. eg. Your graph has range 0-80, and you want an horizontal grid lines every 5 units: 100/80*5=6.25, therefore you will have: chg=0,6.25,5,5
    Tip 8: If the value calculated from the formula is not a whole number, go to two decimal places for more accurate grid lines. (You can go to three or more decimal places, but I find two is generally enough)

    Example 3: Vertical Bar Chart

    http://chart.apis.google.com/chart?
    cht=bvg&chs=350x300&chd=t:20,35,10&
    chxr=1,0,40&chds=0,40&
    chco=ff0000|ffa000|00ff00&
    chbh=65,0,35&
    chxt=x,y,x&chxl=0:|High|Medium|Low|2:||Task+Priority||&chxs=2,000000,12&
    chtt=Tasks+on+my+To+Do+list&chts=000000,20&
    chg=0,25,5,5

    Chart Colour (chco) is quite straight forward. Note that for this example, I have used the vertical bar '|' to separate the three hex colours in order to get different coloured bars. If I had used a comma ',' then all the bars will be red (the first colour).

    Chart Axis Style (chxs) allows you to apply a style to your axis.chxt and chxl (explained in Example 2) specify which axis you want, and their labels whilechxs lets you specify the font colour and size for a particular axis. In this examplechxs=2,000000,12 has set axis #2 to be black with font size of 12. Note: If you look carefully you'll see something "strange" in thechxl for axis #2 (Task Priority axis). The empty '||' on either side of the label is so the label will be centred.

    Tip 9: If you want a second x-axis for say an axis label you can centre the label by having empty labels '||' left and right of your actual label. The number of empty labels will depend on the number of categories in your main x-axis, and how long your axis label is. In this example, the axis label is quite short and there is a total of 3 categories (High, Medium, Low) so i have put one empty label on each side of 'Task Priority'

    Chart Title (chtt) specifies the title of the graph. Like other labels, if you want a space in your title use the '+' character wherever you need a space.

    Chart Title Style (chts) specifies the font colour and size of the title. It is quite similar tochxs.

    Example 4: Stacked Vertical Bar Chart

    http://chart.apis.google.com/chart?
    cht=bvs&chs=350x300&chd=t:20,35,10,5|30,55,25,0|5,25,5,5&
    chxr=1,0,120&chds=0,120&
    chco=0A8C8A,EBB671,DE091A&
    chbh=45,20,15&
    chxt=x,y&chxl=0:|Pizza|Pasta|Pide|Salad&
    chdl=Large|Medium|Small&
    chg=0,8.3,5,5

    Chart Data (chd) as explained in Example 1 specifies the data in your chart. However, note how the data for this slightly more complicated graph is written - it is separated using both commas and vertical bars. Each group separated by a vertical bar represents one series: the first group is Large, then Medium, then Small.

    Chart Legend (chdl) specifies the legend for the chart. It is separated by vertical bars and corresponds directly to the way the data is represented.

    Note that even though the largest individual data value is 55 (the 2nd value of group 2), the range/scale is put as 120 because the largest SUM of corresponding data values is 115 (sum of the 2nd values).

    Tip 10: If you have a stacked chart, the range/scale will be the maximum of the sum of the corresponding values of each group. That is, compare the sum of all the first values in each group with the sum of the second, third values etc.

    Example 5: Vertical Bar Chart

    http://chart.apis.google.com/chart?
    cht=bvg&chs=350x300&chd=t:20,35,10,10|30,55,25,5|5,25,5,5&
    chxr=1,0,60&chds=0,60&
    chco=0A8C8A,EBB671,DE091A&
    chbh=15,0,20&
    chxt=x,y&chxl=0:|Pizza|Pasta|Pide|Salad&
    chdl=Large|Medium|Small&
    chg=0,8.3,5,5

    Data-wise, this chart is identical to Example 4a - the only difference is it is not a stacked chart (bvs), but just a standard vertical chart (bvg). The only changes are in thechxr, chds and chbh parameters to make the chart display nicely. Note how the range/scale is now 0-60, since it is no longer a stacked chart so the maximum value is 55.

    Example 6: Line Chart

    http://chart.apis.google.com/chart?
    cht=lc&chs=450x330&chd=t:7,18,11,26,22,11,14&
    chxr=1,0,30&chds=0,30&
    chco=4d89f9&
    chxt=x,y&chxl=0:|Mon|Tue|Wed|Thu|Fri|Sat|Sun&
    chls=3,1,0&
    chm=d,4d89f9,0,0,12,0|d,4d89f9,0,1,12,0|d,4d89f9,0,2,12,0|d,4d89f9,0,3,12,0|d,4d89f9,0,4,12,0|d,4d89f9,0,5,12,0|d,4d89f9,0,6,12,0&
    chg=0,6.67,5,5

    Chart Line Style (chls) specifies what the line will look like. The numbers are (in order) how thick the line will be, size of line segment and size of blank segment. So if you want a solid line (as per example) you will want the last value to be 0. Note, the line style is just the line - it does not draw the markers, that is specified inchm (see below).

    Chart Markers (chm) specifies what the markers will be for each data point. Setting the markers is quite ugly - you need to specify the marker for each data point you have. Luckily, thesyntax is relatively easy - the shape/type of marker, colour, data group, data point, priority. In this example there is only one data group (so the 3rd value are all zeroes) and you can see that the 4th value of eachchm group goes up by 1 as it specifies the particular data point. The size is set to 12 to make the markers nice and big. Priority specifies how the markers are drawn - below or above the line and other markers.

    Wow, so that finally concludes this tutorial which turned out much longer than I had imagined! Hopefully I've made sense, explained things well and helped you get a better understanding of how to use Google Charts API to get the charts you want/need. If you have any questions please feel free to ask, or if you have some tips please share them:)



    展开全文
  • 【Visual C++】游戏开发笔记二十八 最精简的Direct3D11 Demo筋骨脉络全攻略

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   



    本系列文章由zhmxy555(毛星云)编写,转载请注明出处。

    http://blog.csdn.net/zhmxy555/article/details/7707628

    作者:毛星云    邮箱: happylifemxy@163.com  


     

     

    本篇文章将讲解如何通过我们在之前的文章里面已掌握的DirectX 11的知识,来一步一步创建一个基于Direct3D11的Blank Windows Demo,而我们在这节里面完成的这个demo,将在后面的文章里面作为一个模板,用于演示之后的各种新奇DirectX11的功能。


     

    首先呢,为了代码的重用性着想,我们会写一个 DirectX11DemoBase,并借鉴在笔记二十六中的Win32风格的Blank Win32 Window Demo中的代码,然后通过派生的方式,以及重载一些必要的虚函数,进行整合,来创建我们的demo。


          



    一、  关于代码书写风格的讨论


     

    首先,我们提出一个问题,采用自问自答的形式来讨论:


    在这个demo的设计过程中,我们是采用C语言式的全局变量与全局函数的搭档模式来完成,还是采用C++式的面向对象风格的类Class来编写呢?

     

    答案是后者,采用面向对象的思想来完成至于这个问题的解释,答案就仁者见仁智者见智了。

    浅墨之前看过一本C++界的名著《C++沉思录》,作者在文章的开篇举了一个例子,然后通过例子对比出来的效果,折射出了对C与C++的一个中肯的评价,是这样的一段话:


    “C++鼓励采用类来表示类似于输出流的事物,而类就提供了一个理想的位置来存放状态信息。而C语言倾向于不存储状态信息,除非事先已经规划妥当。因此C程序员趋向于假设有这样一个“环境”:存在一个位置集合,他们可以在其中找到系统的当前状态。如果只有一个环境和一个系统,这样考虑毫无问题,但是,系统在不断增长的过程中往往需要引入某些独一无二的东西,并且创建更多这类东西。”


    对这段话的解释,浅墨还是用自己的话来叙述吧:

    通常我们采用一般的变量作为传递数据的容器,但是随着程序的复杂会导致数据量的加大,有太多的数据需要被传递,而且这些数据基本上都是需要传递到近乎是每一个函数当中的,这样我们就要创建很多的全局变量作为“容器”,如此下去我们的设计的程序只会越来越臃肿,越来越乱。别怕别怕,有绝招呢——我们可以创建一个类或者结构体来收容这些对象,使之显得不是那么乱,取而代之的是井井有条。


    绕了这么大一圈子,一言以蔽之,就是运用全局变量是不太好的编程习惯,我们应当少用甚至不用,转而使用“类”来完成这些任务。

     

     



     

    二、    Dx11DemoBase类的设计


     

    作为目前来说,我们要求本节的demo做到以下几点功能:

     

    ▲初始化D3D

    ▲释放在启动过程中创建的Direct3D对象

    ▲为我们的D3D对象存储成员变量

    ▲提供一个装载demo的具体内容的方式

    ▲提供一个卸载demo的具体内容的方式

    ▲能够显示demo每帧的更新的具体内容

    ▲demo渲染内容的具体代码

     

    由我们上面的清单来看,创建一个公共的初始化和卸载函数,用于装载和卸载内容功能的虚函数,以及渲染和更新游戏循环步骤的虚函数的基类是很有必要的。通过将这些函数设为虚函数,由基类派生出来的demo类能够实现他们自定义的逻辑和行为。

    根据上面的这些叙述,我们可以写出下面的这段为Dx11DemoBase量身打造的代码:

     

     

    代码段一  Dx11DemoBases类的头文件

     

    #ifndef _DEMO_BASE_H_#define _DEMO_BASE_H_#include<d3d11.h>#include<d3dx11.h>#include<DxErr.h>class Dx11DemoBase{public:   Dx11DemoBase();   virtual ~Dx11DemoBase();   bool Initialize( HINSTANCE hInstance, HWND hwnd );   void Shutdown( );   virtual bool LoadContent( );   virtual void UnloadContent( );   virtual void Update( float dt ) = 0;   virtual void Render( ) = 0;   protected:   HINSTANCE hInstance_;   HWND hwnd_;   D3D_DRIVER_TYPE driverType_;   D3D_FEATURE_LEVEL featureLevel_;   ID3D11Device* d3dDevice_;   ID3D11DeviceContext* d3dContext_;   IDXGISwapChain* swapChain_;   ID3D11RenderTargetView* backBufferTarget_;};#endif




     

    上面这段代码中我们可以看到最精简的D3D对象,以protected类成员的形式存在于类之中。在类体外初始化变量是比较好的编程习惯,而且效率比让先调用拷贝构造函数,再调用默认构造函数要高得多。

    Dx11DemoBase类构造函数,析构函数,装载内容,卸载内容,shutdown函数定义如下:

     



    代码段二 一些Dx11DemoBase 组成代码


    #include"Dx11DemoBase.h"Dx11DemoBase::Dx11DemoBase( ) : driverType_( D3D_DRIVER_TYPE_NULL),featureLevel_( D3D_FEATURE_LEVEL_11_0 ), d3dDevice_( 0 ),d3dContext_( 0 ),swapChain_( 0 ), backBufferTarget_( 0 ){}void Dx11DemoBase::UnloadContent( ){//可以在此处进行重载,加入代码实现相关功能void Dx11DemoBase::Shutdown( ){   UnloadContent( );   if( backBufferTarget_ ) backBufferTarget_->Release( );   if( swapChain_ ) swapChain_->Release( );   if( d3dContext_ ) d3dContext_->Release( );   if( d3dDevice_ ) d3dDevice_->Release( );   d3dDevice_ = 0;   d3dContext_ = 0;   swapChain_ = 0;   backBufferTarget_ = 0;}



          

    Dx11DemoBase类中的最后一个函数是Initialize函数。Initialize函数执行我们在这章中讲到的D3D初始化工作。这个函数开始声明我们的硬件,WARP或者软件的驱动类型,和我们的D3D11.0,10.1或者10.0的特征等级。代码的设定即尝试在D3D 11中创建一个硬件设备。如果创建失败,我们会尝试其他的驱动类型和特征等级直到我们找到一个合适的类型。这也意味着如果我们采用D3D10硬件我们可以也可以在硬件中运行这个demo,因为我们可以选择10.1或者10.0的特征等级。

    下一步便是创建交换链的描述,以及使用这些信息来试着找到支持的设备类型和特征等级。如果成功的搜索到了我们需要的这些信息。接下来就是行云流水地创建渲染目标,创建视口,以及调用LoadContent方法加载特定的内容了。需要指出的是,LoadContent方法最好留着最后进行调用,以免出现不必要的错误。

    下面便是DirectX11初始化的全过程:

     



    代码段三 Dx11DemoBase类的初始化函数

     

    bool Dx11DemoBase::Initialize( HINSTANCE hInstance, HWND hwnd ){    hInstance_ =hInstance;    hwnd_ = hwnd;     RECT dimensions;    GetClientRect( hwnd,&dimensions );     unsigned int width =dimensions.right - dimensions.left;    unsigned int height =dimensions.bottom - dimensions.top;     D3D_DRIVER_TYPEdriverTypes[] =    {       D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,       D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE    };     unsigned inttotalDriverTypes = ARRAYSIZE( driverTypes );     D3D_FEATURE_LEVELfeatureLevels[] =    {       D3D_FEATURE_LEVEL_11_0,       D3D_FEATURE_LEVEL_10_1,       D3D_FEATURE_LEVEL_10_0    };     unsigned inttotalFeatureLevels = ARRAYSIZE( featureLevels );     DXGI_SWAP_CHAIN_DESCswapChainDesc;    ZeroMemory(&swapChainDesc, sizeof( swapChainDesc ) );   swapChainDesc.BufferCount = 1;   swapChainDesc.BufferDesc.Width = width;   swapChainDesc.BufferDesc.Height = height;   swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;   swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;   swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;   swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;   swapChainDesc.OutputWindow = hwnd;    swapChainDesc.Windowed= true;   swapChainDesc.SampleDesc.Count = 1;    swapChainDesc.SampleDesc.Quality= 0;     unsigned intcreationFlags = 0#ifdef _DEBUG    creationFlags |=D3D11_CREATE_DEVICE_DEBUG;#endif     HRESULT result;    unsigned int driver =0;     for( driver = 0;driver < totalDriverTypes; ++driver )    {        result =D3D11CreateDeviceAndSwapChain( 0, driverTypes[driver], 0, creationFlags,                                               featureLevels, totalFeatureLevels,                                               D3D11_SDK_VERSION, &swapChainDesc, &swapChain_,                                               &d3dDevice_, &featureLevel_, &d3dContext_ );         if( SUCCEEDED(result ) )        {            driverType_ =driverTypes[driver];            break;        }    }     if( FAILED( result ) )    {        DXTRACE_MSG("创建 Direct3D 设备失败!" );        return false;    }     ID3D11Texture2D*backBufferTexture;     result =swapChain_->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID*)&backBufferTexture );     if( FAILED( result ) )    {        DXTRACE_MSG("获取交换链后台缓存失败!" );        return false;    }     result =d3dDevice_->CreateRenderTargetView( backBufferTexture, 0,&backBufferTarget_ );     if( backBufferTexture)       backBufferTexture->Release( );     if( FAILED( result ) )    {        DXTRACE_MSG("创建渲染目标视图失败!" );        return false;    }    d3dContext_->OMSetRenderTargets( 1, &backBufferTarget_, 0 );     D3D11_VIEWPORTviewport;    viewport.Width =static_cast<float>(width);    viewport.Height =static_cast<float>(height);    viewport.MinDepth =0.0f;    viewport.MaxDepth =1.0f;    viewport.TopLeftX =0.0f;    viewport.TopLeftY =0.0f;    d3dContext_->RSSetViewports( 1, &viewport );     return LoadContent( );}  bool Dx11DemoBase::LoadContent( ){    //可以进行重载来丰富相关功能    return true;}  void Dx11DemoBase::UnloadContent( ){    //可以进行重载来丰富相关功能}  void Dx11DemoBase::Shutdown( ){    UnloadContent( );     if( backBufferTarget_) backBufferTarget_->Release( );    if( swapChain_ )swapChain_->Release( );    if( d3dContext_ )d3dContext_->Release( );    if( d3dDevice_ )d3dDevice_->Release( );        backBufferTarget_ = 0;    swapChain_ = 0;    d3dContext_ = 0;    d3dDevice_ = 0;}






    三、BlankDx11Demo类的设计



     

    万事具备,只欠东风。

    下面我们便从上面写的Dx11DemoBase类里派生出一个叫BlankDx11Demo的类。

    以下就是 BlankDx11Demo类头文件的代码:


    代码段四 BlankDx11Demo 类的头文件

     

    #ifndef _BLANK_DEMO_H_#define _BLANK_DEMO_H_#include"Dx11DemoBase.h"class BlankDx11Demo : public Dx11DemoBase{public: BlankDx11Demo( ); virtual ~BlankDx11Demo( ); bool LoadContent( )void UnloadContent( )void Update( float dt )void Render( );};#endif





    这段代码中可以看到。叫做Update的函数中取了一个叫做dt的变量,后面将更详细地剖析这个变量,目前我们按这样理解就好了:在游戏程序中我们经常需要进行实时的游戏逻辑更新,而dt用于代表最后一帧的时间到当前时间的时间差,这个时间差记录我们用dt记录了下来,便于我们的基于时间的更新操作。

    由于这个只是一个骨架式的空DirectXDemo,以尽量精简易懂作为此Demo的宗旨,以便于大家更容易地理解一个DirectX 11 Demo的筋骨脉络,所以在这里只是只进行了一个清屏的操作,且所有的函数重载都是空的。Render函数中我们也就调用了两个Direct3D的函数:ClearRenderTargetView函数用于清除屏幕上指定的颜色,Present函数用于显示新渲染的场景。

     



    代码段五BlankDx11Demo类的源文件

     

    #include"BlankDx11Demo.h"BlankDx11Demo::BlankDx11Demo( ){}BlankDx11Demo::~BlankDx11Demo( ){}bool BlankDx11Demo::LoadContent( ){ return true;}void BlankDx11Demo::UnloadContent( ){}void BlankDx11Demo::Update( float dt ){}void BlankDx11Demo::Render( ){if( d3dContext_ == 0 )return;float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };d3dContext_->ClearRenderTargetView( backBufferTarget_,clearColor );swapChain_->Present( 0, 0 );}







     

    四、  赋予程序生命——wWinMain函数的书写



     

    之前我们创建的这些类都只是一个躯壳,并没有生命,而现在我们会将今天我们创建的这个主角赋予生命。最后一步就是在工程中修改并添加我们在笔记二十六中提出的Blank Win32 Window demo中的wWinMain函数以及余下的功能函数,使我们今天设计出的这个demo浑然一体。以下就是最后需要的源码:




    代码段六 main.cpp的完整源代码

      

    #include<Windows.h>#include<memory>#include"BlankDx11demo.h"  LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam );  int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE prevInstance,LPWSTR cmdLine, int cmdShow ){   UNREFERENCED_PARAMETER( prevInstance );   UNREFERENCED_PARAMETER( cmdLine );     WNDCLASSEX wndClass ={ 0 };    wndClass.cbSize =sizeof( WNDCLASSEX ) ;    wndClass.style =CS_HREDRAW | CS_VREDRAW;    wndClass.lpfnWndProc =WndProc;    wndClass.hInstance =hInstance;    wndClass.hCursor =LoadCursor( NULL, IDC_ARROW );    wndClass.hbrBackground= ( HBRUSH )( COLOR_WINDOW + 1 );    wndClass.lpszMenuName= NULL;    wndClass.lpszClassName= "DX11BookWindowClass";     if( !RegisterClassEx(&wndClass ) )        return -1;     RECT rc = { 0, 0, 640,480 };    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE );     HWND hwnd =CreateWindowA( "DX11BookWindowClass", "Blank Direct3D 11 Window演示程序", WS_OVERLAPPEDWINDOW,                               CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,                               NULL, NULL, hInstance, NULL );     if( !hwnd )        return -1;     ShowWindow( hwnd,cmdShow );    std::auto_ptr<Dx11DemoBase>demo( new BlankDemo( ) ); //使用智能指针     // Demo初始化工作    bool result =demo.Initialize( hInstance, hwnd );     if( result == false )        return -1;     MSG msg = { 0 };     while( msg.message !=WM_QUIT )    {        if( PeekMessage(&msg, 0, 0, 0, PM_REMOVE ) )        {           TranslateMessage( &msg );           DispatchMessage( &msg );        }         // 更新以及绘制图形        demo.Update( 0.0f);        demo.Render( );    }     // Demo开始卸载    demo.Shutdown( );     returnstatic_cast<int>( msg.wParam );}  LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam ){    PAINTSTRUCTpaintStruct;    HDC hDC;     switch( message )    {        case WM_PAINT:            hDC =BeginPaint( hwnd, &paintStruct );            EndPaint( hwnd,&paintStruct );            break;         case WM_DESTROY:           PostQuitMessage( 0 );            break;         default:            returnDefWindowProc( hwnd, message, wParam, lParam );    }     return 0;}


     

     

    笔记二十六里的demo的基础上,我们在wWinMain函数中加了7行代码。首先我们运用了C++中的标准智能指针auto_ptr<>。

    auto_ptr<>智能指针会在指向的内容结束或者此指针的作用域指向其他的智能指针时自动释放内存。这个作用域可以是,一个if语句,一个内循环,或者在一对大括号里面随意摆放来创建一个新的作用域。

    这样做的好处是非常舒服的——我们并不需要手动删除分配的数据,而且使用auto_ptr<>是非常安全环保的。即使出现了异常或者bug,应用程序停止运行了,auto_ptr<>在堆栈展开过程中依然会释放其数据。这样的话,即使运用程序崩溃了,依然会做到没有内存的泄露。若我们手动删除这个指针,且执行没有停止的话,就会留下泄露的内存。采用类似auto_ptr<>的内存对象有很多好处。

    不是很熟悉这些内容的朋友,最好是阅读一些智能指针和其他新潮的C++编程语言的书籍进行了解和提高,掌握最新标准的C++(C++0x)。

    在wWinMain函数中的最后一件事情是要注意,我们正在返回MSG对象的wParam成员,来返回应用程序的退出代码。由于wWinMain函数返回一个整型,我们把整个对象用C++标准运算符static_cast<>进行强制类型转换,转换为整型。




    Blank Direct3D Window的截图可以在下面看到。采用深蓝色来清屏。






    之后的demo的创建,我们只需要从Dx11DemoBsae里面派生出新类然后重载LoadContent,UnloadContent, Update, 以及Render,进行特殊的逻辑实现即可。




    本节的知识就介绍到这里。



    本篇文章配套的源代码请点击这里下载: 【Visual C++】Note_Code_28








    在这里公告一下,【Visual C++】游戏开发笔记系列文章现在是定在每周的周一进行更新,但是由于浅墨近期得办理回国相关

    手续及收拾行李坐飞机回国,事情比较多比较杂,笔记系列估计得“停播”一周。觉得更新速度不够快,看得不过瘾的读者们

    可以参看下我在笔记一中提到一些游戏开发相关的书籍。下下个周一,我们不见不散~~


    感谢一直支持【Visual C++】游戏开发笔记系列专栏的朋友们。

    【Visual C++】游戏开发 系列文章才刚刚展开一点而已,因为游戏世界实在是太博大精深了~

    但我们不能着急,得慢慢打好基础。做学问最忌好高骛远,不是吗?

     

    浅墨希望看到大家的留言,希望与大家共同交流,希望得到睿智的评论(即使是批评)。

    你们的支持是我写下去的动力~

     

    精通游戏开发的路还很长很长,非常希望能和大家一起交流,共同学习,共同进步。

    大家看过后觉得值得一看的话,可以顶一下这篇文章,你们的支持是我继续写下去的动力~

    如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨相关的问题。

    最后,谢谢你们一直的支持~~~

                                                   

     

                                                      ——————————浅墨于2012年7月8日













     

               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

    新的改变

    我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

    1. 全新的界面设计 ,将会带来全新的写作体验;
    2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
    3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
    4. 全新的 KaTeX数学公式 语法;
    5. 增加了支持甘特图的mermaid语法1 功能;
    6. 增加了 多屏幕编辑 Markdown文章功能;
    7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
    8. 增加了 检查列表 功能。

    功能快捷键

    撤销:Ctrl/Command + Z
    重做:Ctrl/Command + Y
    加粗:Ctrl/Command + B
    斜体:Ctrl/Command + I
    标题:Ctrl/Command + Shift + H
    无序列表:Ctrl/Command + Shift + U
    有序列表:Ctrl/Command + Shift + O
    检查列表:Ctrl/Command + Shift + C
    插入代码:Ctrl/Command + Shift + K
    插入链接:Ctrl/Command + Shift + L
    插入图片:Ctrl/Command + Shift + G

    合理的创建标题,有助于目录的生成

    直接输入1次#,并按下space后,将生成1级标题。
    输入2次#,并按下space后,将生成2级标题。
    以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

    如何改变文本的样式

    强调文本 强调文本

    加粗文本 加粗文本

    标记文本

    删除文本

    引用文本

    H2O is是液体。

    210 运算结果是 1024.

    插入链接与图片

    链接: link.

    图片: Alt

    带尺寸的图片: Alt

    当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

    如何插入一段漂亮的代码片

    博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

    // An highlighted block var foo = 'bar'; 

    生成一个适合你的列表

    • 项目
      • 项目
        • 项目
    1. 项目1
    2. 项目2
    3. 项目3
    • 计划任务
    • 完成任务

    创建一个表格

    一个简单的表格是这么创建的:

    项目 Value
    电脑 $1600
    手机 $12
    导管 $1

    设定内容居中、居左、居右

    使用:---------:居中
    使用:----------居左
    使用----------:居右

    第一列 第二列 第三列
    第一列文本居中 第二列文本居右 第三列文本居左

    SmartyPants

    SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

    TYPE ASCII HTML
    Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
    Quotes "Isn't this fun?" “Isn’t this fun?”
    Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

    创建一个自定义列表

    Markdown
    Text-to-HTML conversion tool
    Authors
    John
    Luke

    如何创建一个注脚

    一个具有注脚的文本。2

    注释也是必不可少的

    Markdown将文本转换为 HTML

    KaTeX数学公式

    您可以使用渲染LaTeX数学表达式 KaTeX:

    Gamma公式展示 Γ(n)=(n1)!nN\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通过欧拉积分

    Γ(z)=0tz1etdt&ThinSpace;. \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

    你可以找到更多关于的信息 LaTeX 数学表达式here.

    新的甘特图功能,丰富你的文章

    gantt
            dateFormat  YYYY-MM-DD
            title Adding GANTT diagram functionality to mermaid
            section 现有任务
            已完成               :done,    des1, 2014-01-06,2014-01-08
            进行中               :active,  des2, 2014-01-09, 3d
            计划一               :         des3, after des2, 5d
            计划二               :         des4, after des3, 5d
    
    • 关于 甘特图 语法,参考 这儿,

    UML 图表

    可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

    张三李四王五你好!李四, 最近怎么样?你最近怎么样,王五?我很好,谢谢!我很好,谢谢!李四想了很长时间,文字太长了不适合放在一行.打量着王五...很好... 王五, 你怎么样?张三李四王五

    这将产生一个流程图。:

    链接
    长方形
    圆角长方形
    菱形
    • 关于 Mermaid 语法,参考 这儿,

    FLowchart流程图

    我们依旧会支持flowchart的流程图:

    • 关于 Flowchart流程图 语法,参考 这儿.

    导出与导入

    导出

    如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

    导入

    如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
    继续你的创作。


    1. mermaid语法说明 ↩︎

    2. 注脚的解释 ↩︎

    展开全文
  • 本篇文章将讲解如何通过我们在之前的文章里面已掌握的DirectX 11的知识,来一步一步创建一个基于Direct3D11的Blank Windows Demo,而我们在这节里面完成的这个demo,将在后面的文章里面作为一个模板,用于演示之后的...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处。

    http://blog.csdn.net/zhmxy555/article/details/7707628

    作者:毛星云    邮箱: happylifemxy@qq.com  


     

     

    本篇文章将讲解如何通过我们在之前的文章里面已掌握的DirectX 11的知识,来一步一步创建一个基于Direct3D11的Blank Windows Demo,而我们在这节里面完成的这个demo,将在后面的文章里面作为一个模板,用于演示之后的各种新奇DirectX11的功能。


     

    首先呢,为了代码的重用性着想,我们会写一个 DirectX11DemoBase,并借鉴在笔记二十六中的Win32风格的Blank Win32 Window Demo中的代码,然后通过派生的方式,以及重载一些必要的虚函数,进行整合,来创建我们的demo。


          



    一、  关于代码书写风格的讨论


     

    首先,我们提出一个问题,采用自问自答的形式来讨论:


    在这个demo的设计过程中,我们是采用C语言式的全局变量与全局函数的搭档模式来完成,还是采用C++式的面向对象风格的类Class来编写呢?

     

    答案是后者,采用面向对象的思想来完成至于这个问题的解释,答案就仁者见仁智者见智了。

    浅墨之前看过一本C++界的名著《C++沉思录》,作者在文章的开篇举了一个例子,然后通过例子对比出来的效果,折射出了对C与C++的一个中肯的评价,是这样的一段话:


    “C++鼓励采用类来表示类似于输出流的事物,而类就提供了一个理想的位置来存放状态信息。而C语言倾向于不存储状态信息,除非事先已经规划妥当。因此C程序员趋向于假设有这样一个“环境”:存在一个位置集合,他们可以在其中找到系统的当前状态。如果只有一个环境和一个系统,这样考虑毫无问题,但是,系统在不断增长的过程中往往需要引入某些独一无二的东西,并且创建更多这类东西。”


    对这段话的解释,浅墨还是用自己的话来叙述吧:

    通常我们采用一般的变量作为传递数据的容器,但是随着程序的复杂会导致数据量的加大,有太多的数据需要被传递,而且这些数据基本上都是需要传递到近乎是每一个函数当中的,这样我们就要创建很多的全局变量作为“容器”,如此下去我们的设计的程序只会越来越臃肿,越来越乱。别怕别怕,有绝招呢——我们可以创建一个类或者结构体来收容这些对象,使之显得不是那么乱,取而代之的是井井有条。


    绕了这么大一圈子,一言以蔽之,就是运用全局变量是不太好的编程习惯,我们应当少用甚至不用,转而使用“类”来完成这些任务。

     

     



     

    二、    Dx11DemoBase类的设计


     

    作为目前来说,我们要求本节的demo做到以下几点功能:

     

    ▲初始化D3D

    ▲释放在启动过程中创建的Direct3D对象

    ▲为我们的D3D对象存储成员变量

    ▲提供一个装载demo的具体内容的方式

    ▲提供一个卸载demo的具体内容的方式

    ▲能够显示demo每帧的更新的具体内容

    ▲demo渲染内容的具体代码

     

    由我们上面的清单来看,创建一个公共的初始化和卸载函数,用于装载和卸载内容功能的虚函数,以及渲染和更新游戏循环步骤的虚函数的基类是很有必要的。通过将这些函数设为虚函数,由基类派生出来的demo类能够实现他们自定义的逻辑和行为。

    根据上面的这些叙述,我们可以写出下面的这段为Dx11DemoBase量身打造的代码:

     

     

    代码段一  Dx11DemoBases类的头文件

     

    1. #ifndef _DEMO_BASE_H_   
    2. #define _DEMO_BASE_H_   
    3. #include<d3d11.h>   
    4. #include<d3dx11.h>   
    5. #include<DxErr.h>   
    6. class Dx11DemoBase  
    7. {  
    8. public:  
    9.    Dx11DemoBase();  
    10.    virtual ~Dx11DemoBase();  
    11.    bool Initialize( HINSTANCE hInstance, HWND hwnd );  
    12.    void Shutdown( );  
    13.    virtual bool LoadContent( );  
    14.    virtual void UnloadContent( );  
    15.    virtual void Update( float dt ) = 0;  
    16.    virtual void Render( ) = 0;  
    17.    protected:  
    18.    HINSTANCE hInstance_;  
    19.    HWND hwnd_;  
    20.    D3D_DRIVER_TYPE driverType_;  
    21.    D3D_FEATURE_LEVEL featureLevel_;  
    22.    ID3D11Device* d3dDevice_;  
    23.    ID3D11DeviceContext* d3dContext_;  
    24.    IDXGISwapChain* swapChain_;  
    25.    ID3D11RenderTargetView* backBufferTarget_;  
    26. };  
    27. #endif  
    #ifndef _DEMO_BASE_H_
    #define _DEMO_BASE_H_
    #include<d3d11.h>
    #include<d3dx11.h>
    #include<DxErr.h>
    class Dx11DemoBase
    {
    public:
       Dx11DemoBase();
       virtual ~Dx11DemoBase();
       bool Initialize( HINSTANCE hInstance, HWND hwnd );
       void Shutdown( );
       virtual bool LoadContent( );
       virtual void UnloadContent( );
       virtual void Update( float dt ) = 0;
       virtual void Render( ) = 0;
       protected:
       HINSTANCE hInstance_;
       HWND hwnd_;
       D3D_DRIVER_TYPE driverType_;
       D3D_FEATURE_LEVEL featureLevel_;
       ID3D11Device* d3dDevice_;
       ID3D11DeviceContext* d3dContext_;
       IDXGISwapChain* swapChain_;
       ID3D11RenderTargetView* backBufferTarget_;
    };
    #endif




     

    上面这段代码中我们可以看到最精简的D3D对象,以protected类成员的形式存在于类之中。在类体外初始化变量是比较好的编程习惯,而且效率比让先调用拷贝构造函数,再调用默认构造函数要高得多。

    Dx11DemoBase类构造函数,析构函数,装载内容,卸载内容,shutdown函数定义如下:

     



    代码段二 一些Dx11DemoBase 组成代码


    1. #include"Dx11DemoBase.h"   
    2.   
    3. Dx11DemoBase::Dx11DemoBase( ) : driverType_( D3D_DRIVER_TYPE_NULL),  
    4. featureLevel_( D3D_FEATURE_LEVEL_11_0 ), d3dDevice_( 0 ),d3dContext_( 0 ),  
    5. swapChain_( 0 ), backBufferTarget_( 0 )  
    6. {  
    7.   
    8. }  
    9.   
    10. void Dx11DemoBase::UnloadContent( )  
    11. {  
    12. //可以在此处进行重载,加入代码实现相关功能   
    13.   
    14.   
    15.   
    16. void Dx11DemoBase::Shutdown( )  
    17. {  
    18.    UnloadContent( );  
    19.    if( backBufferTarget_ ) backBufferTarget_->Release( );  
    20.    if( swapChain_ ) swapChain_->Release( );  
    21.    if( d3dContext_ ) d3dContext_->Release( );  
    22.    if( d3dDevice_ ) d3dDevice_->Release( );  
    23.    d3dDevice_ = 0;  
    24.    d3dContext_ = 0;  
    25.    swapChain_ = 0;  
    26.    backBufferTarget_ = 0;  
    27. }  
    #include"Dx11DemoBase.h"
    
    Dx11DemoBase::Dx11DemoBase( ) : driverType_( D3D_DRIVER_TYPE_NULL),
    featureLevel_( D3D_FEATURE_LEVEL_11_0 ), d3dDevice_( 0 ),d3dContext_( 0 ),
    swapChain_( 0 ), backBufferTarget_( 0 )
    {
    
    }
    
    void Dx11DemoBase::UnloadContent( )
    {
    //可以在此处进行重载,加入代码实现相关功能
    
    
    
    void Dx11DemoBase::Shutdown( )
    {
       UnloadContent( );
       if( backBufferTarget_ ) backBufferTarget_->Release( );
       if( swapChain_ ) swapChain_->Release( );
       if( d3dContext_ ) d3dContext_->Release( );
       if( d3dDevice_ ) d3dDevice_->Release( );
       d3dDevice_ = 0;
       d3dContext_ = 0;
       swapChain_ = 0;
       backBufferTarget_ = 0;
    }



          

    Dx11DemoBase类中的最后一个函数是Initialize函数。Initialize函数执行我们在这章中讲到的D3D初始化工作。这个函数开始声明我们的硬件,WARP或者软件的驱动类型,和我们的D3D11.0,10.1或者10.0的特征等级。代码的设定即尝试在D3D 11中创建一个硬件设备。如果创建失败,我们会尝试其他的驱动类型和特征等级直到我们找到一个合适的类型。这也意味着如果我们采用D3D10硬件我们可以也可以在硬件中运行这个demo,因为我们可以选择10.1或者10.0的特征等级。

    下一步便是创建交换链的描述,以及使用这些信息来试着找到支持的设备类型和特征等级。如果成功的搜索到了我们需要的这些信息。接下来就是行云流水地创建渲染目标,创建视口,以及调用LoadContent方法加载特定的内容了。需要指出的是,LoadContent方法最好留着最后进行调用,以免出现不必要的错误。

    下面便是DirectX11初始化的全过程:

     



    代码段三 Dx11DemoBase类的初始化函数

     

    1. bool Dx11DemoBase::Initialize( HINSTANCE hInstance, HWND hwnd )  
    2. {  
    3.     hInstance_ =hInstance;  
    4.     hwnd_ = hwnd;  
    5.    
    6.     RECT dimensions;  
    7.     GetClientRect( hwnd,&dimensions );  
    8.    
    9.     unsigned int width =dimensions.right - dimensions.left;  
    10.     unsigned int height =dimensions.bottom - dimensions.top;  
    11.    
    12.     D3D_DRIVER_TYPEdriverTypes[] =  
    13.     {  
    14.        D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,  
    15.        D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE  
    16.     };  
    17.    
    18.     unsigned inttotalDriverTypes = ARRAYSIZE( driverTypes );  
    19.    
    20.     D3D_FEATURE_LEVELfeatureLevels[] =  
    21.     {  
    22.        D3D_FEATURE_LEVEL_11_0,  
    23.        D3D_FEATURE_LEVEL_10_1,  
    24.        D3D_FEATURE_LEVEL_10_0  
    25.     };  
    26.    
    27.     unsigned inttotalFeatureLevels = ARRAYSIZE( featureLevels );  
    28.    
    29.     DXGI_SWAP_CHAIN_DESCswapChainDesc;  
    30.     ZeroMemory(&swapChainDesc, sizeof( swapChainDesc ) );  
    31.    swapChainDesc.BufferCount = 1;  
    32.    swapChainDesc.BufferDesc.Width = width;  
    33.    swapChainDesc.BufferDesc.Height = height;  
    34.    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;  
    35.    swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;  
    36.    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;  
    37.    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;  
    38.    swapChainDesc.OutputWindow = hwnd;  
    39.     swapChainDesc.Windowed= true;  
    40.    swapChainDesc.SampleDesc.Count = 1;  
    41.     swapChainDesc.SampleDesc.Quality= 0;  
    42.    
    43.     unsigned intcreationFlags = 0;  
    44.    
    45. #ifdef _DEBUG   
    46.     creationFlags |=D3D11_CREATE_DEVICE_DEBUG;  
    47. #endif   
    48.    
    49.     HRESULT result;  
    50.     unsigned int driver =0;  
    51.    
    52.     for( driver = 0;driver < totalDriverTypes; ++driver )  
    53.     {  
    54.         result =D3D11CreateDeviceAndSwapChain( 0, driverTypes[driver], 0, creationFlags,  
    55.                                                featureLevels, totalFeatureLevels,  
    56.                                                D3D11_SDK_VERSION, &swapChainDesc, &swapChain_,  
    57.                                                &d3dDevice_, &featureLevel_, &d3dContext_ );  
    58.    
    59.         if( SUCCEEDED(result ) )  
    60.         {  
    61.             driverType_ =driverTypes[driver];  
    62.             break;  
    63.         }  
    64.     }  
    65.    
    66.     if( FAILED( result ) )  
    67.     {  
    68.         DXTRACE_MSG("创建 Direct3D 设备失败!" );  
    69.         return false;  
    70.     }  
    71.    
    72.     ID3D11Texture2D*backBufferTexture;  
    73.    
    74.     result =swapChain_->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID*)&backBufferTexture );  
    75.    
    76.     if( FAILED( result ) )  
    77.     {  
    78.         DXTRACE_MSG("获取交换链后台缓存失败!" );  
    79.         return false;  
    80.     }  
    81.    
    82.     result =d3dDevice_->CreateRenderTargetView( backBufferTexture, 0,&backBufferTarget_ );  
    83.    
    84.     if( backBufferTexture)  
    85.        backBufferTexture->Release( );  
    86.    
    87.     if( FAILED( result ) )  
    88.     {  
    89.         DXTRACE_MSG("创建渲染目标视图失败!" );  
    90.         return false;  
    91.     }  
    92.    
    93.    d3dContext_->OMSetRenderTargets( 1, &backBufferTarget_, 0 );  
    94.    
    95.     D3D11_VIEWPORTviewport;  
    96.     viewport.Width =static_cast<float>(width);  
    97.     viewport.Height =static_cast<float>(height);  
    98.     viewport.MinDepth =0.0f;  
    99.     viewport.MaxDepth =1.0f;  
    100.     viewport.TopLeftX =0.0f;  
    101.     viewport.TopLeftY =0.0f;  
    102.    
    103.    d3dContext_->RSSetViewports( 1, &viewport );  
    104.    
    105.     return LoadContent( );  
    106. }  
    107.    
    108.    
    109. bool Dx11DemoBase::LoadContent( )  
    110. {  
    111.     //可以进行重载来丰富相关功能   
    112.     return true;  
    113. }  
    114.    
    115.    
    116. void Dx11DemoBase::UnloadContent( )  
    117. {  
    118.     //可以进行重载来丰富相关功能   
    119. }  
    120.    
    121.    
    122. void Dx11DemoBase::Shutdown( )  
    123. {  
    124.     UnloadContent( );  
    125.    
    126.     if( backBufferTarget_) backBufferTarget_->Release( );  
    127.     if( swapChain_ )swapChain_->Release( );  
    128.     if( d3dContext_ )d3dContext_->Release( );  
    129.     if( d3dDevice_ )d3dDevice_->Release( );     
    130.    
    131.     backBufferTarget_ = 0;  
    132.     swapChain_ = 0;  
    133.     d3dContext_ = 0;  
    134.     d3dDevice_ = 0;  
    135. }  
    bool Dx11DemoBase::Initialize( HINSTANCE hInstance, HWND hwnd )
    {
        hInstance_ =hInstance;
        hwnd_ = hwnd;
     
        RECT dimensions;
        GetClientRect( hwnd,&dimensions );
     
        unsigned int width =dimensions.right - dimensions.left;
        unsigned int height =dimensions.bottom - dimensions.top;
     
        D3D_DRIVER_TYPEdriverTypes[] =
        {
           D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,
           D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE
        };
     
        unsigned inttotalDriverTypes = ARRAYSIZE( driverTypes );
     
        D3D_FEATURE_LEVELfeatureLevels[] =
        {
           D3D_FEATURE_LEVEL_11_0,
           D3D_FEATURE_LEVEL_10_1,
           D3D_FEATURE_LEVEL_10_0
        };
     
        unsigned inttotalFeatureLevels = ARRAYSIZE( featureLevels );
     
        DXGI_SWAP_CHAIN_DESCswapChainDesc;
        ZeroMemory(&swapChainDesc, sizeof( swapChainDesc ) );
       swapChainDesc.BufferCount = 1;
       swapChainDesc.BufferDesc.Width = width;
       swapChainDesc.BufferDesc.Height = height;
       swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
       swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
       swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
       swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
       swapChainDesc.OutputWindow = hwnd;
        swapChainDesc.Windowed= true;
       swapChainDesc.SampleDesc.Count = 1;
        swapChainDesc.SampleDesc.Quality= 0;
     
        unsigned intcreationFlags = 0;
     
    #ifdef _DEBUG
        creationFlags |=D3D11_CREATE_DEVICE_DEBUG;
    #endif
     
        HRESULT result;
        unsigned int driver =0;
     
        for( driver = 0;driver < totalDriverTypes; ++driver )
        {
            result =D3D11CreateDeviceAndSwapChain( 0, driverTypes[driver], 0, creationFlags,
                                                   featureLevels, totalFeatureLevels,
                                                   D3D11_SDK_VERSION, &swapChainDesc, &swapChain_,
                                                   &d3dDevice_, &featureLevel_, &d3dContext_ );
     
            if( SUCCEEDED(result ) )
            {
                driverType_ =driverTypes[driver];
                break;
            }
        }
     
        if( FAILED( result ) )
        {
            DXTRACE_MSG("创建 Direct3D 设备失败!" );
            return false;
        }
     
        ID3D11Texture2D*backBufferTexture;
     
        result =swapChain_->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID*)&backBufferTexture );
     
        if( FAILED( result ) )
        {
            DXTRACE_MSG("获取交换链后台缓存失败!" );
            return false;
        }
     
        result =d3dDevice_->CreateRenderTargetView( backBufferTexture, 0,&backBufferTarget_ );
     
        if( backBufferTexture)
           backBufferTexture->Release( );
     
        if( FAILED( result ) )
        {
            DXTRACE_MSG("创建渲染目标视图失败!" );
            return false;
        }
     
       d3dContext_->OMSetRenderTargets( 1, &backBufferTarget_, 0 );
     
        D3D11_VIEWPORTviewport;
        viewport.Width =static_cast<float>(width);
        viewport.Height =static_cast<float>(height);
        viewport.MinDepth =0.0f;
        viewport.MaxDepth =1.0f;
        viewport.TopLeftX =0.0f;
        viewport.TopLeftY =0.0f;
     
       d3dContext_->RSSetViewports( 1, &viewport );
     
        return LoadContent( );
    }
     
     
    bool Dx11DemoBase::LoadContent( )
    {
        //可以进行重载来丰富相关功能
        return true;
    }
     
     
    void Dx11DemoBase::UnloadContent( )
    {
        //可以进行重载来丰富相关功能
    }
     
     
    void Dx11DemoBase::Shutdown( )
    {
        UnloadContent( );
     
        if( backBufferTarget_) backBufferTarget_->Release( );
        if( swapChain_ )swapChain_->Release( );
        if( d3dContext_ )d3dContext_->Release( );
        if( d3dDevice_ )d3dDevice_->Release( );   
     
        backBufferTarget_ = 0;
        swapChain_ = 0;
        d3dContext_ = 0;
        d3dDevice_ = 0;
    }






    三、BlankDx11Demo类的设计



     

    万事具备,只欠东风。

    下面我们便从上面写的Dx11DemoBase类里派生出一个叫BlankDx11Demo的类。

    以下就是 BlankDx11Demo类头文件的代码:


    代码段四 BlankDx11Demo 类的头文件

     

    1. #ifndef _BLANK_DEMO_H_   
    2. #define _BLANK_DEMO_H_   
    3. #include"Dx11DemoBase.h"   
    4.   
    5. class BlankDx11Demo : public Dx11DemoBase  
    6. {  
    7. public:  
    8.     BlankDx11Demo( );  
    9.     virtual ~BlankDx11Demo( );  
    10.     bool LoadContent( );  
    11.     void UnloadContent( );  
    12.     void Update( float dt );  
    13.     void Render( );  
    14. };  
    15. #endif  
    #ifndef _BLANK_DEMO_H_
    #define _BLANK_DEMO_H_
    #include"Dx11DemoBase.h"
    
    class BlankDx11Demo : public Dx11DemoBase
    {
    public:
    	BlankDx11Demo( );
    	virtual ~BlankDx11Demo( );
    	bool LoadContent( );
    	void UnloadContent( );
    	void Update( float dt );
    	void Render( );
    };
    #endif





    这段代码中可以看到。叫做Update的函数中取了一个叫做dt的变量,后面将更详细地剖析这个变量,目前我们按这样理解就好了:在游戏程序中我们经常需要进行实时的游戏逻辑更新,而dt用于代表最后一帧的时间到当前时间的时间差,这个时间差记录我们用dt记录了下来,便于我们的基于时间的更新操作。

    由于这个只是一个骨架式的空DirectXDemo,以尽量精简易懂作为此Demo的宗旨,以便于大家更容易地理解一个DirectX 11 Demo的筋骨脉络,所以在这里只是只进行了一个清屏的操作,且所有的函数重载都是空的。Render函数中我们也就调用了两个Direct3D的函数:ClearRenderTargetView函数用于清除屏幕上指定的颜色,Present函数用于显示新渲染的场景。

     



    代码段五BlankDx11Demo类的源文件

     

    1. #include"BlankDx11Demo.h"   
    2.   
    3. BlankDx11Demo::BlankDx11Demo( )  
    4. {  
    5. }  
    6.   
    7. BlankDx11Demo::~BlankDx11Demo( )  
    8. {  
    9. }  
    10.   
    11. bool BlankDx11Demo::LoadContent( )  
    12. {  
    13.     return true;  
    14. }  
    15.   
    16. void BlankDx11Demo::UnloadContent( )  
    17. {  
    18. }  
    19.   
    20. void BlankDx11Demo::Update( float dt )  
    21. {  
    22. }  
    23.   
    24. void BlankDx11Demo::Render( )  
    25. {  
    26. if( d3dContext_ == 0 )  
    27. return;  
    28. float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };  
    29. d3dContext_->ClearRenderTargetView( backBufferTarget_,clearColor );  
    30. swapChain_->Present( 0, 0 );  
    31. }  
    #include"BlankDx11Demo.h"
    
    BlankDx11Demo::BlankDx11Demo( )
    {
    }
    
    BlankDx11Demo::~BlankDx11Demo( )
    {
    }
    
    bool BlankDx11Demo::LoadContent( )
    {
    	return true;
    }
    
    void BlankDx11Demo::UnloadContent( )
    {
    }
    
    void BlankDx11Demo::Update( float dt )
    {
    }
    
    void BlankDx11Demo::Render( )
    {
    if( d3dContext_ == 0 )
    return;
    float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };
    d3dContext_->ClearRenderTargetView( backBufferTarget_,clearColor );
    swapChain_->Present( 0, 0 );
    }







     

    四、  赋予程序生命——wWinMain函数的书写



     

    之前我们创建的这些类都只是一个躯壳,并没有生命,而现在我们会将今天我们创建的这个主角赋予生命。最后一步就是在工程中修改并添加我们在笔记二十六中提出的Blank Win32 Window demo中的wWinMain函数以及余下的功能函数,使我们今天设计出的这个demo浑然一体。以下就是最后需要的源码:




    代码段六 main.cpp的完整源代码

      

    1. #include<Windows.h>   
    2. #include<memory>   
    3. #include"BlankDx11demo.h"   
    4.    
    5.    
    6. LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam );  
    7.    
    8.    
    9. int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE prevInstance,LPWSTR cmdLine, int cmdShow )  
    10. {  
    11.    UNREFERENCED_PARAMETER( prevInstance );  
    12.    UNREFERENCED_PARAMETER( cmdLine );  
    13.    
    14.     WNDCLASSEX wndClass ={ 0 };  
    15.     wndClass.cbSize =sizeof( WNDCLASSEX ) ;  
    16.     wndClass.style =CS_HREDRAW | CS_VREDRAW;  
    17.     wndClass.lpfnWndProc =WndProc;  
    18.     wndClass.hInstance =hInstance;  
    19.     wndClass.hCursor =LoadCursor( NULL, IDC_ARROW );  
    20.     wndClass.hbrBackground= ( HBRUSH )( COLOR_WINDOW + 1 );  
    21.     wndClass.lpszMenuName= NULL;  
    22.     wndClass.lpszClassName= "DX11BookWindowClass";  
    23.    
    24.     if( !RegisterClassEx(&wndClass ) )  
    25.         return -1;  
    26.    
    27.     RECT rc = { 0, 0, 640,480 };  
    28.     AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE );  
    29.    
    30.     HWND hwnd =CreateWindowA( "DX11BookWindowClass""Blank Direct3D 11 Window演示程序", WS_OVERLAPPEDWINDOW,  
    31.                                CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,  
    32.                                NULL, NULL, hInstance, NULL );  
    33.    
    34.     if( !hwnd )  
    35.         return -1;  
    36.    
    37.     ShowWindow( hwnd,cmdShow );  
    38.    
    39.    std::auto_ptr<Dx11DemoBase>demo( new BlankDemo( ) ); //使用智能指针   
    40.    
    41.     // Demo初始化工作   
    42.     bool result =demo.Initialize( hInstance, hwnd );  
    43.    
    44.     if( result == false )  
    45.         return -1;  
    46.    
    47.     MSG msg = { 0 };  
    48.    
    49.     while( msg.message !=WM_QUIT )  
    50.     {  
    51.         if( PeekMessage(&msg, 0, 0, 0, PM_REMOVE ) )  
    52.         {  
    53.            TranslateMessage( &msg );  
    54.            DispatchMessage( &msg );  
    55.         }  
    56.    
    57.         // 更新以及绘制图形   
    58.         demo.Update( 0.0f);  
    59.         demo.Render( );  
    60.     }  
    61.    
    62.     // Demo开始卸载   
    63.     demo.Shutdown( );  
    64.    
    65.     returnstatic_cast<int>( msg.wParam );  
    66. }  
    67.    
    68.    
    69. LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam )  
    70. {  
    71.     PAINTSTRUCTpaintStruct;  
    72.     HDC hDC;  
    73.    
    74.     switch( message )  
    75.     {  
    76.         case WM_PAINT:  
    77.             hDC =BeginPaint( hwnd, &paintStruct );  
    78.             EndPaint( hwnd,&paintStruct );  
    79.             break;  
    80.    
    81.         case WM_DESTROY:  
    82.            PostQuitMessage( 0 );  
    83.             break;  
    84.    
    85.         default:  
    86.             returnDefWindowProc( hwnd, message, wParam, lParam );  
    87.     }  
    88.    
    89.     return 0;  
    90. }  
    #include<Windows.h>
    #include<memory>
    #include"BlankDx11demo.h"
     
     
    LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam );
     
     
    int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE prevInstance,LPWSTR cmdLine, int cmdShow )
    {
       UNREFERENCED_PARAMETER( prevInstance );
       UNREFERENCED_PARAMETER( cmdLine );
     
        WNDCLASSEX wndClass ={ 0 };
        wndClass.cbSize =sizeof( WNDCLASSEX ) ;
        wndClass.style =CS_HREDRAW | CS_VREDRAW;
        wndClass.lpfnWndProc =WndProc;
        wndClass.hInstance =hInstance;
        wndClass.hCursor =LoadCursor( NULL, IDC_ARROW );
        wndClass.hbrBackground= ( HBRUSH )( COLOR_WINDOW + 1 );
        wndClass.lpszMenuName= NULL;
        wndClass.lpszClassName= "DX11BookWindowClass";
     
        if( !RegisterClassEx(&wndClass ) )
            return -1;
     
        RECT rc = { 0, 0, 640,480 };
        AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE );
     
        HWND hwnd =CreateWindowA( "DX11BookWindowClass", "Blank Direct3D 11 Window演示程序", WS_OVERLAPPEDWINDOW,
                                   CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
                                   NULL, NULL, hInstance, NULL );
     
        if( !hwnd )
            return -1;
     
        ShowWindow( hwnd,cmdShow );
     
       std::auto_ptr<Dx11DemoBase>demo( new BlankDemo( ) ); //使用智能指针
     
        // Demo初始化工作
        bool result =demo.Initialize( hInstance, hwnd );
     
        if( result == false )
            return -1;
     
        MSG msg = { 0 };
     
        while( msg.message !=WM_QUIT )
        {
            if( PeekMessage(&msg, 0, 0, 0, PM_REMOVE ) )
            {
               TranslateMessage( &msg );
               DispatchMessage( &msg );
            }
     
            // 更新以及绘制图形
            demo.Update( 0.0f);
            demo.Render( );
        }
     
        // Demo开始卸载
        demo.Shutdown( );
     
        returnstatic_cast<int>( msg.wParam );
    }
     
     
    LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAMwParam, LPARAM lParam )
    {
        PAINTSTRUCTpaintStruct;
        HDC hDC;
     
        switch( message )
        {
            case WM_PAINT:
                hDC =BeginPaint( hwnd, &paintStruct );
                EndPaint( hwnd,&paintStruct );
                break;
     
            case WM_DESTROY:
               PostQuitMessage( 0 );
                break;
     
            default:
                returnDefWindowProc( hwnd, message, wParam, lParam );
        }
     
        return 0;
    }


     

     

    笔记二十六里的demo的基础上,我们在wWinMain函数中加了7行代码。首先我们运用了C++中的标准智能指针auto_ptr<>。

    auto_ptr<>智能指针会在指向的内容结束或者此指针的作用域指向其他的智能指针时自动释放内存。这个作用域可以是,一个if语句,一个内循环,或者在一对大括号里面随意摆放来创建一个新的作用域。

    这样做的好处是非常舒服的——我们并不需要手动删除分配的数据,而且使用auto_ptr<>是非常安全环保的。即使出现了异常或者bug,应用程序停止运行了,auto_ptr<>在堆栈展开过程中依然会释放其数据。这样的话,即使运用程序崩溃了,依然会做到没有内存的泄露。若我们手动删除这个指针,且执行没有停止的话,就会留下泄露的内存。采用类似auto_ptr<>的内存对象有很多好处。

    不是很熟悉这些内容的朋友,最好是阅读一些智能指针和其他新潮的C++编程语言的书籍进行了解和提高,掌握最新标准的C++(C++0x)。

    在wWinMain函数中的最后一件事情是要注意,我们正在返回MSG对象的wParam成员,来返回应用程序的退出代码。由于wWinMain函数返回一个整型,我们把整个对象用C++标准运算符static_cast<>进行强制类型转换,转换为整型。




    Blank Direct3D Window的截图可以在下面看到。采用深蓝色来清屏。






    之后的demo的创建,我们只需要从Dx11DemoBsae里面派生出新类然后重载LoadContent,UnloadContent, Update, 以及Render,进行特殊的逻辑实现即可。




    本节的知识就介绍到这里。



    本篇文章配套的源代码请点击这里下载: 【Visual C++】Note_Code_28








    在这里公告一下,【Visual C++】游戏开发笔记系列文章现在是定在每周的周一进行更新,但是由于浅墨近期得办理回国相关

    手续及收拾行李坐飞机回国,事情比较多比较杂,笔记系列估计得“停播”一周。觉得更新速度不够快,看得不过瘾的读者们

    可以参看下我在笔记一中提到一些游戏开发相关的书籍。下下个周一,我们不见不散~~


    感谢一直支持【Visual C++】游戏开发笔记系列专栏的朋友们。

    【Visual C++】游戏开发 系列文章才刚刚展开一点而已,因为游戏世界实在是太博大精深了~

    但我们不能着急,得慢慢打好基础。做学问最忌好高骛远,不是吗?

     

    浅墨希望看到大家的留言,希望与大家共同交流,希望得到睿智的评论(即使是批评)。

    你们的支持是我写下去的动力~

     

    精通游戏开发的路还很长很长,非常希望能和大家一起交流,共同学习,共同进步。

    大家看过后觉得值得一看的话,可以顶一下这篇文章,你们的支持是我继续写下去的动力~

    如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨相关的问题。

    最后,谢谢你们一直的支持~~~

                                                   

     

                                                      ——————————浅墨于2012年7月8日










    展开全文
  • admin, 用户 ...此贴长期更新,定期总结用户所遇问题,萃取精华,不断优化,当然我们也会不断优化key配置使用方案。...(来自admin,部分用户key配置正确但验证不通过的困扰我们...攻略1: 细看申请步骤与说明,最
  • Android Butterknife框架 注解攻略
  • 本人花了一天时间攻略的C# to mongodb 的小demo 和大家分享 绝对不是为了分 绝对不是
  • 【干货】Chrome插件(扩展)开发全攻略

    万次阅读 2021-01-08 18:08:01
    **转载自 小茗同学 的 【干货】Chrome插件(扩展)开发全攻略 写在前面 我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的,所以转载务必保留出处。本文所有涉及到的大部分...
  • 我的博客 《Simulink生成ROS代码详细攻略》相应的视频教学,纯属自己的学习记录,欢迎各位大佬指正交流!小白刚刚起步学习,每次学习都会做学习记录。
  • 博文的配套源码 《 【Visual C++】游戏开发笔记二十八 最精简的Direct3D11 Demo筋骨脉络全攻略》 ,文章地址为http://blog.csdn.net/zhmxy555/article/details/7727753, 点击debug下的exe文件可以直接看到运行...
  • 游戏demo设计前期准备

    2012-04-13 18:16:25
    http://bbs.17173.com/thread/238/515/20080813/4b4fe155c5c533645-1.html 深蓝色右手 http://www.pan3d.me/tutorial/ && ... 如何学好3D游戏引擎 地形制作全攻略 && 地形制作全攻略   论坛: h
  • 网页版流程图插件-myflow.js myflow-min下载地址 web流程图插件-myflow.js-demo下载 源码下载地址-demo: ...过几天,我试试看, 试着写写 操作手册和攻略。 准备发一个 介绍和操作的连载。 web...
  • DRM许可证申请攻略

    万次阅读 2009-03-23 00:45:00
    DRM许可证申请攻略Peter Lee 【前言】Windows Media提供了DRM的解决方案,但DRM解决方案对开发者不是完全开放的,而是通过认证的方式对有资质的企业开放。Windows Media Format SDK中提供了DRM播放的demo,但其中...
  • 个人认为这是慕课网比较好的一个系列教程,而且很多同学在视频下方都附上了自己写的demo,具有一定的参考价值。讲师的水平和教学态度都是非常nice的~感兴趣的小伙伴可以看看其他的课程 如果在看这套教程时遇到...
  • 【DirectX11】2D纹理映射演示demo

    热门讨论 2012-07-30 14:15:10
    博文的配套源码 《 【Visual C++】游戏开发笔记三十 DirectX11 2D纹理映射知识全攻略 》 ,配套博文地址为http://blog.csdn.net/zhmxy555/article/details/7801729 为了更好的理解和提高,建议和配套博文一起...
  • CNNdroid+Caffe使用攻略

    2017-11-08 14:01:39
    CNNdroid+Caffe使用攻略 lab里在弄机器学习,坑了自己那么多,写篇详细点的CNNdroid的资料吧,国内好像好少看到CNNdroid的资料,用起来感觉速度还OK的。 github:https://github.com/hirorogithub/CNNdroid_age_demo...
  • 用C#制作PDF文件全攻略 目 录 前 言 3 第一部分 iText的简单应用 4 第一章 创建一个Document 4 第一步 创建一个Document实例: 5 第二步 创建Writer实例 6 第三步 打开Document 6 第四步 添加内容 10 第五步,关闭 ...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 236
精华内容 94
关键字:

demo攻略