[896] | 1 | #pragma once
|
---|
| 2 | #include <vector>
|
---|
| 3 | #include "Parameters.h"
|
---|
| 4 | #include "Vector.hpp"
|
---|
| 5 | #include "Uniform.hpp"
|
---|
| 6 | #include "Radion.hpp"
|
---|
| 7 | #include "KDTree.hpp"
|
---|
| 8 |
|
---|
| 9 | #define ATLASSIZE 128
|
---|
| 10 | #define DBLATLASSIZE (ATLASSIZE * 2.0)
|
---|
| 11 |
|
---|
| 12 | #define NRADIONS 4096
|
---|
| 13 | #define NCLUSTERS 32
|
---|
| 14 | #define DEPTHMAPRES 512
|
---|
| 15 | #define NCLUSTERSPERENTITY 32
|
---|
| 16 |
|
---|
| 17 |
|
---|
| 18 | class Material;
|
---|
| 19 | class TriangleMesh;
|
---|
| 20 | class Transformed;
|
---|
| 21 | class KDTree;
|
---|
| 22 |
|
---|
| 23 | /*!
|
---|
| 24 | \brief Main class for the PRM computation and usage application.
|
---|
| 25 | This class encapsulates all resources needed for computing PRMs and
|
---|
| 26 | using them in the final rendering. PRM resources may be generated,
|
---|
| 27 | saved to files, or restored.
|
---|
| 28 | */
|
---|
| 29 | class PathMapEffect
|
---|
| 30 | {
|
---|
| 31 | //! pointer to global user-adjustable application parameters object
|
---|
| 32 | static Parameters* parameters;
|
---|
| 33 |
|
---|
| 34 | //! pointer to main DX device
|
---|
| 35 | LPDIRECT3DDEVICE9 device;
|
---|
| 36 | //! pointer to main DX effect
|
---|
| 37 | LPD3DXEFFECT effect;
|
---|
| 38 |
|
---|
| 39 | //! frame color buffer surface
|
---|
| 40 | //! saved before render-to-texture, and restored as the render target for the final rendering to the screen
|
---|
| 41 | LPDIRECT3DSURFACE9 frameColorBuffer;
|
---|
| 42 | //! frame depth buffer surface
|
---|
| 43 | //! saved before render-to-texture, and restored as the render target for the final rendering to the screen
|
---|
| 44 | LPDIRECT3DSURFACE9 frameDepthStencilBuffer;
|
---|
| 45 |
|
---|
| 46 | LPDIRECT3DTEXTURE9 depthMapTexture; //!< depth map texture
|
---|
| 47 | LPDIRECT3DSURFACE9 depthMapDepthStencilBuffer; //!< depth map texture's surface
|
---|
| 48 | LPDIRECT3DTEXTURE9 fakeTexture; //!< depth map dummy render texture
|
---|
| 49 | LPDIRECT3DSURFACE9 fakeSurface; //!< depth map dummy render surface
|
---|
| 50 |
|
---|
| 51 | LPDIRECT3DSURFACE9 prmBlendingDepthStencilBuffer; //!< stencil buffer for rendering a virtual light source to the PRM
|
---|
| 52 |
|
---|
| 53 | LPDIRECT3DVERTEXBUFFER9 starterVertexBuffer; //!< vertex buffer with entry point positions, for entry point visualization
|
---|
| 54 |
|
---|
| 55 | LPDIRECT3DTEXTURE9 weightsTexture; //!< render target texture to which current entry point weights are computed
|
---|
| 56 | LPDIRECT3DSURFACE9 weightsSurface; //!< weights texture's surface
|
---|
| 57 | LPDIRECT3DTEXTURE9 sysMemWeightsTexture; //!< weights texture copy in system mem
|
---|
| 58 | LPDIRECT3DSURFACE9 sysMemWeightsSurface; //!< surface of weights texture copy in system mem
|
---|
| 59 | LPDIRECT3DTEXTURE9 radionTexture; //!< texture containing entry point data, input for weight computation
|
---|
| 60 | LPDIRECT3DSURFACE9 radionSurface; //!< entry point texture's surface
|
---|
| 61 |
|
---|
| 62 | KDTree* kdtree; //!< the kd-tree that contains the scene geometry in raytraceable format
|
---|
| 63 |
|
---|
| 64 | //! clever enum for supported final rendering methods
|
---|
| 65 | class Method{
|
---|
| 66 | unsigned int mid;
|
---|
| 67 | Method(unsigned int mid) {this->mid = mid;}
|
---|
| 68 | static const wchar_t * methodNames[10];
|
---|
| 69 | public:
|
---|
| 70 | Method(const Method& o) {mid = o.mid;}
|
---|
| 71 | const Method& operator=(const Method& o) {mid = o.mid; return *this;}
|
---|
| 72 | bool operator==(const Method& o) const {return mid == o.mid;}
|
---|
| 73 | bool operator!=(const Method& o) const {return mid != o.mid;}
|
---|
| 74 | const static Method PRM;
|
---|
| 75 | const static Method SHOWTEX;
|
---|
| 76 | const static Method LAST;
|
---|
| 77 | const Method& next() {mid = (mid + 1)%LAST.mid; return *this;}
|
---|
| 78 | const Method& prev() {mid = (mid + LAST.mid - 1)%LAST.mid; return *this;}
|
---|
| 79 | const wchar_t* getName() {return methodNames[mid];}
|
---|
| 80 | }method;
|
---|
| 81 | public:
|
---|
| 82 | void nextMethod() {method.next();}
|
---|
| 83 | void prevMethod() {method.prev();}
|
---|
| 84 | const wchar_t* getCurrentMethodName() {return method.getName();}
|
---|
| 85 |
|
---|
| 86 | //! camera
|
---|
| 87 | CFirstPersonCamera* camera;
|
---|
| 88 | //! primary light source (can be moved just like the real camera, and can be used as the camera)
|
---|
| 89 | CFirstPersonCamera* lightCamera;
|
---|
| 90 | private:
|
---|
| 91 |
|
---|
| 92 | //! struct containing all mesh related data. Will be filled from X files in PathMapEffect constructor
|
---|
| 93 | struct RenderMesh
|
---|
| 94 | {
|
---|
| 95 | unsigned int nSubsets; //!< number of submeshes (with possible different material)
|
---|
| 96 | LPD3DXMESH mesh; //!< D3D mesh
|
---|
| 97 | LPD3DXBUFFER materialBuffer; //!< D3D material buffer
|
---|
| 98 | D3DXMATERIAL* materials; //!< D3D material array
|
---|
| 99 | LPDIRECT3DTEXTURE9* textures; //!< D3D textures for the materials
|
---|
| 100 | Material* rayTraceMaterial; //!< material used in for ray tracing
|
---|
| 101 | TriangleMesh* rayTraceMesh; //!< the raytracable representation of the mesh
|
---|
| 102 | LPDIRECT3DVERTEXBUFFER9 edgeVertexBuffer; //!< a set of line primitives for atlas (PRM) rendering
|
---|
| 103 | int nEdges; //!< number of line primitives in edgeVertexBuffer
|
---|
| 104 |
|
---|
| 105 | HRESULT setVertexFormat(DWORD fvf, LPDIRECT3DDEVICE9 device); //!< rebuild D3D to have differnet vertex format
|
---|
| 106 | void buildEdgeVertexBuffer(LPDIRECT3DDEVICE9 device); //!< compute line primitives to edgeVertexBuffer
|
---|
| 107 | };
|
---|
| 108 |
|
---|
| 109 | //! vector of loaded meshes
|
---|
| 110 | std::vector<RenderMesh*> renderMeshes;
|
---|
| 111 | //! vector of loaded textures (textures specified in mesh's material will be loaded here)
|
---|
| 112 | std::vector<LPDIRECT3DTEXTURE9> materialTextures;
|
---|
| 113 |
|
---|
| 114 | //! for materials with no texture we will render with this texture
|
---|
| 115 | LPDIRECT3DTEXTURE9 emptyTexture;
|
---|
| 116 |
|
---|
| 117 | //! private method that loads a mesh and its textures
|
---|
| 118 | void loadMesh(LPCWSTR fileName);
|
---|
| 119 |
|
---|
| 120 | //! private method to load a texture
|
---|
| 121 | LPDIRECT3DTEXTURE9 loadTexture(LPCWSTR fileName);
|
---|
| 122 |
|
---|
| 123 | //! release material texture resources
|
---|
| 124 | void releaseTextures();
|
---|
| 125 | //! release mesh resources
|
---|
| 126 | void releaseMeshes();
|
---|
| 127 | //! release entities
|
---|
| 128 | void releaseEntities();
|
---|
| 129 |
|
---|
| 130 | //! struct that represents a virtual world object: a mesh and a model-world transformation matrix
|
---|
| 131 | friend struct Entity;
|
---|
| 132 | struct Entity
|
---|
| 133 | {
|
---|
| 134 | PathMapEffect* owner; //!< enclosing class instance
|
---|
| 135 |
|
---|
| 136 | RenderMesh* renderMesh; //!< mesh
|
---|
| 137 | Transformed* rayTraceEntity; //!< raytracable entity containing the mesh's TriangleMesh
|
---|
| 138 | D3DXMATRIX modelWorldTransform; //!< modeling transform
|
---|
| 139 | D3DXMATRIX inverseTransposedModelWorldTransform; //!< IT modeling transform for surface normal transformation
|
---|
| 140 |
|
---|
| 141 | LPDIRECT3DTEXTURE9 prmTexture; //!< a collection of tiled texture atlases containing illuminaton contributions of nearest entry point clusters
|
---|
| 142 | LPDIRECT3DSURFACE9 prmSurface; //!< prmTexture's surface
|
---|
| 143 |
|
---|
| 144 | void createRayTraceEntity(); //!< setup rayTraceEntity
|
---|
| 145 |
|
---|
| 146 | //! render contributions of virtual light sources in 'bushRadions' to atlas corresponding to cluster 'bushId'
|
---|
| 147 | void renderPRM(LPDIRECT3DDEVICE9 device,
|
---|
| 148 | LPD3DXEFFECT effect,
|
---|
| 149 | std::vector<Radion>& bushRadions,
|
---|
| 150 | unsigned int bushId,
|
---|
| 151 | float scaleFactor);
|
---|
| 152 |
|
---|
| 153 | //! array of cluster indices storing which clusters are relevant. PRM tiles correspond to these clusters
|
---|
| 154 | unsigned int nearClusterIndices[NCLUSTERSPERENTITY];
|
---|
| 155 |
|
---|
| 156 | //! fill the nearClusterIndices array
|
---|
| 157 | void findNearClusters(const std::vector<Radion>& starters, unsigned int nClusters);
|
---|
| 158 |
|
---|
| 159 | };
|
---|
| 160 |
|
---|
| 161 | //! renders a full screen quad, invoking the pixel shader for all pixels
|
---|
| 162 | //! used for rendering the environment map to the background
|
---|
| 163 | void renderFullScreen(float depth = 0.0f);
|
---|
| 164 |
|
---|
| 165 | //! vector of virtual world objects
|
---|
| 166 | std::vector<Entity> entities;
|
---|
| 167 | public:
|
---|
| 168 | //! constructor: allocates all resources
|
---|
| 169 | PathMapEffect(LPDIRECT3DDEVICE9 device);
|
---|
| 170 | //! destructor: releases all resources
|
---|
| 171 | ~PathMapEffect(void);
|
---|
| 172 |
|
---|
| 173 | //! renders the scene using the currently selected method
|
---|
| 174 | void render();
|
---|
| 175 |
|
---|
| 176 | //! renders the scene, usings the PRMs for indirect illumination
|
---|
| 177 | void renderWithPRM();
|
---|
| 178 |
|
---|
| 179 | //! displays a part of a PRM texture
|
---|
| 180 | void showPRMTexture();
|
---|
| 181 |
|
---|
| 182 | //! moves the virtual world objects (camera, light)
|
---|
| 183 | void move(float fElapsedTime);
|
---|
| 184 |
|
---|
| 185 | LRESULT handleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
---|
| 186 |
|
---|
| 187 | //! adds controls for the user-adjustable application parameters
|
---|
| 188 | static void addUiParameters(Parameters* parameters);
|
---|
| 189 | static void setUiParameterDefaults(Parameters* parameters);
|
---|
| 190 |
|
---|
| 191 | LPDIRECT3DDEVICE9 getDevice() {return device;}
|
---|
| 192 |
|
---|
| 193 | const wchar_t* getWeightsString();
|
---|
| 194 | private:
|
---|
| 195 | float weights[NCLUSTERS]; //!< the array of averaged cluster weights
|
---|
| 196 | unsigned int clusterLenghts[NCLUSTERS]; //!< array thet contasins the number of entry points in every cluster (entry points are stored continously [bushStarters, starterVertexBuffer])
|
---|
| 197 |
|
---|
| 198 | float sumSurfaceArea; //!< summed surface area of all entities
|
---|
| 199 |
|
---|
| 200 | void createPRMTextures(); //!< allocates PRM resources for every entity
|
---|
| 201 |
|
---|
| 202 | //! generates a random direction (cosine distribution) near a normal vector
|
---|
| 203 | static void sampleShootingDiffuseDirection(int depth, const Vector& normal, Vector& outDir);
|
---|
| 204 | //! generates a random direction an the unit sphere
|
---|
| 205 | static void sampleSphereDirection(Vector& outDir);
|
---|
| 206 |
|
---|
| 207 | //! finds a random entry point (all entities considered with equal probability)
|
---|
| 208 | void sampleSurfaceRadion(Radion& starter);
|
---|
| 209 | //! finds a random entry point (all entities considered with probability proporstional to surface area)
|
---|
| 210 | void sampleSurfaceRadionUniform(Radion& starter);
|
---|
| 211 |
|
---|
| 212 | //! shoot virtual light sources from original entry point and add them to the vector
|
---|
| 213 | void shootRadionBush(Radion& starter, std::vector<Radion>& bushRadions);
|
---|
| 214 |
|
---|
| 215 | //! sort radions into initial, uniform length clusters
|
---|
| 216 | int clusterRadions(Radion* partition, int psize, char axis);
|
---|
| 217 |
|
---|
| 218 | //! use K-means clustering to cluster radions
|
---|
| 219 | void clusterRadionsKMeans();
|
---|
| 220 |
|
---|
| 221 | //! perform computaions: generate entry points, render PRMs
|
---|
| 222 | void precompute();
|
---|
| 223 |
|
---|
| 224 | int getNBushes() {return NRADIONS; }
|
---|
| 225 | int getNClusters() {return NCLUSTERS;}
|
---|
| 226 |
|
---|
| 227 | //! entry points
|
---|
| 228 | std::vector<Radion> bushStarters;
|
---|
| 229 |
|
---|
| 230 | int rayId;
|
---|
| 231 | Ray ray;
|
---|
| 232 | HitRec hitRec;
|
---|
| 233 |
|
---|
| 234 | //! render a full-screen quad
|
---|
| 235 | 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);
|
---|
| 236 |
|
---|
| 237 | //! fill 'radionsTexture' from 'bushStarters'
|
---|
| 238 | void uploadRadions();
|
---|
| 239 | //! fill *pData (will point to locked 'starterVertexBuffer') from 'bushStarters'
|
---|
| 240 | void fillRadionPosArray(void* pData);
|
---|
| 241 |
|
---|
| 242 | public:
|
---|
| 243 | //! store all precomputed data for the scene in folder prm
|
---|
| 244 | void savePathMaps();
|
---|
| 245 | //! restore all precomputed data for the scene from folder prm
|
---|
| 246 | void loadPathMaps();
|
---|
| 247 | };
|
---|