#pragma once #include #include "Parameters.h" #include "Vector.hpp" #include "Uniform.hpp" #include "Radion.hpp" #include "KDTree.hpp" #include "xmlParser.h" class Material; class TriangleMesh; class Transformed; class KDTree; class RenderStrategy; /*! \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 { int NRADIONS; int NCLUSTERS; int DEPTHMAPRES; int testClusterId; friend class SubEntity; friend class SubMesh; friend class Entity; friend class Mesh; friend class DepthRenderStrategy; friend class FinalCompositionRenderStrategy; float clusterSweepCurrentIndex; //!< test, cycling displayed entry point clusters //! 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 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 LPDIRECT3DTEXTURE9 aggrWeightsTexture; LPDIRECT3DSURFACE9 aggrWeightsSurface; 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(); //! camera CFirstPersonCamera* camera; //! primary light source (can be moved just like the real camera, and can be used as the camera) CFirstPersonCamera* lightCamera; private: //! xml data with material name -> texture reference XMLNode xMaterials; std::vector meshes; //! vector of loaded textures (textures specified in mesh's material/bumpmap will be loaded here) std::vector materialTextures; std::vector materialTextureFileNames; //! vector of ray trace materials std::vector rayTraceMaterials; //! for materials with no texture we will render with this texture LPDIRECT3DTEXTURE9 emptyTexture; LPDIRECT3DTEXTURE9 shipBrdfTexture; LPD3DXMESH shipMesh; D3DXMATRIX shipPos; D3DXMATRIX shipPosInverse; int cruiseLoop; float loopPos; //! private method that loads a mesh and its textures void loadMesh(DWORD fileType, LPCWSTR fileName, LPCWSTR ogreName, int prmAtlasSize, const char* name, int dividePcs, bool generateUV, bool generateTBN, unsigned int originalAtlasTexCoordIndex); //! private method to load a texture LPDIRECT3DTEXTURE9 loadTexture(LPCWSTR fileName, Material** rayTraceMaterial=NULL); //! private method make a CPU Material out of a D3D texture Material* createRayTraceMaterial(LPDIRECT3DTEXTURE9 texture); //! 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 //! 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, char* prmDirectory, char* meshDirectory, char* mediaDirectory, char* levelFileName, char* materialFileName, bool segmentMeshes, bool computePRM, bool uniformSampling, bool atlasGen, unsigned int nEntryPoints, unsigned int nClusters, unsigned int depthMapResolution); wchar_t prmDirectory[256]; wchar_t meshDirectory[256]; wchar_t mediaDirectory[256]; wchar_t levelFileName[256]; wchar_t materialFileName[256]; bool SEGMENTMESHES; bool UNIFORMSAMPLING; //! destructor: releases all resources ~PathMapEffect(void); //! renders the scene using the currently selected method void render(); //! renders the scene, using 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; //!< the array of averaged cluster weights unsigned int* clusterLenghts; //!< 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; //! 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(); void exportEntityData(); void loadScene(const char* sceneFileName); void saveScene(const char* sceneFileName); void renderScene(const RenderStrategy& renderStrategy); wchar_t* getCruiseLoop(); };