C++-directx中如何让纹理刚好和窗口一样大显示?
这个是上次问的问题: directx旋转图片的问题
现在已经实现了纹理正反面贴不同的图(图你随便找两张一样大的就行了),下面是我的实现代码:
//=============================================================================
// Desc: 最简单的Direct3D程序,
//=============================================================================
#include <d3d9.h>
#pragma comment(lib,"d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib,"d3dx9.lib")
#include <tchar.h>
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9 g_pd3dVerText1 = NULL; //顶点缓冲区
LPDIRECT3DVERTEXBUFFER9 g_pd3dVerText2 = NULL; //顶点缓冲区
LPDIRECT3DTEXTURE9 g_pd3dTexture1 = NULL;
LPDIRECT3DTEXTURE9 g_pd3dTexture2 = NULL;
int g_nRotateY = 0; //实体的旋转角度
UINT_PTR g_nTimer = 0;
//定义FVF的顶点结构
struct CUSTOMVERTEXT
{
float x,y,z; //顶点坐标
float u,v; //纹理
};
//d定义FVF用到的数据项:坐标,颜色
#define D3DFVF_CUSTOMVERTEXT (D3DFVF_XYZ | D3DFVF_TEX1)
//该函数用于设置旋转矩阵
void SetupMatrices()
{
float angle = g_nRotateY*D3DX_PI/180; //把旋转角度换算成弧度
D3DXMATRIX matWorld;
//计算世界变化矩阵
D3DXMatrixRotationY(&matWorld,angle);
//把世界变换矩阵设置到渲染环境
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);
D3DXVECTOR3 eye(0.0f,0.0f,-4.0f); //观察点
D3DXVECTOR3 lookat(0.0f,0.0f,0.0f); //视线目标点
D3DXVECTOR3 up(0.0f,1.0f,0.0f); //上方向
D3DXMATRIX matView;
//计算视角变换矩阵
D3DXMatrixLookAtLH(&matView,&eye,&lookat,&up);
//把视角变换矩阵设置到渲染环境
g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
D3DXMATRIXA16 matProj;
//计算透视投影变换矩阵
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f);
//把投影变换矩阵设置到渲染环境
g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}
//-----------------------------------------------------------------------------
// Desc: 初始化Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
//创建Direct3D对象, 该对象用来创建Direct3D设备对象
if( NULL == ( g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
return E_FAIL;
//设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES;
//创建Direct3D设备对象
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
//因为使用顶点颜色渲染,所以要禁用光照
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
//关闭挑选功能,允许渲染背面
//g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
g_pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
return S_OK;
}
//建模
HRESULT BuildModel1()
{
//三角形尸体的数值模型
CUSTOMVERTEXT vertices[] =
{
//正面
{ -1.0f, -1.0f, 0.0f, 0.0f,1.0f}, // 点A,红色
{ -1.0f, 1.0f, 0.0f, 0.0f,0.0f}, //点B ,绿色
{ 1.0f, 1.0f, 0.0f, 1.0f,0.0f},
{ 1.0f, -1.0f, 0.0f, 1.0f,1.0f}
};//点C,浅蓝
//创建顶点缓冲区
if (FAILED( g_pd3dDevice->CreateVertexBuffer(
sizeof(vertices), //缓冲区尺寸
0,D3DFVF_CUSTOMVERTEXT,D3DPOOL_DEFAULT,&g_pd3dVerText1,NULL)))
{
return E_FAIL;
}
//将顶点数据填入顶点缓冲区
void* pVertices;
if (FAILED(g_pd3dVerText1->Lock(0,sizeof(vertices),(void**)&pVertices,0)))
{
return E_FAIL;
}
memcpy(pVertices,vertices,sizeof(vertices));
g_pd3dVerText1->Unlock();
if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,_T("z.png"),&g_pd3dTexture1)))
{
return E_FAIL;
}
return S_OK;
}
HRESULT BuildModel2()
{
//三角形尸体的数值模型
CUSTOMVERTEXT vertices[] =
{
//正面
{ -1.0f, -1.0f, 0.0f,1.0f,1.0f}, // 点A,红色
{ 1.0f, -1.0f, 0.0f,0.0f,1.0f}, //点B ,绿色
{ 1.0f, 1.0f, 0.0f,0.0f,0.0f},
{ -1.0f, 1.0f, 0.0f,1.0f,0.0f}
};//点C,浅蓝
//创建顶点缓冲区
if (FAILED( g_pd3dDevice->CreateVertexBuffer(
sizeof(vertices), //缓冲区尺寸
0,D3DFVF_CUSTOMVERTEXT,
D3DPOOL_DEFAULT,
&g_pd3dVerText2,NULL)))
{
return E_FAIL;
}
//将顶点数据填入顶点缓冲区
void* pVertices;
if (FAILED(g_pd3dVerText2->Lock(0,sizeof(vertices),(void**)&pVertices,0)))
{
return E_FAIL;
}
memcpy(pVertices,vertices,sizeof(vertices));
g_pd3dVerText2->Unlock();
if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,_T("f.png"),&g_pd3dTexture2)))
{
return E_FAIL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 释放创建对象
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if (g_pd3dTexture1 != NULL)
g_pd3dTexture1->Release();
if (g_pd3dTexture2 != NULL)
g_pd3dTexture2->Release();
if (g_pd3dVerText1 != NULL)
g_pd3dVerText1->Release();
if (g_pd3dVerText2 != NULL)
g_pd3dVerText2->Release();
//释放Direct3D设备对象
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
//释放Direct3D对象
if( g_pD3D != NULL)
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Desc: 渲染图形
//-----------------------------------------------------------------------------
VOID Render()
{
//清空后台缓冲区
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );
//开始在后台缓冲区绘制图形
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
//在此在后台缓冲区绘制图形
SetupMatrices();
//设置自定义的FVF
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEXT);
g_pd3dDevice->SetStreamSource(0,g_pd3dVerText2,0,sizeof(CUSTOMVERTEXT));
g_pd3dDevice->SetTexture(0,g_pd3dTexture2);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
g_pd3dDevice->SetStreamSource(0,g_pd3dVerText1,0,sizeof(CUSTOMVERTEXT));
g_pd3dDevice->SetTexture(0,g_pd3dTexture1);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
//结束在后台缓冲区渲染图形
g_pd3dDevice->EndScene();
}
//将在后台缓冲区绘制的图形提交到前台缓冲区显示
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
//
//-----------------------------------------------------------------------------
// Desc: 消息处理
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
{
KillTimer(hWnd,g_nTimer);
Cleanup();
PostQuitMessage( 0 );
return 0;
}
case WM_PAINT:
{
Render();
ValidateRect( hWnd, NULL );
return 0;
}
case WM_CREATE:
{
g_nTimer = SetTimer(hWnd,1,40,NULL);
}break;
case WM_TIMER:
{
g_nRotateY += 2; //每次旋转2度
InvalidateRect(hWnd,NULL,TRUE);
UpdateWindow(hWnd);
}break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Desc: 程序入口
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
//注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L"ClassName", NULL };
RegisterClassEx( &wc );
//创建窗口
HWND hWnd = CreateWindow( L"ClassName", L"最简单的Direct3D程序",
WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
NULL, NULL, wc.hInstance, NULL );
//初始化Direct3D
if( SUCCEEDED( InitD3D( hWnd ) ) && SUCCEEDED(BuildModel1()) && SUCCEEDED(BuildModel2()))
{
//显示主窗口
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
//进入消息循环
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(); //渲染图形
}
}
}
UnregisterClass( L"ClassName", wc.hInstance );
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
DirectX有提供2D绘制的操作吧。。。如果你一定要使用3D来绘制2D,那么就要弄清楚视口设置时的那几个参数的意义,DirectX我不太熟,不知道和OpenGL是不是一样的,在OpenGL中设置视口用的gluPerspective, 他的参数是
gluPerspective(
GLdouble fovy //角度,
GLdouble aspect,//视景体的宽高比
GLdouble zNear,//沿z轴方向的两裁面之间的距离的近处
GLdouble zFar //沿z轴方向的两裁面之间的距离的远处 )
根据这四个参数就可以手动计算出投影后与原图像相同的那一个z值,你看看在DirectX中有没有和这四个参数相近的。。。
对了,就算你计算出来了,绘制出来的图像也不会是平整的,因为还有一个高度的透视,所以图像的上下会显得窄一些。。。当然图像小的话看不出来。。。
画2D图像的时候直接关掉VertexShader,输入XYZRHW(名字差不多吧)这种类型的顶点,这是已经变换好的顶点类型,不经过顶点管线。位置就写[-0.5, -0.5, 0.1, 1.0], [-0.5, h-0.5, 0.1, 1.0], [w-0.5, -0.5, 0.1, 1.0], [w-0.5, h-0.5, 0.1, 1.0], -0.5像素的偏移可以让每一个像素都刚好对齐到贴图上的像素点。
另一种方法是输入[0, 0, 0.1, 1.0] [0, 1.0, 0.1, 1.0]这样的坐标,但不关闭Vertex处理;这时候需要把projectMatrix设置成平行投影矩阵,另外两个变换设成单位矩阵即可
代码太长,没仔细看,不过你要做的就是创建一个屏幕空间的mesh,也就是x,y是-1.1之间,z是0,1之间,w=1,不需要worldviewproj计算,shader里直接输出顶点即可,固定管线的话我没试过,或许直接设置单位矩阵吧