├── ApplicationPaths.props ├── Framework.props ├── LICENSE ├── MakeLinks.py ├── README.md ├── Shaders └── DrawSurface.fx ├── Source ├── ClearRenderingRoutine.cpp ├── ClearRenderingRoutine.h ├── ConstBufferTypes.h ├── DrawRoutine.cpp ├── DrawRoutine.h ├── HeightMapLoader.h ├── HeightmapLoader.cpp ├── MaterialTable.cpp ├── MaterialTable.h ├── PresentRoutine.cpp ├── PresentRoutine.h ├── Scene.cpp ├── Scene.h ├── VertexTypes.cpp ├── VertexTypes.h ├── VolumeRenderingApplication.cpp ├── VolumeRenderingApplication.h ├── Voxel │ ├── VoxelLodOctree.cpp │ └── VoxelLodOctree.h ├── VoxelBall.cpp ├── VoxelBall.h ├── VoxelBox.cpp ├── VoxelBox.h ├── VoxelPlane.cpp ├── VoxelPlane.h ├── VoxelProc.cpp ├── VoxelProc.h ├── lodepng.cpp ├── lodepng.h ├── main.cpp ├── stdafx.cpp └── stdafx.h ├── VolumeRendering.sln ├── VolumeRendering.vcxproj ├── VolumeRendering.vcxproj.filters └── media ├── materials.json ├── testHmap.png ├── testHmap2.png └── textures ├── Deep-Freeze.jpg ├── Deep-Freeze_normal.dds ├── Snow.jpg ├── Snow_normal.dds ├── calcare.jpg ├── calcare_normal.dds ├── canyon.jpg ├── canyon_normal.dds ├── dry_grass.jpg ├── dry_grass_normal.dds ├── grass.png ├── grass_normal.dds ├── grey_stone.jpg ├── grey_stone_normal.dds ├── sand.jpg ├── sand_normal.dds ├── sand_stone.jpg └── sand_stone_normal.dds /ApplicationPaths.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | ..\ 6 | 7 | 8 | 9 | 10 | 11 | $(ProgramsPath) 12 | 13 | 14 | -------------------------------------------------------------------------------- /Framework.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | ..\ 6 | 7 | 8 | ..\dx11-framework;$(IncludePath) 9 | $(LibraryPath) 10 | 11 | 12 | 13 | ..\dx11-framework;$(ProgramsPath);%(AdditionalIncludeDirectories) 14 | %(PreprocessorDefinitions) 15 | 16 | 17 | 18 | 19 | $(ProgramsPath) 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014, Stoyan Nikolov 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 | DISCLAIMED. IN NO EVENT SHALL STOYAN NIKOLOV BE LIABLE FOR ANY 16 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /MakeLinks.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path 3 | from subprocess import call 4 | 5 | def makeLinks(dllFolder, coherentFolder, includePDBandLIB = False): 6 | fullDllFolder = os.path.abspath(dllFolder) 7 | files = os.listdir(fullDllFolder) 8 | 9 | for f in files: 10 | splitted = os.path.splitext(f) 11 | extensions = [".dll"] 12 | if includePDBandLIB: 13 | extensions.append(".pdb") 14 | extensions.append(".lib") 15 | if splitted[1] in extensions: 16 | call('mklink "%s" "%s"' % (os.path.join(coherentFolder, f), os.path.join(fullDllFolder, f)), shell=True) 17 | 18 | dllFolder32 = "..\\Voxels\\src\\bin32" 19 | buildFolder32 = "bin32\\" 20 | makeLinks(dllFolder32, buildFolder32) 21 | 22 | dllFolder64 = "..\\Voxels\\src\\bin64" 23 | buildFolder64 = "bin64\\" 24 | makeLinks(dllFolder64, buildFolder64) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *Volume rendering sample* - this is a sample for the **Voxels** library that shows realtime volume rendering of large meshes 2 | The **Voxels** library is available for free at http://github.com/stoyannk/voxels 3 | 4 | Official *Voxels* website: http://stoyannk.wordpress.com/voxels-library/ 5 | 6 | ## Features 7 | - Voxel grid loading saving 8 | - Realtime scalable polygonization 9 | - Materials 10 | - Simple surface editing 11 | - Procedural surface creation 12 | 13 | ## Control 14 | 15 | - Arrows to move around 16 | - Left shift for faster movement 17 | - Left mouse buton - Modify grid based on current active modification 18 | - Right mouse button for freelook 19 | - F2 - Save voxel grid 20 | - S - Toggle solid draw 21 | - W - Toggle wireframe 22 | - T - Show/hide transition meshes 23 | - A - Draw/hide surface 24 | - L - Toggle dynamic LOD culling 25 | - U - Disable/enable updating LOD & culling (will freeze LOD so that you can look around) 26 | - R - Recalculate grid 27 | - + - Add material blend 28 | - - - Subtract material blend 29 | - Z - LOD level +1 (only if dynamic LOD & culling update is disabled) 30 | - X - LOD level -1 (only if dynamic LOD & culling update is disabled) 31 | - M - Circle modification types - modify surface or material 32 | - 0 - Set current material to 0 33 | - 1 - Set current material to 1 or "Add" to surface (depending on current mode) 34 | - 2 - Set current material to 2 or "SubtractAddInner" to surface (depending on current mode) 35 | - 3 - Set current material to 3 or "Subtract" from surface (depending on current mode) 36 | - 4 - Set current material to 4 37 | - 5 - Set current material to 5 38 | - F5-F8 - Change modification brush size 39 | 40 | ## Command line parameters 41 | 42 | - grid - load a specified voxel grid 43 | - gridsize - grid size in voxels 44 | - surface - seed the grid with a surface type 45 | - materials - materials definition file 46 | - heightmap - heightmap file 47 | - hscale - heightmap scale factor 48 | - xscale - grid scale factor on X coordinate 49 | - yscale - grid scale factor on Y coordinate 50 | - zscale - grid scale factor on Z coordinate 51 | - msaa - msaa samples 52 | 53 | ## Examples 54 | 55 | "VolumeRendering --surface proc" - will create a perlin-noise generated surface of default size 56 | 57 | "VolumeRendering --surface sphere --gridsize 128" - will create a 128x128x128 procedural voxel sphere 58 | 59 | "VolumeRendering --surface plane --gridsize 128 --xscale 2 --yscale 2 --zscale 2" - will create a flat plane in a 128x128x128 grid scaled by a factor of 2 in all directions 60 | 61 | "VolumeRendering --heightmap ..\media\testHmap2.png --gridsize 128 --xscale 4 --zscale 4" - will load a heightmap from a file, create a voxel grid from it and polygonize it, stretching it by a factor of 4 in the XZ plane 62 | 63 | ## Interesting classes 64 | 65 | The purpose of this sample is to showcase the **Voxels** Library. The *VoxelPlane*, *VoxelBall*, *VoxelProc* and *VoxelBox* 66 | classes show procedural generation of grids. 67 | 68 | The *VoxelLodOctree* shows a class that dynamically culls surface blocks and computes the LOD levels to use. 69 | 70 | The *MaterialTable* class shows how to implement the *Voxels::MaterialMap* interface and loads it's material definitions from a JSON file. 71 | 72 | ## System requirements 73 | - Windows Vista+ 74 | - DirectX 11 level video card 75 | - Visual Studio 2012 toolset for building 76 | 77 | ## Building 78 | 79 | The application is also available pre-built for Windows. 80 | 81 | The sample depends on the (http://github.com/stoyannk/dx11-framework), the **Voxels** Library (http://github.com/stoyannk/voxels) 82 | and Boost (http://boost.org) and makes heavy use of the DirectXMath library. 83 | 84 | To build the sample checkout the dx11-framework, the **Voxels** Library and the sample in one root folder. The result is having them 85 | laid out like this: 86 | 87 | - {ROOT}\dx11-framework 88 | - {ROOT}\voxels 89 | - {ROOT}\volumerendering 90 | 91 | Setup the dx11-framework by following it's instructions (you'll need to build Boost). 92 | 93 | **NOTE:** You must also modify the paths in *ApplicationPaths.props* and *Framework.props*. 94 | 95 | If you follow this default directory structure you should now be able to build *volumerendering* via the VolumeRendering.sln solution. 96 | 97 | The *MakeLinks.py* script can be run from an Administrator console with Python and will created symlinks to the *Voxels* library for use by the 98 | application on runtime. You should respect the above given directory structure for this to work. 99 | 100 | ## License 101 | 102 | Code for the sample is licensed under the "New BSD License". The **Voxels** Library is free to use but with some limitations 103 | desribed in it's repo. 104 | 105 | *Feedback welcome!* 106 | -------------------------------------------------------------------------------- /Shaders/DrawSurface.fx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | 7 | cbuffer PerFrame : register(b0) 8 | { 9 | matrix View; 10 | matrix Projection; 11 | }; 12 | 13 | cbuffer PerBlockBuffer : register(b1) 14 | { 15 | matrix World; 16 | matrix InvTranspWorld; 17 | vector Properties; // x - adj. flags, y - lod level(debug) 18 | }; 19 | 20 | // Scales the UV coordinates of textures 21 | cbuffer TextureProperties : register(b2) 22 | { 23 | float4 UVScale[256 / 4]; 24 | }; 25 | 26 | struct VSInput 27 | { 28 | float4 Pos : POSITION0; 29 | float4 SecondaryPos : POSITION1; 30 | float3 Normal : TEXCOORD0; 31 | uint2 TextureIndices : TEXCOORD1; 32 | }; 33 | 34 | // Use this define to visualize the LOD levels in color 35 | // NB: this define is incompatible with the normal rendering ones 36 | //#define DRAW_LOD_LEVEL 37 | 38 | // If you don't draw textures - the normals will be shown 39 | #define DRAW_TEXTURES 40 | #define DRAW_LIGHTING 41 | 42 | struct VSOutput 43 | { 44 | float4 Pos : SV_POSITION; 45 | #ifdef DRAW_LOD_LEVEL 46 | float3 Color : TEXCOORD0; 47 | #else 48 | float3 Normal : TEXCOORD0; 49 | float3 ObjectPosition : TEXCOORD1; 50 | uint2 TextureIndices : TEXCOORD2; 51 | float TexBlend : TEXCOORD3; 52 | 53 | float3 Tangent1 : TEXCOORD4; 54 | float3 Tangent2 : TEXCOORD5; 55 | #endif 56 | }; 57 | 58 | SamplerState texSampler : register(s0); 59 | Texture2DArray diffuseTextures : register(t0); 60 | Texture2DArray normalTextures : register(t1); 61 | 62 | float4 SelectPositionCell(int vertexAdj, int blockAdj, float4 primary, float4 secondary) { 63 | if(vertexAdj && ((vertexAdj & blockAdj) == vertexAdj)) { 64 | return float4(secondary.xyz, 1); 65 | } else { 66 | return primary; 67 | } 68 | } 69 | 70 | #ifdef DRAW_LOD_LEVEL 71 | // Debug LOD level rendering 72 | VSOutput DrawLODOutput(VSInput input, float4 inPos) { 73 | VSOutput output = (VSOutput)0; 74 | 75 | output.Pos = mul(inPos, World); 76 | output.Pos = mul(output.Pos, View); 77 | output.Pos = mul(output.Pos, Projection); 78 | 79 | float3 lodColors[] = 80 | { 81 | float3(0, 0, 0), 82 | float3(0.5f, 0.5f, 0.5f), 83 | float3(1.0f, 0.0f, 0.0f), 84 | float3(0.0f, 1.0f, 0.0f), 85 | float3(0.0f, 0.0f, 1.0f), 86 | float3(0.0f, 1.0f, 1.0f), 87 | float3(1.0f, 1.0f, 0.0f), 88 | float3(1.0f, 0.0f, 1.0f) 89 | }; 90 | 91 | int lodlevel = asint(Properties.y); 92 | 93 | output.Color = lodColors[lodlevel]; 94 | 95 | return output; 96 | } 97 | 98 | #else 99 | 100 | #define TBN_EPSILON 0.03125f 101 | // Normal rendering 102 | VSOutput CalculateOutput(VSInput input, float4 inPos) { 103 | VSOutput output = (VSOutput)0; 104 | 105 | output.ObjectPosition = inPos; 106 | 107 | output.Pos = mul(inPos, World); 108 | output.Pos = mul(output.Pos, View); 109 | output.Pos = mul(output.Pos, Projection); 110 | 111 | output.Normal = mul(input.Normal, InvTranspWorld); 112 | 113 | const float t1denom = max(sqrt(output.Normal.x * output.Normal.x + output.Normal.y * output.Normal.y), TBN_EPSILON); 114 | output.Tangent1 = float3(output.Normal.y / t1denom, -output.Normal.x / t1denom, 0); 115 | 116 | const float t2denom = max(sqrt(output.Normal.x * output.Normal.x + output.Normal.z * output.Normal.z), TBN_EPSILON); 117 | output.Tangent2 = float3(-output.Normal.z / t2denom, 0, output.Normal.x / t2denom); 118 | 119 | output.TextureIndices = input.TextureIndices; 120 | output.TexBlend = ((input.TextureIndices[0] >> 8) & 0xFF) / 255.f; 121 | 122 | return output; 123 | } 124 | #endif // DRAW_LOD_LEVEL 125 | 126 | VSOutput VS(VSInput input) 127 | { 128 | int vertexAdj = asint(input.SecondaryPos.w); 129 | int blockAdj = asint(Properties.x); 130 | 131 | float4 inPos = SelectPositionCell(vertexAdj, blockAdj, input.Pos, input.SecondaryPos); 132 | #ifdef DRAW_LOD_LEVEL // For debug puposes 133 | return DrawLODOutput(input, inPos); 134 | #else 135 | return CalculateOutput(input, inPos); 136 | #endif 137 | } 138 | 139 | VSOutput VSTransition(VSInput input) 140 | { 141 | int vertexAdj = asint(input.SecondaryPos.w); 142 | int blockAdj = asint(Properties.x); 143 | 144 | float4 inPos = SelectPositionCell(vertexAdj, blockAdj, input.Pos, input.SecondaryPos); 145 | #ifdef DRAW_LOD_LEVEL 146 | return DrawLODOutput(input, inPos); 147 | #else 148 | return CalculateOutput(input, inPos); 149 | #endif 150 | } 151 | 152 | float4 PS(VSOutput input) : SV_Target 153 | { 154 | #ifdef DRAW_LOD_LEVEL 155 | return float4(input.Color, 1.0f); 156 | #else 157 | static const float3 SUN_DIRECTION = normalize(float3(.5, 1, 0.5)); 158 | static const float AMBIENT = 0.15f; 159 | 160 | const float delta = 0.5f; 161 | const float m = 4.f; 162 | 163 | #ifdef DRAW_TEXTURES 164 | const float3 normal = normalize(input.Normal); 165 | float3 blend = saturate(abs(normal) - delta); 166 | blend = pow(blend, m); 167 | blend /= dot(blend, float3(1.0f, 1.0f, 1.0f)); 168 | 169 | // Txz, Uxz 170 | float2 material1 = float2(input.TextureIndices[0] >> 24, (input.TextureIndices[0] >> 16) & 0xFF); 171 | // Tpy, Tny, Upy, Uny 172 | float4 material2 = float4(input.TextureIndices[1] >> 24 173 | , (input.TextureIndices[1] >> 16) & 0xFF 174 | , (input.TextureIndices[1] >> 8) & 0xFF 175 | , (input.TextureIndices[1]) & 0xFF); 176 | 177 | float3 flip = float3(normal.x < 0.0, normal.y < 0.0, normal.z >= 0.0); 178 | 179 | float2 zindex = lerp(material2.xz, material2.yw, flip.y); 180 | 181 | float3 p = input.ObjectPosition; 182 | 183 | float3 s = lerp(p.zxx, -p.zxx, flip.xzy); 184 | float3 t = p.yyz; 185 | 186 | // Scale UV coordinates for artistic freedom 187 | float scalingFactor0xz = UVScale[floor(material1.x / 4)][int(material1.x) % 4]; 188 | float scalingFactor0y = UVScale[floor(zindex.x / 4)][int(zindex.x) % 4]; 189 | float scalingFactor1xz = UVScale[floor(material1.y / 4)][int(material1.y) % 4]; 190 | float scalingFactor1y = UVScale[floor(zindex.y / 4)][int(zindex.y) % 4]; 191 | 192 | // Sample the diffuse color 193 | const float3 cx0 = diffuseTextures.Sample(texSampler, float3(float2(s.x, t.x) / scalingFactor0xz, material1.x)).xyz; 194 | const float3 cz0 = diffuseTextures.Sample(texSampler, float3(float2(s.y, t.y) / scalingFactor0xz, material1.x)).xyz; 195 | const float3 cy0 = diffuseTextures.Sample(texSampler, float3(float2(s.z, t.z) / scalingFactor0y, zindex.x)).xyz; 196 | 197 | const float3 cx1 = diffuseTextures.Sample(texSampler, float3(float2(s.x, t.x) / scalingFactor1xz, material1.y)).xyz; 198 | const float3 cz1 = diffuseTextures.Sample(texSampler, float3(float2(s.y, t.y) / scalingFactor1xz, material1.y)).xyz; 199 | const float3 cy1 = diffuseTextures.Sample(texSampler, float3(float2(s.z, t.z) / scalingFactor1y, zindex.y)).xyz; 200 | 201 | float3 albedo = lerp((blend.x * cx0 + blend.y * cy0 + blend.z * cz0), (blend.x * cx1 + blend.y * cy1 + blend.z * cz1), input.TexBlend); 202 | 203 | // Calculate tangent & bitangent 204 | const float3 tangent1 = normalize(input.Tangent1); 205 | const float3 tangent2 = normalize(input.Tangent2); 206 | 207 | const float3 bitangent1 = normalize(cross(tangent1, normal)); 208 | const float3 bitangent2 = normalize(cross(tangent2, normal)); 209 | 210 | // Fetch and calculate normals 211 | const float3 nx0 = normalTextures.Sample(texSampler, float3(float2(s.x, t.x) / scalingFactor0xz, material1.x)).xyz; 212 | const float3 nz0 = normalTextures.Sample(texSampler, float3(float2(s.y, t.y) / scalingFactor0xz, material1.x)).xyz; 213 | const float3 ny0 = normalTextures.Sample(texSampler, float3(float2(s.z, t.z) / scalingFactor0y, zindex.x)).xyz; 214 | 215 | const float3 nx1 = normalTextures.Sample(texSampler, float3(float2(s.x, t.x) / scalingFactor1xz, material1.y)).xyz; 216 | const float3 nz1 = normalTextures.Sample(texSampler, float3(float2(s.y, t.y) / scalingFactor1xz, material1.y)).xyz; 217 | const float3 ny1 = normalTextures.Sample(texSampler, float3(float2(s.z, t.z) / scalingFactor1y, zindex.y)).xyz; 218 | 219 | const float3 nx = normalize(lerp(nx0, nx1, input.TexBlend) * 2.0f - 1.0f); 220 | const float3 ny = normalize(lerp(ny0, ny1, input.TexBlend) * 2.0f - 1.0f); 221 | const float3 nz = normalize(lerp(nz0, nz1, input.TexBlend) * 2.0f - 1.0f); 222 | 223 | const float3x3 tbn1 = transpose(float3x3(tangent1, bitangent1, normal)); 224 | const float3x3 tbn2 = transpose(float3x3(tangent2, bitangent2, normal)); 225 | 226 | const float3 sun_dir1 = mul(SUN_DIRECTION, tbn1); 227 | const float3 sun_dir2 = mul(SUN_DIRECTION, tbn2); 228 | 229 | float3 nl_vec = float3(saturate(dot(nx, sun_dir1)), 230 | saturate(dot(ny, sun_dir1)), 231 | saturate(dot(nz, sun_dir2))); 232 | 233 | float nl = dot(nl_vec, blend); 234 | 235 | #ifdef DRAW_LIGHTING 236 | albedo = saturate(albedo * (nl + AMBIENT)); 237 | #endif 238 | 239 | return float4(albedo, 1.0f); 240 | #else 241 | return float4(input.Normal, 1.0f); 242 | #endif // DRAW_TEXTURES 243 | 244 | #endif // DRAW_LOD_LEVELS 245 | } 246 | -------------------------------------------------------------------------------- /Source/ClearRenderingRoutine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "ClearRenderingRoutine.h" 9 | 10 | bool ClearRenderingRoutine::Render(float deltaTime) 11 | { 12 | ID3D11DeviceContext* context = m_Renderer->GetImmediateContext(); 13 | 14 | // Set rt to back buffer 15 | ID3D11RenderTargetView* bbufferRTV = m_Renderer->GetBackBufferView(); 16 | context->OMSetRenderTargets(1, &bbufferRTV, m_Renderer->GetBackDepthStencilView()); 17 | 18 | // Clear the back buffer 19 | float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; 20 | context->ClearRenderTargetView(m_Renderer->GetBackBufferView(), ClearColor); 21 | context->ClearDepthStencilView(m_Renderer->GetBackDepthStencilView(), D3D11_CLEAR_DEPTH, 1.0f, 0); 22 | 23 | return true; 24 | } -------------------------------------------------------------------------------- /Source/ClearRenderingRoutine.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | 10 | class ClearRenderingRoutine : public DxRenderingRoutine 11 | { 12 | public: 13 | virtual bool Render(float deltaTime); 14 | }; -------------------------------------------------------------------------------- /Source/ConstBufferTypes.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | struct PerFrameBuffer 9 | { 10 | DirectX::XMMATRIX View; 11 | DirectX::XMMATRIX Projection; 12 | }; 13 | 14 | struct PerSubsetBuffer 15 | { 16 | DirectX::XMMATRIX World; 17 | DirectX::XMVECTOR MaterialParams; 18 | }; 19 | 20 | struct PerBlockBuffer 21 | { 22 | DirectX::XMMATRIX World; 23 | DirectX::XMMATRIX InvTranspWorld; 24 | DirectX::XMVECTOR Properties; // x - adjacency flags, y - block level(debug) 25 | }; 26 | 27 | struct TexturePropertiesBuffer 28 | { 29 | float UVScale[256]; 30 | }; 31 | 32 | struct GridProperties 33 | { 34 | DirectX::XMVECTOR Properties; 35 | }; 36 | -------------------------------------------------------------------------------- /Source/DrawRoutine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "DrawRoutine.h" 9 | #include "ConstBufferTypes.h" 10 | #include "VertexTypes.h" 11 | #include "Scene.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace DirectX; 18 | 19 | DrawRoutine::DrawRoutine() 20 | : m_DrawSolid(true) 21 | , m_DrawSurface(true) 22 | , m_DrawWireframe(false) 23 | , m_DrawTransitions(true) 24 | , m_CurrentLodToDraw(0) 25 | , m_UseLodOctree(true) 26 | , m_LodUpdate(true) 27 | {} 28 | 29 | DrawRoutine::~DrawRoutine() 30 | {} 31 | 32 | bool DrawRoutine::Initialize(Renderer* renderer, Camera* camera, const XMFLOAT4X4& projection, Scene* scene) 33 | { 34 | DxRenderingRoutine::Initialize(renderer); 35 | 36 | m_Camera = camera; 37 | m_Projection = projection; 38 | m_Scene = scene; 39 | 40 | ShaderManager shaderManager(m_Renderer->GetDevice()); 41 | ShaderManager::CompilationOutput compilationResult; 42 | // Create shaders 43 | if(!shaderManager.CompileShaderDuo("..\\Shaders\\DrawSurface.fx" 44 | , "VS" 45 | , "vs_4_0" 46 | , "PS" 47 | , "ps_4_0" 48 | , compilationResult)) 49 | { 50 | compilationResult.ReleaseAll(); 51 | return false; 52 | } 53 | 54 | ReleaseGuard vsGuard(compilationResult.vsBlob); 55 | ReleaseGuard psGuard(compilationResult.psBlob); 56 | m_VS.Set(compilationResult.vertexShader); 57 | m_PS.Set(compilationResult.pixelShader); 58 | 59 | m_VSTransition.Set(shaderManager.CompileVertexShader("..\\Shaders\\DrawSurface.fx", "VSTransition", "vs_4_0")); 60 | if(!m_VSTransition.Get()) { 61 | SLOG(Sev_Error, Fac_Rendering, "Unable to compile transition VS"); 62 | return false; 63 | } 64 | 65 | // Create per frame buffer 66 | if(!shaderManager.CreateEasyConstantBuffer(m_PerFrameBuffer.Receive())) 67 | { 68 | SLOG(Sev_Error, Fac_Rendering, "Unable to create per frame buffer"); 69 | return false; 70 | } 71 | 72 | // Create per-subset properties buffer 73 | if(!shaderManager.CreateEasyConstantBuffer(m_PerBlockBuffer.Receive())) 74 | { 75 | SLOG(Sev_Error, Fac_Rendering, "Unable to create per-block buffer"); 76 | return false; 77 | } 78 | 79 | // Create texture props buffer 80 | if(!shaderManager.CreateEasyConstantBuffer(m_TexturePropsBuffer.Receive())) 81 | { 82 | SLOG(Sev_Error, Fac_Rendering, "Unable to create texture properties buffer"); 83 | return false; 84 | } 85 | 86 | UINT numElements = ARRAYSIZE(SurfaceVertexLayout); 87 | HRESULT hr = S_OK; 88 | // Create the input layout 89 | hr = m_Renderer->GetDevice()->CreateInputLayout(SurfaceVertexLayout, numElements, vsGuard.Get()->GetBufferPointer(), 90 | vsGuard.Get()->GetBufferSize(), m_SurfaceVertexLayout.Receive()); 91 | if(FAILED(hr)) 92 | { 93 | SLOG(Sev_Error, Fac_Rendering, "Unable to create input layout"); 94 | return false; 95 | } 96 | 97 | CD3D11_RASTERIZER_DESC rsDesc((CD3D11_DEFAULT())); 98 | rsDesc.FrontCounterClockwise = TRUE; 99 | //rsDesc.CullMode = D3D11_CULL_NONE; 100 | hr = m_Renderer->GetDevice()->CreateRasterizerState(&rsDesc, m_RasterizerState.Receive()); 101 | if(FAILED(hr)) 102 | { 103 | SLOG(Sev_Error, Fac_Rendering, "Unable to create rasterizer state for surface"); 104 | return false; 105 | } 106 | rsDesc.FillMode = D3D11_FILL_WIREFRAME; 107 | hr = m_Renderer->GetDevice()->CreateRasterizerState(&rsDesc, m_WireframeRasterizerState.Receive()); 108 | if(FAILED(hr)) 109 | { 110 | SLOG(Sev_Error, Fac_Rendering, "Unable to create wireframe rasterizer state for surface"); 111 | return false; 112 | } 113 | 114 | auto texManager = m_Renderer->GetTextureManager(); 115 | 116 | // Create sampler 117 | m_SamplerState.Set(texManager.MakeSampler(D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_WRAP)); 118 | 119 | // Load textures 120 | const auto& diffuseFiles = m_Scene->GetMaterials().GetDiffuseTextureList(); 121 | m_DiffuseTextures = texManager.LoadTexture2DArray(diffuseFiles, "../media/textures", true); 122 | if(!m_DiffuseTextures) 123 | { 124 | SLOG(Sev_Error, Fac_Rendering, "Unable to load diffuse terrain textures"); 125 | return false; 126 | } 127 | 128 | // load normal maps 129 | MaterialTable::TextureNames normalFiles; 130 | normalFiles.reserve(diffuseFiles.size()); 131 | std::transform(diffuseFiles.cbegin(), diffuseFiles.cend(), std::back_inserter(normalFiles), [](const std::string& filename) { 132 | std::string name(filename.begin(), filename.begin() + filename.find_first_of('.')); 133 | return name + "_normal.dds"; 134 | }); 135 | 136 | m_NormalTextures = texManager.LoadTexture2DArray(normalFiles, "../media/textures", false); 137 | if (!m_NormalTextures) 138 | { 139 | SLOG(Sev_Error, Fac_Rendering, "Unable to load normal terrain textures"); 140 | return false; 141 | } 142 | 143 | if(!ReloadGrid()) 144 | return false; 145 | 146 | return true; 147 | } 148 | 149 | bool DrawRoutine::CreateBuffersForBlock(const Voxels::BlockPolygons* inBlock, LodLevel::BlockData& outputBlock) { 150 | unsigned indicesCnt = 0; 151 | auto indices = inBlock->GetIndices(&indicesCnt); 152 | if (!indicesCnt) { 153 | return true; 154 | } 155 | unsigned verticesCnt = 0; 156 | auto vertices = inBlock->GetVertices(&verticesCnt); 157 | 158 | D3D11_BUFFER_DESC vbDesc; 159 | ::ZeroMemory(&vbDesc, sizeof(vbDesc)); 160 | vbDesc.Usage = D3D11_USAGE_DEFAULT; 161 | vbDesc.ByteWidth = sizeof(SurfaceVertex)* verticesCnt; 162 | vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 163 | vbDesc.CPUAccessFlags = 0; 164 | D3D11_SUBRESOURCE_DATA InitData; 165 | ::ZeroMemory(&InitData, sizeof(InitData)); 166 | InitData.pSysMem = vertices; 167 | 168 | HRESULT hr = m_Renderer->GetDevice()->CreateBuffer(&vbDesc, &InitData, outputBlock.VertexBuffer.Receive()); 169 | if(FAILED(hr)) 170 | { 171 | SLOG(Sev_Error, Fac_Rendering, "Unable to create vertex buffer for surface"); 172 | return false; 173 | } 174 | 175 | D3D11_BUFFER_DESC ibDesc; 176 | ::ZeroMemory(&ibDesc, sizeof(ibDesc)); 177 | ibDesc.Usage = D3D11_USAGE_DEFAULT; 178 | ibDesc.ByteWidth = sizeof(int)* indicesCnt; 179 | ibDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; 180 | ibDesc.CPUAccessFlags = 0; 181 | ::ZeroMemory(&InitData, sizeof(InitData)); 182 | InitData.pSysMem = indices; 183 | 184 | hr = m_Renderer->GetDevice()->CreateBuffer(&ibDesc, &InitData, outputBlock.IndexBuffer.Receive()); 185 | if(FAILED(hr)) 186 | { 187 | SLOG(Sev_Error, Fac_Rendering, "Unable to create index buffer for surface"); 188 | return false; 189 | } 190 | outputBlock.IndicesSize = indicesCnt; 191 | 192 | // Create the transition buffers 193 | for (auto tr = 0u; tr < Voxels::BlockPolygons::Face_Count; ++tr) { 194 | unsigned transitionVerticesCnt = 0; 195 | auto transitionInVertices = inBlock->GetTransitionVertices( 196 | Voxels::BlockPolygons::TransitionFaceId(tr), &transitionVerticesCnt); 197 | unsigned transitionIndicesCnt = 0; 198 | auto transitionInIndices = inBlock->GetTransitionIndices( 199 | Voxels::BlockPolygons::TransitionFaceId(tr), &transitionIndicesCnt); 200 | 201 | outputBlock.TransitionIndicesSizes.push_back(transitionIndicesCnt); 202 | outputBlock.TransitionVertexBuffers.push_back(ReleaseGuard()); 203 | outputBlock.TransitionIndexBuffers.push_back(ReleaseGuard()); 204 | 205 | if (!transitionIndicesCnt) { 206 | continue; 207 | } 208 | 209 | vbDesc.ByteWidth = sizeof(SurfaceVertex)* transitionVerticesCnt; 210 | InitData.pSysMem = transitionInVertices; 211 | hr = m_Renderer->GetDevice()->CreateBuffer(&vbDesc, &InitData, outputBlock.TransitionVertexBuffers[tr].Receive()); 212 | if(FAILED(hr)) 213 | { 214 | SLOG(Sev_Error, Fac_Rendering, "Unable to create transition vertex buffer for block!"); 215 | return false; 216 | } 217 | 218 | ibDesc.ByteWidth = sizeof(int) * transitionIndicesCnt; 219 | InitData.pSysMem = transitionInIndices; 220 | hr = m_Renderer->GetDevice()->CreateBuffer(&ibDesc, &InitData, outputBlock.TransitionIndexBuffers[tr].Receive()); 221 | if(FAILED(hr)) 222 | { 223 | SLOG(Sev_Error, Fac_Rendering, "Unable to create transition index buffer for block!"); 224 | return false; 225 | } 226 | } 227 | 228 | return true; 229 | } 230 | 231 | bool DrawRoutine::ReloadGrid() 232 | { 233 | SLOG(Sev_Debug, Fac_Rendering, "Uploading grid polygons to GPU..."); 234 | 235 | const auto surface = m_Scene->GetPolygonSurface(); 236 | 237 | const auto levelsCount = surface->GetLevelsCount(); 238 | 239 | m_LodLevels.clear(); 240 | m_BlocksMap.clear(); 241 | m_LodLevels.resize(levelsCount); 242 | 243 | for(auto lodLevel = 0u; lodLevel < levelsCount; ++lodLevel) { 244 | auto blocksCount = surface->GetBlocksForLevelCount(lodLevel); 245 | assert(blocksCount); 246 | 247 | auto& currentLodLevel = m_LodLevels[lodLevel]; 248 | currentLodLevel.Blocks.resize(blocksCount); 249 | 250 | for(auto blockId = 0u; blockId < blocksCount; ++blockId) { 251 | auto& currentOutputBlock = currentLodLevel.Blocks[blockId]; 252 | auto inBlock = surface->GetBlockForLevel(lodLevel, blockId); 253 | 254 | const auto inputBlockId = inBlock->GetId(); 255 | currentOutputBlock.Id = inputBlockId; 256 | currentOutputBlock.LODLevel = lodLevel; 257 | m_BlocksMap.insert(std::make_pair(inputBlockId, ¤tOutputBlock)); 258 | 259 | if(!CreateBuffersForBlock(inBlock, currentOutputBlock)) 260 | return false; 261 | } 262 | } 263 | 264 | SLOG(Sev_Debug, Fac_Rendering, "Successfully uploaded grid polygons to GPU"); 265 | 266 | UpdateCulledObjects(); 267 | 268 | // Update the texture properties 269 | ID3D11DeviceContext* context = m_Renderer->GetImmediateContext(); 270 | const auto& props = m_Scene->GetMaterials().GetDiffuseTextureProperties(); 271 | TexturePropertiesBuffer tpb; 272 | ::memcpy(&tpb, &props[0], sizeof(MaterialTable::TextureProperties) * props.size()); 273 | context->UpdateSubresource(m_TexturePropsBuffer.Get(), 0, nullptr, &tpb, 0, 0); 274 | 275 | return true; 276 | } 277 | 278 | bool DrawRoutine::UpdateGrid() { 279 | SLOG(Sev_Debug, Fac_Rendering, "Uploading modified grid polygons to GPU.."); 280 | 281 | m_BlocksMap.clear(); 282 | 283 | const auto surface = m_Scene->GetPolygonSurface(); 284 | const auto levelsCount = surface->GetLevelsCount(); 285 | for(auto lodLevel = 0u; lodLevel < levelsCount; ++lodLevel) { 286 | auto blocksCnt = surface->GetBlocksForLevelCount(lodLevel); 287 | assert(blocksCnt); 288 | 289 | //TODO: the whole algo is somewhat unoptimal due to the many traversals of the 290 | // structs. However the element count is relatively low so optimizing it is not 291 | // a priority for now 292 | 293 | auto& currentBlocksOut = m_LodLevels[lodLevel].Blocks; 294 | // find all blocks that have been modified and need deletion 295 | auto last = std::remove_if(currentBlocksOut.begin(), 296 | currentBlocksOut.end(), [&](LodLevel::BlockData& outBlock) { 297 | for (auto bl = 0; bl < blocksCnt; ++bl) 298 | { 299 | if (outBlock.Id == surface->GetBlockForLevel(lodLevel, bl)->GetId()) 300 | { 301 | return false; 302 | } 303 | } 304 | return true; 305 | }); 306 | 307 | // delete the old blocks 308 | currentBlocksOut.erase(last, currentBlocksOut.end()); 309 | currentBlocksOut.reserve(blocksCnt); 310 | 311 | // create the buffers for all new blocks 312 | for (auto bl = 0; bl < blocksCnt; ++bl) { 313 | auto inBlock = surface->GetBlockForLevel(lodLevel, bl); 314 | auto found = std::find_if(currentBlocksOut.begin(), currentBlocksOut.end(), [&](LodLevel::BlockData& outBlock) { 315 | return outBlock.Id == inBlock->GetId(); 316 | }); 317 | 318 | if(found != currentBlocksOut.cend()) 319 | continue; 320 | 321 | currentBlocksOut.push_back(LodLevel::BlockData()); 322 | auto& outBlock = currentBlocksOut.back(); 323 | outBlock.Id = inBlock->GetId(); 324 | outBlock.LODLevel = lodLevel; 325 | if(!CreateBuffersForBlock(inBlock, outBlock)) 326 | return false; 327 | } 328 | 329 | std::for_each(currentBlocksOut.begin(), currentBlocksOut.end(), [&](LodLevel::BlockData& outBlock) { 330 | m_BlocksMap.insert(std::make_pair(outBlock.Id, &outBlock)); 331 | }); 332 | } 333 | 334 | SLOG(Sev_Debug, Fac_Rendering, "Successfully uploaded modified grid polygons to GPU"); 335 | 336 | // Update the culled objects here - otherwise if culling updates are disabled we might 337 | // remain with invalid block IDs in the block to draw collection 338 | UpdateCulledObjects(); 339 | 340 | return true; 341 | } 342 | 343 | void DrawRoutine::UpdateCulledObjects() { 344 | // The drawn surface might have some transformation (in the world matrix). 345 | // The Cull & LOD class expects works with the un-transformed grid so we have 346 | // to transform our Camera and Frustum planes in the objects space of the 347 | // gid. 348 | 349 | auto camPos = m_Camera->GetPos(); 350 | XMFLOAT4 frustumPlanes[6]; 351 | FrustumCuller::CalculateFrustumPlanes(m_Camera->GetViewMatrix(), m_Projection, frustumPlanes); 352 | 353 | const auto worldMat = XMLoadFloat4x4(&m_Scene->GetGridWorldMatrix()); 354 | XMVECTOR det; 355 | const auto invWorld = XMMatrixInverse(&det, worldMat); 356 | // To transform the planes we need to transform by the inverse-transpose of the matrix 357 | // We want to go from world to grid space so we want to transform with the inv(world) matrix 358 | // So we have transp(inv(inv(world))) which is just transp(world) 359 | const auto transpWorld = XMMatrixTranspose(worldMat); 360 | 361 | // Convert to grid space 362 | for (int i = 0; i < 6; ++i) 363 | { 364 | XMVECTOR plane = XMLoadFloat4(&frustumPlanes[i]); 365 | plane = XMPlaneNormalize(XMPlaneTransform(plane, transpWorld)); 366 | XMStoreFloat4(&frustumPlanes[i], plane); 367 | } 368 | XMVECTOR camVec = XMLoadFloat3(&camPos); 369 | camVec = XMVector3Transform(camVec, invWorld); 370 | XMStoreFloat3(&camPos, camVec); 371 | 372 | m_BlockToDraw = m_Scene->GetLodOctree().Cull(frustumPlanes, camPos); 373 | } 374 | 375 | bool DrawRoutine::Render(float deltaTime) 376 | { 377 | ID3D11DeviceContext* context = m_Renderer->GetImmediateContext(); 378 | 379 | ReleaseGuard oldRsState; 380 | context->RSGetState(oldRsState.Receive()); 381 | context->RSSetState(m_RasterizerState.Get()); 382 | 383 | ReleaseGuard oldSamplerState; 384 | context->PSGetSamplers(0, 1, oldSamplerState.Receive()); 385 | context->PSSetSamplers(0, 1, m_SamplerState.GetConstPP()); 386 | 387 | context->PSSetShader(m_PS.Get(), nullptr, 0); 388 | context->IASetInputLayout(m_SurfaceVertexLayout.Get()); 389 | UINT strides[] = { sizeof(Voxels::PolygonVertex) }; 390 | UINT offsets[] = { 0 }; 391 | context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 392 | 393 | PerFrameBuffer pfb; 394 | pfb.Projection = XMMatrixTranspose(XMLoadFloat4x4(&m_Projection)); 395 | pfb.View = XMMatrixTranspose(XMLoadFloat4x4(&m_Camera->GetViewMatrix())); 396 | context->UpdateSubresource(m_PerFrameBuffer.Get(), 0, nullptr, &pfb, 0, 0); 397 | 398 | PerBlockBuffer psb; 399 | XMMATRIX world = XMLoadFloat4x4(&m_Scene->GetGridWorldMatrix()); 400 | psb.World = XMMatrixTranspose(world); 401 | XMVECTOR determinant; 402 | auto invWrold = XMMatrixInverse(&determinant, world); 403 | psb.InvTranspWorld = invWrold; 404 | 405 | // Set shaders 406 | context->VSSetConstantBuffers(0, 1, m_PerFrameBuffer.GetConstPP()); 407 | context->VSSetConstantBuffers(1, 1, m_PerBlockBuffer.GetConstPP()); 408 | context->PSSetConstantBuffers(2, 1, m_TexturePropsBuffer.GetConstPP()); 409 | 410 | // Set textures 411 | ID3D11ShaderResourceView* const psTextures[] = {m_DiffuseTextures->GetSHRV(), m_NormalTextures->GetSHRV()}; 412 | context->PSSetShaderResources(0, 2, psTextures); 413 | 414 | if(m_UseLodOctree) { 415 | if(m_LodUpdate) { 416 | UpdateCulledObjects(); 417 | } 418 | } else { 419 | m_BlockToDraw.clear(); 420 | auto& currentLodLevel = m_LodLevels[m_CurrentLodToDraw]; 421 | std::for_each(currentLodLevel.Blocks.begin(), currentLodLevel.Blocks.end(), 422 | [&](LodLevel::BlockData& block) { 423 | auto outputBlock = Voxels::VoxelLodOctree::VisibleBlock(block.Id); 424 | std::fill(outputBlock.TransitionFaces, outputBlock.TransitionFaces + 6, true); 425 | m_BlockToDraw.push_back(outputBlock); 426 | }); 427 | } 428 | 429 | const auto blocksCount = m_BlockToDraw.size(); 430 | for(auto id = 0u; id < blocksCount; ++id) { 431 | auto blockIt = m_BlocksMap.find(m_BlockToDraw[id].Id); 432 | assert(blockIt != m_BlocksMap.end()); 433 | auto& currentBlock = blockIt->second; 434 | 435 | if(!currentBlock->IndexBuffer.Get()) 436 | continue; 437 | 438 | int transitionFlags = 0; 439 | for(auto tr = 0u; tr < 6; ++tr) { 440 | if(!currentBlock->TransitionIndicesSizes[tr] || !m_BlockToDraw[id].TransitionFaces[tr]) 441 | continue; 442 | transitionFlags |= (1 << tr); 443 | } 444 | psb.Properties = XMVectorSetInt(transitionFlags, currentBlock->LODLevel, 0, 0); 445 | context->UpdateSubresource(m_PerBlockBuffer.Get(), 0, nullptr, &psb, 0, 0); 446 | 447 | if(m_DrawSurface) { 448 | context->VSSetShader(m_VS.Get(), nullptr, 0); 449 | 450 | context->IASetIndexBuffer(currentBlock->IndexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); 451 | context->IASetVertexBuffers(0, 1, currentBlock->VertexBuffer.GetConstPP(), strides, offsets); 452 | 453 | // Draw 454 | if(m_DrawSolid) 455 | { 456 | context->DrawIndexed(currentBlock->IndicesSize, 0, 0); 457 | } 458 | 459 | if(m_DrawWireframe) 460 | { 461 | context->RSSetState(m_WireframeRasterizerState.Get()); 462 | context->DrawIndexed(currentBlock->IndicesSize, 0, 0); 463 | context->RSSetState(oldRsState.Get()); 464 | } 465 | } 466 | if(m_DrawTransitions) { 467 | context->VSSetShader(m_VSTransition.Get(), nullptr, 0); 468 | for(auto tr = 0u; tr < 6; ++tr) { 469 | if(!currentBlock->TransitionIndicesSizes[tr] || !m_BlockToDraw[id].TransitionFaces[tr]) 470 | continue; 471 | 472 | context->IASetIndexBuffer(currentBlock->TransitionIndexBuffers[tr].Get(), DXGI_FORMAT_R32_UINT, 0); 473 | context->IASetVertexBuffers(0, 1, currentBlock->TransitionVertexBuffers[tr].GetConstPP(), strides, offsets); 474 | if(m_DrawSolid) 475 | { 476 | context->DrawIndexed(currentBlock->TransitionIndicesSizes[tr], 0, 0); 477 | } 478 | if(m_DrawWireframe) 479 | { 480 | context->RSSetState(m_WireframeRasterizerState.Get()); 481 | context->DrawIndexed(currentBlock->TransitionIndicesSizes[tr], 0, 0); 482 | context->RSSetState(oldRsState.Get()); 483 | } 484 | } 485 | } 486 | } 487 | 488 | context->PSSetSamplers(0, 1, oldSamplerState.GetConstPP()); 489 | 490 | return true; 491 | } 492 | 493 | unsigned DrawRoutine::SetCurrentLodToDraw(unsigned id) 494 | { 495 | m_CurrentLodToDraw = std::min(std::max(0u, id), m_Scene->GetPolygonSurface()->GetLevelsCount() - 1); 496 | return m_CurrentLodToDraw; 497 | } 498 | 499 | unsigned DrawRoutine::GetCurrentLodToDraw() const 500 | { 501 | return m_CurrentLodToDraw; 502 | } 503 | -------------------------------------------------------------------------------- /Source/DrawRoutine.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Voxel/VoxelLodOctree.h" 13 | #include "Scene.h" 14 | 15 | class Camera; 16 | class AllocatorBase; 17 | 18 | // Draws the polygonized surface. It's responsible for loading the grid 19 | // to the GPU and rendering the relevant blocks each frame. 20 | class DrawRoutine : public DxRenderingRoutine, public Aligned<16> 21 | { 22 | public: 23 | DrawRoutine(); 24 | virtual ~DrawRoutine(); 25 | 26 | virtual bool Initialize(Renderer* renderer, Camera* camera, const DirectX::XMFLOAT4X4& projection, Scene* scene); 27 | 28 | virtual bool Render(float deltaTime); 29 | 30 | bool ReloadGrid(); 31 | bool UpdateGrid(); 32 | 33 | bool GetDrawSolid() const { return m_DrawSolid; } 34 | void SetDrawSolid(bool draw) { m_DrawSolid = draw; }; 35 | 36 | bool GetDrawWireframe() const { return m_DrawWireframe; } 37 | void SetDrawWireframe(bool draw) { m_DrawWireframe = draw; }; 38 | 39 | bool GetDrawTransitions() const { return m_DrawTransitions; } 40 | void SetDrawTransitions(bool draw) { m_DrawTransitions = draw; }; 41 | 42 | bool GetDrawSurface() const { return m_DrawSurface; } 43 | void SetDrawSurface(bool draw) { m_DrawSurface = draw; }; 44 | 45 | unsigned SetCurrentLodToDraw(unsigned id); 46 | unsigned GetCurrentLodToDraw() const; 47 | 48 | bool GetUseLodOctree() const { return m_UseLodOctree; } 49 | void SetUseLodOctree(bool use) { m_UseLodOctree = use; m_DrawTransitions = use; }; 50 | 51 | bool GetLodUpdateEnabled() const { return m_LodUpdate; } 52 | void SetLodUpdateEnabled(bool enabled) { m_LodUpdate = enabled; }; 53 | 54 | private: 55 | void UpdateCulledObjects(); 56 | 57 | Camera* m_Camera; 58 | DirectX::XMFLOAT4X4 m_Projection; 59 | 60 | Scene* m_Scene; 61 | 62 | bool m_DrawSolid; 63 | bool m_DrawWireframe; 64 | bool m_DrawTransitions; 65 | bool m_DrawSurface; 66 | bool m_UseLodOctree; 67 | bool m_LodUpdate; 68 | 69 | Voxels::VoxelLodOctree::VisibleBlocksVec m_BlockToDraw; 70 | 71 | ReleaseGuard m_PerFrameBuffer; 72 | ReleaseGuard m_PerBlockBuffer; 73 | ReleaseGuard m_TexturePropsBuffer; 74 | 75 | ReleaseGuard m_SurfaceVertexLayout; 76 | 77 | typedef std::vector> BuffersVec; 78 | 79 | // An entire LOD level data uploaded on the GPU 80 | struct LodLevel : boost::noncopyable 81 | { 82 | LodLevel() {} 83 | LodLevel(LodLevel&& rhs) 84 | : Blocks(std::move(rhs.Blocks)) 85 | {} 86 | 87 | LodLevel& operator=(LodLevel&& rhs) { 88 | if(this != &rhs) { 89 | std::swap(Blocks, rhs.Blocks); 90 | } 91 | return *this; 92 | } 93 | 94 | // A block uploaded on the GPU 95 | struct BlockData 96 | { 97 | BlockData(){} 98 | 99 | BlockData(BlockData&& rhs) 100 | : Id(rhs.Id) 101 | , LODLevel(rhs.LODLevel) 102 | , VertexBuffer(std::move(rhs.VertexBuffer)) 103 | , IndexBuffer(std::move(rhs.IndexBuffer)) 104 | , IndicesSize(std::move(rhs.IndicesSize)) 105 | , TransitionVertexBuffers(std::move(rhs.TransitionVertexBuffers)) 106 | , TransitionIndexBuffers(std::move(rhs.TransitionIndexBuffers)) 107 | , TransitionIndicesSizes(std::move(rhs.TransitionIndicesSizes)) 108 | {} 109 | 110 | BlockData& operator=(BlockData&& rhs) 111 | { 112 | if(this != &rhs) { 113 | std::swap(Id, rhs.Id); 114 | std::swap(LODLevel, rhs.LODLevel); 115 | std::swap(VertexBuffer, rhs.VertexBuffer); 116 | std::swap(IndexBuffer, rhs.IndexBuffer); 117 | std::swap(IndicesSize, rhs.IndicesSize); 118 | std::swap(TransitionVertexBuffers, rhs.TransitionVertexBuffers); 119 | std::swap(TransitionIndexBuffers, rhs.TransitionIndexBuffers); 120 | std::swap(TransitionIndicesSizes, rhs.TransitionIndicesSizes); 121 | } 122 | return *this; 123 | } 124 | 125 | unsigned Id; 126 | unsigned LODLevel; 127 | ReleaseGuard VertexBuffer; 128 | ReleaseGuard IndexBuffer; 129 | unsigned IndicesSize; 130 | 131 | BuffersVec TransitionVertexBuffers; 132 | BuffersVec TransitionIndexBuffers; 133 | std::vector TransitionIndicesSizes; 134 | }; 135 | 136 | typedef std::vector BlocksVec; 137 | BlocksVec Blocks; 138 | }; 139 | bool CreateBuffersForBlock(const Voxels::BlockPolygons* inBlock, LodLevel::BlockData& outputBlock); 140 | 141 | typedef std::vector LodLevels; 142 | LodLevels m_LodLevels; 143 | unsigned m_CurrentLodToDraw; 144 | 145 | typedef std::map BlocksMap; 146 | BlocksMap m_BlocksMap; 147 | 148 | ReleaseGuard m_VS; 149 | ReleaseGuard m_VSTransition; 150 | ReleaseGuard m_PS; 151 | 152 | ReleaseGuard m_RasterizerState; 153 | ReleaseGuard m_WireframeRasterizerState; 154 | 155 | ReleaseGuard m_SamplerState; 156 | TexturePtr m_DiffuseTextures; 157 | TexturePtr m_NormalTextures; 158 | }; -------------------------------------------------------------------------------- /Source/HeightMapLoader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include "../Voxels/include/Grid.h" 9 | 10 | // Loads an image that can later be used as source for a voxel grid 11 | class HeightMapLoader 12 | { 13 | public: 14 | typedef Voxels::VoxelGrid grid_t; 15 | static bool Load(const std::string& filename, unsigned& w, std::shared_ptr& heightmap, float heightScale = 1.f); 16 | }; 17 | -------------------------------------------------------------------------------- /Source/HeightmapLoader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | 7 | #include "stdafx.h" 8 | #include "HeightMapLoader.h" 9 | 10 | #include "lodepng.h" 11 | #include 12 | 13 | using namespace DirectX; 14 | 15 | bool HeightMapLoader::Load(const std::string& filename, unsigned& w, std::shared_ptr& heightmap, float heightScale) 16 | { 17 | unsigned imageW = 0, imageH = 0; 18 | std::vector image; 19 | auto ec = lodepng::decode(image, imageW, imageH, filename); 20 | if(ec != 0) { 21 | SLLOG(Sev_Error, Fac_Rendering, "Unable to decode ", filename, " error: ", lodepng_error_text(ec)); 22 | return false; 23 | } 24 | 25 | if(imageW != imageH) { 26 | SLOG(Sev_Error, Fac_Rendering, "Only square heightmaps are supported. Failed generation on ", filename); 27 | return false; 28 | } 29 | 30 | heightmap = std::shared_ptr(new char[imageW*imageH], std::default_delete()); 31 | w = imageW; 32 | 33 | const auto heightPtr = heightmap.get(); 34 | const auto sz = image.size(); 35 | for (auto pixel = 0u, hid = 0u; pixel < sz; pixel += 4, ++hid) 36 | { 37 | heightPtr[hid] = (char)StMath::clamp_value(((int)image[pixel] - 127) * heightScale, -127, 127); 38 | } 39 | 40 | return true; 41 | } -------------------------------------------------------------------------------- /Source/MaterialTable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | 7 | #include "stdafx.h" 8 | 9 | #include "MaterialTable.h" 10 | 11 | #include 12 | #include 13 | 14 | bool MaterialTable::Load(const std::string& filename) 15 | { 16 | using boost::property_tree::ptree; 17 | ptree jsonTree; 18 | 19 | try { 20 | read_json(filename, jsonTree); 21 | } catch(std::exception& ex) { 22 | SLLOG(Sev_Error, Fac_Rendering, "Error reading materials file: ", ex.what()); 23 | } 24 | 25 | std::unordered_map propertiesSet; 26 | try { 27 | auto properties = jsonTree.get_child("properties"); 28 | 29 | std::for_each(properties.begin(), properties.end(), [&](ptree::value_type& property) { 30 | auto texObj = property.second.begin(); 31 | auto texName = texObj->first.data(); 32 | TextureProperties props; 33 | props.UVScale = texObj->second.get_child("UVScale").get_value(); 34 | propertiesSet.insert(std::make_pair(texName, props)); 35 | }); 36 | 37 | } catch(std::exception& ex) { 38 | SLLOG(Sev_Error, Fac_Rendering, "Error parsing texture properties: ", ex.what()); 39 | return false; 40 | } 41 | 42 | TextureNames localTextures; 43 | TexturePropertiesVec localProperties; 44 | std::unordered_map texturesSet; 45 | auto addTexture = [&](const std::string& texture)->unsigned { 46 | auto it = texturesSet.find(texture); 47 | if(it != texturesSet.end()) 48 | return it->second; 49 | 50 | localTextures.push_back(texture); 51 | auto id = localTextures.size()-1; 52 | texturesSet.insert(std::make_pair(texture, id)); 53 | 54 | TextureProperties properties; 55 | auto props = propertiesSet.find(texture); 56 | if(props != propertiesSet.end()) { 57 | properties = props->second; 58 | } 59 | 60 | localProperties.push_back(properties); 61 | 62 | return id; 63 | }; 64 | 65 | MaterialsVec localMeterials; 66 | try { 67 | auto materials = jsonTree.get_child("materials"); 68 | const auto count = materials.count(""); 69 | 70 | if(!count) { 71 | SLOG(Sev_Error, Fac_Rendering, "No materials specified in the table!"); 72 | return false; 73 | } 74 | 75 | localMeterials.reserve(count); 76 | 77 | std::for_each(materials.begin(), materials.end(), [&](ptree::value_type& material) { 78 | Material output; 79 | auto tex0 = material.second.get_child("diffuse0").begin(); 80 | auto tex1 = material.second.get_child("diffuse1").begin(); 81 | for(auto i = 0; i < 3; ++i, ++tex0, ++tex1) { 82 | output.DiffuseIds0[i] = addTexture(tex0->second.data()); 83 | output.DiffuseIds1[i] = addTexture(tex1->second.data()); 84 | } 85 | localMeterials.emplace_back(output); 86 | }); 87 | } catch(std::exception& ex) { 88 | SLLOG(Sev_Error, Fac_Rendering, "Error parsing materials: ", ex.what()); 89 | return false; 90 | } 91 | 92 | std::swap(localMeterials, m_Materials); 93 | std::swap(localTextures, m_DiffuseTextures); 94 | std::swap(localProperties, m_TextureProperties); 95 | 96 | return true; 97 | } 98 | 99 | const MaterialTable::TextureNames& MaterialTable::GetDiffuseTextureList() const 100 | { 101 | return m_DiffuseTextures; 102 | } 103 | 104 | const MaterialTable::TexturePropertiesVec& MaterialTable::GetDiffuseTextureProperties() const 105 | { 106 | return m_TextureProperties; 107 | } 108 | 109 | MaterialTable::Material* MaterialTable::GetMaterial(unsigned char id) const 110 | { 111 | if(m_Materials.size() <= id) 112 | return nullptr; 113 | 114 | return const_cast(&(m_Materials[id])); 115 | } 116 | 117 | unsigned MaterialTable::GetMaterialsCount() const 118 | { 119 | return m_Materials.size(); 120 | } 121 | -------------------------------------------------------------------------------- /Source/MaterialTable.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include "../Voxels/include/MaterialMap.h" 9 | 10 | // Implements a MaterialMap for the voxel grid. 11 | // The textures are loaded from JSON descriptions 12 | class MaterialTable : public Voxels::MaterialMap 13 | { 14 | public: 15 | typedef std::vector TextureNames; 16 | 17 | struct TextureProperties 18 | { 19 | TextureProperties() 20 | : UVScale(1) 21 | {} 22 | float UVScale; 23 | }; 24 | typedef std::vector TexturePropertiesVec; 25 | 26 | bool Load(const std::string& filename); 27 | 28 | const TextureNames& GetDiffuseTextureList() const; 29 | const TexturePropertiesVec& GetDiffuseTextureProperties() const; 30 | 31 | virtual Material* GetMaterial(unsigned char id) const override; 32 | unsigned GetMaterialsCount() const; 33 | 34 | private: 35 | typedef std::vector MaterialsVec; 36 | 37 | TextureNames m_DiffuseTextures; 38 | TexturePropertiesVec m_TextureProperties; 39 | MaterialsVec m_Materials; 40 | }; 41 | -------------------------------------------------------------------------------- /Source/PresentRoutine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | 7 | #include "stdafx.h" 8 | 9 | #include "PresentRoutine.h" 10 | 11 | bool PresentRoutine::Render(float deltaTime) 12 | { 13 | if(FAILED(m_Renderer->GetSwapChain()->Present(1, 0))) 14 | { 15 | SLOG(Sev_Error, Fac_Rendering, "Unable to present"); 16 | return false; 17 | } 18 | 19 | return true; 20 | } 21 | -------------------------------------------------------------------------------- /Source/PresentRoutine.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | 10 | class PresentRoutine : public DxRenderingRoutine 11 | { 12 | public: 13 | virtual bool Render(float deltaTime); 14 | }; -------------------------------------------------------------------------------- /Source/Scene.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "Scene.h" 9 | #include "VoxelPlane.h" 10 | #include "VoxelBall.h" 11 | #include "VoxelProc.h" 12 | #include "VoxelBox.h" 13 | 14 | #include 15 | #include "HeightMapLoader.h" 16 | 17 | #include 18 | 19 | using namespace DirectX; 20 | 21 | Scene::Scene(const std::string& filename /*leave empty to generate*/ 22 | , unsigned gridSize 23 | , const std::string& materialTable 24 | , const std::string& heightmap /*leave empty to generate*/ 25 | , SeedSurface surfaceType 26 | , float scale 27 | , const XMFLOAT3& gridScale) 28 | : m_Scale(gridScale) 29 | , m_Grid(nullptr) 30 | , m_PolygonSurface(nullptr) 31 | { 32 | const float start_x = -(gridSize / 8.f); 33 | const float start_y = -(gridSize / 8.f); 34 | const float start_z = -(gridSize / 8.f); 35 | const float step = 0.5f; 36 | 37 | m_Polygonizer.reset(new Voxels::Polygonizer); 38 | if(filename.empty() && heightmap.empty()) 39 | { 40 | switch(surfaceType) { 41 | case SSU_Plane: 42 | m_Surface.reset(new Voxels::VoxelPlane(XMFLOAT3(0.0f, 0.0f, 1.0f), 5.0f)); 43 | break; 44 | case SSU_Sphere: 45 | m_Surface.reset(new Voxels::VoxelBall(XMFLOAT3(5, 5, 5), gridSize / 8.f)); 46 | break; 47 | case SSU_Proc: 48 | { 49 | Voxels::ProceduralParams params; 50 | params.DimensionFactor = 0.25f; 51 | params.ScaleFactor = 7.5f; 52 | m_Surface.reset(new Voxels::VoxelProc(XMFLOAT3(0.0f, 0.0f, 1.0f), 53 | 5.0f, 54 | params)); 55 | } 56 | break; 57 | case SSU_Box: 58 | m_Surface.reset(new Voxels::VoxelBox(XMFLOAT3(5.0f, 5.0f, 5.0f))); 59 | break; 60 | } 61 | 62 | m_Grid = SceneGridType::Create(gridSize, gridSize, gridSize, start_x, start_y, start_z, step, m_Surface.get()); 63 | } 64 | else 65 | { 66 | if(!filename.empty()) { 67 | std::ifstream fin(filename.c_str(), std::ios::binary); 68 | if (!fin.is_open()) 69 | { 70 | SLOG(Sev_Error, Fac_Rendering, "Unable to open voxel grid file!"); 71 | } 72 | 73 | fin.seekg(0, std::ios::end); 74 | unsigned length = (unsigned)fin.tellg(); 75 | fin.seekg(0, std::ios::beg); 76 | 77 | std::unique_ptr data(new char[length]); 78 | fin.read(data.get(), length); 79 | 80 | m_Grid = SceneGridType::Load(data.get(), length); 81 | } else { 82 | unsigned int w; 83 | std::shared_ptr heightValues; 84 | if (!HeightMapLoader::Load(heightmap, w, heightValues, scale)) { 85 | SLOG(Sev_Error, Fac_Rendering, "Unable generate grid from hightmap!"); 86 | } 87 | m_Grid = SceneGridType::Create(w, heightValues.get()); 88 | } 89 | } 90 | 91 | if (!m_Grid) { 92 | SLOG(Sev_Error, Fac_Rendering, "Unable to create voxel grid!"); 93 | return; 94 | } 95 | 96 | if(!m_Materials.Load(materialTable)) { 97 | SLOG(Sev_Error, Fac_Rendering, "Unable to load the material table!"); 98 | } 99 | 100 | RecalculateGrid(); 101 | 102 | XMStoreFloat4x4(&m_GridWorld, XMMatrixScaling(gridScale.x, gridScale.y, gridScale.z)); 103 | } 104 | 105 | bool Scene::SaveVoxelGrid(const std::string& filename) 106 | { 107 | std::ofstream fout(filename.c_str(), std::ios::binary); 108 | 109 | if (!fout.is_open()) 110 | return false; 111 | 112 | auto pack = m_Grid->PackForSave(); 113 | 114 | fout.write(pack->GetData(), pack->GetSize()); 115 | 116 | pack->Destroy(); 117 | 118 | return true; 119 | } 120 | 121 | void Scene::RecalculateGrid(const Voxels::float3pair* modified) 122 | { 123 | SLLOG(Sev_Info, Fac_Rendering, "Memory used for grid blocks: ", m_Grid->GetGridBlocksMemorySize()); 124 | 125 | Voxels::Modification* modification = Voxels::Modification::Create(); 126 | if(modified) { 127 | modification->Map = m_PolygonSurface; 128 | modification->MinCornerModified = modified->first; 129 | modification->MaxCornerModified = modified->second; 130 | } 131 | else { 132 | if (m_PolygonSurface) 133 | { 134 | m_PolygonSurface->Destroy(); 135 | m_PolygonSurface = nullptr; 136 | } 137 | } 138 | 139 | SLOG(Sev_Debug, Fac_Rendering, "Recalculating grid..."); 140 | 141 | m_PolygonSurface = std::move(decltype(m_PolygonSurface)(m_Polygonizer->Execute(*m_Grid, &m_Materials, modified ? modification : nullptr))); 142 | 143 | modification->Destroy(); 144 | 145 | SLLOG(Sev_Info, Fac_Rendering, "Polygon data size: ", m_PolygonSurface->GetPolygonDataSizeBytes()); 146 | SLLOG(Sev_Info, Fac_Rendering, "Material cache size: ", m_PolygonSurface->GetCacheSizeBytes()); 147 | 148 | // Print stat data 149 | unsigned totalVertices = 0; 150 | unsigned totalIndices = 0; 151 | 152 | auto stats = m_PolygonSurface->GetStatistics(); 153 | SLOG(Sev_Debug, Fac_Rendering, "TransVoxel results:"); 154 | SLOG(Sev_Debug, Fac_Rendering, "Total blocks recalculated: ", stats->BlocksCalculated); 155 | for (auto level = 0u; level < m_PolygonSurface->GetLevelsCount(); ++level) 156 | { 157 | unsigned blocksCnt = m_PolygonSurface->GetBlocksForLevelCount(level); 158 | SLOG(Sev_Debug, Fac_Rendering, "Blocks produced ", blocksCnt); 159 | for (auto blockId = 0u; blockId < blocksCnt; ++blockId) 160 | { 161 | unsigned temp = 0; 162 | auto block = m_PolygonSurface->GetBlockForLevel(level, blockId); 163 | block->GetVertices(&temp); 164 | SLOG(Sev_Trace, Fac_Rendering, "Vertices produced ", temp); 165 | totalVertices += temp; 166 | block->GetIndices(&temp); 167 | totalIndices += temp; 168 | SLOG(Sev_Trace, Fac_Rendering, "Indices produced ", temp); 169 | } 170 | } 171 | SLOG(Sev_Debug, Fac_Rendering, "Total vertices produced: ", totalVertices); 172 | SLOG(Sev_Debug, Fac_Rendering, "Total indices produced: ", totalIndices); 173 | 174 | SLOG(Sev_Debug, Fac_Rendering, "Trivial cells ", stats->TrivialCells); 175 | SLOG(Sev_Debug, Fac_Rendering, "NonTrivial cells ", stats->NonTrivialCells); 176 | for (auto i = 0u; i < Voxels::PolygonizationStatistics::CASES_COUNT; ++i) 177 | { 178 | SLOG(Sev_Trace, Fac_Rendering, "Cells with Case[", i, "] ", stats->PerCaseCellsCount[i]); 179 | } 180 | 181 | // Rebuild the octree 182 | m_LodOctree.reset(new Voxels::VoxelLodOctree()); 183 | if(!m_LodOctree->Build(*m_PolygonSurface)) { 184 | SLOG(Sev_Error, Fac_Rendering, "LOD octree building failed!"); 185 | } 186 | 187 | SLLOG(Sev_Debug, Fac_Rendering, "LOD octree levels: ", m_LodOctree->GetLodLevelsCount()); 188 | SLLOG(Sev_Debug, Fac_Rendering, "LOD octree non-empty cells: ", m_LodOctree->GetNonEmptyNodesCount()); 189 | } 190 | 191 | bool Scene::Intersect(DirectX::FXMVECTOR start, 192 | DirectX::FXMVECTOR end, 193 | XMVECTOR& intersection) const 194 | { 195 | using namespace DirectX; 196 | 197 | const auto recScale = XMVectorReciprocal(XMLoadFloat3(&m_Scale)); 198 | const auto origin = XMVectorMultiply(start, recScale); 199 | const auto endPoint = XMVectorMultiply(end, recScale); 200 | 201 | unsigned blocksCnt = m_PolygonSurface->GetBlocksForLevelCount(0); 202 | auto direction = DirectX::XMVector3Normalize(end - start); 203 | 204 | typedef std::pair HitBlock; 205 | std::vector hitBlocks; 206 | for (auto blockId = 0u; blockId < blocksCnt; ++blockId) 207 | { 208 | BoundingBox aabb; 209 | auto block = m_PolygonSurface->GetBlockForLevel(0, blockId); 210 | const auto minCorner = block->GetMinimalCorner(); 211 | const auto maxCorner = block->GetMaximalCorner(); 212 | aabb.Extents = XMFLOAT3((maxCorner.x - minCorner.x) / 2.f, 213 | (maxCorner.y - minCorner.y) / 2.f, 214 | (maxCorner.z - minCorner.z) / 2.f); 215 | 216 | aabb.Center = XMFLOAT3(minCorner.x + aabb.Extents.x, 217 | minCorner.y + aabb.Extents.y, 218 | minCorner.z + aabb.Extents.z); 219 | 220 | float distance = 0; 221 | if (aabb.Intersects(start, direction, distance)) 222 | { 223 | hitBlocks.push_back(std::make_pair(distance, block)); 224 | } 225 | } 226 | 227 | std::sort(hitBlocks.begin(), hitBlocks.end(), 228 | [](HitBlock& block1, HitBlock& block2) { 229 | return std::abs(block1.first) < std::abs(block2.first); 230 | }); 231 | 232 | float distance = 0; 233 | float nearest = std::numeric_limits::max(); 234 | bool found = false; 235 | XMVECTOR V0, V1, V2; 236 | for (auto block = hitBlocks.cbegin(); block != hitBlocks.cend(); ++block) 237 | { 238 | const auto blockRef = block->second; 239 | unsigned indicesCnt = 0; 240 | auto indices = blockRef->GetIndices(&indicesCnt); 241 | for (auto triangle = 0u; triangle < indicesCnt; triangle += 3) 242 | { 243 | auto vertices = blockRef->GetVertices(nullptr); 244 | V0 = XMLoadFloat3(reinterpret_cast(&vertices[indices[triangle]].Position)); 245 | V1 = XMLoadFloat3(reinterpret_cast(&vertices[indices[triangle + 1]].Position)); 246 | V2 = XMLoadFloat3(reinterpret_cast(&vertices[indices[triangle + 2]].Position)); 247 | if (TriangleTests::Intersects(start, direction, V0, V1, V2, distance)) 248 | { 249 | nearest = std::min(nearest, distance); 250 | found = true; 251 | } 252 | } 253 | 254 | if (found) 255 | break; 256 | } 257 | 258 | intersection = start + nearest * direction; 259 | 260 | return found; 261 | } 262 | 263 | const MaterialTable& Scene::GetMaterials() const { 264 | return m_Materials; 265 | } 266 | 267 | void Scene::DestroySurface() 268 | { 269 | if (m_PolygonSurface) 270 | { 271 | m_PolygonSurface->Destroy(); 272 | m_PolygonSurface = nullptr; 273 | } 274 | } 275 | 276 | Scene::~Scene() 277 | { 278 | if (m_Grid) 279 | { 280 | m_Grid->Destroy(); 281 | } 282 | DestroySurface(); 283 | } 284 | -------------------------------------------------------------------------------- /Source/Scene.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include "../Voxels/include/Grid.h" 9 | #include "../Voxels/include/Polygonizer.h" 10 | 11 | #include "MaterialTable.h" 12 | #include "Voxel/VoxelLodOctree.h" 13 | 14 | class AllocatorBase; 15 | 16 | class Scene 17 | { 18 | public: 19 | typedef char GridType; 20 | typedef Voxels::Grid SceneGridType; 21 | typedef Voxels::Polygonizer VoxelAlgorithm; 22 | 23 | enum SeedSurface 24 | { 25 | SSU_Plane, 26 | SSU_Sphere, 27 | SSU_Proc, 28 | SSU_Box 29 | }; 30 | 31 | Scene(const std::string& filename /*leave empty to generate*/ 32 | , unsigned gridSize 33 | , const std::string& materialTable 34 | , const std::string& heightmap /*leave empty to generate*/ 35 | , SeedSurface surfaceType 36 | , float scale 37 | , const DirectX::XMFLOAT3& gridScale); 38 | ~Scene(); 39 | 40 | const MaterialTable& GetMaterials() const; 41 | 42 | const Voxels::PolygonSurface* GetPolygonSurface() const { return m_PolygonSurface; } 43 | void DestroySurface(); 44 | SceneGridType* GetVoxelGrid() const { return m_Grid; } 45 | 46 | bool Intersect(DirectX::FXMVECTOR start, 47 | DirectX::FXMVECTOR end, 48 | DirectX::XMVECTOR& intersection) const; 49 | 50 | bool SaveVoxelGrid(const std::string& filename); 51 | 52 | const DirectX::XMFLOAT4X4& GetGridWorldMatrix() const { return m_GridWorld; } 53 | 54 | void RecalculateGrid(const Voxels::float3pair* modified = nullptr); 55 | 56 | Voxels::VoxelLodOctree& GetLodOctree() const { return *m_LodOctree; } 57 | 58 | private: 59 | SceneGridType* m_Grid; 60 | std::unique_ptr m_Surface; 61 | std::unique_ptr m_Polygonizer; 62 | Voxels::PolygonSurface* m_PolygonSurface; 63 | std::unique_ptr m_LodOctree; 64 | MaterialTable m_Materials; 65 | 66 | DirectX::XMFLOAT3 m_Scale; 67 | 68 | DirectX::XMFLOAT4X4 m_GridWorld; 69 | }; -------------------------------------------------------------------------------- /Source/VertexTypes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VertexTypes.h" 9 | 10 | D3D11_INPUT_ELEMENT_DESC GridVertexLayout[] = 11 | { 12 | { "POSITION", 0, DXGI_FORMAT_R32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 13 | }; 14 | 15 | D3D11_INPUT_ELEMENT_DESC SurfaceVertexLayout[] = 16 | { 17 | { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 18 | { "POSITION", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 19 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 20 | { "TEXCOORD", 1, DXGI_FORMAT_R32G32_UINT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 21 | }; 22 | -------------------------------------------------------------------------------- /Source/VertexTypes.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | struct GridVertex 9 | { 10 | float Distance; 11 | }; 12 | 13 | //TODO: Split this in two declarations. One with and one without the secondary vertices 14 | // Use the smaller definition for the blocks that don't have transitions 15 | struct SurfaceVertex 16 | { 17 | DirectX::XMFLOAT3 Position; 18 | DirectX::XMFLOAT4 SecondaryPosition; 19 | DirectX::XMFLOAT3 Normal; 20 | unsigned TextureIndices[2]; 21 | }; 22 | 23 | extern D3D11_INPUT_ELEMENT_DESC GridVertexLayout[1]; 24 | extern D3D11_INPUT_ELEMENT_DESC SurfaceVertexLayout[4]; 25 | -------------------------------------------------------------------------------- /Source/VolumeRenderingApplication.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VolumeRenderingApplication.h" 9 | #include "Scene.h" 10 | 11 | #include "ClearRenderingRoutine.h" 12 | #include "PresentRoutine.h" 13 | #include "DrawRoutine.h" 14 | 15 | #include "VoxelBall.h" 16 | 17 | #include 18 | 19 | #if TRACK_MEMORY 20 | #include 21 | #endif 22 | 23 | using namespace DirectX; 24 | 25 | namespace po = boost::program_options; 26 | 27 | static const float MV_SPEED = 0.005f * 10; 28 | 29 | void LogVoxelsMessage(Voxels::LogSeverity severity, const char* message) 30 | { 31 | Logging::Severity sev; 32 | switch (severity) 33 | { 34 | case Voxels::LS_Trace: 35 | sev = Logging::Sev_Trace; 36 | break; 37 | case Voxels::LS_Debug: 38 | sev = Logging::Sev_Debug; 39 | break; 40 | case Voxels::LS_Info: 41 | sev = Logging::Sev_Info; 42 | break; 43 | case Voxels::LS_Warning: 44 | sev = Logging::Sev_Warning; 45 | break; 46 | case Voxels::LS_Error: 47 | sev = Logging::Sev_Error; 48 | break; 49 | case Voxels::LS_CriticalError: 50 | sev = Logging::Sev_Error; 51 | break; 52 | } 53 | 54 | STLOG(sev, Logging::Fac_Voxels, std::tie(message)); 55 | } 56 | 57 | class AllocatorImpl 58 | { 59 | public: 60 | static void* Allocate(size_t size); 61 | static void Deallocate(void* ptr); 62 | 63 | static void* AllocateAligned(size_t size, size_t alignment); 64 | static void DeallocateAligned(void* ptr); 65 | static void ReportMemory(); 66 | 67 | static size_t GetCurrentMemoryUse() 68 | { 69 | #if TRACK_MEMORY 70 | return CurrentUsedMemory; 71 | #else 72 | return 0; 73 | #endif 74 | } 75 | static size_t GetMaxMemoryUse() 76 | { 77 | #if TRACK_MEMORY 78 | return MaxUsedMemory; 79 | #else 80 | return 0; 81 | #endif 82 | } 83 | private: 84 | #if TRACK_MEMORY 85 | static size_t CurrentUsedMemory; 86 | static size_t MaxUsedMemory; 87 | static unsigned GetNextId(); 88 | static unsigned NextId; 89 | static std::mutex MemoryLock; 90 | 91 | struct AllocationInfo 92 | { 93 | unsigned Id; 94 | size_t Size; 95 | }; 96 | static std::unordered_map Allocations; 97 | #endif 98 | }; 99 | 100 | #if TRACK_MEMORY 101 | size_t AllocatorImpl::CurrentUsedMemory = 0; 102 | size_t AllocatorImpl::MaxUsedMemory = 0; 103 | std::mutex AllocatorImpl::MemoryLock; 104 | unsigned AllocatorImpl::NextId = 0; 105 | std::unordered_map AllocatorImpl::Allocations; 106 | #endif 107 | 108 | #if TRACK_MEMORY 109 | unsigned AllocatorImpl::GetNextId() 110 | { 111 | return NextId++; 112 | } 113 | #endif 114 | 115 | void* AllocatorImpl::Allocate(size_t size) 116 | { 117 | auto ret = malloc(size); 118 | 119 | #if TRACK_MEMORY 120 | std::lock_guard lock(MemoryLock); 121 | CurrentUsedMemory += size; 122 | MaxUsedMemory = std::max(MaxUsedMemory, CurrentUsedMemory); 123 | AllocationInfo info = { GetNextId(), size}; 124 | Allocations.insert(std::make_pair(ret, info)); 125 | #endif 126 | 127 | return ret; 128 | } 129 | 130 | void AllocatorImpl::Deallocate(void* ptr) 131 | { 132 | #if TRACK_MEMORY 133 | { 134 | std::lock_guard lock(MemoryLock); 135 | auto it = Allocations.find(ptr); 136 | assert(it != Allocations.end()); 137 | CurrentUsedMemory -= it->second.Size; 138 | Allocations.erase(it); 139 | } 140 | #endif 141 | free(ptr); 142 | } 143 | 144 | void* AllocatorImpl::AllocateAligned(size_t size, size_t alignment) 145 | { 146 | auto ret = _aligned_malloc(size, alignment); 147 | 148 | #if TRACK_MEMORY 149 | std::lock_guard lock(MemoryLock); 150 | 151 | CurrentUsedMemory += size; 152 | MaxUsedMemory = std::max(MaxUsedMemory, CurrentUsedMemory); 153 | AllocationInfo info = { GetNextId(), size }; 154 | Allocations.insert(std::make_pair(ret, info)); 155 | #endif 156 | return ret; 157 | } 158 | 159 | void AllocatorImpl::DeallocateAligned(void* ptr) 160 | { 161 | #if TRACK_MEMORY 162 | { 163 | std::lock_guard lock(MemoryLock); 164 | 165 | auto it = Allocations.find(ptr); 166 | assert(it != Allocations.end()); 167 | CurrentUsedMemory -= it->second.Size; 168 | Allocations.erase(it); 169 | } 170 | #endif 171 | _aligned_free(ptr); 172 | } 173 | 174 | void AllocatorImpl::ReportMemory() 175 | { 176 | #if TRACK_MEMORY 177 | SLOG(Sev_Info, Fac_Voxels, "Max Voxels used memory ", MaxUsedMemory, " bytes"); 178 | assert(Allocations.empty() && "Voxels leaks detected!"); 179 | for (auto it = Allocations.cbegin(); it != Allocations.cend(); ++it) 180 | { 181 | SLOG(Sev_Warning, Fac_Voxels, "Voxel leak - Id: ", it->second.Id, " Size: ", it->second.Size); 182 | } 183 | #endif 184 | } 185 | 186 | VolumeRenderingApplication::VolumeRenderingApplication(HINSTANCE instance) 187 | : DxGraphicsApplication(instance) 188 | , m_IsRightButtonDown(false) 189 | , m_LastMousePos(std::make_pair(0, 0)) 190 | , m_InjectionType(Voxels::IT_Add) 191 | , m_Modification(MT_Inject) 192 | , m_GridScale(1, 1, 1) 193 | , m_MaterialId(0) 194 | , m_MaterialCount(0) 195 | , m_AddMaterialBlend(true) 196 | , m_MaterialEditSize(20) 197 | , m_VolumeEditSize(3) 198 | {} 199 | 200 | VolumeRenderingApplication::~VolumeRenderingApplication() 201 | { 202 | m_Scene.reset(); 203 | DeinitializeVoxels(); 204 | 205 | #if TRACK_MEMORY 206 | AllocatorImpl::ReportMemory(); 207 | #endif 208 | } 209 | 210 | bool VolumeRenderingApplication::Initiate(char* className, char* windowName, unsigned width, unsigned height, WNDPROC winProc, bool sRGBRT) 211 | { 212 | po::options_description desc("Options"); 213 | desc.add_options()("grid", po::value(), "load a specified voxel grid") 214 | ("gridsize", po::value(), "grid size in voxels") 215 | ("surface", po::value(), "seed the grid with a surface type") 216 | ("materials", po::value(), "materials definition file") 217 | ("heightmap", po::value(), "heightmap file") 218 | ("hscale", po::value(), "heightmap scale factor") 219 | ("xscale", po::value(), "grid scale factor on X coordinate") 220 | ("yscale", po::value(), "grid scale factor on Y coordinate") 221 | ("zscale", po::value(), "grid scale factor on Z coordinate") 222 | ("msaa", po::value(), "msaa samples"); 223 | 224 | po::variables_map options; 225 | auto arguments = po::split_winmain(::GetCommandLine()); 226 | try { 227 | po::store(po::command_line_parser(arguments).options(desc).run(), options); 228 | po::notify(options); 229 | } catch (std::exception& ex) { 230 | SLLOG(Sev_Error, Fac_Rendering, "Unable to parse command line arguments - ", ex.what()); 231 | return false; 232 | } 233 | 234 | int msaaSamples = 4; 235 | if(options.count("msaa")) { 236 | msaaSamples = options["msaa"].as(); 237 | } 238 | 239 | bool result = true; 240 | result &= DxGraphicsApplication::Initiate(className, windowName, width, height, false, winProc, true, msaaSamples); 241 | 242 | SetProjection(XM_PIDIV2, float(GetWidth())/GetHeight(), 1.0f, 3000.f); 243 | 244 | GetMainCamera()->SetLookAt(XMFLOAT3(0, 20, 0) 245 | , XMFLOAT3(0, 100, 1) 246 | , XMFLOAT3(0, 1, 0)); 247 | 248 | DxRenderer* renderer = static_cast(GetRenderer()); 249 | 250 | std::string grid = ""; 251 | if(options.count("grid")) { 252 | grid = options["grid"].as(); 253 | } 254 | Scene::SeedSurface surfaceType = Scene::SSU_Plane; 255 | if(options.count("surface")) { 256 | auto type = options["surface"].as(); 257 | if(type == "sphere") { 258 | surfaceType = Scene::SSU_Sphere; 259 | } else if(type == "proc") { 260 | surfaceType = Scene::SSU_Proc; 261 | } else if(type == "box") { 262 | surfaceType = Scene::SSU_Box; 263 | } 264 | } 265 | std::string materials = "..\\media\\materials.json"; 266 | if(options.count("materials")) { 267 | materials = options["materials"].as(); 268 | } 269 | std::string heightmap = ""; 270 | if(options.count("heightmap")) { 271 | heightmap = options["heightmap"].as(); 272 | } 273 | float hscale = 1; 274 | if(options.count("hscale")) { 275 | hscale = options["hscale"].as(); 276 | } 277 | 278 | if(options.count("xscale")) { 279 | m_GridScale.x = options["xscale"].as(); 280 | } 281 | if(options.count("yscale")) { 282 | m_GridScale.y = options["yscale"].as(); 283 | } 284 | if(options.count("zscale")) { 285 | m_GridScale.z = options["zscale"].as(); 286 | } 287 | 288 | unsigned gridSize = 64; 289 | if (options.count("gridsize")) { 290 | gridSize = options["gridsize"].as(); 291 | } 292 | 293 | // Initialize the Voxels library 294 | Voxels::VoxelsAllocators allocators; 295 | allocators.VoxelsAllocate = AllocatorImpl::Allocate; 296 | allocators.VoxelsDeallocate = AllocatorImpl::Deallocate; 297 | allocators.VoxelsAllocateAligned = AllocatorImpl::AllocateAligned; 298 | allocators.VoxelsDeallocateAligned = AllocatorImpl::DeallocateAligned; 299 | if (InitializeVoxels(VOXELS_VERSION, &LogVoxelsMessage, &allocators) != Voxels::IE_Ok) { 300 | return false; 301 | } 302 | 303 | m_Scene.reset(new Scene(grid, gridSize, materials, heightmap, surfaceType, hscale, m_GridScale)); 304 | 305 | if (!m_Scene->GetPolygonSurface()) 306 | return false; 307 | 308 | m_MaterialCount = m_Scene->GetMaterials().GetMaterialsCount(); 309 | 310 | m_ClearRoutine.reset(new ClearRenderingRoutine()); 311 | ReturnUnless(m_ClearRoutine->Initialize(renderer), false); 312 | renderer->AddRoutine(m_ClearRoutine.get()); 313 | 314 | m_DrawRoutine.reset(new DrawRoutine()); 315 | ReturnUnless(m_DrawRoutine->Initialize(renderer, GetMainCamera(), GetProjection(), m_Scene.get()), false); 316 | renderer->AddRoutine(m_DrawRoutine.get()); 317 | 318 | m_PresentRoutine.reset(new PresentRoutine()); 319 | ReturnUnless(m_PresentRoutine->Initialize(renderer), false); 320 | renderer->AddRoutine(m_PresentRoutine.get()); 321 | 322 | return result; 323 | } 324 | 325 | void VolumeRenderingApplication::Update(float delta) 326 | { 327 | } 328 | 329 | void VolumeRenderingApplication::KeyDown(unsigned int key) 330 | { 331 | bool isShiftDown = !!(GetKeyState(VK_SHIFT) & 0x8000); 332 | 333 | switch(key) 334 | { 335 | case VK_UP: 336 | m_MainCamera.Move(MV_SPEED * (1 + 3*isShiftDown)); 337 | break; 338 | case VK_DOWN: 339 | m_MainCamera.Move(-MV_SPEED * (1 + 3*isShiftDown)); 340 | break; 341 | case VK_LEFT: 342 | m_MainCamera.Yaw(-MV_SPEED); 343 | break; 344 | case VK_RIGHT: 345 | m_MainCamera.Yaw(MV_SPEED); 346 | break; 347 | case VK_INSERT: 348 | m_MainCamera.Up(MV_SPEED); 349 | break; 350 | case VK_DELETE: 351 | m_MainCamera.Up(-MV_SPEED); 352 | break; 353 | case VK_HOME: 354 | m_MainCamera.Pitch(-MV_SPEED); 355 | break; 356 | case VK_END: 357 | m_MainCamera.Pitch(MV_SPEED); 358 | break; 359 | case VK_F2: 360 | m_Scene->SaveVoxelGrid("output.grd"); 361 | break; 362 | case 'S': 363 | m_DrawRoutine->SetDrawSolid(!m_DrawRoutine->GetDrawSolid()); 364 | break; 365 | case 'W': 366 | m_DrawRoutine->SetDrawWireframe(!m_DrawRoutine->GetDrawWireframe()); 367 | break; 368 | case 'T': 369 | m_DrawRoutine->SetDrawTransitions(!m_DrawRoutine->GetDrawTransitions()); 370 | break; 371 | case 'A': 372 | m_DrawRoutine->SetDrawSurface(!m_DrawRoutine->GetDrawSurface()); 373 | break; 374 | case 'L': 375 | m_DrawRoutine->SetUseLodOctree(!m_DrawRoutine->GetUseLodOctree()); 376 | break; 377 | case 'U': 378 | m_DrawRoutine->SetLodUpdateEnabled(!m_DrawRoutine->GetLodUpdateEnabled()); 379 | break; 380 | case 'R': 381 | RecalculateGrid(); 382 | break; 383 | case VK_ADD: 384 | m_AddMaterialBlend = true; 385 | break; 386 | case VK_SUBTRACT: 387 | m_AddMaterialBlend = false; 388 | break; 389 | case 'Z': 390 | m_DrawRoutine->SetCurrentLodToDraw(m_DrawRoutine->GetCurrentLodToDraw() + 1); 391 | break; 392 | case 'X': 393 | m_DrawRoutine->SetCurrentLodToDraw(m_DrawRoutine->GetCurrentLodToDraw() - 1); 394 | break; 395 | 396 | case 'M': 397 | m_Modification = ModificationType((m_Modification + 1) % MT_Count); 398 | break; 399 | 400 | case '0': 401 | m_MaterialId = std::min(m_MaterialCount - 1, 0u); 402 | break; 403 | case '1': 404 | m_InjectionType = Voxels::IT_Add; 405 | m_MaterialId = std::min(m_MaterialCount - 1, 1u); 406 | break; 407 | case '2': 408 | m_InjectionType = Voxels::IT_SubtractAddInner; 409 | m_MaterialId = std::min(m_MaterialCount - 1, 2u); 410 | break; 411 | case '3': 412 | m_InjectionType = Voxels::IT_Subtract; 413 | m_MaterialId = std::min(m_MaterialCount - 1, 3u); 414 | break; 415 | case '4': 416 | m_MaterialId = std::min(m_MaterialCount - 1, 4u); 417 | break; 418 | case '5': 419 | m_MaterialId = std::min(m_MaterialCount - 1, 5u); 420 | break; 421 | 422 | case VK_F5: 423 | m_VolumeEditSize = 2; 424 | m_MaterialEditSize = 5; 425 | break; 426 | case VK_F6: 427 | m_VolumeEditSize = 3; 428 | m_MaterialEditSize = 10; 429 | break; 430 | case VK_F7: 431 | m_VolumeEditSize = 6; 432 | m_MaterialEditSize = 20; 433 | break; 434 | case VK_F8: 435 | m_VolumeEditSize = 12; 436 | m_MaterialEditSize = 40; 437 | break; 438 | 439 | case VK_F9: 440 | { 441 | SLLOG(Sev_Info, Fac_Rendering, "Maximum memory use: ", AllocatorImpl::GetMaxMemoryUse()); 442 | SLLOG(Sev_Info, Fac_Rendering, "Current memory use: ", AllocatorImpl::GetCurrentMemoryUse()); 443 | 444 | ID3D11Debug* d3dDebug = nullptr; 445 | m_Renderer->GetDevice()->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast(&d3dDebug)); 446 | if (d3dDebug) 447 | { 448 | d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL); 449 | d3dDebug->Release(); 450 | } 451 | 452 | #ifdef _CRTDBG_MAP_ALLOC 453 | static std::unique_ptr<_CrtMemState> lastState; 454 | std::unique_ptr<_CrtMemState> currentState(new _CrtMemState); 455 | _CrtMemCheckpoint(currentState.get()); 456 | OutputDebugString("Current memory snapshot: \n"); 457 | _CrtMemDumpStatistics(currentState.get()); 458 | if (lastState) 459 | { 460 | std::unique_ptr<_CrtMemState> diff(new _CrtMemState); 461 | _CrtMemDifference(diff.get(), lastState.get(), currentState.get()); 462 | OutputDebugString("Memory diff snapshot: \n"); 463 | _CrtMemDumpStatistics(diff.get()); 464 | } 465 | std::swap(lastState, currentState); 466 | #endif 467 | } 468 | break; 469 | case VK_F11: 470 | m_Scene->DestroySurface(); 471 | break; 472 | 473 | default: 474 | break; 475 | } 476 | } 477 | 478 | void VolumeRenderingApplication::MouseButtonDown(MouseBtn button, int x, int y) 479 | { 480 | switch(button) 481 | { 482 | case MBT_Left: 483 | ModifyGrid(x, y); 484 | break; 485 | case MBT_Right: 486 | m_IsRightButtonDown = true; 487 | break; 488 | default: 489 | break; 490 | } 491 | } 492 | 493 | void VolumeRenderingApplication::MouseButtonUp(MouseBtn button, int x, int y) 494 | { 495 | switch(button) 496 | { 497 | case MBT_Right: 498 | m_IsRightButtonDown = false; 499 | break; 500 | default: 501 | break; 502 | } 503 | } 504 | 505 | void VolumeRenderingApplication::MouseMove(int x, int y) 506 | { 507 | if(m_IsRightButtonDown) { 508 | const int dX = m_LastMousePos.first - x; 509 | const int dY = m_LastMousePos.second - y; 510 | 511 | m_MainCamera.Yaw(-dX*MV_SPEED); 512 | m_MainCamera.Pitch(-dY*MV_SPEED); 513 | } 514 | 515 | m_LastMousePos = std::make_pair(x, y); 516 | } 517 | 518 | void VolumeRenderingApplication::ModifyGrid(int mouseX, int mouseY) 519 | { 520 | const XMMATRIX gridWrld = XMLoadFloat4x4(&m_Scene->GetGridWorldMatrix()); 521 | const XMMATRIX view = XMLoadFloat4x4(&GetMainCamera()->GetViewMatrix()); 522 | const XMMATRIX proj = XMLoadFloat4x4(&GetProjection()); 523 | 524 | const XMVECTOR startW = XMVector3Unproject(XMVectorSet(float(mouseX), float(mouseY), 0, 0), 0, 0, float(GetWidth()), float(GetHeight()), 0, 1, proj, view, gridWrld); 525 | const XMVECTOR endW = XMVector3Unproject(XMVectorSet(float(mouseX), float(mouseY), 1, 0), 0, 0, float(GetWidth()), float(GetHeight()), 0, 1, proj, view, gridWrld); 526 | 527 | Voxels::float3pair modified; 528 | XMVECTOR intersection; 529 | 530 | if(m_Scene->Intersect(startW, endW, intersection)) { 531 | XMFLOAT3 position; 532 | XMStoreFloat3(&position, intersection); 533 | 534 | // The grid works with Z up so swap 535 | auto posfl3 = Voxels::float3(position.x, position.z, position.y); 536 | 537 | if(m_Modification == MT_Inject) { 538 | auto ball = Voxels::VoxelBall(XMFLOAT3(0, 0, 0), float(m_VolumeEditSize)); 539 | float ext = float(m_VolumeEditSize) * 2 + 1; 540 | modified = m_Scene->GetVoxelGrid()->InjectSurface( 541 | posfl3, 542 | Voxels::float3(ext, ext, ext), 543 | &ball, 544 | m_InjectionType); 545 | } else if(m_Modification == MT_ChangeMaterial) { 546 | const auto ext = Voxels::float3( 547 | float(m_MaterialEditSize), 548 | float(m_MaterialEditSize), 549 | float(m_MaterialEditSize)); 550 | modified = m_Scene->GetVoxelGrid()->InjectMaterial( 551 | posfl3, 552 | ext, 553 | m_MaterialId, 554 | m_AddMaterialBlend); 555 | } 556 | 557 | RecalculateGrid(&modified); 558 | } 559 | } 560 | 561 | void VolumeRenderingApplication::RecalculateGrid(const Voxels::float3pair* modified) 562 | { 563 | m_Scene->RecalculateGrid(modified); 564 | 565 | auto result = modified ? m_DrawRoutine->UpdateGrid() : m_DrawRoutine->ReloadGrid(); 566 | 567 | if(!result) 568 | { 569 | SLOG(Sev_Error, Fac_Rendering, "Unable to reload grid for drawing"); 570 | } 571 | } 572 | -------------------------------------------------------------------------------- /Source/VolumeRenderingApplication.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include "../Voxels/include/Grid.h" 10 | 11 | #if defined(_DEBUG) || defined(TRACKING_BUILD) 12 | #define TRACK_MEMORY 1 13 | #else 14 | #define TRACK_MEMORY 0 15 | #endif 16 | 17 | class Scene; 18 | class ClearRenderingRoutine; 19 | class PresentRoutine; 20 | class DrawRoutine; 21 | 22 | class VolumeRenderingApplication : public DxGraphicsApplication 23 | { 24 | public: 25 | 26 | VolumeRenderingApplication (HINSTANCE instance); 27 | virtual ~VolumeRenderingApplication(); 28 | bool Initiate(char* className, char* windowName, unsigned width, unsigned height, WNDPROC winProc, bool sRGBRT = true); 29 | virtual void Update(float delta) override; 30 | virtual void KeyDown(unsigned int key) override; 31 | virtual void MouseButtonDown(MouseBtn button, int x, int y) override; 32 | virtual void MouseButtonUp(MouseBtn button, int x, int y) override; 33 | virtual void MouseMove(int x, int y) override; 34 | 35 | void ModifyGrid(int mouseX, int mouseY); 36 | 37 | private: 38 | void RecalculateGrid(const Voxels::float3pair* modified = nullptr); 39 | 40 | std::unique_ptr m_Scene; 41 | 42 | std::unique_ptr m_ClearRoutine; 43 | std::unique_ptr m_PresentRoutine; 44 | std::unique_ptr m_DrawRoutine; 45 | 46 | DirectX::XMFLOAT3 m_GridScale; 47 | 48 | enum ModificationType 49 | { 50 | MT_Inject = 0, 51 | MT_ChangeMaterial, 52 | 53 | MT_Count 54 | }; 55 | ModificationType m_Modification; 56 | Voxels::InjectionType m_InjectionType; 57 | int m_MaterialId; 58 | unsigned m_MaterialCount; 59 | bool m_AddMaterialBlend; 60 | 61 | unsigned m_MaterialEditSize; 62 | unsigned m_VolumeEditSize; 63 | 64 | bool m_IsRightButtonDown; 65 | std::pair m_LastMousePos; 66 | }; 67 | 68 | -------------------------------------------------------------------------------- /Source/Voxel/VoxelLodOctree.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | #include "VoxelLodOctree.h" 8 | 9 | using namespace DirectX; 10 | 11 | namespace Voxels 12 | { 13 | 14 | // if the distance between the camera and the center of the node is 15 | // >= than the coeff than we settle for this block, otherwise we examine it's children 16 | // NB: setting a number < 1.6875 might lead to incorrect results 17 | static const float LOD_SETTLE_COEFF = 2.0f; 18 | 19 | inline DirectX::XMVECTOR XMLoadFloat3(const float3* fl) 20 | { 21 | static_assert(sizeof(float3) == sizeof(DirectX::XMFLOAT3), "Float types incompatible!"); 22 | return XMLoadFloat3(reinterpret_cast(fl)); 23 | } 24 | 25 | inline DirectX::XMVECTOR XMLoadFloat4(const float4* fl) 26 | { 27 | static_assert(sizeof(float4) == sizeof(DirectX::XMFLOAT4), "Float types incompatible!"); 28 | return XMLoadFloat4(reinterpret_cast(fl)); 29 | } 30 | 31 | inline void XMStoreFloat3(float3* pDestination, DirectX::FXMVECTOR V) 32 | { 33 | XMStoreFloat3(reinterpret_cast(pDestination), V); 34 | } 35 | 36 | inline void XMStoreFloat4(float4* pDestination, DirectX::FXMVECTOR V) 37 | { 38 | XMStoreFloat4(reinterpret_cast(pDestination), V); 39 | } 40 | 41 | struct VoxelLodOctree::Node 42 | { 43 | static NodePtr Create(unsigned level, const XMFLOAT3& min, const XMFLOAT3& max) 44 | { 45 | return NodePtr(new Node(level, min, max)); 46 | } 47 | 48 | unsigned Id; 49 | unsigned Level; 50 | XMFLOAT3 MinCorner; 51 | XMFLOAT3 MaxCorner; 52 | 53 | unsigned ChildCount; 54 | NodePtr Children[8]; 55 | 56 | private: 57 | Node(unsigned level, const XMFLOAT3& min, const XMFLOAT3& max) 58 | : Id(PolygonSurface::INVALID_ID) 59 | , Level(level) 60 | , MinCorner(min) 61 | , MaxCorner(max) 62 | , ChildCount(0) 63 | {} 64 | }; 65 | 66 | VoxelLodOctree::VoxelLodOctree() 67 | : m_LodLevels(0) 68 | , m_NonEmptyNodes(0) 69 | {} 70 | 71 | VoxelLodOctree::~VoxelLodOctree() 72 | {} 73 | 74 | bool VoxelLodOctree::PruneNode(NodePtr& node) { 75 | for(auto i = 0; i < 8 ; ++i) { 76 | if(node->Children[i]) { 77 | // this child is empty 78 | if(!PruneNode(node->Children[i])) { 79 | node->Children[i].reset(); 80 | } else { 81 | ++node->ChildCount; 82 | } 83 | } 84 | } 85 | 86 | return !!node->ChildCount || node->Id != PolygonSurface::INVALID_ID; 87 | } 88 | 89 | bool VoxelLodOctree::Build(const PolygonSurface& map) 90 | { 91 | auto levelExtents = map.GetExtents(); 92 | m_LodLevels = map.GetLevelsCount(); 93 | 94 | m_Root = Node::Create(m_LodLevels - 1, 95 | XMFLOAT3(0.f, 0.f, 0.f), 96 | XMFLOAT3(levelExtents.x, levelExtents.y, levelExtents.z)); 97 | 98 | NodesQueue currentLevelNodes; 99 | NodesQueue nextLevelNodes; 100 | 101 | currentLevelNodes.push(&m_Root); 102 | for(int lodLevel = m_LodLevels - 1; lodLevel >= 0; --lodLevel) { 103 | const auto blocksCnt = map.GetBlocksForLevelCount(lodLevel); 104 | while(!currentLevelNodes.empty()) { 105 | auto& currentNode = *currentLevelNodes.front(); 106 | 107 | // look for a polygon block to assign to this node 108 | const auto currentNodeMin = XMLoadFloat3(¤tNode->MinCorner); 109 | for (auto bit = 0; bit < blocksCnt; ++bit) { 110 | auto block = map.GetBlockForLevel(lodLevel, bit); 111 | 112 | const auto minCorner = block->GetMinimalCorner(); 113 | const auto blockMin = XMLoadFloat3(&minCorner); 114 | UINT areEqual; 115 | XMVectorEqualIntR(&areEqual, currentNodeMin, blockMin); 116 | if(XMComparisonAllTrue(areEqual)) { 117 | currentNode->Id = block->GetId(); 118 | ++m_NonEmptyNodes; 119 | 120 | #ifdef _DEBUG 121 | // assert that the max corners are the same 122 | const auto currentNodeMax = XMLoadFloat3(¤tNode->MaxCorner); 123 | const auto maxCorner = block->GetMaximalCorner(); 124 | const auto blockMax = XMLoadFloat3(&maxCorner); 125 | XMVectorEqualIntR(&areEqual, currentNodeMax, blockMax); 126 | assert(XMComparisonAllTrue(areEqual)); 127 | #endif 128 | } 129 | } 130 | 131 | if(lodLevel > 0) { 132 | // create all the children 133 | auto nextLevelNodeExtents = XMFLOAT3(levelExtents.x / 2, levelExtents.y / 2, levelExtents.z / 2); 134 | 135 | auto childId = 0u; 136 | 137 | for(auto x = 0; x < 2; ++x) 138 | for(auto y = 0; y < 2; ++y) 139 | for(auto z = 0; z < 2; ++z) 140 | { 141 | const auto minCorner = XMFLOAT3(currentNode->MinCorner.x + (x * nextLevelNodeExtents.x) 142 | , currentNode->MinCorner.y + (y * nextLevelNodeExtents.y) 143 | , currentNode->MinCorner.z + (z * nextLevelNodeExtents.z)); 144 | 145 | const auto maxCorner = XMFLOAT3(currentNode->MinCorner.x + ((x + 1) * nextLevelNodeExtents.x) 146 | , currentNode->MinCorner.y + ((y + 1) * nextLevelNodeExtents.y) 147 | , currentNode->MinCorner.z + ((z + 1) * nextLevelNodeExtents.z)); 148 | 149 | currentNode->Children[childId] = Node::Create(lodLevel - 1, minCorner, maxCorner); 150 | 151 | nextLevelNodes.push(¤tNode->Children[childId]); 152 | 153 | ++childId; 154 | } 155 | } 156 | 157 | currentLevelNodes.pop(); 158 | } 159 | levelExtents.x /= 2; 160 | levelExtents.y /= 2; 161 | levelExtents.z /= 2; 162 | 163 | std::swap(currentLevelNodes, nextLevelNodes); 164 | assert(nextLevelNodes.empty()); 165 | } 166 | 167 | #ifdef _DEBUG 168 | // assert that all blocks are in the octree 169 | auto blockTotalCnt = 0u; 170 | for(auto lodLevel = 0u; lodLevel < m_LodLevels; ++lodLevel) { 171 | blockTotalCnt += map.GetBlocksForLevelCount(lodLevel); 172 | } 173 | assert(blockTotalCnt == m_NonEmptyNodes); 174 | #endif 175 | 176 | // Prune all empty nodes 177 | PruneNode(m_Root); 178 | 179 | return true; 180 | } 181 | 182 | VoxelLodOctree::VisibleBlocksVec VoxelLodOctree::Cull(const XMFLOAT4 frustumPlanes[6], const XMFLOAT3& cameraPosition) { 183 | VisibleBlocksVec output; 184 | 185 | typedef std::vector LodNodesVec; 186 | LodNodesVec nodesToDraw; 187 | nodesToDraw.resize(m_LodLevels); 188 | 189 | NodesQueue unvisitedNodes; 190 | unvisitedNodes.push(&m_Root); 191 | 192 | XMVECTOR camPos = XMLoadFloat3(&cameraPosition); 193 | 194 | while(!unvisitedNodes.empty()) { 195 | auto& node = *unvisitedNodes.front(); 196 | 197 | if(IsCubeVisible(frustumPlanes, node->MinCorner, node->MaxCorner)) { 198 | bool hasToPushChildren = true; 199 | if(node->Id != PolygonSurface::INVALID_ID) { 200 | if(node->ChildCount == 0) { 201 | // push this because it has no children anyway - a leaf 202 | nodesToDraw[node->Level].push_back(&node); 203 | hasToPushChildren = false; 204 | } else { 205 | // check the distance 206 | XMVECTOR minCorner = XMLoadFloat3(&node->MinCorner); 207 | XMVECTOR maxCorner = XMLoadFloat3(&node->MaxCorner); 208 | 209 | XMVECTOR nodeCenter = (maxCorner + minCorner) / 2; 210 | XMFLOAT3A distanceVec; 211 | XMStoreFloat3A(&distanceVec, XMVectorAbs(nodeCenter - camPos)); 212 | auto chebishevDistance = std::max(std::max(distanceVec.x, distanceVec.y), distanceVec.z); 213 | 214 | XMVECTOR nodeExtent = maxCorner - minCorner; // it's a cube - all axes should have the same extent 215 | 216 | if (chebishevDistance >= XMVectorGetX(nodeExtent) * LOD_SETTLE_COEFF) { 217 | // settle for this node - it is far away 218 | nodesToDraw[node->Level].push_back(&node); 219 | hasToPushChildren = false; 220 | } 221 | } 222 | } 223 | 224 | if(hasToPushChildren) { 225 | for(auto child = 0u; child < 8; ++child) { 226 | auto& theChild = (*node).Children[child]; 227 | if(theChild) { 228 | unvisitedNodes.push(&theChild); 229 | } 230 | } 231 | } 232 | } 233 | 234 | unvisitedNodes.pop(); 235 | } 236 | 237 | for(int level = m_LodLevels - 1; level >= 0; --level) { 238 | std::for_each(nodesToDraw[level].cbegin(), nodesToDraw[level].cend(), [&](NodePtr* node_p) { 239 | auto& node = (*node_p); 240 | output.emplace_back(VisibleBlock(node->Id)); 241 | 242 | // we skip the transition face calculation for the nowest level nodes - they never draw transitions 243 | if(level == 0) return; 244 | 245 | // check the higher-res nodes for potential neighbours 246 | std::for_each(nodesToDraw[level - 1].cbegin(), nodesToDraw[level - 1].cend(), [&](NodePtr* highnode_p) { 247 | CheckForNeighbour(node, *highnode_p, output.back()); 248 | }); 249 | }); 250 | } 251 | 252 | return std::move(output); 253 | } 254 | 255 | void VoxelLodOctree::CheckForNeighbour(const NodePtr& lowResNode, const NodePtr& highResNode, VisibleBlock& output) 256 | { 257 | #ifdef _DEBUG 258 | const XMFLOAT3& lMin = lowResNode->MinCorner; 259 | const XMFLOAT3& lMax = lowResNode->MaxCorner; 260 | 261 | const XMFLOAT3& hMin = highResNode->MinCorner; 262 | const XMFLOAT3& hMax = highResNode->MaxCorner; 263 | // check that no two nodes overlap! 264 | if(((lMin.x < hMax.x) && (hMin.x < lMax.x)) 265 | && ((lMin.y < hMax.y) && (hMin.y < lMax.y)) 266 | && ((lMin.z < hMax.z) && (hMin.z < lMax.z))) { 267 | assert(false && "Detected overlapping blocks for drawing!"); 268 | } 269 | #endif 270 | 271 | XMVECTOR lowMin = XMLoadFloat3(&lowResNode->MinCorner); 272 | XMVECTOR lowMax = XMLoadFloat3(&lowResNode->MaxCorner); 273 | 274 | XMVECTOR highMin = XMLoadFloat3(&highResNode->MinCorner); 275 | XMVECTOR highMax = XMLoadFloat3(&highResNode->MaxCorner); 276 | 277 | // check if it's a direct neighbour 278 | auto XPosPlane = XMPlaneFromPointNormal(lowMax, XMVectorSet(1, 0, 0, 1)); 279 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(XPosPlane, highMin))) < std::numeric_limits::epsilon() 280 | && floor(lowResNode->MaxCorner.y) > floor(highResNode->MinCorner.y) 281 | && floor(lowResNode->MaxCorner.z) > floor(highResNode->MinCorner.z) 282 | && floor(lowResNode->MinCorner.y) <= floor(highResNode->MinCorner.y) 283 | && floor(lowResNode->MinCorner.z) <= floor(highResNode->MinCorner.z)) { 284 | output.TransitionFaces[BlockPolygons::XPos] = true; 285 | return; 286 | } 287 | auto XNegPlane = XMPlaneFromPointNormal(lowMin, XMVectorSet(-1, 0, 0, 1)); 288 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(XNegPlane, highMax))) < std::numeric_limits::epsilon() 289 | && floor(lowResNode->MinCorner.y) < floor(highResNode->MaxCorner.y) 290 | && floor(lowResNode->MinCorner.z) < floor(highResNode->MaxCorner.z) 291 | && floor(lowResNode->MaxCorner.y) >= floor(highResNode->MaxCorner.y) 292 | && floor(lowResNode->MaxCorner.z) >= floor(highResNode->MaxCorner.z)) { 293 | output.TransitionFaces[BlockPolygons::XNeg] = true; 294 | return; 295 | } 296 | 297 | auto YPosPlane = XMPlaneFromPointNormal(lowMax, XMVectorSet(0, 1, 0, 1)); 298 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(YPosPlane, highMin))) < std::numeric_limits::epsilon() 299 | && floor(lowResNode->MaxCorner.x) > floor(highResNode->MinCorner.x) 300 | && floor(lowResNode->MaxCorner.z) > floor(highResNode->MinCorner.z) 301 | && floor(lowResNode->MinCorner.x) <= floor(highResNode->MinCorner.x) 302 | && floor(lowResNode->MinCorner.z) <= floor(highResNode->MinCorner.z)) { 303 | output.TransitionFaces[BlockPolygons::YPos] = true; 304 | return; 305 | } 306 | auto YNegPlane = XMPlaneFromPointNormal(lowMin, XMVectorSet(0, -1, 0, 1)); 307 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(YNegPlane, highMax))) < std::numeric_limits::epsilon() 308 | && floor(lowResNode->MinCorner.x) < floor(highResNode->MaxCorner.x) 309 | && floor(lowResNode->MinCorner.z) < floor(highResNode->MaxCorner.z) 310 | && floor(lowResNode->MaxCorner.x) >= floor(highResNode->MaxCorner.x) 311 | && floor(lowResNode->MaxCorner.z) >= floor(highResNode->MaxCorner.z)) { 312 | output.TransitionFaces[BlockPolygons::YNeg] = true; 313 | return; 314 | } 315 | 316 | auto ZPosPlane = XMPlaneFromPointNormal(lowMax, XMVectorSet(0, 0, 1, 1)); 317 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(ZPosPlane, highMin))) < std::numeric_limits::epsilon() 318 | && floor(lowResNode->MaxCorner.x) > floor(highResNode->MinCorner.x) 319 | && floor(lowResNode->MaxCorner.y) > floor(highResNode->MinCorner.y) 320 | && floor(lowResNode->MinCorner.x) <= floor(highResNode->MinCorner.x) 321 | && floor(lowResNode->MinCorner.y) <= floor(highResNode->MinCorner.y)) { 322 | output.TransitionFaces[BlockPolygons::ZPos] = true; 323 | return; 324 | } 325 | 326 | auto ZNegPlane = XMPlaneFromPointNormal(lowMin, XMVectorSet(0, 0, -1, 1)); 327 | if(std::abs(XMVectorGetX(XMPlaneDotCoord(ZNegPlane, highMax))) < std::numeric_limits::epsilon() 328 | && floor(lowResNode->MinCorner.x) < floor(highResNode->MaxCorner.x) 329 | && floor(lowResNode->MinCorner.y) < floor(highResNode->MaxCorner.y) 330 | && floor(lowResNode->MaxCorner.x) >= floor(highResNode->MaxCorner.x) 331 | && floor(lowResNode->MaxCorner.y) >= floor(highResNode->MaxCorner.y)) { 332 | output.TransitionFaces[BlockPolygons::ZNeg] = true; 333 | return; 334 | } 335 | } 336 | 337 | bool VoxelLodOctree::IsCubeVisible(const XMFLOAT4 frustumPlanes[6], const XMFLOAT3& cubeMin, const XMFLOAT3& cubeMax) { 338 | XMFLOAT4 minExtreme; 339 | 340 | for(unsigned i = 0; i < 6; i++) 341 | { 342 | if (frustumPlanes[i].x <= 0) 343 | { 344 | minExtreme.x = cubeMin.x; 345 | } 346 | else 347 | { 348 | minExtreme.x = cubeMax.x; 349 | } 350 | 351 | if (frustumPlanes[i].y <= 0) 352 | { 353 | minExtreme.y = cubeMin.y; 354 | } 355 | else 356 | { 357 | minExtreme.y = cubeMax.y; 358 | } 359 | 360 | if (frustumPlanes[i].z <= 0) 361 | { 362 | minExtreme.z = cubeMin.z; 363 | } 364 | else 365 | { 366 | minExtreme.z = cubeMax.z; 367 | } 368 | 369 | if ((frustumPlanes[i].x * minExtreme.x + frustumPlanes[i].y * minExtreme.y + frustumPlanes[i].z * minExtreme.z + frustumPlanes[i].w) < 0.f) 370 | { 371 | return false; 372 | } 373 | } 374 | 375 | return true; 376 | } 377 | 378 | } 379 | -------------------------------------------------------------------------------- /Source/Voxel/VoxelLodOctree.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include "../../Voxels/include/Polygonizer.h" 9 | 10 | namespace Voxels 11 | { 12 | 13 | // Culls surface blocks and decides wich LOD levels to use based on 14 | // the position of the camera each frame 15 | class VoxelLodOctree 16 | { 17 | public: 18 | struct VisibleBlock { 19 | VisibleBlock(unsigned id) 20 | : Id(id) 21 | { 22 | std::fill(TransitionFaces, TransitionFaces + BlockPolygons::Face_Count, false); 23 | } 24 | unsigned Id; 25 | 26 | bool TransitionFaces[BlockPolygons::Face_Count]; 27 | }; 28 | typedef std::vector VisibleBlocksVec; 29 | 30 | VoxelLodOctree(); 31 | ~VoxelLodOctree(); 32 | 33 | bool Build(const PolygonSurface& map); 34 | 35 | // Culls blocks and decides which LOD levels to use 36 | // NB: Planes and camera position MUST be in un-transformed grid coordinates 37 | VisibleBlocksVec Cull(const DirectX::XMFLOAT4 frustumPlanes[6], const DirectX::XMFLOAT3& cameraPosition); 38 | 39 | unsigned GetLodLevelsCount() const { return m_LodLevels; } 40 | unsigned GetNonEmptyNodesCount() const { return m_NonEmptyNodes; } 41 | 42 | private: 43 | struct Node; 44 | typedef std::unique_ptr NodePtr; 45 | typedef std::vector NodePtrVec; 46 | 47 | bool PruneNode(NodePtr& node); 48 | void CheckForNeighbour(const NodePtr& lowResNode, const NodePtr& highResNode, VisibleBlock& output); 49 | static bool IsCubeVisible(const DirectX::XMFLOAT4 frustumPlanes[6], const DirectX::XMFLOAT3& cubeMin, const DirectX::XMFLOAT3& cubeMax); 50 | 51 | NodePtr m_Root; 52 | 53 | typedef std::deque qcontainer; 54 | typedef std::queue NodesQueue; 55 | 56 | // statistical data 57 | unsigned m_LodLevels; 58 | unsigned m_NonEmptyNodes; 59 | }; 60 | 61 | } -------------------------------------------------------------------------------- /Source/VoxelBall.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VoxelBall.h" 9 | 10 | using namespace DirectX; 11 | 12 | namespace Voxels 13 | { 14 | 15 | VoxelBall::VoxelBall(const XMFLOAT3& position, float radius) 16 | : m_Ball(XMVectorSet(position.x, position.y, position.z, radius)) 17 | {} 18 | 19 | void VoxelBall::GetSurface(float xStart, float xEnd, float xStep, 20 | float yStart, float yEnd, float yStep, 21 | float zStart, float zEnd, float zStep, 22 | float* output, 23 | unsigned char* materialid, 24 | unsigned char* blend) 25 | { 26 | auto id = 0; 27 | for (auto z = zStart; z < zEnd; z += zStep) 28 | { 29 | for (auto y = yStart; y < yEnd; y += yStep) 30 | { 31 | for (auto x = xStart; x < xEnd; x += xStep) 32 | { 33 | const XMVECTOR vec = XMVectorSubtract(m_Ball, XMVectorSet(x, y, z, 0)); 34 | const XMVECTOR dist = XMVector3Length(vec); 35 | 36 | output[id] = XMVectorGetW(XMVectorSubtract(dist, m_Ball)); 37 | if (materialid != nullptr) 38 | { 39 | materialid[id] = 0; 40 | blend[id] = 0; 41 | } 42 | ++id; 43 | } 44 | } 45 | } 46 | } 47 | 48 | VoxelBall::~VoxelBall() 49 | {} 50 | 51 | } -------------------------------------------------------------------------------- /Source/VoxelBall.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include "../Voxels/include/VoxelSurface.h" 10 | 11 | namespace Voxels 12 | { 13 | 14 | __declspec(align(16)) 15 | class VoxelBall : public VoxelSurface, public Aligned<16> 16 | { 17 | public: 18 | VoxelBall(const DirectX::XMFLOAT3& position, float radius); 19 | virtual ~VoxelBall(); 20 | virtual void GetSurface(float xStart, float xEnd, float xStep, 21 | float yStart, float yEnd, float yStep, 22 | float zStart, float zEnd, float zStep, 23 | float* output, 24 | unsigned char* materialid, 25 | unsigned char* blend) override; 26 | private: 27 | DirectX::XMVECTOR m_Ball; 28 | }; 29 | 30 | }; -------------------------------------------------------------------------------- /Source/VoxelBox.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VoxelBox.h" 9 | 10 | using namespace DirectX; 11 | 12 | namespace Voxels 13 | { 14 | 15 | VoxelBox::VoxelBox(const XMFLOAT3& extents) 16 | : m_Extents(extents) 17 | {} 18 | 19 | void VoxelBox::GetSurface(float xStart, float xEnd, float xStep, 20 | float yStart, float yEnd, float yStep, 21 | float zStart, float zEnd, float zStep, 22 | float* output, 23 | unsigned char* materialid, 24 | unsigned char* blend) 25 | { 26 | auto id = 0; 27 | for (auto z = zStart; z < zEnd; z += zStep) 28 | { 29 | for (auto y = yStart; y < yEnd; y += yStep) 30 | { 31 | for (auto x = xStart; x < xEnd; x += xStep) 32 | { 33 | XMFLOAT3 d(std::abs(x) - m_Extents.x, std::abs(y) - m_Extents.y, std::abs(z) - m_Extents.z); 34 | XMFLOAT3 dm(std::max(d.x, 0.f), std::max(d.y, 0.f), std::max(d.z, 0.f)); 35 | auto dl = std::sqrtf(dm.x * dm.x + dm.y * dm.y + dm.z * dm.z); 36 | 37 | output[id] = std::min(std::max(d.x, std::max(d.y, d.z)), 0.f) + dl; 38 | if (materialid != nullptr) 39 | { 40 | materialid[id] = 0; 41 | blend[id] = 0; 42 | } 43 | ++id; 44 | } 45 | } 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /Source/VoxelBox.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include "../Voxels/include/VoxelSurface.h" 10 | 11 | namespace Voxels 12 | { 13 | 14 | class VoxelBox : public VoxelSurface 15 | { 16 | public: 17 | VoxelBox(const DirectX::XMFLOAT3& extents); 18 | virtual void GetSurface(float xStart, float xEnd, float xStep, 19 | float yStart, float yEnd, float yStep, 20 | float zStart, float zEnd, float zStep, 21 | float* output, 22 | unsigned char* materialid, 23 | unsigned char* blend) override; 24 | private: 25 | DirectX::XMFLOAT3 m_Extents; 26 | }; 27 | 28 | } -------------------------------------------------------------------------------- /Source/VoxelPlane.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VoxelPlane.h" 9 | 10 | using namespace DirectX; 11 | 12 | namespace Voxels 13 | { 14 | 15 | VoxelPlane::VoxelPlane(const XMFLOAT3& normal, float d) 16 | : m_Plane(XMVectorSet(normal.x, normal.y, normal.z, d)) 17 | { 18 | m_Plane = XMPlaneNormalize(m_Plane); 19 | } 20 | 21 | void VoxelPlane::GetSurface(float xStart, float xEnd, float xStep, 22 | float yStart, float yEnd, float yStep, 23 | float zStart, float zEnd, float zStep, 24 | float* output, 25 | unsigned char* materialid, 26 | unsigned char* blend) 27 | { 28 | auto id = 0; 29 | for (auto z = zStart; z < zEnd; z += zStep) 30 | { 31 | for (auto y = yStart; y < yEnd; y += yStep) 32 | { 33 | for (auto x = xStart; x < xEnd; x += xStep) 34 | { 35 | const XMVECTOR point = XMVectorSet(x, y, z, 1); 36 | output[id] = XMVectorGetX(XMPlaneDot(m_Plane, point)); 37 | if (materialid != nullptr) 38 | { 39 | materialid[id] = 0; 40 | blend[id] = 0; 41 | } 42 | ++id; 43 | } 44 | } 45 | } 46 | } 47 | 48 | VoxelPlane::~VoxelPlane() 49 | {} 50 | 51 | } -------------------------------------------------------------------------------- /Source/VoxelPlane.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include "../Voxels/include/VoxelSurface.h" 10 | 11 | namespace Voxels 12 | { 13 | 14 | __declspec(align(16)) 15 | class VoxelPlane : public VoxelSurface, public Aligned<16> 16 | { 17 | public: 18 | VoxelPlane(const DirectX::XMFLOAT3& normal, float d); 19 | virtual ~VoxelPlane(); 20 | virtual void GetSurface(float xStart, float xEnd, float xStep, 21 | float yStart, float yEnd, float yStep, 22 | float zStart, float zEnd, float zStep, 23 | float* output, 24 | unsigned char* materialid, 25 | unsigned char* blend) override; 26 | private: 27 | DirectX::XMVECTOR m_Plane; 28 | }; 29 | 30 | } -------------------------------------------------------------------------------- /Source/VoxelProc.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" 7 | 8 | #include "VoxelProc.h" 9 | 10 | #include 11 | #include 12 | 13 | using namespace DirectX; 14 | 15 | namespace Voxels 16 | { 17 | 18 | VoxelProc::VoxelProc(const XMFLOAT3& normal, float d, const ProceduralParams& params) 19 | : m_Plane(XMVectorSet(normal.x, normal.y, normal.z, d)) 20 | , m_Params(params) 21 | { 22 | m_Plane = XMPlaneNormalize(m_Plane); 23 | } 24 | 25 | VoxelProc::~VoxelProc() 26 | {} 27 | 28 | void VoxelProc::GetSurface(float xStart, float xEnd, float xStep, 29 | float yStart, float yEnd, float yStep, 30 | float zStart, float zEnd, float zStep, 31 | float* output, 32 | unsigned char* materialid, 33 | unsigned char* blend) 34 | { 35 | auto id = 0; 36 | /*for (auto z = zStart; z < zEnd; z += zStep) 37 | { 38 | for (auto y = yStart; y < yEnd; y += yStep) 39 | { 40 | for (auto x = xStart; x < xEnd; x += xStep) 41 | { 42 | XMVECTOR point = XMVectorSet(x, y, z, 1); 43 | auto density = XMVectorGetX(XMPlaneDot(m_Plane, point)); 44 | density += glm::perlin(glm::vec3( 45 | x * m_Params.DimensionFactor, 46 | y * m_Params.DimensionFactor, 47 | z * m_Params.DimensionFactor)) * m_Params.ScaleFactor; 48 | 49 | output[id] = density; 50 | if (materialid != nullptr) 51 | { 52 | materialid[id] = 0; 53 | blend[id] = 0; 54 | } 55 | ++id; 56 | } 57 | } 58 | }*/ 59 | 60 | /*for (auto z = zStart/2; z < zEnd/2; z += zStep/2) 61 | { 62 | for (auto y = yStart/2; y < yEnd/2; y += yStep/2) 63 | { 64 | for (auto x = xStart/2; x < xEnd/2; x += xStep/2) 65 | { 66 | XMVECTOR point = XMVectorSet(x, y, z, 1); 67 | auto density = XMVectorGetX(XMPlaneDot(m_Plane, point)); 68 | density += glm::perlin(glm::vec3( 69 | x * m_Params.DimensionFactor, 70 | y * m_Params.DimensionFactor, 71 | z * m_Params.DimensionFactor)) * m_Params.ScaleFactor * 2; 72 | 73 | output[id] = density; 74 | if (materialid != nullptr) 75 | { 76 | materialid[id] = 0; 77 | blend[id] = 0; 78 | } 79 | ++id; 80 | } 81 | } 82 | }*/ 83 | 84 | static const int DFACT = 2; 85 | 86 | for (auto z = zStart / DFACT; z < zEnd / DFACT; z += zStep / DFACT) 87 | { 88 | for (auto y = yStart / DFACT; y < yEnd / DFACT; y += yStep / DFACT) 89 | { 90 | for (auto x = xStart / DFACT; x < xEnd / DFACT; x += xStep / DFACT) 91 | { 92 | XMVECTOR point = XMVectorSet(x, y, z, 1); 93 | auto density = XMVectorGetX(XMPlaneDot(m_Plane, point)); 94 | density += glm::perlin(glm::vec3( 95 | x * m_Params.DimensionFactor, 96 | y * m_Params.DimensionFactor, 97 | z * m_Params.DimensionFactor)) * m_Params.ScaleFactor * 4; 98 | 99 | output[id] = density; 100 | if (materialid != nullptr) 101 | { 102 | materialid[id] = 0; 103 | blend[id] = 0; 104 | } 105 | ++id; 106 | } 107 | } 108 | } 109 | } 110 | 111 | } -------------------------------------------------------------------------------- /Source/VoxelProc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #include 9 | #include "../Voxels/include/VoxelSurface.h" 10 | 11 | namespace Voxels 12 | { 13 | 14 | struct ProceduralParams 15 | { 16 | float DimensionFactor; 17 | float ScaleFactor; 18 | }; 19 | 20 | __declspec(align(16)) 21 | class VoxelProc : public VoxelSurface, public Aligned<16> 22 | { 23 | public: 24 | VoxelProc(const DirectX::XMFLOAT3& normal, float d, const ProceduralParams& params); 25 | virtual ~VoxelProc(); 26 | 27 | virtual void GetSurface(float xStart, float xEnd, float xStep, 28 | float yStart, float yEnd, float yStep, 29 | float zStart, float zEnd, float zStep, 30 | float* output, 31 | unsigned char* materialid, 32 | unsigned char* blend) override; 33 | private: 34 | DirectX::XMVECTOR m_Plane; 35 | ProceduralParams m_Params; 36 | }; 37 | 38 | } -------------------------------------------------------------------------------- /Source/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | 7 | #include "stdafx.h" 8 | 9 | #include "VolumeRenderingApplication.h" 10 | 11 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 12 | { 13 | PAINTSTRUCT ps; 14 | HDC hdc; 15 | 16 | switch(message) 17 | { 18 | case WM_PAINT: 19 | hdc = BeginPaint(hWnd, &ps); 20 | EndPaint(hWnd, &ps); 21 | break; 22 | 23 | case WM_DESTROY: 24 | PostQuitMessage(0); 25 | break; 26 | 27 | default: 28 | return DefWindowProc(hWnd, message, wParam, lParam); 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | #ifdef PROFI_ENABLE 35 | #ifdef DEBUG 36 | typedef profi::DebugMallocAllocator ProfiAllocator; 37 | #else 38 | typedef profi::DefaultMallocAllocator ProfiAllocator; 39 | #endif 40 | #endif 41 | 42 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 43 | { 44 | #ifdef PROFI_ENABLE 45 | ProfiAllocator allocator; 46 | profi::Initialize(&allocator); 47 | #endif 48 | 49 | Logging::Logger::Initialize(); 50 | Logging::Logger::Get().AddTarget(new std::ofstream("VolumeRenderingApplication_App.log")); 51 | Logging::Logger::Get().SetMinimalLogSeverity(Logging::Sev_Debug); 52 | 53 | auto app = std::unique_ptr(new VolumeRenderingApplication(hInstance)); 54 | 55 | if(app->Initiate("VolumeRenderingApp", "VolumeRendering application", 1280, 720, &WndProc)) 56 | { 57 | app->DoMessageLoop(); 58 | } 59 | 60 | app.reset(); 61 | 62 | Logging::Logger::Deinitialize(); 63 | 64 | #ifdef PROFI_ENABLE 65 | // dump the perf 66 | profi::IReport* report(profi::GetReportJSON()); 67 | 68 | std::ofstream fout("performance.json"); 69 | fout.write((const char*)report->Data(), report->Size()); 70 | 71 | report->Release(); 72 | profi::Deinitialize(); 73 | #endif 74 | 75 | #ifdef _CRTDBG_MAP_ALLOC 76 | _CrtDumpMemoryLeaks(); 77 | #endif 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /Source/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #include "stdafx.h" -------------------------------------------------------------------------------- /Source/stdafx.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013-2014, Stoyan Nikolov 2 | // All rights reserved. 3 | // This sample is governed by a permissive BSD-style license. See LICENSE. 4 | // Note: The Voxels Library itself has a separate license. Check out it's 5 | // website for more information 6 | #pragma once 7 | 8 | #define CHECK_MEMORY 0 9 | 10 | #if CHECK_MEMORY 11 | #define _CRTDBG_MAP_ALLOC 12 | #include 13 | #include 14 | #endif 15 | 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | #ifdef PROFI_ENABLE 26 | #include 27 | #include 28 | #endif 29 | 30 | #include "../Voxels/include/Voxels.h" 31 | -------------------------------------------------------------------------------- /VolumeRendering.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30110.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VolumeRendering", "VolumeRendering.vcxproj", "{A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utilities", "..\dx11-framework\Utilities\Utilities.vcxproj", "{AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{7DC34584-B70F-4B1B-AD3C-E0DC0E023585}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppCore", "..\dx11-framework\Dx11\AppCore\AppCore.vcxproj", "{C866D5A2-553D-4E96-8795-14B5803376EC}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppGraphics", "..\dx11-framework\Dx11\AppGraphics\AppGraphics.vcxproj", "{46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Rendering", "..\dx11-framework\Dx11\Rendering\Rendering.vcxproj", "{5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Win32 = Debug|Win32 21 | Debug|x64 = Debug|x64 22 | Profile|Win32 = Profile|Win32 23 | Profile|x64 = Profile|x64 24 | Release|Win32 = Release|Win32 25 | Release|x64 = Release|x64 26 | ReleaseTrack|Win32 = ReleaseTrack|Win32 27 | ReleaseTrack|x64 = ReleaseTrack|x64 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Debug|Win32.ActiveCfg = Debug|Win32 31 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Debug|Win32.Build.0 = Debug|Win32 32 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Debug|x64.ActiveCfg = Debug|x64 33 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Debug|x64.Build.0 = Debug|x64 34 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Profile|Win32.ActiveCfg = Profile|Win32 35 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Profile|Win32.Build.0 = Profile|Win32 36 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Profile|x64.ActiveCfg = Profile|x64 37 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Profile|x64.Build.0 = Profile|x64 38 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Release|Win32.ActiveCfg = Release|Win32 39 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Release|Win32.Build.0 = Release|Win32 40 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Release|x64.ActiveCfg = Release|x64 41 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.Release|x64.Build.0 = Release|x64 42 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.ReleaseTrack|Win32.ActiveCfg = ReleaseTrack|Win32 43 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.ReleaseTrack|Win32.Build.0 = ReleaseTrack|Win32 44 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.ReleaseTrack|x64.ActiveCfg = Release|x64 45 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF}.ReleaseTrack|x64.Build.0 = Release|x64 46 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Debug|Win32.ActiveCfg = Debug|Win32 47 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Debug|Win32.Build.0 = Debug|Win32 48 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Debug|x64.ActiveCfg = Debug|x64 49 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Debug|x64.Build.0 = Debug|x64 50 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Profile|Win32.ActiveCfg = Release|Win32 51 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Profile|Win32.Build.0 = Release|Win32 52 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Profile|x64.ActiveCfg = Release|x64 53 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Profile|x64.Build.0 = Release|x64 54 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Release|Win32.ActiveCfg = Release|Win32 55 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Release|Win32.Build.0 = Release|Win32 56 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Release|x64.ActiveCfg = Release|x64 57 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.Release|x64.Build.0 = Release|x64 58 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.ReleaseTrack|Win32.ActiveCfg = Release|Win32 59 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.ReleaseTrack|Win32.Build.0 = Release|Win32 60 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.ReleaseTrack|x64.ActiveCfg = Release|x64 61 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A}.ReleaseTrack|x64.Build.0 = Release|x64 62 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Debug|Win32.ActiveCfg = Debug|Win32 63 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Debug|Win32.Build.0 = Debug|Win32 64 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Debug|x64.ActiveCfg = Debug|x64 65 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Debug|x64.Build.0 = Debug|x64 66 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Profile|Win32.ActiveCfg = Release|Win32 67 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Profile|Win32.Build.0 = Release|Win32 68 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Profile|x64.ActiveCfg = Release|x64 69 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Profile|x64.Build.0 = Release|x64 70 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Release|Win32.ActiveCfg = Release|Win32 71 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Release|Win32.Build.0 = Release|Win32 72 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Release|x64.ActiveCfg = Release|x64 73 | {C866D5A2-553D-4E96-8795-14B5803376EC}.Release|x64.Build.0 = Release|x64 74 | {C866D5A2-553D-4E96-8795-14B5803376EC}.ReleaseTrack|Win32.ActiveCfg = Release|Win32 75 | {C866D5A2-553D-4E96-8795-14B5803376EC}.ReleaseTrack|Win32.Build.0 = Release|Win32 76 | {C866D5A2-553D-4E96-8795-14B5803376EC}.ReleaseTrack|x64.ActiveCfg = Release|x64 77 | {C866D5A2-553D-4E96-8795-14B5803376EC}.ReleaseTrack|x64.Build.0 = Release|x64 78 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Debug|Win32.ActiveCfg = Debug|Win32 79 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Debug|Win32.Build.0 = Debug|Win32 80 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Debug|x64.ActiveCfg = Debug|x64 81 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Debug|x64.Build.0 = Debug|x64 82 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Profile|Win32.ActiveCfg = Release|Win32 83 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Profile|Win32.Build.0 = Release|Win32 84 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Profile|x64.ActiveCfg = Release|x64 85 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Profile|x64.Build.0 = Release|x64 86 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Release|Win32.ActiveCfg = Release|Win32 87 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Release|Win32.Build.0 = Release|Win32 88 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Release|x64.ActiveCfg = Release|x64 89 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.Release|x64.Build.0 = Release|x64 90 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.ReleaseTrack|Win32.ActiveCfg = Release|Win32 91 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.ReleaseTrack|Win32.Build.0 = Release|Win32 92 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.ReleaseTrack|x64.ActiveCfg = Release|x64 93 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57}.ReleaseTrack|x64.Build.0 = Release|x64 94 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Debug|Win32.ActiveCfg = Debug|Win32 95 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Debug|Win32.Build.0 = Debug|Win32 96 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Debug|x64.ActiveCfg = Debug|x64 97 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Debug|x64.Build.0 = Debug|x64 98 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Profile|Win32.ActiveCfg = Release|Win32 99 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Profile|Win32.Build.0 = Release|Win32 100 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Profile|x64.ActiveCfg = Release|x64 101 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Profile|x64.Build.0 = Release|x64 102 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Release|Win32.ActiveCfg = Release|Win32 103 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Release|Win32.Build.0 = Release|Win32 104 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Release|x64.ActiveCfg = Release|x64 105 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.Release|x64.Build.0 = Release|x64 106 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.ReleaseTrack|Win32.ActiveCfg = Release|Win32 107 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.ReleaseTrack|Win32.Build.0 = Release|Win32 108 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.ReleaseTrack|x64.ActiveCfg = Release|x64 109 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF}.ReleaseTrack|x64.Build.0 = Release|x64 110 | EndGlobalSection 111 | GlobalSection(SolutionProperties) = preSolution 112 | HideSolutionNode = FALSE 113 | EndGlobalSection 114 | GlobalSection(NestedProjects) = preSolution 115 | {AAF2E973-6CBB-44F1-B07D-B2327DD83B6A} = {7DC34584-B70F-4B1B-AD3C-E0DC0E023585} 116 | {C866D5A2-553D-4E96-8795-14B5803376EC} = {7DC34584-B70F-4B1B-AD3C-E0DC0E023585} 117 | {46C56AA3-F32B-4E7F-9C7B-F4FA95A03D57} = {7DC34584-B70F-4B1B-AD3C-E0DC0E023585} 118 | {5F07F4AB-1F6F-49F1-83A9-07B5EC0E29BF} = {7DC34584-B70F-4B1B-AD3C-E0DC0E023585} 119 | EndGlobalSection 120 | EndGlobal 121 | -------------------------------------------------------------------------------- /VolumeRendering.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Profile 14 | Win32 15 | 16 | 17 | Profile 18 | x64 19 | 20 | 21 | ReleaseTrack 22 | Win32 23 | 24 | 25 | ReleaseTrack 26 | x64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | {A59DCFBF-F8E9-4E6C-A774-964A99DC49EF} 39 | Win32Proj 40 | VolumeRendering 41 | 42 | 43 | 44 | Application 45 | true 46 | NotSet 47 | v110 48 | 49 | 50 | Application 51 | true 52 | NotSet 53 | v110 54 | 55 | 56 | Application 57 | false 58 | true 59 | NotSet 60 | v110 61 | 62 | 63 | Application 64 | false 65 | true 66 | NotSet 67 | v110 68 | 69 | 70 | Application 71 | false 72 | true 73 | NotSet 74 | v110 75 | 76 | 77 | Application 78 | false 79 | true 80 | NotSet 81 | v110 82 | 83 | 84 | Application 85 | false 86 | true 87 | NotSet 88 | v110 89 | 90 | 91 | Application 92 | false 93 | true 94 | NotSet 95 | v110 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | true 159 | bin$(PlatformArchitecture)\ 160 | $(ProjectName)D 161 | 162 | 163 | $(ProjectName)D 164 | true 165 | bin$(PlatformArchitecture)\ 166 | 167 | 168 | false 169 | bin$(PlatformArchitecture)\ 170 | 171 | 172 | false 173 | bin$(PlatformArchitecture)\ 174 | 175 | 176 | false 177 | bin$(PlatformArchitecture)\ 178 | 179 | 180 | false 181 | bin$(PlatformArchitecture)\ 182 | 183 | 184 | false 185 | bin$(PlatformArchitecture)\ 186 | 187 | 188 | false 189 | bin$(PlatformArchitecture)\ 190 | 191 | 192 | 193 | Use 194 | Level3 195 | Disabled 196 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 197 | stdafx.h 198 | StreamingSIMDExtensions2 199 | Fast 200 | Default 201 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 202 | true 203 | 204 | 205 | Windows 206 | true 207 | Voxelsd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 208 | ..\voxels\src\bin32;%(AdditionalLibraryDirectories) 209 | 210 | 211 | 212 | 213 | Use 214 | Level3 215 | Disabled 216 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 217 | stdafx.h 218 | StreamingSIMDExtensions2 219 | Fast 220 | Default 221 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 222 | true 223 | 224 | 225 | Windows 226 | true 227 | Voxelsd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 228 | ..\voxels\src\bin64;%(AdditionalLibraryDirectories) 229 | 230 | 231 | 232 | 233 | Level3 234 | Use 235 | MaxSpeed 236 | true 237 | true 238 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 239 | stdafx.h 240 | StreamingSIMDExtensions2 241 | Fast 242 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 243 | true 244 | 245 | 246 | Windows 247 | true 248 | true 249 | true 250 | Voxels.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 251 | ..\voxels\src\bin32;%(AdditionalLibraryDirectories) 252 | true 253 | 254 | 255 | 256 | 257 | Level3 258 | Use 259 | MaxSpeed 260 | true 261 | true 262 | TRACKING_BUILD;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 263 | stdafx.h 264 | StreamingSIMDExtensions2 265 | Fast 266 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 267 | true 268 | 269 | 270 | Windows 271 | true 272 | true 273 | true 274 | Voxels.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 275 | ..\voxels\src\bin32;%(AdditionalLibraryDirectories) 276 | true 277 | 278 | 279 | 280 | 281 | Level3 282 | Use 283 | MaxSpeed 284 | true 285 | true 286 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 287 | stdafx.h 288 | StreamingSIMDExtensions2 289 | Fast 290 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 291 | true 292 | 293 | 294 | Windows 295 | true 296 | true 297 | true 298 | Voxels.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 299 | ..\voxels\src\bin64;%(AdditionalLibraryDirectories) 300 | true 301 | 302 | 303 | 304 | 305 | Level3 306 | Use 307 | MaxSpeed 308 | true 309 | true 310 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 311 | stdafx.h 312 | StreamingSIMDExtensions2 313 | Fast 314 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 315 | true 316 | 317 | 318 | Windows 319 | true 320 | true 321 | true 322 | Voxels.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 323 | ..\voxels\src\bin64;%(AdditionalLibraryDirectories) 324 | true 325 | 326 | 327 | 328 | 329 | Level3 330 | Use 331 | MaxSpeed 332 | true 333 | true 334 | PROFI_ENABLE;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 335 | stdafx.h 336 | StreamingSIMDExtensions2 337 | Fast 338 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 339 | true 340 | 341 | 342 | Windows 343 | true 344 | true 345 | true 346 | Voxelsp.lib;profi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 347 | ..\voxels\src\bin32;..\profi\bin;%(AdditionalLibraryDirectories) 348 | 349 | 350 | 351 | 352 | Level3 353 | Use 354 | MaxSpeed 355 | true 356 | true 357 | PROFI_ENABLE;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 358 | stdafx.h 359 | StreamingSIMDExtensions2 360 | Fast 361 | ..\profi\include;$(ProgramsPath);%(AdditionalIncludeDirectories) 362 | true 363 | 364 | 365 | Windows 366 | true 367 | true 368 | true 369 | Voxels.lib;profi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 370 | ..\voxels\src\bin64;%(AdditionalLibraryDirectories) 371 | 372 | 373 | 374 | 375 | {c866d5a2-553d-4e96-8795-14b5803376ec} 376 | 377 | 378 | {46c56aa3-f32b-4e7f-9c7b-f4fa95a03d57} 379 | 380 | 381 | {5f07f4ab-1f6f-49f1-83a9-07b5ec0e29bf} 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | Create 411 | Create 412 | Create 413 | Create 414 | Create 415 | Create 416 | Create 417 | Create 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | -------------------------------------------------------------------------------- /VolumeRendering.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {5604e06d-297b-4eee-bf0d-b73b312ced2f} 14 | 15 | 16 | 17 | 18 | Header Files 19 | 20 | 21 | Header Files 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | 67 | 68 | Source Files 69 | 70 | 71 | Source Files 72 | 73 | 74 | Source Files 75 | 76 | 77 | Source Files 78 | 79 | 80 | Source Files 81 | 82 | 83 | Source Files 84 | 85 | 86 | Source Files 87 | 88 | 89 | Source Files 90 | 91 | 92 | Source Files 93 | 94 | 95 | Source Files 96 | 97 | 98 | Source Files 99 | 100 | 101 | Source Files 102 | 103 | 104 | Source Files 105 | 106 | 107 | Source Files 108 | 109 | 110 | Source Files 111 | 112 | 113 | Source Files 114 | 115 | 116 | 117 | 118 | Shaders 119 | 120 | 121 | -------------------------------------------------------------------------------- /media/materials.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties" : [ 3 | { "grass.png" : { "UVScale" : 8 } }, 4 | { "canyon.jpg" : { "UVScale" : 8 } }, 5 | { "snow.jpg" : { "UVScale" : 8 } }, 6 | { "Deep-Freeze.jpg" : { "UVScale" : 8 } }, 7 | { "dry_grass.jpg" : { "UVScale" : 8 } }, 8 | { "sand.jpg" : { "UVScale" : 8 } }, 9 | { "sand_stone.jpg" : { "UVScale" : 8 } }, 10 | { "calcare.jpg" : { "UVScale" : 8 } }, 11 | { "grey_stone.jpg" : { "UVScale" : 8 } } 12 | ], 13 | 14 | "materials" : [ 15 | { 16 | "diffuse0" : [ "grass.png", "canyon.jpg", "canyon.jpg" ], 17 | "diffuse1" : [ "snow.jpg", "Deep-Freeze.jpg", "Deep-Freeze.jpg" ] 18 | }, 19 | { 20 | "diffuse0" : [ "grass.png", "canyon.jpg", "canyon.jpg" ], 21 | "diffuse1" : [ "dry_grass.jpg", "canyon.jpg", "canyon.jpg" ] 22 | }, 23 | { 24 | "diffuse0" : [ "grass.png", "canyon.jpg", "canyon.jpg" ], 25 | "diffuse1" : [ "sand.jpg", "sand_stone.jpg", "sand_stone.jpg" ] 26 | }, 27 | { 28 | "diffuse0" : [ "dry_grass.jpg", "grey_stone.jpg", "grey_stone.jpg" ], 29 | "diffuse1" : [ "sand.jpg", "sand_stone.jpg", "sand_stone.jpg" ] 30 | }, 31 | { 32 | "diffuse0" : [ "dry_grass.jpg", "grey_stone.jpg", "grey_stone.jpg" ], 33 | "diffuse1" : [ "sand.jpg", "calcare.jpg", "calcare.jpg" ] 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /media/testHmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/testHmap.png -------------------------------------------------------------------------------- /media/testHmap2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/testHmap2.png -------------------------------------------------------------------------------- /media/textures/Deep-Freeze.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/Deep-Freeze.jpg -------------------------------------------------------------------------------- /media/textures/Deep-Freeze_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/Deep-Freeze_normal.dds -------------------------------------------------------------------------------- /media/textures/Snow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/Snow.jpg -------------------------------------------------------------------------------- /media/textures/Snow_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/Snow_normal.dds -------------------------------------------------------------------------------- /media/textures/calcare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/calcare.jpg -------------------------------------------------------------------------------- /media/textures/calcare_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/calcare_normal.dds -------------------------------------------------------------------------------- /media/textures/canyon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/canyon.jpg -------------------------------------------------------------------------------- /media/textures/canyon_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/canyon_normal.dds -------------------------------------------------------------------------------- /media/textures/dry_grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/dry_grass.jpg -------------------------------------------------------------------------------- /media/textures/dry_grass_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/dry_grass_normal.dds -------------------------------------------------------------------------------- /media/textures/grass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/grass.png -------------------------------------------------------------------------------- /media/textures/grass_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/grass_normal.dds -------------------------------------------------------------------------------- /media/textures/grey_stone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/grey_stone.jpg -------------------------------------------------------------------------------- /media/textures/grey_stone_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/grey_stone_normal.dds -------------------------------------------------------------------------------- /media/textures/sand.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/sand.jpg -------------------------------------------------------------------------------- /media/textures/sand_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/sand_normal.dds -------------------------------------------------------------------------------- /media/textures/sand_stone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/sand_stone.jpg -------------------------------------------------------------------------------- /media/textures/sand_stone_normal.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoyannk/volumerendering/c284edff340d9cf3b8d913770ada7f8abf110143/media/textures/sand_stone_normal.dds --------------------------------------------------------------------------------