#include "dxstdafx.h" #include ".\hreeffect.h" struct ProcessedTriangle //< a vertex encoding a triangle { Vector sphereCentre; //< endclosig sphere centre : POSITION.xyz float radius; //< endclosing sphere radius : POSITION.w Vector planePos; //< triangle plane point nearest to origin : NORMAL Vector inverseVertexMatrix[3]; //< Cartesian-to-barycentric transformation matrix : TEXCOORD0-2 Vector normals[3]; //< model normals at triangle vertices : TEXCOORD3-5 Vector tex[3]; //< model texture coords at triangle vertices : TEXCOORD6-8 }; //! D3D vector-matrix multiplication D3DVECTOR operator *(const D3DVECTOR& v, const D3DMATRIX& m) { D3DVECTOR r; r.x = v.x * m._11 + v.y * m._21 + v.z * m._31 + m._41; r.y = v.x * m._12 + v.y * m._22 + v.z * m._32 + m._42; r.z = v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43; float h = v.x * m._14 + v.y * m._24 + v.z * m._34 + m._44; if(h > 0.00001f || h < 0.00001f) { r.x /= h; r.y /= h; r.z /= h; } return r; } //! method name strings to be displayed on screen const wchar_t* HREEffect::Method::methodNames[10] = { L"Ray Engine", L"_", L"_", L"_" , NULL, NULL, NULL, NULL, NULL, NULL }; //! method constants const HREEffect::Method HREEffect::Method::RAYENGINE(0); const HREEffect::Method HREEffect::Method::LAST(1); HREEffect::HREEffect(LPDIRECT3DDEVICE9 device) :method(Method::RAYENGINE) { this->device = device; //first person camera allows more freedom of movement camera = new CFirstPersonCamera(); lightCamera = new CFirstPersonCamera(); HRESULT hr; DWORD effectCompileFlag=0; LPD3DXBUFFER compilationErrors; if(FAILED( hr = D3DXCreateEffectFromFile( device, L"rayEngine.fx", NULL, NULL, 0, NULL, &effect, &compilationErrors) )){ MessageBoxA( NULL, (LPSTR)compilationErrors->GetBufferPointer(), "Failed to load effect file!", MB_OK); exit(-1); } //store buffers so we can reset them after rendering to texture render targets device->GetRenderTarget(0, &frameColorBuffer); device->GetDepthStencilSurface(&frameDepthStencilBuffer); camera->SetViewParams( &D3DXVECTOR3(0.0f, 0.0f, 4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f)); D3DSURFACE_DESC fbdesc; frameColorBuffer->GetDesc(&fbdesc); camera->SetProjParams( D3DX_PI/2, (float)fbdesc.Width / fbdesc.Height, 0.1f, 300.0f ); hr = D3DXCreateCubeTextureFromFile(device, L"media//uffizi_lowrange.dds", &environmentCubeTexture); hr=device->CreateTexture(RAY_TABLE_WIDTH / 16,RAY_TABLE_HEIGHT / 16,1,D3DUSAGE_RENDERTARGET,D3DFMT_A32B32G32R32F,D3DPOOL_DEFAULT,&conePeakTexture,NULL); hr=conePeakTexture->GetSurfaceLevel(0,&conePeakSurface); hr=device->CreateTexture(RAY_TABLE_WIDTH / 16,RAY_TABLE_HEIGHT / 16,1,0,D3DFMT_A32B32G32R32F,D3DPOOL_SYSTEMMEM,&conePeakTextureMem,NULL); hr=conePeakTextureMem->GetSurfaceLevel(0,&conePeakSurfaceMem); hr=device->CreateTexture(RAY_TABLE_WIDTH / 16,RAY_TABLE_HEIGHT / 16,1,D3DUSAGE_RENDERTARGET,D3DFMT_A32B32G32R32F,D3DPOOL_DEFAULT,&coneDirTexture,NULL); hr=coneDirTexture->GetSurfaceLevel(0,&coneDirSurface); hr=device->CreateTexture(RAY_TABLE_WIDTH / 16,RAY_TABLE_HEIGHT / 16,1,0,D3DFMT_A32B32G32R32F,D3DPOOL_SYSTEMMEM,&coneDirTextureMem,NULL); hr=coneDirTextureMem->GetSurfaceLevel(0,&coneDirSurfaceMem); hr=device->CreateTexture(RAY_TABLE_WIDTH,RAY_TABLE_HEIGHT,1,D3DUSAGE_RENDERTARGET,RAY_ORIGIN_COLOR_FORMAT,D3DPOOL_DEFAULT,&rayOriginTableTexture,NULL); hr=rayOriginTableTexture->GetSurfaceLevel(0,&rayOriginTableSurface); hr=device->CreateTexture(RAY_TABLE_WIDTH,RAY_TABLE_HEIGHT,1,D3DUSAGE_RENDERTARGET,RAY_DIR_COLOR_FORMAT,D3DPOOL_DEFAULT,&rayDirTableTexture,NULL); hr=rayDirTableTexture->GetSurfaceLevel(0,&rayDirTableSurface); hr=device->CreateTexture(RAY_TABLE_WIDTH,RAY_TABLE_HEIGHT,1,D3DUSAGE_RENDERTARGET,RAY_ORIGIN_COLOR_FORMAT,D3DPOOL_DEFAULT,&rayOriginTableTexture2,NULL); hr=rayOriginTableTexture2->GetSurfaceLevel(0,&rayOriginTableSurface2); hr=device->CreateTexture(RAY_TABLE_WIDTH,RAY_TABLE_HEIGHT,1,D3DUSAGE_RENDERTARGET,RAY_DIR_COLOR_FORMAT,D3DPOOL_DEFAULT,&rayDirTableTexture2,NULL); hr=rayDirTableTexture2->GetSurfaceLevel(0,&rayDirTableSurface2); device->CreateDepthStencilSurface(RAY_TABLE_WIDTH / 16,RAY_TABLE_HEIGHT / 16,DEPTH_FORMAT,D3DMULTISAMPLE_NONE,0,false,&coneStencil,NULL); device->CreateDepthStencilSurface(RAY_TABLE_WIDTH,RAY_TABLE_HEIGHT,DEPTH_FORMAT,D3DMULTISAMPLE_NONE,0,false,&depthSurface,NULL); D3DVERTEXELEMENT9 trianglePrimitiveDeclElements[] = { {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION , 0}, {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL , 0}, {0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 0}, {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 1}, {0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 2}, {0, 64, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 3}, {0, 76, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 4}, {0, 88, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 5}, {0, 100, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 6}, {0, 112, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 7}, {0, 124, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD , 8}, D3DDECL_END() }; hr = device->CreateVertexDeclaration(trianglePrimitiveDeclElements, &trianglePrimitiveDeclaration); //load empty texture D3DXCreateTextureFromFile(device, L"media\\empty.bmp", &emptyTexture); //set up a scene loadMesh( L"media\\pillow.x" ); loadMesh( L"media\\torus.x" ); Entity e1; e1.owner = this; e1.mesh = meshes.at(0); D3DXMatrixIdentity(&e1.modelWorldTransform); D3DXMatrixIdentity(&e1.inverseTransposedModelWorldTransform); entities.push_back(e1); Entity e2; e2.owner = this; e2.mesh = meshes.at(1); D3DXMatrixIdentity(&e2.modelWorldTransform); D3DXMatrixTranslation(&e2.modelWorldTransform, 5.0, 0.0, 0.0); D3DXMatrixInverse( &e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform); D3DXMatrixTranspose( &e2.inverseTransposedModelWorldTransform, &e2.inverseTransposedModelWorldTransform); entities.push_back(e2); } HREEffect::~HREEffect(void) { rayOriginTableSurface->Release(); rayOriginTableTexture->Release(); rayDirTableSurface->Release(); rayDirTableTexture->Release(); depthSurface->Release(); rayOriginTableSurface2->Release(); rayOriginTableTexture2->Release(); rayDirTableSurface2->Release(); rayDirTableTexture2->Release(); environmentCubeTexture->Release(); conePeakSurface->Release(); conePeakTexture->Release(); coneDirSurface->Release(); coneDirTexture->Release(); emptyTexture->Release(); releaseTextures(); releaseMeshes(); releaseEntities(); frameColorBuffer->Release(); frameDepthStencilBuffer->Release(); effect->Release(); delete camera; delete lightCamera; } void HREEffect::loadMesh(LPCWSTR fileName) { Mesh* renderMesh = new Mesh(); if(S_OK != D3DXLoadMeshFromX( fileName, D3DXMESH_MANAGED, device, NULL, &renderMesh->materialBuffer, NULL, (DWORD*)&renderMesh->nSubsets, &renderMesh->mesh)) { MessageBox(NULL, fileName, L"Could not load mesh file!", MB_OK); return; } //convert mesh into a vertex format using a position, a normal and a texture register //this is the only data our vertex shaders will require renderMesh->setVertexFormat(D3DFVF_XYZ | D3DFVF_NORMAL, device); //extract the D3DXMATERIAL* pointer from the generic D3DXBUFFER renderMesh->materials = (D3DXMATERIAL*)renderMesh->materialBuffer->GetBufferPointer(); //for every material, load the specified texture renderMesh->textures = new LPDIRECT3DTEXTURE9[renderMesh->nSubsets]; for(unsigned int i=0; inSubsets; i++) { wchar_t* wideTextureFileName = NULL; if(renderMesh->materials[i].pTextureFilename) { wideTextureFileName = new wchar_t[MultiByteToWideChar(CP_ACP, 0, renderMesh->materials[i].pTextureFilename, -1, NULL, 0)]; MultiByteToWideChar(CP_ACP, 0, renderMesh->materials[i].pTextureFilename, -1, wideTextureFileName, 511); } renderMesh->textures[i] = loadTexture( wideTextureFileName ); if(wideTextureFileName) delete wideTextureFileName; } { ProcessedTriangle *tris; device->CreateVertexBuffer(renderMesh->mesh->GetNumFaces() * sizeof(ProcessedTriangle), D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &renderMesh->primitiveVertexBuffer, NULL); renderMesh->primitiveVertexBuffer->Lock(0, 0, (void**)&tris, 0); LPDIRECT3DVERTEXBUFFER9 vertexBuffer; renderMesh->mesh->GetVertexBuffer(&vertexBuffer); unsigned int nVertices = renderMesh->mesh->GetNumVertices(); unsigned int nFaces = renderMesh->mesh->GetNumFaces(); struct D3DVERTEX{ D3DXVECTOR3 pos; D3DXVECTOR3 normal; }; D3DVERTEX* vertices; vertexBuffer->Lock(0, 0, (void**)&vertices, 0); LPDIRECT3DINDEXBUFFER9 indexBuffer; renderMesh->mesh->GetIndexBuffer(&indexBuffer); unsigned short* indices; indexBuffer->Lock(0, 0, (void**)&indices, 0); for(int i=0; i < nFaces; i++) { Vector A[3]; A[0] = Vector(vertices[indices[i*3]].pos); A[1] = Vector(vertices[indices[i*3+1]].pos); A[2] = Vector(vertices[indices[i*3+2]].pos); float t4 = A[0][0]*A[1][1]; float t6 = A[0][0]*A[1][2]; float t8 = A[0][1]*A[1][0]; float t10 = A[0][2]*A[1][0]; float t12 = A[0][1]*A[2][0]; float t14 = A[0][2]*A[2][0]; float t17 = 1/(t4*A[2][2]-t6*A[2][1]-t8*A[2][2]+t10*A[2][1]+t12*A[1][2]-t14*A[1][1]); // if(_isnan (t17) ) // AfxMessageBox("mtx inversion gbz"); Vector* m = tris[i].inverseVertexMatrix; m[0][0] = (A[1][1]*A[2][2]-A[1][2]*A[2][1])*t17; m[1][0] = -(A[0][1]*A[2][2]-A[0][2]*A[2][1])*t17; m[2][0] = -(-A[0][1]*A[1][2]+A[0][2]*A[1][1])*t17; m[0][1] = -(A[1][0]*A[2][2]-A[1][2]*A[2][0])*t17; m[1][1] = (A[0][0]*A[2][2]-t14)*t17; m[2][1] = -(t6-t10)*t17; m[0][2] = -(-A[1][0]*A[2][1]+A[1][1]*A[2][0])*t17; m[1][2] = -(A[0][0]*A[2][1]-t12)*t17; m[2][2] = (t4-t8)*t17; Vector c = A[0] - A[1]; Vector b = A[0] - A[2]; Vector a = A[1] - A[2]; Vector trinormal = a && b; trinormal.normalize(); float s = trinormal * A[0]; Vector triPlanePos = trinormal * s; tris[i].planePos = triPlanePos; tris[i].normals[0] = Vector(vertices[indices[i*3]].normal); tris[i].normals[1] = Vector(vertices[indices[i*3+1]].normal); tris[i].normals[2] = Vector(vertices[indices[i*3+2]].normal); float a2 = a.norm2(); float b2 = b.norm2(); float c2 = c.norm2(); float wa = a2 * (b2 + c2 - a2); float wb = b2 * (a2 + c2 - b2); float wc = c2 * (a2 + b2 - c2); float wsum = wa+wb+wc; Vector spcen = A[0] * (wa / wsum); spcen += A[1] * (wb / wsum); spcen += A[2] * (wc / wsum); Vector cTriNormal = Vector( tris[i].inverseVertexMatrix[0].x + tris[i].inverseVertexMatrix[1].x + tris[i].inverseVertexMatrix[2].x, tris[i].inverseVertexMatrix[0].y + tris[i].inverseVertexMatrix[1].y + tris[i].inverseVertexMatrix[2].y, tris[i].inverseVertexMatrix[0].z + tris[i].inverseVertexMatrix[1].z + tris[i].inverseVertexMatrix[2].z ); cTriNormal *= 1.0 / cTriNormal.norm2(); tris[i].sphereCentre = spcen; tris[i].radius = (spcen - A[0]).norm(); } renderMesh->primitiveVertexBuffer->Unlock(); vertexBuffer->Unlock(); indexBuffer->Unlock(); vertexBuffer->Release(); indexBuffer->Release(); } //store completed mesh meshes.push_back(renderMesh); } LPDIRECT3DTEXTURE9 HREEffect::loadTexture(LPCWSTR fileName) { if(fileName == NULL || wcscmp(fileName, L"") == 0) return NULL; wchar_t* mediaFileName = new wchar_t[wcslen(fileName) + 64]; //we assume the x file was in folder .\media wcscpy(mediaFileName, L"media\\"); wcscat(mediaFileName, fileName); LPDIRECT3DTEXTURE9 tex; D3DXIMAGE_INFO bobo; if(S_OK != D3DXCreateTextureFromFileEx(device, mediaFileName, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_FROM_FILE, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, &bobo, NULL, &tex )) { MessageBox(NULL, mediaFileName, L"Could not load texture file!", MB_OK); return NULL; } materialTextures.push_back(tex); return tex; } void HREEffect::releaseTextures() { std::vector::iterator i = materialTextures.begin(); while(i != materialTextures.end()) { (*i)->Release(); i++; } } void HREEffect::releaseMeshes() { std::vector::iterator i = meshes.begin(); while(i != meshes.end()) { (*i)->mesh->Release(); (*i)->materialBuffer->Release(); (*i)->primitiveVertexBuffer->Release(); delete *i; i++; } } void HREEffect::releaseEntities() { std::vector::iterator entityIterator = entities.begin(); while(entityIterator != entities.end()) { entityIterator++; } } LRESULT HREEffect::handleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if(parameters->Get(bMoveLight)) return lightCamera->HandleMessages(hWnd, uMsg, wParam, lParam); else return camera->HandleMessages(hWnd, uMsg, wParam, lParam); } void HREEffect::addUiParameters(Parameters* parameters) { HREEffect::parameters = parameters; parameters->Add( bLookFromLight, "Look from light", 1); parameters->Add( bMoveLight, "Move light", 1); parameters->Add( bDots, "Entry points", 1); parameters->Add( bTurbo, "Turbo", 1); parameters->Add( fRayPathLength, "Iterations", 10, 'V', 'B', convert10); } Parameters* HREEffect::parameters = NULL; HRESULT HREEffect::Mesh::setVertexFormat(DWORD fvf, LPDIRECT3DDEVICE9 device) { LPD3DXMESH tempMesh; //clone the mesh to the appropriate format HRESULT hr = mesh->CloneMeshFVF( mesh->GetOptions(), fvf , device, &tempMesh ); if(hr == S_OK) { DWORD* padj = new DWORD[mesh->GetNumFaces() * 3]; mesh->GenerateAdjacency(0.00001f, padj); delete padj; //forget he old mesh mesh->Release(); //use the cloned mesh mesh = tempMesh; } return hr; } void HREEffect::move(float fElapsedTime) { //apply some rotation to one of the entities D3DXMATRIX rot; D3DXMatrixRotationY(&rot, fElapsedTime * 1.0); D3DXMatrixMultiply( &entities.at(0).modelWorldTransform, &rot, &entities.at(0).modelWorldTransform); D3DXMatrixInverse( &entities.at(0).inverseTransposedModelWorldTransform, NULL, &entities.at(0).modelWorldTransform); D3DXMatrixTranspose( &entities.at(0).inverseTransposedModelWorldTransform, &entities.at(0).inverseTransposedModelWorldTransform); if(parameters->Get(bTurbo)) { camera->FrameMove(fElapsedTime * 10.0f); lightCamera->FrameMove(fElapsedTime * 10.0f); } else { camera->FrameMove(fElapsedTime); lightCamera->FrameMove(fElapsedTime); } } void HREEffect::render() { HRESULT hr; UINT nPasses=1; D3DXIMAGE_FILEFORMAT fileFormat=D3DXIFF_HDR; device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); D3DXMATRIX worldToScreen = *camera->GetViewMatrix() * *camera->GetProjMatrix(); Vector eyePos = *camera->GetEyePt(); hr=device->SetRenderTarget(0,rayOriginTableSurface); hr=device->SetRenderTarget(1,rayDirTableSurface); hr=device->SetDepthStencilSurface(depthSurface); device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); device->SetRenderState(D3DRS_STENCILENABLE, TRUE); device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); device->SetRenderState(D3DRS_STENCILREF, 0x1); hr=device->SetRenderState(D3DRS_STENCILMASK, 0x1); hr=device->SetRenderState(D3DRS_STENCILWRITEMASK, 0x01); device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_ARGB(1,0,0,0), 1.0f, 0 ); // Render initial rays if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"RenderPrimaryRayArray"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr = effect->SetFloatArray("EyePos", (float*)&eyePos, 3); hr = effect->SetFloat("RefractionIndex", 0.9); //loop through all entities, all mesh subsets, set proper transformations std::vector::iterator entityIterator = entities.begin(); while(entityIterator != entities.end()) { hr=effect->SetMatrix("WorldViewProj", &(entityIterator->modelWorldTransform * *camera->GetViewMatrix() * *camera->GetProjMatrix() )); hr=effect->SetMatrix("World", &entityIterator->modelWorldTransform); hr=effect->SetMatrix("WorldIT", &entityIterator->inverseTransposedModelWorldTransform); hr=effect->SetFloat("colOrder", 10.0f); effect->CommitChanges(); unsigned int nSubsets = entityIterator->mesh->nSubsets; for(int i = 0; i< nSubsets; i++) { entityIterator->mesh->mesh->DrawSubset(i); } entityIterator++; } effect->EndPass(); } effect->End(); } device->EndScene(); } //ray cast device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); device->SetRenderState(D3DRS_STENCILREF, 0xff); device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); float pointSize = 16.0f; hr = device->SetRenderState(D3DRS_POINTSIZE_MAX, *((DWORD*)&pointSize)); hr = device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&pointSize)); unsigned int nIter = parameters->Get(fRayPathLength); for(int rd =0; rd < nIter; rd++) { device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); hr=device->SetRenderState(D3DRS_STENCILENABLE, FALSE); hr=device->SetRenderTarget(1, coneDirSurface); hr=device->SetRenderTarget(0, conePeakSurface); hr=device->SetDepthStencilSurface(NULL); if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"ComputeCones"); if(hTechnique==NULL){ return ; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr=effect->SetTexture("rayOriginTable", rayOriginTableTexture); hr=effect->SetTexture("rayDirTable", rayDirTableTexture); effect->CommitChanges(); drawFullScreenQuad(device); effect->EndPass(); } effect->End(); } device->EndScene(); } /* device->SetRenderTarget(1, NULL); device->SetRenderTarget(0, rayOriginTableSurface2); device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(1,0,0,0), 1.0f, 0 ); if( SUCCEEDED( device->BeginScene() ) ){ if(effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"ConeChecker"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0; jBeginPass(j); effect->SetTexture("rayOriginTable", rayOriginTableTexture); effect->SetTexture("rayDirTable", rayDirTableTexture); effect->SetTexture("conePeakTable", conePeakTexture); effect->SetTexture("coneDirTable", coneDirTexture); effect->CommitChanges(); drawFullScreenQuad(device); effect->EndPass(); } effect->End(); } device->EndScene(); } /*/ hr=device->SetRenderState(D3DRS_STENCILENABLE, TRUE); device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); hr=device->SetRenderState(D3DRS_STENCILMASK, 0x1 << rd); hr=device->SetRenderState(D3DRS_STENCILWRITEMASK, 0x2 << rd); hr=device->SetRenderTarget(1,rayDirTableSurface2); hr=device->SetRenderTarget(0,rayOriginTableSurface2); hr=device->SetDepthStencilSurface(depthSurface); device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(1,0,0,0), 1.0f, 0 ); D3DLOCKED_RECT peakData; hr = device->GetRenderTargetData(conePeakSurface, conePeakSurfaceMem); hr = conePeakSurfaceMem->LockRect(&peakData, NULL, D3DLOCK_READONLY); float* conePeaks = (float*)peakData.pBits; D3DLOCKED_RECT coneData; hr = device->GetRenderTargetData(coneDirSurface, coneDirSurfaceMem); hr = coneDirSurfaceMem->LockRect(&coneData, NULL, D3DLOCK_READONLY); float* coneDirs = (float*)coneData.pBits; if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"RayCast"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr = effect->SetFloat("RefractionIndex", 0.9); hr=effect->SetTexture("conePeakTable",conePeakTexture); hr=effect->SetTexture("coneDirTable",coneDirTexture); hr=effect->SetTexture("rayOriginTable",rayOriginTableTexture); hr=effect->SetTexture("rayDirTable",rayDirTableTexture); hr = device->SetVertexDeclaration(trianglePrimitiveDeclaration); //loop through all entities, all mesh subsets, set proper transformations std::vector::iterator entityIterator = entities.begin(); while(entityIterator != entities.end()) { hr = device->SetStreamSource(0, entityIterator->mesh->primitiveVertexBuffer, 0, sizeof(ProcessedTriangle)); hr=effect->SetMatrix("World", &entityIterator->modelWorldTransform); hr=effect->SetMatrix("WorldIT", &entityIterator->inverseTransposedModelWorldTransform); hr=effect->SetFloat("colOrder", 10.0f); for(int cx=0; cx<32; cx++) for(int cy=0; cy<32; cy++) { Vector tilePos(-1.0 + 0.0625 * 0.5 + 0.0625*cx, -1.0 + 0.0625 * 0.5 + 0.0625*cy, 0.0); hr = effect->SetFloatArray("TilePos", (float*)&tilePos, 3); // D3DVECTOR worldConePeak = *(D3DVECTOR*)(conePeaks + cx * 4 + (31 - cy) * 32 * 4); // D3DVECTOR modelConePeak = worldConePeak * entityIterator->inverseTransposedModelWorldTransform; hr = effect->SetFloatArray("ConePeak",conePeaks + cx * 4 + (31 - cy) * 32 * 4 , 4); hr = effect->SetFloatArray("ConeDirAndCosAngle", coneDirs + cx * 4 + (31 - cy) * 32 * 4, 4); effect->CommitChanges(); device->DrawPrimitive(D3DPT_POINTLIST, 0, entityIterator->mesh->mesh->GetNumFaces()); } entityIterator++; } effect->EndPass(); } effect->End(); } device->EndScene(); } conePeakSurfaceMem->UnlockRect(); coneDirSurfaceMem->UnlockRect(); hr=device->SetRenderState(D3DRS_STENCILMASK, 0x2 << rd); hr=device->SetRenderState(D3DRS_STENCILWRITEMASK, 0x0); hr=device->SetRenderTarget(1,rayDirTableSurface); hr=device->SetRenderTarget(0,rayOriginTableSurface); if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"CopyBack"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr=effect->SetTexture("rayOriginTable",rayOriginTableTexture2); hr=effect->SetTexture("rayDirTable",rayDirTableTexture2); effect->CommitChanges(); drawFullScreenQuad(device); effect->EndPass(); } effect->End(); } device->EndScene(); }//*/ } //eval directions, read from envmap hr=device->SetRenderTarget(0,rayOriginTableSurface2); hr=device->SetRenderTarget(1,NULL); device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device->Clear( 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); D3DXMATRIX screenToWorld; D3DXMATRIX screenToWorldIT = *camera->GetViewMatrix() * *camera->GetProjMatrix(); D3DXMatrixInverse(&screenToWorld, NULL, &screenToWorldIT); if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"Background"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr = effect->SetFloatArray("EyePos", (float*)&eyePos, 3); hr=effect->SetMatrix("ViewProjI", &screenToWorld); hr=effect->SetTexture("rayDirTable",rayDirTableTexture); hr=effect->SetTexture("environmentTexture",environmentCubeTexture); effect->CommitChanges(); drawFullScreenQuad(device); effect->EndPass(); } effect->End(); } device->EndScene(); } //render image hr=device->SetDepthStencilSurface(frameDepthStencilBuffer); hr=device->SetRenderTarget(1,NULL); hr=device->SetRenderTarget(0, frameColorBuffer); device->SetRenderState(D3DRS_STENCILENABLE, FALSE); device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); if( SUCCEEDED( device->BeginScene() ) ){ if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"ShowTex"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr=effect->SetTexture("coneDirTableSampler",coneDirTexture); hr=effect->SetTexture("conePeakTableSampler",coneDirTexture); hr=effect->SetTexture("rayOriginTable",rayOriginTableTexture2); hr=effect->SetTexture("rayDirTable",rayDirTableTexture); // hr=effect->SetTexture("rayOriginTable",rayOriginTableTexture); // hr=effect->SetTexture("rayDirTable",rayDirTableTexture); // hr=effect->SetTexture("rayDirTable",coneDirTexture); // hr=effect->SetTexture("rayOriginTable",conePeakTexture); effect->CommitChanges(); drawFullScreenQuad(device); effect->EndPass(); } effect->End(); } device->EndScene(); } } void HREEffect::drawFullScreenQuad(LPDIRECT3DDEVICE9 device, float depth, float fLeftU, float fTopV, float fRightU, float fBottomV) { D3DSURFACE_DESC dtdsdRT; PDIRECT3DSURFACE9 pSurfRT; // Acquire render target width and height device->GetRenderTarget(0, &pSurfRT); pSurfRT->GetDesc(&dtdsdRT); pSurfRT->Release(); // Ensure that we're directly mapping texels to pixels by offset by 0.5 // For more info see the doc page titled "Directly Mapping Texels to Pixels" FLOAT fWidth5 = (FLOAT)dtdsdRT.Width - 0.5f; FLOAT fHeight5 = (FLOAT)dtdsdRT.Height - 0.5f; struct D3DVERTEX{ D3DXVECTOR3 pos; D3DXVECTOR2 tex0; }; // Draw the quad D3DVERTEX svQuad[4]; svQuad[0].pos=D3DXVECTOR3(-1, 1, depth); svQuad[0].tex0 = D3DXVECTOR2(fLeftU, fTopV); svQuad[1].pos = D3DXVECTOR3(1, 1, depth); svQuad[1].tex0 = D3DXVECTOR2(fRightU, fTopV); svQuad[2].pos = D3DXVECTOR3(-1, -1, depth); svQuad[2].tex0 = D3DXVECTOR2(fLeftU, fBottomV); svQuad[3].pos = D3DXVECTOR3(1, -1, depth); svQuad[3].tex0 = D3DXVECTOR2(fRightU, fBottomV); device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); device->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, svQuad, sizeof(D3DVERTEX)); }