├── 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
--------------------------------------------------------------------------------