zuze
Опытный
Offline
Пол:
Россия, Москва
|
|
« : 21-06-2009 15:22 » |
|
Сделать тень с помощью stencil-буфера, алгоритм вроде такой: 1. Очистка буферов z-буфера и трафарета; 2. Выводим объекты (объект) 3. Включение теста трафарета и маскирование части экрана с помощью операций с буфером трафарета; 4. Очистка z-буфера; 5. Вывод всей сцены с учетом трафаретной маски. Вот мой код функции рендеринга до теней// Функция рендеринга Direct3D void RenderingDirect3D(void) { if (pDirect3DDevice == NULL) return; // Очистка z-буфера pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(172, 221, 101), 1.0f, 0);
pDirect3DDevice->BeginScene();
pDirect3DDevice->SetStreamSource(0, pBufferVertices, 0, sizeof(TRIANGLEVERTEX)); pDirect3DDevice->SetIndices(pBufferIndexes); pDirect3DDevice->SetFVF(D3DFVF_TRIANGLEVERTEX);
pDirect3DDevice->SetTexture(1, NULL); // Установка идентификатора первой текстуры pDirect3DDevice->SetTexture(0, pTexture0); // Устанавливает состояния и операции первой текстуры pDirect3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);
pDirect3DDevice->SetTexture(0, NULL); // Установка идентификатора второй текстуры pDirect3DDevice->SetTexture (1, pTexture1); // Устанавливает состояния и операции второй текстуры pDirect3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix1(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);
pDirect3DDevice->EndScene();
pDirect3DDevice->Present(NULL, NULL, NULL, NULL); }
Вот мой код функции рендеринга и функции создания тени, но почему-то тени не появились, всё как было, так и осталось// Функция рендеринга Direct3D void RenderingDirect3D(void) { if (pDirect3DDevice == NULL) return; // Очистка z-буфера pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(172, 221, 101), 1.0f, 0);
// Очистка буфера трафарета (stencil) pDirect3DDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(255,255,255), 0.0f, 0);
pDirect3DDevice->BeginScene();
pDirect3DDevice->SetStreamSource(0, pBufferVertices, 0, sizeof(TRIANGLEVERTEX)); pDirect3DDevice->SetIndices(pBufferIndexes); pDirect3DDevice->SetFVF(D3DFVF_TRIANGLEVERTEX);
pDirect3DDevice->SetTexture(1, NULL); // Установка идентификатора первой текстуры pDirect3DDevice->SetTexture(0, pTexture0); // Устанавливает состояния и операции первой текстуры pDirect3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);
pDirect3DDevice->SetTexture(0, NULL); // Установка идентификатора второй текстуры pDirect3DDevice->SetTexture (1, pTexture1); // Устанавливает состояния и операции второй текстуры pDirect3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix1(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);
EnterStencilBuffer();
pDirect3DDevice->SetTexture(1, NULL); // Установка идентификатора первой текстуры pDirect3DDevice->SetTexture(0, pTexture0); // Устанавливает состояния и операции первой текстуры pDirect3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12);
pDirect3DDevice->SetTexture(0, NULL); // Установка идентификатора второй текстуры pDirect3DDevice->SetTexture (1, pTexture1); // Устанавливает состояния и операции второй текстуры pDirect3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); pDirect3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
Matrix1(); pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 36, 0, 12); // Установка нового режима обновления pDirect3DDevice->SetRenderState(D3DRS_STENCILREF, 1);
pDirect3DDevice->EndScene();
pDirect3DDevice->Present(NULL, NULL, NULL, NULL); } // Создание плоской тени (stencil Buffer) void EnterStencilBuffer(void) { // Включаем буфер трафарета (stencil) pDirect3DDevice->SetRenderState(D3DRS_STENCILENABLE, true); // Установка для трафарета операцию сравнения pDirect3DDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); // Установка режима обновления pDirect3DDevice->SetRenderState(D3DRS_STENCILREF, 0); // Установка маски сравнения pDirect3DDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); // Увеличить значение stencil-буфера на единицу pDirect3DDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR); pDirect3DDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR);
// Очистка z-буфера pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(172, 221, 101), 1.0f, 0); }
Что я сделал не так, почему нет теней?Есть мнение, что я не рассчитываю контурные ребра и не вытягиваю теневой объём.Хотя в книге "Advanced 3D Game Programming Using DirectX 9.0", главу 10, ничего про это не сказано. Там всего было написано всего два куска кода, не считая текста и вспомогательных таблиц. Вот код из книгиListing 10.20: Sample code to set up the stencil buffer for an overdraw counter // pDevice is a valid Direct3D Device // Turn on stenciling pDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); // Set the function to always pass. pDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); pDevice->SetRenderState( D3DRS_STENCILREF, 0 ); pDevice->SetRenderState( D3DRS_STENCILMASK, -1 ); // Always increment the stencil value pDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR ); pDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
Listing 10.21: Sample code to set up the stencil buffer for a wipe // Stencil is initially cleared to 0. // pDevice is a valid Direct3D Device pointer // Set up stencil states for the wipe polygon pDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); pDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); pDevice->SetRenderState( D3DRS_STENCILPASS,D3DSTENCILOP_INCR); pDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_NEVER ); pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); // Render the wipe polygon ... pDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_ALWAYS ); pDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ); pDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_EQUAL ); pDevice->SetRenderState( D3DRS_STENCILPASS,D3DSTENCILOP_KEEP); pDevice->SetRenderState( D3DRS_STENCILREF, 0 ); // Render the old scene ... pDevice->SetRenderState( D3DS_STENCILREF, 1 ); // Render the new scene ...
|