#pragma once #include #include "Parameters.h" #include "Vector.hpp" #include "Uniform.hpp" #include "Radion.hpp" #include "KDTree.hpp" #define ATLASSIZE 128 #define DBLATLASSIZE (ATLASSIZE * 2.0) #define NRADIONS 4096 #define NCLUSTERS 32 #define DEPTHMAPRES 512 #define NCLUSTERSPERENTITY 32 class Material; class TriangleMesh; class Transformed; class KDTree; /*! \brief Main class for the PRM computation and usage application. This class encapsulates all resources needed for computing PRMs and using them in the final rendering. PRM resources may be generated, saved to files, or restored. */ class PathMapEffect { //! pointer to global user-adjustable application parameters object static Parameters* parameters; //! pointer to main DX device LPDIRECT3DDEVICE9 device; //! pointer to main DX effect LPD3DXEFFECT effect; //! frame color buffer surface //! saved before render-to-texture, and restored as the render target for the final rendering to the screen LPDIRECT3DSURFACE9 frameColorBuffer; //! frame depth buffer surface //! saved before render-to-texture, and restored as the render target for the final rendering to the screen LPDIRECT3DSURFACE9 frameDepthStencilBuffer; LPDIRECT3DTEXTURE9 depthMapTexture; //!< depth map texture LPDIRECT3DSURFACE9 depthMapDepthStencilBuffer; //!< depth map texture's surface LPDIRECT3DTEXTURE9 fakeTexture; //!< depth map dummy render texture LPDIRECT3DSURFACE9 fakeSurface; //!< depth map dummy render surface LPDIRECT3DSURFACE9 prmBlendingDepthStencilBuffer; //!< stencil buffer for rendering a virtual light source to the PRM LPDIRECT3DVERTEXBUFFER9 starterVertexBuffer; //!< vertex buffer with entry point positions, for entry point visualization LPDIRECT3DTEXTURE9 weightsTexture; //!< render target texture to which current entry point weights are computed LPDIRECT3DSURFACE9 weightsSurface; //!< weights texture's surface LPDIRECT3DTEXTURE9 sysMemWeightsTexture; //!< weights texture copy in system mem LPDIRECT3DSURFACE9 sysMemWeightsSurface; //!< surface of weights texture copy in system mem LPDIRECT3DTEXTURE9 radionTexture; //!< texture containing entry point data, input for weight computation LPDIRECT3DSURFACE9 radionSurface; //!< entry point texture's surface KDTree* kdtree; //!< the kd-tree that contains the scene geometry in raytraceable format //! clever enum for supported final rendering methods class Method{ unsigned int mid; Method(unsigned int mid) {this->mid = mid;} static const wchar_t * methodNames[10]; public: Method(const Method& o) {mid = o.mid;} const Method& operator=(const Method& o) {mid = o.mid; return *this;} bool operator==(const Method& o) const {return mid == o.mid;} bool operator!=(const Method& o) const {return mid != o.mid;} const static Method PRM; const static Method SHOWTEX; const static Method LAST; const Method& next() {mid = (mid + 1)%LAST.mid; return *this;} const Method& prev() {mid = (mid + LAST.mid - 1)%LAST.mid; return *this;} const wchar_t* getName() {return methodNames[mid];} }method; public: void nextMethod() {method.next();} void prevMethod() {method.prev();} const wchar_t* getCurrentMethodName() {return method.getName();} //! camera CFirstPersonCamera* camera; //! primary light source (can be moved just like the real camera, and can be used as the camera) CFirstPersonCamera* lightCamera; private: //! struct containing all mesh related data. Will be filled from X files in PathMapEffect constructor struct RenderMesh { unsigned int nSubsets; //!< number of submeshes (with possible different material) LPD3DXMESH mesh; //!< D3D mesh LPD3DXBUFFER materialBuffer; //!< D3D material buffer D3DXMATERIAL* materials; //!< D3D material array LPDIRECT3DTEXTURE9* textures; //!< D3D textures for the materials Material* rayTraceMaterial; //!< material used in for ray tracing TriangleMesh* rayTraceMesh; //!< the raytracable representation of the mesh LPDIRECT3DVERTEXBUFFER9 edgeVertexBuffer; //!< a set of line primitives for atlas (PRM) rendering int nEdges; //!< number of line primitives in edgeVertexBuffer HRESULT setVertexFormat(DWORD fvf, LPDIRECT3DDEVICE9 device); //!< rebuild D3D to have differnet vertex format void buildEdgeVertexBuffer(LPDIRECT3DDEVICE9 device); //!< compute line primitives to edgeVertexBuffer }; //! vector of loaded meshes std::vector renderMeshes; //! vector of loaded textures (textures specified in mesh's material will be loaded here) std::vector materialTextures; //! for materials with no texture we will render with this texture LPDIRECT3DTEXTURE9 emptyTexture; //! private method that loads a mesh and its textures void loadMesh(LPCWSTR fileName); //! private method to load a texture LPDIRECT3DTEXTURE9 loadTexture(LPCWSTR fileName); //! release material texture resources void releaseTextures(); //! release mesh resources void releaseMeshes(); //! release entities void releaseEntities(); //! struct that represents a virtual world object: a mesh and a model-world transformation matrix friend struct Entity; struct Entity { PathMapEffect* owner; //!< enclosing class instance RenderMesh* renderMesh; //!< mesh Transformed* rayTraceEntity; //!< raytracable entity containing the mesh's TriangleMesh D3DXMATRIX modelWorldTransform; //!< modeling transform D3DXMATRIX inverseTransposedModelWorldTransform; //!< IT modeling transform for surface normal transformation LPDIRECT3DTEXTURE9 prmTexture; //!< a collection of tiled texture atlases containing illuminaton contributions of nearest entry point clusters LPDIRECT3DSURFACE9 prmSurface; //!< prmTexture's surface void createRayTraceEntity(); //!< setup rayTraceEntity //! render contributions of virtual light sources in 'bushRadions' to atlas corresponding to cluster 'bushId' void renderPRM(LPDIRECT3DDEVICE9 device, LPD3DXEFFECT effect, std::vector& bushRadions, unsigned int bushId, float scaleFactor); //! array of cluster indices storing which clusters are relevant. PRM tiles correspond to these clusters unsigned int nearClusterIndices[NCLUSTERSPERENTITY]; //! fill the nearClusterIndices array void findNearClusters(const std::vector& starters, unsigned int nClusters); }; //! renders a full screen quad, invoking the pixel shader for all pixels //! used for rendering the environment map to the background void renderFullScreen(float depth = 0.0f); //! vector of virtual world objects std::vector entities; public: //! constructor: allocates all resources PathMapEffect(LPDIRECT3DDEVICE9 device); //! destructor: releases all resources ~PathMapEffect(void); //! renders the scene using the currently selected method void render(); //! renders the scene, usings the PRMs for indirect illumination void renderWithPRM(); //! displays a part of a PRM texture void showPRMTexture(); //! moves the virtual world objects (camera, light) void move(float fElapsedTime); LRESULT handleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //! adds controls for the user-adjustable application parameters static void addUiParameters(Parameters* parameters); static void setUiParameterDefaults(Parameters* parameters); LPDIRECT3DDEVICE9 getDevice() {return device;} const wchar_t* getWeightsString(); private: float weights[NCLUSTERS]; //!< the array of averaged cluster weights unsigned int clusterLenghts[NCLUSTERS]; //!< array thet contasins the number of entry points in every cluster (entry points are stored continously [bushStarters, starterVertexBuffer]) float sumSurfaceArea; //!< summed surface area of all entities void createPRMTextures(); //!< allocates PRM resources for every entity //! generates a random direction (cosine distribution) near a normal vector static void sampleShootingDiffuseDirection(int depth, const Vector& normal, Vector& outDir); //! generates a random direction an the unit sphere static void sampleSphereDirection(Vector& outDir); //! finds a random entry point (all entities considered with equal probability) void sampleSurfaceRadion(Radion& starter); //! finds a random entry point (all entities considered with probability proporstional to surface area) void sampleSurfaceRadionUniform(Radion& starter); //! shoot virtual light sources from original entry point and add them to the vector void shootRadionBush(Radion& starter, std::vector& bushRadions); //! sort radions into initial, uniform length clusters int clusterRadions(Radion* partition, int psize, char axis); //! use K-means clustering to cluster radions void clusterRadionsKMeans(); //! perform computaions: generate entry points, render PRMs void precompute(); int getNBushes() {return NRADIONS; } int getNClusters() {return NCLUSTERS;} //! entry points std::vector bushStarters; int rayId; Ray ray; HitRec hitRec; //! render a full-screen quad static void drawFullScreenQuad(LPDIRECT3DDEVICE9 device, float depth = 0.0f, float fLeftU=0.0f, float fTopV=0.0f, float fRightU=1.0f, float fBottomV=1.0f); //! fill 'radionsTexture' from 'bushStarters' void uploadRadions(); //! fill *pData (will point to locked 'starterVertexBuffer') from 'bushStarters' void fillRadionPosArray(void* pData); public: //! store all precomputed data for the scene in folder prm void savePathMaps(); //! restore all precomputed data for the scene from folder prm void loadPathMaps(); };