Skip to content

Commit de23003

Browse files
committed
Write brief documentation for CubeMapArray tutorial
1 parent ff73ed9 commit de23003

File tree

3 files changed

+134
-4
lines changed

3 files changed

+134
-4
lines changed

Apps/06-CubeMapArray/CubeMapArrayApp.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,7 @@ bool CubeMapArrayApp::Render()
249249
if (!UserInterfaceApp::Render())
250250
return false;
251251

252-
// Update uniforms buffer related to current frame
253252
const CubeMapArrayFrame& frame = GetCurrentFrame();
254-
const rhi::CommandQueue render_cmd_queue = GetRenderContext().GetRenderCommandKit().GetQueue();
255253

256254
// 1) Render cube instances of 'CUBE_MAP_ARRAY_SIZE' count
257255
META_DEBUG_GROUP_VAR(s_debug_group, "Cube Instances Rendering");
@@ -267,7 +265,7 @@ bool CubeMapArrayApp::Render()
267265
frame.render_cmd_list.Commit();
268266

269267
// Execute command list on render queue and present frame to screen
270-
render_cmd_queue.Execute(frame.execute_cmd_list_set);
268+
GetRenderContext().GetRenderCommandKit().GetQueue().Execute(frame.execute_cmd_list_set);
271269
GetRenderContext().Present();
272270

273271
return true;

Apps/06-CubeMapArray/README.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,139 @@ Common keyboard controls are enabled by the `Platform`, `Graphics` and `UserInte
2525
- [Methane::Graphics::AppController, AppContextController](/Modules/Graphics/App/README.md#graphics-application-controllers)
2626
- [Methane::UserInterface::AppController](/Modules/UserInterface/App/README.md#user-interface-application-controllers)
2727

28+
## Cube-Map Texture Initialization
29+
30+
Cube-map texture is created using settings generated with `rhi::ITexture::Settings::ForCubeImage(...)`
31+
amd is set the `TexturedMeshBuffers` instance with `m_cube_buffers_ptr->SetTexture(...)`. Then this texture
32+
is bound to Pixel shader argument `g_texture_array` in `frame.cube.program_bindings` initialization.
33+
34+
Content of the texture is rendered to its faces using `TextureLabeler` class, which is rendering face identification
35+
text labels to the texture faces. Rendering is done after `UserInterfaceApp::CompleteInitialization()` call,
36+
to be sure that all necessary resources have been uploaded to the GPU.
37+
38+
```cpp
39+
void CubeMapArrayApp::Init()
40+
{
41+
...
42+
43+
// Create cube mesh buffer resources
44+
gfx::CubeMesh<CubeVertex> cube_mesh(CubeVertex::layout);
45+
m_cube_buffers_ptr = std::make_unique<TexturedMeshBuffers>(render_cmd_queue, std::move(cube_mesh), "Cube");
46+
47+
// Create cube-map render target texture
48+
m_cube_buffers_ptr->SetTexture(
49+
rhi::Texture(
50+
GetRenderContext(),
51+
rhi::ITexture::Settings::ForCubeImage(
52+
g_cube_texture_size, CUBE_MAP_ARRAY_SIZE, gfx::PixelFormat::RGBA8Unorm, false,
53+
rhi::ResourceUsageMask({ rhi::ResourceUsage::RenderTarget, rhi::ResourceUsage::ShaderRead })
54+
)));
55+
56+
...
57+
58+
// Create frame buffer resources
59+
for(CubeMapArrayFrame& frame : GetFrames())
60+
{
61+
// Configure program resource bindings
62+
frame.cube.program_bindings = m_render_state.GetProgram().CreateBindings({
63+
{ { rhi::ShaderType::Pixel, "g_texture_array" }, m_cube_buffers_ptr->GetTexture().GetResourceView() },
64+
{ { rhi::ShaderType::Pixel, "g_sampler" }, m_texture_sampler.GetResourceView() },
65+
}, frame.index);
66+
frame.cube.uniforms_argument_binding_ptr = &frame.cube.program_bindings.Get({ rhi::ShaderType::Vertex, "g_uniforms" });
67+
...
68+
}
69+
70+
// Create all resources for texture labels rendering before resources upload in UserInterfaceApp::CompleteInitialization()
71+
TextureLabeler cube_texture_labeler(GetUIContext(), GetFontContext(), m_cube_buffers_ptr->GetTexture(),
72+
rhi::ResourceState::Undefined, { g_cube_texture_size / 4U, 10U });
73+
74+
// Upload all resources, including font texture and text mesh buffers required for rendering
75+
UserInterfaceApp::CompleteInitialization();
76+
77+
// Encode and execute texture labels rendering commands when all resources are uploaded and ready on GPU
78+
cube_texture_labeler.Render();
79+
80+
GetRenderContext().WaitForGpu(rhi::IContext::WaitFor::RenderComplete);
81+
}
82+
```
83+
84+
## Cube-Map Rendering
85+
86+
Rendering of the cube instances is done similarly to other tutorials, but with the use of `instance_count` parameter
87+
in the `m_cube_buffers_ptr->Draw(..., CUBE_MAP_ARRAY_SIZE)` call. `instance_id` related to this count is passed in the
88+
vertex shader and used to form texture coordinates for cube-map array texture sampling.
89+
90+
```cpp
91+
bool CubeMapArrayApp::Render()
92+
{
93+
...
94+
95+
META_DEBUG_GROUP_VAR(s_debug_group, "Cube Instances Rendering");
96+
frame.render_cmd_list.ResetWithState(m_render_state, &s_debug_group);
97+
frame.render_cmd_list.SetViewState(GetViewState());
98+
m_cube_buffers_ptr->Draw(frame.render_cmd_list, frame.cube.program_bindings, 0U, CUBE_MAP_ARRAY_SIZE);
99+
100+
...
101+
}
102+
```
103+
104+
## Cube-Map Array Shaders
105+
106+
### CubeMapArrayUniforms.h
107+
108+
Uniforms structure with array of MVP matrices for all cube instances:
109+
110+
```hlsl
111+
```cpp
112+
#define CUBE_MAP_ARRAY_SIZE 8 // NOSONAR
113+
114+
struct Uniforms
115+
{
116+
float4x4 mvp_matrix_per_instance[CUBE_MAP_ARRAY_SIZE]; // NOSONAR
117+
};
118+
```
119+
120+
### CubeMapArray.hlsl
121+
122+
Vertex shader prepares texture coordinates `uvwi` for cube-map texture sampling by writing cube vertex position to `uvw`
123+
texture coordinates and instance id to the `i` component, which is used as index in the texture array.
124+
Sampling of cube-map array texture `g_texture_array` is done in the pixel shader from interpolated coordinates `uvwi`.
125+
126+
```hlsl
127+
128+
```cpp
129+
#include "CubeMapArrayUniforms.h"
130+
131+
struct VSInput
132+
{
133+
uint instance_id : SV_InstanceID;
134+
float3 position : POSITION;
135+
};
136+
137+
struct PSInput
138+
{
139+
float4 position : SV_POSITION;
140+
float4 uvwi : UVFACE;
141+
};
142+
143+
ConstantBuffer<Uniforms> g_uniforms : register(b0, META_ARG_FRAME_CONSTANT);
144+
TextureCubeArray g_texture_array : register(t0, META_ARG_CONSTANT);
145+
SamplerState g_sampler : register(s0, META_ARG_CONSTANT);
146+
147+
PSInput CubeVS(VSInput input)
148+
{
149+
PSInput output;
150+
output.position = mul(float4(input.position, 1.F), g_uniforms.mvp_matrix_per_instance[input.instance_id]);
151+
output.uvwi = float4(-input.position, input.instance_id); // use position with negative sign to fix texture reflection
152+
return output;
153+
}
154+
155+
float4 CubePS(PSInput input) : SV_TARGET
156+
{
157+
return g_texture_array.Sample(g_sampler, input.uvwi);
158+
}
159+
```
160+
28161
## Continue learning
29162

30163
Continue learning Methane Graphics programming in the next tutorial [ParallelRendering](../07-ParallelRendering),

Apps/06-CubeMapArray/Shaders/CubeMapArray.hlsl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Shaders for cube-map array textured rendering with Phong lighting model
2222
******************************************************************************/
2323

2424
#include "CubeMapArrayUniforms.h"
25-
#include "../../Common/Shaders/Primitives.hlsl"
2625

2726
struct VSInput
2827
{

0 commit comments

Comments
 (0)