Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //-----------------------------------------------------------------------------
- // Name: dx9u_cgfx_volumetric_lines.cpp
- // Author: Adel Amro (adel_w_amro@hotmail.com)
- // Last Modified: May 24, 2013 by belfegor
- // Description: This sample demonstrates a technique for efficiently drawing
- // what is often called volume lines. These are quads oriented
- // and textured in such a way to be rendered as though they were
- // thick lines. This sample is based on the OpenGL sample from
- // Nvidia titled CG Volume Lines. It should work on low end
- // cards.
- //
- // Control Keys: Click and drag to spin the bunch of lines.
- // The + and - keys to control line thickness.
- // Page Down (PgDn) to cycle through available textures.
- // Arrow keys: Move the bunch of lines.
- //-----------------------------------------------------------------------------
- # define STRICT
- # define WIN32_LEAN_AND_MEAN
- #define D3D_DEBUG_INFO 1
- # include <windows.h>
- # include <d3dx9.h>
- #include <vector>
- #include <limits>
- #ifdef min
- #undef min
- #endif
- #ifdef max
- #undef max
- #endif
- // Instruct the linker to use these libraries.
- # pragma comment (lib, "d3d9.lib" )
- # pragma comment (lib, "d3dx9d.lib" )
- # define ARRAY_SIZE( x ) ( (sizeof((x))/sizeof((x)[0])) )
- inline FLOAT frand01() { return (FLOAT)rand()/RAND_MAX; }
- inline FLOAT frand( float fMin, float fMax ) { return fMin + (fMax - fMin) * ((float)rand()/RAND_MAX); }
- inline FLOAT frand() { return (float)rand()/RAND_MAX + rand(); }
- // Globals
- const std::size_t maxLinesCnt = 5;
- const std::size_t vertsPerLine = 4;
- const std::size_t triPerLine = 2;
- const std::size_t numVerts = maxLinesCnt * vertsPerLine;
- struct Line
- {
- D3DXVECTOR3 pt0;
- D3DXVECTOR3 pt1;
- };
- std::vector<Line> vLines;
- // Array of texture file names.
- const TCHAR* g_aFileNames[] = {
- TEXT( "1d_INNER1.png" ),
- TEXT( "1d_INNER2.png" ),
- TEXT( "1d_DEBUG.png" ),
- TEXT( "1d_DEBUG2.png" ),
- TEXT( "1d_glow1.png" )
- };
- HWND g_hWnd = NULL;
- LPDIRECT3D9 g_pD3D = NULL;
- LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
- LPDIRECT3DTEXTURE9 g_pTexture = NULL;
- LPD3DXEFFECT g_pEffect = NULL;
- D3DXVECTOR3 g_aLines[ maxLinesCnt ];
- INT g_iCurrentTexture = 0;
- FLOAT g_fThickness = 1.f;
- FLOAT g_fSpinX = 0.f;
- FLOAT g_fSpinY = 0.f;
- FLOAT g_fTX = 0.f;
- FLOAT g_fTY = 0.f;
- FLOAT g_fTZ = 14.f;
- D3DXMATRIX g_mProjection;
- // The vertex structure we'll be using for line drawing. Each line is defined as two vertices,
- // and the vertex shader will create a quad from these two vertices. However, since the vertex
- // shader can only process one vertex at a time, we need to store information in each vertex
- // about the other vertex (the other end of the line).
- struct TVertex
- {
- D3DXVECTOR3 pos;
- D3DXVECTOR3 otherPos;
- D3DXVECTOR4 texOffset;
- D3DXVECTOR3 thickness;
- //static const DWORD FVF = D3DFVF_XYZ | D3DFVF_NORMAL |
- // D3DFVF_TEX2 | // D3DFVF_TEX2 specifies we have two sets of texture coordinates.
- // D3DFVF_TEXCOORDSIZE4(0) | // This specifies that the first (0th) tex coord set has size 4 floats.
- // D3DFVF_TEXCOORDSIZE3(1); // Specifies that second tex coord set has size 2 floats.
- };
- D3DVERTEXELEMENT9 vertexElements[] =
- {
- {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
- {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
- {0, 24, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
- {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
- D3DDECL_END()
- };
- LPDIRECT3DVERTEXDECLARATION9 vDeclaration = nullptr;
- LPDIRECT3DVERTEXBUFFER9 vBuffer = nullptr;
- LPDIRECT3DINDEXBUFFER9 iBuffer = nullptr;
- // Prototypes
- INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, INT );
- LRESULT CALLBACK WindowProc( HWND, UINT, WPARAM, LPARAM );
- HRESULT Init();
- VOID ShutDown();
- VOID Render();
- // Application's entry point.
- INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd )
- {
- WNDCLASSEX winClass;
- MSG uMsg;
- memset(&uMsg,0,sizeof(uMsg));
- winClass.lpszClassName = TEXT("WC_DX9_VOLUMELINES");
- winClass.cbSize = sizeof(WNDCLASSEX);
- winClass.style = CS_HREDRAW | CS_VREDRAW;
- winClass.lpfnWndProc = WindowProc;
- winClass.hInstance = hInstance;
- winClass.hIcon = NULL;//LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
- winClass.hIconSm = NULL;//LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
- winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- winClass.lpszMenuName = NULL;
- winClass.cbClsExtra = 0;
- winClass.cbWndExtra = 0;
- if( !RegisterClassEx(&winClass) )
- return E_FAIL;
- RECT rWindow = { 0, 0, 1280, 720 };
- AdjustWindowRect( &rWindow, WS_OVERLAPPEDWINDOW, FALSE );
- g_hWnd = CreateWindowEx( NULL, winClass.lpszClassName,
- TEXT("Direct3D (DX9) - Volume Lines"),
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- 0, 0, rWindow.right - rWindow.left,
- rWindow.bottom - rWindow.top,
- NULL, NULL, hInstance, NULL );
- if( g_hWnd == NULL )
- return E_FAIL;
- ShowWindow( g_hWnd, nShowCmd );
- UpdateWindow( g_hWnd );
- if( FAILED( Init() ) )
- {
- MessageBox( g_hWnd, TEXT( "Direct3D initialization failure!" ), TEXT("ERROR!"), MB_OK | MB_ICONSTOP );
- return 1;
- }
- while( uMsg.message != WM_QUIT )
- {
- if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
- {
- TranslateMessage( &uMsg );
- DispatchMessage( &uMsg );
- }
- else
- Render();
- }
- ShutDown();
- UnregisterClass( winClass.lpszClassName, winClass.hInstance );
- return (INT)uMsg.wParam;
- }
- // Initialize the application.
- HRESULT Init()
- {
- HRESULT hr;
- g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
- if( !g_pD3D ) return E_FAIL;
- D3DDISPLAYMODE d3ddm;
- g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory( &d3dpp, sizeof(d3dpp) );
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = d3ddm.Format;
- d3dpp.EnableAutoDepthStencil = TRUE;
- d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
- d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // No need to burn the CPU.
- d3dpp.hDeviceWindow = g_hWnd;
- hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
- D3DCREATE_HARDWARE_VERTEXPROCESSING,
- &d3dpp, &g_pD3DDevice );
- if( FAILED( hr ) )
- return hr;
- // Load the texture.
- hr = D3DXCreateTextureFromFile( g_pD3DDevice, g_aFileNames[0], &g_pTexture );
- if( FAILED( hr ) )
- return hr;
- // Load the effect from file.
- LPD3DXBUFFER pErrors = NULL;
- hr = D3DXCreateEffectFromFile( g_pD3DDevice, TEXT("VolumeLines.fx"), NULL, NULL,
- 0, NULL, &g_pEffect, &pErrors );
- if( FAILED( hr ) )
- {
- if( pErrors )
- {
- MessageBoxA( g_hWnd, (LPCSTR)pErrors->GetBufferPointer(), "Effect error", MB_OK | MB_ICONSTOP );
- pErrors->Release();
- }
- return hr;
- }
- g_pEffect->SetTexture( "lineTexture", g_pTexture );
- //g_pEffect->SetTexture( "texture1", g_pTexture );
- // Set up some device states.
- D3DXMatrixPerspectiveFovLH( &g_mProjection, 45.f,
- (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight,
- 0.1f, 100.f );
- g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &g_mProjection );
- g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
- g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
- hr = g_pD3DDevice->CreateVertexDeclaration(vertexElements, &vDeclaration);
- if(FAILED(hr))
- {
- MessageBox(0, "CreateVertexDeclaration() failed!", 0, MB_OK);
- return E_FAIL;
- }
- D3DPOOL pool = D3DPOOL_DEFAULT;
- DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
- UINT len = sizeof(TVertex) * numVerts;
- hr = g_pD3DDevice->CreateVertexBuffer(len, usage, 0, pool, &vBuffer, nullptr);
- if(FAILED(hr))
- {
- MessageBox(0, "CreateVertexBuffer() failed!", 0, MB_OK);
- return E_FAIL;
- }
- D3DFORMAT indFormat = (std::numeric_limits<WORD>::max() < numVerts) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
- std::size_t indBytes = (std::numeric_limits<WORD>::max() < numVerts) ? sizeof(DWORD) : sizeof(WORD);
- std::size_t numIndices = maxLinesCnt * triPerLine * 3;
- len = indBytes * numIndices;
- hr = g_pD3DDevice->CreateIndexBuffer(len, usage, indFormat, pool, &iBuffer, nullptr);
- if(FAILED(hr))
- {
- MessageBox(0, "CreateIndexBuffer() failed!", 0, MB_OK);
- return E_FAIL;
- }
- WORD* pIndices = 0;
- iBuffer->Lock(0, 0, (LPVOID*)&pIndices, D3DLOCK_DISCARD);
- WORD j = 0;
- for(WORD i = 0; i < numIndices; i += 6)
- {
- pIndices[0+i] = 0+j;
- pIndices[1+i] = 2+j;
- pIndices[2+i] = 1+j;
- pIndices[3+i] = 2+j;
- pIndices[4+i] = 3+j;
- pIndices[5+i] = 1+j;
- j += 4;
- }
- iBuffer->Unlock();
- // Now create a random list of lines (pairs of vertices) that we will render
- srand( GetTickCount() );
- //for( UINT i=0; i<ARRAY_SIZE(g_aLines); i++ )
- for(std::size_t i = 0; i < maxLinesCnt; ++i)
- {
- //g_aLines[i].x = frand(-1, 1) * 5.f;
- //g_aLines[i].y = frand(-1, 1) * 5.f;
- //g_aLines[i].z = frand(-1, 1) * 5.f;
- Line l;
- l.pt0 = D3DXVECTOR3(frand(-1, 1) * 5.f, frand(-1, 1) * 5.f, frand(-1, 1) * 5.f);
- l.pt1 = D3DXVECTOR3(frand(-1, 1) * 5.f, frand(-1, 1) * 5.f, frand(-1, 1) * 5.f);
- vLines.push_back(l);
- }
- return S_OK;
- }
- // Free all resources.
- VOID ShutDown()
- {
- if(vBuffer) vBuffer->Release();
- if(iBuffer) iBuffer->Release();
- if(vDeclaration) vDeclaration->Release();
- if( g_pTexture ) g_pTexture->Release();
- if( g_pEffect ) g_pEffect->Release();
- if( g_pD3DDevice ) g_pD3DDevice->Release();
- if( g_pD3D ) g_pD3D->Release();
- }
- /*VOID RenderLine( D3DXVECTOR3& v0, D3DXVECTOR3& v1 )
- {
- TVertex vrts[4];
- vrts[0].pos = v0; vrts[0].otherPos = v1;
- vrts[1].pos = v1; vrts[1].otherPos = v0;
- vrts[2].pos = v0; vrts[2].otherPos = v1;
- vrts[3].pos = v1; vrts[3].otherPos = v0;
- vrts[0].thickness = D3DXVECTOR3( -g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[1].thickness = D3DXVECTOR3( g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[2].thickness = D3DXVECTOR3( g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[3].thickness = D3DXVECTOR3( -g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[0].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.f, 0.f );
- vrts[1].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.25f, 0.f );
- vrts[2].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.f, 0.25f );
- vrts[3].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.25f, 0.25f );
- g_pD3DDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vrts, sizeof( TVertex ) );
- }*/
- VOID RenderLines()
- {
- TVertex* vrts;
- vBuffer->Lock(0, 0, (LPVOID*)&vrts, D3DLOCK_DISCARD);
- std::size_t numTriDraw = 0u;
- std::size_t numVertDraw = 0u;
- for(std::size_t i = 0; i < maxLinesCnt; ++i)
- {
- if( i > maxLinesCnt)
- {
- vBuffer->Unlock();
- g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,0, numVertDraw, 0, numTriDraw);
- vBuffer->Lock(0, 0, (LPVOID*)&vrts, D3DLOCK_DISCARD);
- numTriDraw = 0u;
- }
- numTriDraw += triPerLine;
- numVertDraw += 4;
- const D3DXVECTOR3& v0 = vLines[i].pt0;
- const D3DXVECTOR3& v1 = vLines[i].pt1;
- vrts[i*4 + 0].pos = v0; vrts[i*4 + 0].otherPos = v1;
- vrts[i*4 + 1].pos = v1; vrts[i*4 + 1].otherPos = v0;
- vrts[i*4 + 2].pos = v0; vrts[i*4 + 2].otherPos = v1;
- vrts[i*4 + 3].pos = v1; vrts[i*4 + 3].otherPos = v0;
- vrts[i*4 + 0].thickness = D3DXVECTOR3( -g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[i*4 + 1].thickness = D3DXVECTOR3( g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[i*4 + 2].thickness = D3DXVECTOR3( g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[i*4 + 3].thickness = D3DXVECTOR3( -g_fThickness, 0.f, g_fThickness * 0.5f );
- vrts[i*4 + 0].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.f, 0.f );
- vrts[i*4 + 1].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.25f, 0.f );
- vrts[i*4 + 2].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.f, 0.25f );
- vrts[i*4 + 3].texOffset = D3DXVECTOR4( g_fThickness, g_fThickness, 0.25f, 0.25f );
- }
- vBuffer->Unlock();
- if(numTriDraw > 0u)
- {
- g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,0, numVertDraw, 0, numTriDraw);
- }
- }
- VOID Render()
- {
- g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,70), 1.f, 0 );
- if( SUCCEEDED( g_pD3DDevice->BeginScene() ) )
- {
- D3DXMATRIX mWorld;
- D3DXMATRIX mWorldProjection;
- D3DXMATRIX mTranslation;
- D3DXMATRIX mRotation;
- D3DXMatrixRotationYawPitchRoll( &mRotation, D3DXToRadian( g_fSpinX ),
- D3DXToRadian( g_fSpinY ), 0.f );
- D3DXMatrixTranslation( &mTranslation, g_fTX, g_fTY, g_fTZ );//0.f, 0.f, 14.f );
- mWorld = mRotation * mTranslation;
- mWorldProjection = mWorld * g_mProjection;
- // We will not be using a viewing transformation, so the view matrix will be identity.
- g_pEffect->SetMatrix( "mWV", &mWorld );
- g_pEffect->SetMatrix( "mWVP", &mWorldProjection );
- g_pD3DDevice->SetVertexDeclaration(vDeclaration);
- g_pD3DDevice->SetIndices(iBuffer);
- g_pD3DDevice->SetStreamSource(0, vBuffer, 0, sizeof(TVertex));
- UINT passes = 0;
- if( SUCCEEDED( g_pEffect->Begin( &passes, 0 ) ) )
- {
- g_pEffect->BeginPass( 0 );
- RenderLines();
- //g_pD3DDevice->SetFVF( TVertex::FVF );
- //for( UINT i=0; i < ARRAY_SIZE( g_aLines ) / 2; i++ )
- // RenderLine( g_aLines[i*2], g_aLines[i*2 + 1] );
- g_pEffect->EndPass();
- g_pEffect->End();
- }
- g_pD3DDevice->EndScene();
- }
- g_pD3DDevice->Present( NULL, NULL, NULL, NULL );
- }
- // The message procedure for the main window.
- LRESULT CALLBACK WindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
- {
- static POINT ptLastCursorPos;
- static POINT ptCurrentCursorPos;
- static BOOL bMousing = FALSE;
- switch( Msg )
- {
- case WM_CLOSE:
- PostQuitMessage( 0 );
- break;
- case WM_KEYDOWN:
- if( wParam == VK_ESCAPE )
- PostQuitMessage( 0 );
- else if( wParam == VK_NEXT )
- {
- // Cycle textures.
- g_iCurrentTexture = (g_iCurrentTexture+1)%ARRAY_SIZE(g_aFileNames);
- g_pTexture->Release();
- HRESULT hr = D3DXCreateTextureFromFile( g_pD3DDevice, g_aFileNames[ g_iCurrentTexture ],
- &g_pTexture );
- if( SUCCEEDED( hr ) )
- {
- g_pEffect->SetTexture( "lineTexture", g_pTexture );
- //g_pEffect->SetTexture( "texture1", g_pTexture );
- }
- else
- {
- MessageBox( g_hWnd, TEXT( "Couldn't open texture file!" ), TEXT("ERROR"), MB_OK | MB_ICONSTOP );
- PostQuitMessage( 0 );
- }
- }
- else if( wParam == VK_ADD )
- g_fThickness += 0.03f;
- else if( wParam == VK_SUBTRACT )
- g_fThickness -= 0.03f;
- else if( wParam == VK_LEFT )
- g_fTX += 0.5f;
- else if( wParam == VK_RIGHT )
- g_fTX -= 0.5f;
- else if( wParam == VK_UP )
- g_fTZ -= 0.5f;
- else if( wParam == VK_DOWN )
- g_fTZ += 0.5f;
- break;
- case WM_LBUTTONDOWN:
- ptLastCursorPos.x = ptCurrentCursorPos.x = LOWORD(lParam);
- ptLastCursorPos.y = ptCurrentCursorPos.y = HIWORD(lParam);
- bMousing = TRUE;
- // Set capture so we know when the user releases the left button even
- // if it's not over the window.
- SetCapture( hWnd );
- break;
- case WM_MOUSELEAVE: // Stop mousing if mouse button is released or cursor leaves window.
- case WM_LBUTTONUP:
- bMousing = FALSE;
- SetCapture( NULL );
- break;
- case WM_MOUSEMOVE:
- ptCurrentCursorPos.x = LOWORD( lParam );
- ptCurrentCursorPos.y = HIWORD( lParam );
- if( bMousing )
- {
- g_fSpinX -= (ptCurrentCursorPos.x - ptLastCursorPos.x) / 3;
- g_fSpinY -= (ptCurrentCursorPos.y - ptLastCursorPos.y) / 3;
- }
- ptLastCursorPos = ptCurrentCursorPos;
- break;
- }
- return DefWindowProc( hWnd, Msg, wParam, lParam );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement