@@ -25,6 +25,139 @@ Common keyboard controls are enabled by the `Platform`, `Graphics` and `UserInte
25
25
- [ Methane::Graphics::AppController, AppContextController] ( /Modules/Graphics/App/README.md#graphics-application-controllers )
26
26
- [ Methane::UserInterface::AppController] ( /Modules/UserInterface/App/README.md#user-interface-application-controllers )
27
27
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
+
28
161
## Continue learning
29
162
30
163
Continue learning Methane Graphics programming in the next tutorial [ ParallelRendering] ( ../07-ParallelRendering ) ,
0 commit comments