使用 DirectX 渲染单独的纹理
Rendering separate textures using DirectX
我相信在某处有一个简单的答案。我目前有一个程序,可以将.png图像正确呈现为顶点矩形上的纹理。这一切都工作正常并正确显示。
我的问题是如何使用单独的图像在屏幕上渲染第二个纹理?最简单/最佳的方式(我知道它们可能不同!我要添加的第二张图像将用作背景图像。我尝试复制自定义顶点结构、顶点缓冲区、单独的顶点数据、平移矩阵、纹理阶段设置等。对于我想使用的第二个纹理,但我只能在屏幕上成功渲染一个纹理,有些东西被覆盖了。不幸的是,我仍在学习纹理,并且缺少正确的方法。甚至需要完全独立的顶点设置吗?
下面的代码反映了我到目前为止的工作代码,将图像显示为覆盖在顶点矩形上的纹理。我应该在设置中添加什么并为背景渲染单独的纹理?
//////////////////////////////////////////////////////
// I N V A D E R S
//////////////////////////////////////////////////////
#include <Windows.h> // Windows library (for window functions, menus, dialog boxes, etc)
#include <d3dx9.h> // Direct 3D library (for all Direct 3D functions).
//-----START-----DEFINE GLOBAL ELEMENTS----------//
LPDIRECT3D9 D3D_Object = NULL; // Name of the Direct3D Obeject. Used to create the D3DDevice
LPDIRECT3DDEVICE9 D3D_Device = NULL; // Name of the rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; // Buffer to hold vertices for the rectangle
LPDIRECT3DTEXTURE9 D3D_Tex_Background = NULL; // The texture for the background
LPDIRECT3DTEXTURE9 D3D_Tex_Invader = NULL; // The texture for the invader
float g_InvaderX = -50, g_InvaderY = 0, g_InvaderZ = 0; // starting cooordinates of object
// A structure for our custom vertex type, containing the vertex & texture coordinates
struct CUSTOMVERTEX
{
D3DXVECTOR3 position; // Vertex coordinates
FLOAT u, v; // Texture coordinates
};
// The structure of a vertex in our vertex buffer...
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1) // it will contain xyz coordinates & a texture
//////////////////////////////////////////////////////
// Setup Direct3D
//////////////////////////////////////////////////////
HRESULT SetupD3D(HWND hWnd)
{
// Create the D3D object.
if (NULL == (D3D_Object = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL;
// Set up the structure used to create the D3D Device
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE; // application will be windowed
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // back to front buffer behavior - DISCARD = random data used for error checking
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // back buffer format - UNKNOWN = use current display resolution to retain consistency
d3dpp.EnableAutoDepthStencil = TRUE; // D3D device to create and manage depth and stencil buffer automatically
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // format of the surfaces which hold the depth & stencil buffers - D16 = 16Bit colours
// Create the D3D Device - on successful completion return a pointer to the created device D3D_Device
if (FAILED(D3D_Object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &D3D_Device)))
{
return E_FAIL; // return error if D3D Device creation has failed
}
return S_OK;
}
//////////////////////////////////////////////////////
// DIRECT3D CLEANUP
//
// Release (delete) all the resources used by this program.
// Only release things if they are valid (i.e. have a valid pointer).
// If not, the program will crash at this point.
//////////////////////////////////////////////////////
void CleanUp()
{
// Delete the textures
if (D3D_Tex_Background != NULL) D3D_Tex_Background -> Release();
if (D3D_Tex_Invader != NULL) D3D_Tex_Invader -> Release();
// Release other D3D Device resources
if (g_pVertexBuffer != NULL) g_pVertexBuffer -> Release();
if (D3D_Device != NULL) D3D_Device -> Release();
if (D3D_Object != NULL) D3D_Object -> Release();
}
//////////////////////////////////////////////////////
// Setup the camera
//////////////////////////////////////////////////////
void SetupMatrices()
{
// Setup View Matrix
D3DXVECTOR3 vCamera(5.0f, 5.0f, -100.0f);
D3DXVECTOR3 vLookat(5.0f, 5.0f, 0.0f);
D3DXVECTOR3 vUpVector(0.0f, 1.0f, 0.0f);
D3DXMATRIX matrixView;
D3DXMatrixLookAtLH(&matrixView, &vCamera, &vLookat, &vUpVector);
D3D_Device -> SetTransform(D3DTS_VIEW, &matrixView);
// Setup Projection Matrix
// This transforms 2D geometry into a 3D space
D3DXMATRIX matrixProjection;
D3DXMatrixPerspectiveFovLH(&matrixProjection, D3DX_PI/4, 1.0f, 1.0f, 800.0f);
D3D_Device -> SetTransform(D3DTS_PROJECTION, &matrixProjection);
}
//////////////////////////////////////////////////////
// SETUP GEOMETRY -
// Define a square using the required verticies
//////////////////////////////////////////////////////
HRESULT SetupGeometry()
{
// Calculate the number of vertices required for the desired graphic
int Vertices = 2 * 3; // Six vertices required for the 2 triangles which make up the square.
// Calculate the size in bytes of the buffer which will hold the vertex information
// based on the number of verticies required and the elements contained within the CUSTOMVERTEX structure
int BufferSize = Vertices * sizeof(CUSTOMVERTEX);
// Create the vertex buffer which will store the vertex data to render
// (buffer size, special instructions, vertex buffer format, target memory location for buffer,pointer to vertex buffer, future use only)
if (FAILED(D3D_Device -> CreateVertexBuffer(BufferSize, 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer, NULL)))
{
return E_FAIL; // if the vertex buffer could not be created.
}
//////////////////////////////////////////////////////
// Fill vertex buffer with required vertex & texture info
//////////////////////////////////////////////////////
CUSTOMVERTEX *pVertices; // Create a pointer to the first vertex in the buffer.
if (FAILED(g_pVertexBuffer -> Lock(0, 0, (void**)&pVertices, 0))) // lock the buffer to prevent interference, allow access using the
{ // &pVerticies pointer
return E_FAIL; // if the pointer to the vertex buffer could not be established.
}
// Fill the vertex buffers with data concerning both vertex and texture locations
// Triangle 1
// Vertex 0
pVertices[0].position.x = 0; // Vertex coordinates
pVertices[0].position.y = 0;
pVertices[0].position.z = 0;
pVertices[0].u = 0; // texture coordinates
pVertices[0].v = 1;
// Vertex 1
pVertices[1].position.x = 0;
pVertices[1].position.y = 10;
pVertices[1].position.z = 0;
pVertices[1].u = 0;
pVertices[1].v = 0;
// Vertex 2
pVertices[2].position.x = 10;
pVertices[2].position.y = 0;
pVertices[2].position.z = 0;
pVertices[2].u = 1;
pVertices[2].v = 1;
// Triangle 2
// Vertex 3
pVertices[3].position.x = 10;
pVertices[3].position.y = 0;
pVertices[3].position.z = 0;
pVertices[3].u = 1;
pVertices[3].v = 1;
// Vertex 4
pVertices[4].position.x = 0;
pVertices[4].position.y = 10;
pVertices[4].position.z = 0;
pVertices[4].u = 0;
pVertices[4].v = 0;
// Vertex 5
pVertices[5].position.x = 10;
pVertices[5].position.y = 10;
pVertices[5].position.z = 0;
pVertices[5].u = 1;
pVertices[5].v = 0;
// Unlock the vertex buffer...
g_pVertexBuffer -> Unlock();
return S_OK;
}
//////////////////////////////////////////////////////
// Load the textures for the invaders and background
//////////////////////////////////////////////////////
void LoadTextures()
{
//D3DXCreateTextureFromFile(D3D_Device, // Direct3D Device name
// "background.jpg", // Source file in program folder
// &D3D_Tex_Background); // address of target texture object
D3DXCreateTextureFromFile(D3D_Device,
"invader300x300.png",
&D3D_Tex_Invader);
}
//////////////////////////////////////////////////////
// Render
//////////////////////////////////////////////////////
void Render()
{
// Clearing the current frame & Z buffers
// (rectangles to clear, rectangle coords, clear current buffer & Z buffer, RGB background colour of screen, initial z buffer value, initial
// stencil buffer value)
D3D_Device -> Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
// Once current frame has been cleared, begin drawing new frame
// lock is created at this point to prevent anything else drawing on the frame
if (SUCCEEDED(D3D_Device -> BeginScene()))
{
// Construct a translation matrix to move the Invader
D3DXMATRIX TranslateMatrix;
D3DXMatrixTranslation(&TranslateMatrix, g_InvaderX, g_InvaderY, g_InvaderZ);
D3D_Device -> SetTransform(D3DTS_WORLD, &TranslateMatrix);
// Render the contents of the vertex buffer.
D3D_Device -> SetStreamSource(0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX));
D3D_Device -> SetFVF(D3DFVF_CUSTOMVERTEX);
D3D_Device -> DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
// Select the invader texture, and initialise the texture stage state...
D3D_Device -> SetTexture(0, // the texture stage being set
D3D_Tex_Invader); // the object associated with the texture image
D3D_Device -> SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
D3D_Device -> SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
// Update the invader's x co-ordinate.
//if (g_RectX <=14.5)
g_InvaderX += 0.5f;
// Drawing of the scene has finished
D3D_Device -> EndScene();
}
// Present the back frame buffer contents to the screen (front frame buffer swaped with back fram buffer)
D3D_Device -> Present(NULL, NULL, NULL, NULL);
}
//////////////////////////////////////////////////////
// Windows Message Handling
//////////////////////////////////////////////////////
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//////////////////////////////////////////////////////
// Create the application window
//////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
// Register the window class
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"Invaders", NULL};
RegisterClassEx(&wc);
// Create the application window
HWND hWnd = CreateWindow( "Invaders", // Window class's name
"I N V A D E R S", // Title bar text
WS_OVERLAPPEDWINDOW, // The window style
100, // window horizontal position
500, // window vertical position
800, // window width
800, // window height
GetDesktopWindow(), // the parent window's module
NULL, // the window's menu handle
wc.hInstance, // the instance handle
NULL);
// Initialize Direct3D
if (SUCCEEDED(SetupD3D(hWnd)))
{
// Create the scene geometry
if (SUCCEEDED(SetupGeometry()))
{
// Load the required texture(s) from files into memeory
LoadTextures();
// Display the window onscreen
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Initialse the Viewpoint / Camera based on defined settings
SetupMatrices();
// Enter message loop to handle any messages MS Windows sends to the application
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Render();
}
}
}
CleanUp(); // release resources used ( delete all dynamically allocated objects)
UnregisterClass("Server", wc.hInstance);
return 0;
} // end WinMain
看来你需要对使用directx编程有更多的基本了解。尝试做一些这样的教程,它们非常有用。
对于您的具体问题:您似乎想用绘制在屏幕上的图像制作 2D 游戏。因此,使用 D3DFVF_XYZRHW
(doc) 更容易,因为您可以使用 2D 坐标渲染未转换的顶点。要渲染背景,请先绘制一个全屏大小的四边形,并应用您的图像。之后,您将在前面渲染您的船只。如果你的飞船没有被绘制,Mabye Z 缓冲确定你的背景在它前面,并将其剪掉。对于 2D 游戏,您可以停用 ZBuffering 或在顶点中设置深度。
相关文章:
- 如何在C++中从两个单独的for循环中添加两个数组
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- 用C++在单独的头文件中完成函数体
- 类模板的成员功能的定义在单独的TU中完全专业化
- SFML纹理像播放器
- 如何使用单独文件中的派生类访问友元函数对象
- CoInitialize()在单独的线程上崩溃而不返回
- OpenGL大的3D纹理(>2GB)非常慢
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- avrogencpp能为模式中的每种类型生成单独的头文件吗
- 着色器纹理值与创建纹理时写入的值不同
- OpenGL将纹理四边形渲染为(0,0)
- 宽度为奇数的16位纹理为片状
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- 单独定义模板化嵌套类方法的正确语法
- 如何将 2 个类分成单独的 .h 文件并正确设置它们
- C++ 链接到单独的.cpp文件说"multiple definitions"
- 如何在单独的线程上加载纹理到主内存并使用它在另一个线程上渲染
- OpenGL/ c++将所有纹理资源作为静态成员存储在一个单独的类中
- 使用 DirectX 渲染单独的纹理