#include "dxstdafx.h" #include "media.h" #include ".\cameraeffects.h" CameraEffects::CameraEffects(void) { } CameraEffects::~CameraEffects(void) { } // Loads the selected mesh void CameraEffects::changeMesh(int meshid) { if(meshid!=currentmesh) { switch (meshid) { case 1: mesh->Load(pixelMESH0);break; case 2: mesh->Load(pixelMESH1);break; default: return; } currentmesh=meshid; mesh->computeTangent(); } } void CameraEffects::OnCreateDevice( IDirect3DDevice9* pd3dDevice) { this->pd3dDevice = pd3dDevice; mesh = new Mesh(pixelMESH0, 1, D3DXVECTOR3(0,0,0)); mesh->computeTangent(); // loading light sphere model lightmesh = new Mesh(L"Media\\Objects\\light.x", 1, D3DXVECTOR3(0,0,0)); ID3DXBuffer* errBuff = NULL; // loading simple rendering shaders if( FAILED(D3DXCreateEffectFromFile( pd3dDevice, L"shaders/BumpMapping.fx", NULL, NULL, NULL, NULL, &g_pEffect, &errBuff ))) { int BufSize = errBuff->GetBufferSize(); // displaying error message of arbitrary length wchar_t* wbuf = new wchar_t[BufSize]; mbstowcs( wbuf, (const char*)errBuff->GetBufferPointer(), BufSize ); MessageBox(NULL, wbuf, L".fx Compilation Error", MB_ICONERROR); // show error message delete wbuf; exit(-1); } // loading Depth Of Field shaders if( FAILED(D3DXCreateEffectFromFile( pd3dDevice, L"shaders/CameraEffects.fx", NULL, NULL, NULL, NULL, &g_pPostEffect, &errBuff ))) { int BufSize = errBuff->GetBufferSize(); // displaying error message of arbitrary length wchar_t* wbuf = new wchar_t[BufSize]; mbstowcs( wbuf, (const char*)errBuff->GetBufferPointer(), BufSize ); MessageBox(NULL, wbuf, L".fx Compilation Error", MB_ICONERROR); // show error message delete wbuf; exit(-1); } } void CameraEffects::OnDestroyDevice() { delete mesh; delete lightmesh; SAFE_RELEASE( g_pEffect ); SAFE_RELEASE( g_pPostEffect ); } void CameraEffects::OnResetDevice(D3DSURFACE_DESC* pBackBufferDesc) { m_ScreenWidth = pBackBufferDesc->Width; m_ScreenHeight = pBackBufferDesc->Height; if( g_pEffect ) g_pEffect->OnResetDevice(); // loading color texture D3DXCreateTextureFromFile( pd3dDevice, COLOR_TEXTURE_PATH, &ColorTexture ); // loading height map and converting to (RGB - normal, A - height) format without mipmap creation CreateBumpMap(false); // Create full-screen texture for post-process effects (RGB) FrameBufferTexture = new CDXTexture(); if (!FrameBufferTexture->InitTex(pd3dDevice, "framebuffer", m_ScreenWidth, m_ScreenHeight, D3DFMT_A8R8G8B8, false)) { MessageBox(NULL, L"FrameBufferTexture creation failed!",L"", MB_OK); } // create full-screen texture for post-process effects (blurriness, depth) FrameBufferDepthTexture = new CDXTexture(); if (!FrameBufferDepthTexture->InitTex(pd3dDevice, "framebufferdepth", m_ScreenWidth, m_ScreenHeight, D3DFMT_G16R16F, false)) { MessageBox(NULL, L"FrameBufferDepthTexture creation failed!",L"", MB_OK); } // create vertex buffer for full-screen quad pd3dDevice->CreateVertexBuffer(sizeof(float) * 18, D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_DEFAULT, &FullScreenQuad, 0); float* snipet; FullScreenQuad->Lock(0, 0, (void**)&snipet, D3DLOCK_DISCARD); int index = 0; snipet[index++] = -1; snipet[index++] = -1; snipet[index++] = 0; snipet[index++] = 1; snipet[index++] = 1; snipet[index++] = 0; snipet[index++] = 1; snipet[index++] = -1; snipet[index++] = 0; snipet[index++] = -1; snipet[index++] = -1; snipet[index++] = 0; snipet[index++] = -1; snipet[index++] = 1; snipet[index++] = 0; snipet[index++] = 1; snipet[index++] = 1; snipet[index++] = 0; FullScreenQuad->Unlock(); } void CameraEffects::OnLostDevice() { if( g_pEffect ) g_pEffect->OnLostDevice(); if( g_pPostEffect ) g_pPostEffect->OnLostDevice(); SAFE_RELEASE(DisplacementTexture); SAFE_RELEASE(ColorTexture); SAFE_RELEASE(FullScreenQuad); delete FrameBufferTexture; delete FrameBufferDepthTexture; } void CameraEffects::CreateBumpMap(bool createMipMaps) { D3DXIMAGE_INFO info; // height field is loaded into temporal texture LPDIRECT3DTEXTURE9 heightTex; D3DXCreateTextureFromFileEx( pd3dDevice, DISPLACEMENT_TEXTURE_PATH, D3DX_DEFAULT, D3DX_DEFAULT, createMipMaps ? D3DX_DEFAULT : 1, // mipmap levels 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, NULL, &info, NULL, &heightTex); // texture creation V(D3DXCreateTexture(pd3dDevice, info.Width, info.Height, createMipMaps ? D3DX_DEFAULT : 1, 0, D3DFMT_Q8W8V8U8, D3DPOOL_MANAGED, &DisplacementTexture)); // normal map számítás V(D3DXComputeNormalMap(DisplacementTexture, heightTex, NULL, 0, D3DX_CHANNEL_RED, 5.0f)); D3DLOCKED_RECT rect1, rect2; V(heightTex->LockRect(0, &rect2, 0, D3DLOCK_READONLY)); // // copy height map to DisplacementTexture's alpha channel // mipmap levels too, biased to [-128, +127] // int level = 0; while (createMipMaps ? (pow(2, level) <= info.Height) : (level == 0)) { V(DisplacementTexture->LockRect(level, &rect1, 0, 0)); char* target = (char*)rect1.pBits; unsigned char* source = (unsigned char*)rect2.pBits; int mul = (int)pow(2, level); for (unsigned int i = 0; i < info.Height / mul; i++) { for (unsigned int j = 0; j < info.Width / mul; j++) { int index1 = i * rect1.Pitch / 4 + j; int index2a = i * mul * rect2.Pitch / 4 + j * mul; int index2b = (i*mul+mul/2) * rect2.Pitch / 4+ j*mul; int index2c = i*mul * rect2.Pitch / 4+ j*mul + mul/2; int index2d = (i*mul+mul/2) * rect2.Pitch / 4 + j*mul + mul/2; target[index1 * 4 + 3] =(char)((source[4*index2a]+source[4*index2b]+source[4*index2c]+source[4*index2d]) / 8.0f); } } DisplacementTexture->UnlockRect(level); level++; } heightTex->UnlockRect(0); heightTex->Release(); } // prepares the depth of field filter kernel array void CameraEffects::SetupFilterKernel() { FLOAT dx = 1.0f / (FLOAT)m_ScreenWidth; FLOAT dy = 1.0f / (FLOAT)m_ScreenHeight; D3DXVECTOR4 v[12]; v[0] = D3DXVECTOR4(-0.326212f * dx, -0.405805f * dy, 0.0f, 0.0f); v[1] = D3DXVECTOR4(-0.840144f * dx, -0.07358f * dy, 0.0f, 0.0f); v[2] = D3DXVECTOR4(-0.695914f * dx, 0.457137f * dy, 0.0f, 0.0f); v[3] = D3DXVECTOR4(-0.203345f * dx, 0.620716f * dy, 0.0f, 0.0f); v[4] = D3DXVECTOR4(0.96234f * dx, -0.194983f * dy, 0.0f, 0.0f); v[5] = D3DXVECTOR4(0.473434f * dx, -0.480026f * dy, 0.0f, 0.0f); v[6] = D3DXVECTOR4(0.519456f * dx, 0.767022f * dy, 0.0f, 0.0f); v[7] = D3DXVECTOR4(0.185461f * dx, -0.893124f * dy, 0.0f, 0.0f); v[8] = D3DXVECTOR4(0.507431f * dx, 0.064425f * dy, 0.0f, 0.0f); v[9] = D3DXVECTOR4(0.89642f * dx, 0.412458f * dy, 0.0f, 0.0f); v[10] = D3DXVECTOR4(-0.32194f * dx, -0.932615f * dy, 0.0f, 0.0f); v[11] = D3DXVECTOR4(-0.791559f * dx, -0.597705f * dy, 0.0f, 0.0f); g_pPostEffect->SetVectorArray("filterTaps", v, 12); } // rendering void CameraEffects::OnFrameRender( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ) { // setting the full screen-textures as render targets 0 and 1 FrameBufferTexture->StartRender(true, 0); FrameBufferDepthTexture->StartRender(false, 1); // clear screen D3DCOLOR backgroundColor = D3DCOLOR_ARGB(0, 66, 75, 121); V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, backgroundColor, 1.0f, 0) ); // setting up matrices D3DXMATRIXA16 mWorld; D3DXMatrixTranslation(&mWorld,LightPos->x,LightPos->y,LightPos->z); pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProj ); pd3dDevice->SetTransform( D3DTS_WORLD, &mWorld ); pd3dDevice->SetTransform( D3DTS_VIEW, &mView ); // draw light source lightmesh->Draw(); D3DXMATRIX Trans, Rot; D3DXMatrixTranslation(&Trans, 0, 0, -27); D3DXMatrixRotationY(&Rot, 3.1415792); D3DXMatrixMultiply(&mWorld, &Trans, &Rot); SetWorldViewProj(mWorld,mView,mProj); // LightPos and CameraPos is needed in Model Space in shader D3DXVECTOR4 mEye, mLight, wEye, wLight; wEye = D3DXVECTOR4(camera->GetEyePt()->x,camera->GetEyePt()->y,camera->GetEyePt()->z, 1.0f); wLight=D3DXVECTOR4(LightPos->x, LightPos->y, LightPos->z, 1.0f); D3DXVec4Transform(&mEye, &wEye, &m_InvWorld); D3DXVec4Transform(&mLight, &wLight, &m_InvWorld); // setting shader parameters D3DSURFACE_DESC desc; DisplacementTexture->GetLevelDesc(0,&desc); g_pEffect->SetTexture("BumpMap", DisplacementTexture); g_pEffect->SetTexture("ColorMap", ColorTexture); g_pEffect->SetFloat("focalDist", params->Get(fFocalDistance)); g_pEffect->SetFloat("focalRange", 0.1f); float lp[] = {mLight.x, mLight.y, mLight.z}; g_pEffect->SetFloatArray("mLightPos", lp, 3); float cp[] = {mEye.x, mEye.y, mEye.z}; g_pEffect->SetFloatArray("mCameraPos", cp, 3); g_pEffect->CommitChanges(); g_pEffect->SetTechnique("BumpMapping"); UINT p; g_pEffect->Begin(&p, 0 ); g_pEffect->BeginPass( 0 ); mesh->Draw(); g_pEffect->EndPass(); g_pEffect->End(); FrameBufferTexture->EndRender(); FrameBufferDepthTexture->EndRender(); // doing DoF post-processing pd3dDevice->SetStreamSource(0, FullScreenQuad, 0, sizeof(float) * 3); pd3dDevice->SetFVF(D3DFVF_XYZ); g_pPostEffect->SetTexture("ColorMap", FrameBufferTexture->m_Tex); g_pPostEffect->SetTexture("DepthMap", FrameBufferDepthTexture->m_Tex); SetupFilterKernel(); g_pPostEffect->CommitChanges(); g_pPostEffect->SetTechnique("DepthOfField"); g_pPostEffect->Begin(&p, 0 ); g_pPostEffect->BeginPass( 0 ); // drawing full-screen quad pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); g_pPostEffect->EndPass(); g_pPostEffect->End(); } void CameraEffects::addUiParams(Parameters& p) { params=&p; p.Add( fFocalDistance, "Focal Distance", 100, convertToZeroTo30 ); //p.Add( fDisplacementScale, "Scale", 100, convertToMinusOne_One ); } void CameraEffects::SetWorldViewProj(D3DXMATRIXA16& mWorld, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ) { D3DXMatrixInverse(&m_InvWorld,0,&mWorld); // inverse matrix D3DXMATRIXA16 mWorldView = mWorld * mView; D3DXMATRIXA16 mWorldViewProjection = mWorldView * mProj; D3DXMATRIXA16 mWorldViewI, mWorldViewIT; D3DXMatrixInverse(&mWorldViewI, NULL, &mWorldView); D3DXMatrixTranspose(&mWorldViewIT, &mWorldViewI); V( g_pEffect->SetMatrix( "WorldView", &mWorldView ) ); V( g_pEffect->SetMatrix( "WorldViewIT", &mWorldViewIT ) ); V( g_pEffect->SetMatrix( "WorldViewProj", &mWorldViewProjection ) ); V( g_pEffect->CommitChanges() ); }