d3d9 使用模板测试绘制出镜子特效

1.Direct3D  9 渲染流水线


Vertex Data:在顶点buffer 中存储的没有转换的模型顶点。

Primitive Data:通过index buffer 可以在顶点数据中索引得到包括点,直线,三角形和多边形 的图形几何原型。

Tessellation: 

Vertex Processing: vertex buffer 中顶点的 Direct3D transformations 

Geometry Processing:transfromed 顶点的裁剪(Clipping),背面消隐(back face culling), attribute evaluation, and 光栅化(rasterization)操作。 

Textured Surface:通过IDirect3DTexture9 接口传入纹理坐标

Texture Sampler: 纹理

Pixel Processing: Pixel shader 中有关 修改顶点,纹理数据,产生输出像素颜色的 operations

Pix rendering:最后的渲染处理,配合alpha,深度(depth),或者模板检测,alpha 混合或者雾效等修改像素颜色数值。


implementation

下面用D3D 实现一个 模板检测的 镜子例子

 计算任意坐标点在平面 的反射点


  

首先 渲染整个场景,包括地表、墙、以及茶壶

	//
	// Make walls have low specular reflectance - 20%.
	//

	WallMtrl.Specular = d3d::WHITE * 0.2f;

	//
	// Create the teapot.
	//

	D3DXCreateTeapot(Device, &Teapot, 0);

	//
	// Create and specify geometry.  For this sample we draw a floor
	// and a wall with a mirror on it.  We put the floor, wall, and
	// mirror geometry in one vertex buffer.
	//
    //   |----|----|----|
    //   |Wall|Mirr|Wall|
	//   |    | or |    |
    //   /--------------/
    //  /   Floor      /
	// /--------------/
	//
	Device->CreateVertexBuffer(
		24 * sizeof(Vertex),
		0, // usage
		Vertex::FVF,
		D3DPOOL_MANAGED,
		&VB,
		0);

	Vertex* v = 0;
	VB->Lock(0, 0, (void**)&v, 0);

	// floor
	v[0] = Vertex(-7.5f, 0.0f, -10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[1] = Vertex(-7.5f, 0.0f,   0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
	v[2] = Vertex( 7.5f, 0.0f,   0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
	
	v[3] = Vertex(-7.5f, 0.0f, -10.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[4] = Vertex( 7.5f, 0.0f,   0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
	v[5] = Vertex( 7.5f, 0.0f, -10.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);

	// wall
	v[6]  = Vertex(-7.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[7]  = Vertex(-7.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[8]  = Vertex(-2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	
	v[9]  = Vertex(-7.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[10] = Vertex(-2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	v[11] = Vertex(-2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

	// Note: We leave gap in middle of walls for mirror

	v[12] = Vertex(2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[13] = Vertex(2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[14] = Vertex(7.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	
	v[15] = Vertex(2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[16] = Vertex(7.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	v[17] = Vertex(7.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

	// mirror
	v[18] = Vertex(-2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[19] = Vertex(-2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[20] = Vertex( 2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	
	v[21] = Vertex(-2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[22] = Vertex( 2.5f, 5.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	v[23] = Vertex( 2.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

	VB->Unlock();
	
	//
	// Load Textures, set filters.
	//

	D3DXCreateTextureFromFile(Device, L"checker.jpg", &FloorTex);
	D3DXCreateTextureFromFile(Device, L"brick0.jpg", &WallTex);
	D3DXCreateTextureFromFile(Device, L"ice.bmp", &MirrorTex);

	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

	//
	// Lights.
	//

	D3DXVECTOR3 lightDir(0.707f, -0.707f, 0.707f);
	D3DXCOLOR color(1.0f, 1.0f, 1.0f, 1.0f);
	D3DLIGHT9 light = d3d::InitDirectionalLight(&lightDir, &color);

	Device->SetLight(0, &light);
	Device->LightEnable(0, true);

	Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, true);

	//
	// Set Camera.
	//

	D3DXVECTOR3    pos(-10.0f, 3.0f, -15.0f);
	D3DXVECTOR3 target(0.0, 0.0f, 0.0f);
	D3DXVECTOR3     up(0.0f, 1.0f, 0.0f);

	D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &pos, &target, &up);

	Device->SetTransform(D3DTS_VIEW, &V);

	//
	// Set projection matrix.
	//
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
			&proj,
			D3DX_PI / 4.0f, // 45 - degree
			(float)Width / (float)Height,
			1.0f,
			1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;

然后渲染出镜子中的茶壶,分为一下几个步骤

1. 对模板buffer清空,设为0

2. 把镜子图元放入 模板buffer,并且设置测试条件为总是成功,并成功后替换值为1。 mask 表示测试 位 ffffffff, 如果仅仅测试末尾,则 mask = 0x01; 

3. 最后渲染反射的茶壶。测试条件为仅当模板buffer中的值为1,这样茶壶就只能渲染到镜子中。

4. reset render state


// Draw Mirror quad to stencil buffer ONLY.  In this way
	// only the stencil bits that correspond to the mirror will
	// be on.  Therefore, the reflected teapot can only be rendered
	// where the stencil bits are turned on, and thus on the mirror 
	// only.
	//

    Device->SetRenderState(D3DRS_STENCILENABLE,    true);
    Device->SetRenderState(D3DRS_STENCILFUNC,      D3DCMP_ALWAYS);
    Device->SetRenderState(D3DRS_STENCILREF,       0x1);
    Device->SetRenderState(D3DRS_STENCILMASK,      0xffffffff);
    Device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
    Device->SetRenderState(D3DRS_STENCILZFAIL,     D3DSTENCILOP_KEEP);
    Device->SetRenderState(D3DRS_STENCILFAIL,      D3DSTENCILOP_KEEP);
    Device->SetRenderState(D3DRS_STENCILPASS,      D3DSTENCILOP_REPLACE);

	// disable writes to the depth and back buffers
    Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
    Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

    // draw the mirror to the stencil buffer
	Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
	Device->SetFVF(Vertex::FVF);
	Device->SetMaterial(&MirrorMtrl);
	Device->SetTexture(0, MirrorTex);
	D3DXMATRIX I;
	D3DXMatrixIdentity(&I);
	Device->SetTransform(D3DTS_WORLD, &I);
	Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);

	// re-enable depth writes
	Device->SetRenderState( D3DRS_ZWRITEENABLE, true );

	// only draw reflected teapot to the pixels where the mirror
	// was drawn to.
	Device->SetRenderState(D3DRS_STENCILFUNC,  D3DCMP_EQUAL);
    Device->SetRenderState(D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP);

	// position reflection
	D3DXMATRIX W, T, R;
	D3DXPLANE plane(0.0f, 0.0f, 1.0f, 0.0f); // xy plane
	D3DXMatrixReflect(&R, &plane);

	D3DXMatrixTranslation(&T,
		TeapotPosition.x, 
		TeapotPosition.y,
		TeapotPosition.z); 

	W = T * R;

	// clear depth buffer and blend the reflected teapot with the mirror
	Device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
	Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_DESTCOLOR);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);

	// Finally, draw the reflected teapot
	Device->SetTransform(D3DTS_WORLD, &W);
	Device->SetMaterial(&TeapotMtrl);
	Device->SetTexture(0, 0);

	Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
	Teapot->DrawSubset(0);
	
	// Restore render states.
	Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	Device->SetRenderState( D3DRS_STENCILENABLE, false);
	Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);




Refference:

msdn.microsoft.com/en-us/library/windows/desktop/bb219679(v=vs.85).aspx

Introduce to 3D Game Programming with Directx9.0


directx 3d 实例#include #include "d3d9.h" #include "d3dx9.h" #include "Direct3D.h" // Direct3D objects IDirect3D9 *g_pD3D = NULL; IDirect3DDevice9 *g_pD3DDevice = NULL; // Sky vertex structure, fvf, vertex buffer, and texture typedef struct { float x, y, z, rhw; float u, v; } sSkyVertex; #define SKYFVF (D3DFVF_XYZRHW | D3DFVF_TEX1) IDirect3DVertexBuffer9 *g_SkyVB = NULL; IDirect3DTexture9 *g_SkyTexture = NULL; // Land and water meshes D3DXMESHCONTAINER_EX *g_WaterMesh = NULL; D3DXMESHCONTAINER_EX *g_LandMesh = NULL; // Window class and caption text char g_szClass[] = "TextureTransformationClass"; char g_szCaption[] = "Texture Transformation Demo by Jim Adams"; // Function prototypes int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow); long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Matrix4x4To3x3(D3DXMATRIX *matOut, D3DXMATRIX *matIn); BOOL DoInit(HWND hWnd, BOOL Windowed = TRUE); void DoShutdown(); void DoFrame(); int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow) { WNDCLASSEX wcex; MSG Msg; HWND hWnd; // Initialize the COM system CoInitialize(NULL); // Create the window class here and register it wcex.cbSize = sizeof(wcex); wcex.style = CS_CLASSDC; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInst; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = NULL; wcex.lpszClassName = g_szClass; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wcex)) return FALSE; // Create the main window hWnd = CreateWindow(g_szClass, g_szCaption, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 0, 0, 640, 480, NULL, NULL, hInst, NULL); if(!hWnd) return FALSE; ShowWindow(hWnd, SW_NORMAL); UpdateWindow(hWnd); // Call init function and enter message pump if(DoInit(hWnd) == TRUE) { // Start message pump, waiting for user to exit ZeroMemory(&Msg, sizeof(MSG)); while(Msg.message != WM_QUIT) { if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } // Render a single frame DoFrame(); } } // Call shutdown DoShutdown(); // Unregister the window class UnregisterClass(g_szClass, hInst); // Shut down the COM system CoUninitialize(); return 0; } long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, \ WPARAM wParam, LPARAM lParam) { // Only handle window destruction messages switch(uMsg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; } BOOL DoInit(HWND hWnd, BOOL Windowed) { // Initialize Direct3D InitD3D(&g_pD3D, &g_pD3DDevice, hWnd); // Load the land and water meshes LoadMesh(&g_WaterMesh, g_pD3DDevice, "..\\Data\\Water.x", "..\\Data\\"); LoadMesh(&g_LandMesh, g_pD3DDevice, "..\\Data\\Land.x", "..\\Data\\"); // Create the sky backdrop sSkyVertex SkyVerts[4] = { { 0.0f, 0.0, 1.0, 1.0f, 0.0f, 0.0f }, { 640.0f, 0.0, 1.0, 1.0f, 1.0f, 0.0f }, { 0.0f, 480.0, 1.0, 1.0f, 0.0f, 1.0f }, { 640.0f, 480.0, 1.0, 1.0f, 1.0f, 1.0f } }; g_pD3DDevice->CreateVertexBuffer(sizeof(SkyVerts), D3DUSAGE_WRITEONLY, SKYFVF, D3DPOOL_DEFAULT, &g_SkyVB, NULL); char *Ptr; g_SkyVB->Lock(0,0, (void**)&Ptr, 0); memcpy(Ptr, SkyVerts, sizeof(SkyVerts)); g_SkyVB->Unlock(); D3DXCreateTextureFromFile(g_pD3DDevice, "..\\Data\\Sky.bmp", &g_SkyTexture); // Setup a light D3DLIGHT9 Light; ZeroMemory(&Light, sizeof(Light)); Light.Diffuse.r = Light.Diffuse.g = Light.Diffuse.b = Light.Diffuse.a = 1.0f; Light.Type = D3DLIGHT_DIRECTIONAL; D3DXVECTOR3 vecLight = D3DXVECTOR3(-1.0f, -1.0f, 0.5f); D3DXVec3Normalize(&vecLight, &vecLight); Light.Direction = vecLight; g_pD3DDevice->SetLight(0, &Light); g_pD3DDevice->LightEnable(0, TRUE); // Start playing a waterfall sound PlaySound("..\\Data\\Waterfall.wav", NULL, SND_ASYNC | SND_LOOP); return TRUE; } void DoShutdown() { // Stop playing an ocean sound PlaySound(NULL, NULL, 0); // Free meshes delete g_WaterMesh; g_WaterMesh = NULL; delete g_LandMesh; g_LandMesh = NULL; // Release sky data ReleaseCOM(g_SkyVB); ReleaseCOM(g_SkyTexture); // Release D3D objects ReleaseCOM(g_pD3DDevice); ReleaseCOM(g_pD3D); } void DoFrame() { // Create and set the view transformation D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(360.0f, -170.0f, -430.0f), &D3DXVECTOR3(65.0f, 70.0f, -15.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView); // Clear the device and start drawing the scene g_pD3DDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0,0,64,255), 1.0, 0); if(SUCCEEDED(g_pD3DDevice->BeginScene())) { // Set identity matrix for world transformation D3DXMATRIX matWorld; D3DXMatrixIdentity(&matWorld); g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld); // Draw the sky g_pD3DDevice->SetFVF(SKYFVF); g_pD3DDevice->SetStreamSource(0, g_SkyVB, 0, sizeof(sSkyVertex)); g_pD3DDevice->SetTexture(0, g_SkyTexture); g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); // Enable lighting g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE); // Draw the land meshes DrawMeshes(g_LandMesh); // Setup the texture transformation float TimeFactor = (float)(timeGetTime() / 500.0f); D3DXMATRIX matTexture; D3DXMatrixTranslation(&matTexture, 0.0f, -TimeFactor, 0.0f); Matrix4x4To3x3(&matTexture, &matTexture); g_pD3DDevice->SetTransform(D3DTS_TEXTURE0, &matTexture); g_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); // Draw the water (using alpha blending) DrawMeshes(g_WaterMesh); g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); // Disable lighting g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); // Turn off texture transformations g_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); // End the scene g_pD3DDevice->EndScene(); } // Present the scene to the user g_pD3DDevice->Present(NULL, NULL, NULL, NULL); } void Matrix4x4To3x3(D3DXMATRIX *matOut, D3DXMATRIX *matIn) { matOut->_11 = matIn->_11; // Copy over 1st row matOut->_12 = matIn->_12; matOut->_13 = matIn->_13; matOut->_14 = 0.0f; matOut->_21 = matIn->_21; // Copy over 2nd row matOut->_22 = matIn->_22; matOut->_23 = matIn->_23; matOut->_24 = 0.0f; matOut->_31 = matIn->_41; // Copy bottom row matOut->_32 = matIn->_42; // used for translation matOut->_33 = matIn->_43; matOut->_34 = 0.0f; matOut->_41 = 0.0f; // Clear the bottom row matOut->_42 = 0.0f; matOut->_43 = 0.0f; matOut->_44 = 1.0f; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不负初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值