注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

刘邓

每天收获一点点-目标:富足

 
 
 

日志

 
 

每天翻译一点点——Direct3D 10系列(1)  

2012-03-24 23:23:55|  分类: 翻译类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Summary

In this first tutorial, we will go through the elements necessary to create a minimal Direct3D 10 application. Every Direct3D 10 application must have these elements to function properly. The elements include setting up a window and a device object then displaying a color on the window.

D3D10 指南1Direct3D 10基础

在这个教程中,我们大致的过了一遍创建一个最简单的D3D10应用程序所必需

的组件。每一个D3D10应用程序都需要这些组件的正确运作。这些内容包括创建

一个窗口和设备然后在窗口上呈现一种颜色。

Source

(SDK root)\Samples\C++\Direct3D10\Tutorials\Tutorial01

Setting Up The Direct3D 10 Device

Now that we have a window displaying, we can continue to set up a Direct3D 10 device, which is necessary if we are going to render any 3D scene. The first thing to do is to create two objects: a device and a swap chain.

创建一个D3D10设备

现在我们有了一个窗口显示,如果我们想要继续绘制任何的3D场景,那么就需要继续创建一个Direct3D 10 的设备。第一件事要做的就是创建两个对象:一个设备和一个交换链。

设备对象被应用程序用来在缓存上绘制,同时设备对象也包含创建资源的方法。

The device object is used by the application to perform rendering onto a buffer. The device also contains methods to create resources.

The swap chain is responsible for taking the buffer that the device renders to and displaying the content on the actual monitor screen. The swap chain contains two or more buffers, mainly the front and the back. These are textures that the device renders to, for displaying on the monitor. The front buffer is what is currently being presented to the user. This buffer is read-only and cannot be modified. The back buffer is the render target that the device will draw to. Once it finishes the drawing operation, the swap chain will present the backbuffer, by swapping the two buffers. The back buffer becomes the front buffer, and vice versa.

交换链负责把设备渲染完成的缓存内容显示到实际的显示屏上。交换量包含2个或者2个以上的缓存区,主要包括前景缓存区和后台缓存区。缓存区里有设备渲染完成的纹理。(These are textures that the device renders to, for displaying on the monitor.)前台缓冲区存储的是现在在显示屏上显示的那部分内容,前台缓冲区内的数据已经是准好的(ready-only)且不可更改。后台缓存区则保存着设备接下来即将显示的内容。一旦后台缓存区的内容渲染完毕,交换链就通过交换2个缓存区的方式显示后台缓存的内容。后台缓存区就成了前台缓存区,以此类推。

To create the swap chain, we fill out a DXGI_SWAPCHAIN_DESC structure that describes the swap chain we are about to create. A few fields are worth mentioning. BackBufferUsage is a flag that tells the application how the back buffer will be used. In this case, we want to render to the back buffer, so we'll set BackBufferUsage to DXGI_USAGE_RENDER_TARGET_OUTPUT. 

为了创建一个交换链,我们需要填充一个名为DXGI_SWAPCHAIN_DESC的结构体,这个结构体的内容包含了我们需要创建的交换链的描述。有一点需要注意的是,BackBufferUsage是一个描述应用程序使用后台缓存方式的标识符。在这个例子中,我们想渲染后台缓存,所以我们把BackBufferUsage设置为DXGI_USAGE_RENDER_TARGET_OUTPUT.

The OutputWindow field represents the window that the swap chain will use to present images on the screen. SampleDesc is used to enable multi-sampling. Since this tutorial does not use multi-sampling, SampleDesc's Count is set to 1 and Quality to 0 to have multi-sampling disabled.

OutputWindow字段(field)代表着交换链将要把当前图像在显示屏上显示的窗口;SampleDesc用来设置是否开次多重采样(multi-sampling.因为这个例子里面不需要用到多重采样,所以把SampleDesc的值设为0(设置为1则为开启多重采样)

Once the description has been filled out, we can call the D3D10CreateDeviceAndSwapChaing function to create both the device and the swap chain for us. The code to create a device and a swap chain is listed below:

当交换链的结构体被填充完毕,我们就调用D3D10D3D10CreateDeviceAndSwapChaing函数来同时创建设备和交换链。下面是创建设备和交换链的代码:

    DXGI_SWAP_CHAIN_DESC sd;

    ZeroMemory( &sd, sizeof(sd) );

    sd.BufferCount = 1;

    sd.BufferDesc.Width = 640;

    sd.BufferDesc.Height = 480;

    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

    sd.BufferDesc.RefreshRate.Numerator = 60;

    sd.BufferDesc.RefreshRate.Denominator = 1;

    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

    sd.OutputWindow = g_hWnd;

    sd.SampleDesc.Count = 1;

    sd.SampleDesc.Quality = 0;

    sd.Windowed = TRUE;

    if( FAILED( D3D10CreateDeviceAndSwapChain( NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,

                     0, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ) ) )

    {

        return FALSE;

    }

The next thing that we need to do is to create a render target view. A render target view is a type of resource view in Direct3D 10. A resource view allows a resource to be bound to the graphics pipeline at a specific stage. Think of resource views as typecast in C. A chunk of raw memory in C can be cast to any data type. 接下来我们要做的事就是创建一个目标渲染视图/窗口。目标渲染视图是D3D10资源视图的一种。资源视图允许把一个资源绑定在渲染流水线的特殊状态。(A resource view allows a resource to be bound to the graphics pipeline at a specific stage. )把资源视图想象成C语言中的类型化,一个原始的内存区域可以被任意一种数据类型填充。

We can cast that chunk of memory to an array of integers, an array of floats, a structure, an array of structures, so on. The raw memory itself is not very useful to us if we don't know its type. Direct3D 10 resource views act in a similar way. For instance a 2D texture, analogous to the raw memory chunk, is the raw underlying resource. 我们可以把指定区域内的内存填充整数,浮点数组,一个结构体,一个结构体数组等等。如果我们不知道这块原始内存区域内数据的类型,那么它基本上是无用的。D3D10资源起类似的作用。比如说(For instance)一个2D纹理就好比一个内存块(memory chunk),是一个原始的基础资源。

Once we have that resource we can create different resource views to bind that texture to different stages in the graphics pipeline with different formats: as a render target to render to, as a depth stencil buffer that will receive depth information, or as a texture resource. Where C typecasts allow a memory chunk to be used in a different manner, so do Direct3D 10 resource views.

一旦我们拥有了一个2D纹理资源,那么我们可以创建不同的资源视图来把资源以不同的格式绑定在图形渲染流水线的不同状态上:比如说作为一个渲染不表来渲染,作为一个深度模板缓存(depth stencil buffer)来接受深度信息,或者只是作为一个纹理资源。和在C语言的模型化允许一个内存块被用在不同的组织方式上一样,Direct3D10的资源视图也是这样的。

We need to create a render target view because we would like to bind the back buffer of our swap chain as a render target, so that Direct3D 10 can render onto it. We first call GetBuffer() to obtain the back buffer object. Optionally, we can fill in a D3D10_RENDERTARGETVIEW_DESC structure that describes the render target view to be created. 我们需要创建一个渲染目标视图,因为我们需要把交换链的后台缓存作为渲染的目标,这样Direct3D10才可以在上面渲染。我们首先调用GetBuffer()函数来获得后台缓存对象。作为可选项,我们也可以填充一个描述渲染目标视图的名为D3D10_RENDERTARGETVIEW_DESC结构体。这个描述是函数CreatRenderTargetView函数的第二个参数。但是对于这些指南中的应用,默认的渲染目标视图已经足够。默认的渲染目标视图可以通过传递NULL值给第二个参数来获得。一旦我们创建了渲染目标视图,我们就可以调用OMSetRenderTargets()函数来把他绑定到流水线中,这样结果流水线渲染的输出就可以被写入后台缓存中。创建和设置渲染目标视图的代码如下:

This description is normally the second parameter to CreateRenderTargetView. However, for these tutorials, the default render target view will suffice. The default render target view can be obtained by passing NULL as the second parameter. Once we have created the render target view, we can call OMSetRenderTargets() to bind it to the pipeline so that the output that the pipeline renders gets written to the back buffer. The code to create and set the render target view is listed below:

    // Create a render target view

    ID3D10Texture2D *pBackBuffer;

    if( FAILED( g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pBackBuffer ) ) )

        return FALSE;

    hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );

    pBackBuffer->Release();

    if( FAILED( hr ) )

        return FALSE;

    g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );

The last thing that we need to set up before Direct3D 10 can render is initialize the viewport. The viewport maps clip space coordinates, where X and Y range from -1 to 1 and Z ranges from 0 to 1, to render target space, sometimes known as pixel space. In Direct3D 9, if the application does not set up a viewport, a default viewport is set up to be the same size as the render target. In Direct3D 10, no viewport is set by default. Therefore, we must do so before we can see anything on the screen. Since we would like to use the entire render target for the output, we set the top left point to (0, 0) and width and height to be identical to the render target's size. The code to do so is shown below:在我们的Direct3D10可以开始渲染前还有最后一件事:初始化视口/视点(viewport)。视口映射齐次坐标系(XY的范围为-11Z的范围为01)为了渲染目标空间有时被认为是像素空间。(The viewport maps clip space coordinates, where X and Y range from -1 to 1 and Z ranges from 0 to 1, to render target space, sometimes known as pixel space.)在D3D9中,如果应用程序没有设置一个视口,那么默认的视口将被设置为和渲染目标相同的尺寸。然而在D3D10中没有初始化默认视口,因此我们必须对其进行初始化操作。因为我们绝大多数情况下用全部的范围作为输出的渲染目标,因此我们把左上角设置为(00)而宽和高则设置的和渲染目标一致。实现上述操作的代码如下:

    D3D10_VIEWPORT vp;

    vp.Width = 640;

    vp.Height = 480;

    vp.MinDepth = 0.0f;

    vp.MaxDepth = 1.0f;

    vp.TopLeftX = 0;

    vp.TopLeftY = 0;

    g_pd3dDevice->RSSetViewports( 1, &vp );

Modifying the Message Loop

We have set up the window and Direct3D 10 device, and we are ready to render. However, there is still a problem with our message loop: it uses GetMessage() to obtain messages. The problem with GetMessage() is that if there is no message in the queue for the application window, GetMessage() blocks and does not return until a message is available. 

修改(Modifying)消息循环

我们已经成功创建了窗口和Direct3D10设备,现在我们已经准备开始绘制了。然而,这里还有一个问题,在我们的消息循环中使用GetMessage()函数来获取消息。使用GetMessage()函数的问题在于如果消息队列中没有应用程序的消息,函数将处于堵塞(Block)状态不会返回。

Thus, instead of doing something like rendering, our application is waiting within GetMessage() when the message queue is empty. We can solve this problem by using PeekMessage() instead of GetMessage(). PeekMessage() can retrieve a message like GetMessage() does, but when there is no message waiting, PeekMessage() returns immediately instead of blocking. We can then take this time to do some rendering. The modified message loop, which uses PeekMessage(), looks like this:因此,应用程序在GetMessage()没有返回的情况下处于等待状态而不是做像渲染之类的事。为了解决这一问题我们使用PeekMessage()函数来代替GetMessage()函数。PeekMessage()可以像GetMessage()一样获得消息,但是当消息队列中没有消息时,PeekMessage不是处于堵塞状态而是立即返回。我们可以利用这段时间来做一些渲染工作。修改后的消息循环代码如下:

    MSG msg = {0};

    while( WM_QUIT != msg.message )

    {

        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )

        {

            TranslateMessage( &msg );

            DispatchMessage( &msg );

        }

        else

        {

            Render();  // Do some rendering

        }

    }

The Rendering Code渲染实现代码

Rendering is done in the Render() function. In this tutorial, we will render the simplest scene possible, which is to fill the screen with a single color. In Direct3D 10, an easy way to fill the render target with a single color is to use the device's ClearRenderTargetView() method. We first define a D3D10_COLOR structure that describes the color we would like to fill the screen with, then pass it to ClearRenderTargetView(). In this example, a shade of blue is chosen. Once we have filled our back buffer, we call the swap chain's Present() method to complete the rendering. Present() is responsible for displaying the swap chain's back buffer content onto the screen so that the user can see it. The Render() function looks like below:

所有的渲染行为都是在Render()函数中进行的。在这个指南中,我们将渲染一个尽可能简单的场景,就是把窗口以一种单一的眼神填充,在Direct3D10中,一种用单一颜色填出目标区域的方法是使用ClearRenderTargetView()函数。我们首先定义一个D3D10_COLOR结构体来描述我们将要渲染的颜色,然后把他传递给ClearRenderTargetView()函数、在这个例子中,我们选择蓝色。一旦我们填充完后台缓存,调用交换链的Present()函数来完成渲染。Present()函数负责在屏幕是显示交换链后台缓存中的内容。Render()函数的代码如下:

    void Render()

    {

        //

        // Clear the backbuffer

        //

        float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f }; // RGBA

        g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );

    

        g_pSwapChain->Present( 0, 0 );

    }

  评论这张
 
阅读(478)| 评论(1)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017