MethaneKit

Форк
0
/
TexturedCubeApp.cpp 
257 строк · 10.7 Кб
1
/******************************************************************************
2

3
Copyright 2019 Evgeny Gorodetskiy
4

5
Licensed under the Apache License, Version 2.0 (the "License"),
6
you may not use this file except in compliance with the License.
7
You may obtain a copy of the License at
8

9
    http://www.apache.org/licenses/LICENSE-2.0
10

11
Unless required by applicable law or agreed to in writing, software
12
distributed under the License is distributed on an "AS IS" BASIS,
13
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
See the License for the specific language governing permissions and
15
limitations under the License.
16

17
*******************************************************************************
18

19
FILE: TexturedCubeApp.cpp
20
Tutorial demonstrating textured cube rendering with Methane graphics API
21

22
******************************************************************************/
23

24
#include "TexturedCubeApp.h"
25

26
#include <Methane/Tutorials/AppSettings.h>
27
#include <Methane/Graphics/CubeMesh.hpp>
28
#include <Methane/Graphics/TypeConverters.hpp>
29
#include <Methane/Data/TimeAnimation.h>
30

31
namespace Methane::Tutorials
32
{
33

34
struct CubeVertex
35
{
36
    gfx::Mesh::Position position;
37
    gfx::Mesh::Normal   normal;
38
    gfx::Mesh::TexCoord texcoord;
39

40
    inline static const gfx::Mesh::VertexLayout layout{
41
        gfx::Mesh::VertexField::Position,
42
        gfx::Mesh::VertexField::Normal,
43
        gfx::Mesh::VertexField::TexCoord,
44
    };
45
};
46

47
TexturedCubeApp::TexturedCubeApp()
48
    : UserInterfaceApp(
49
        GetGraphicsTutorialAppSettings("Methane Textured Cube", AppOptions::GetDefaultWithColorOnlyAndAnim()),
50
        GetUserInterfaceTutorialAppSettings(AppOptions::GetDefaultWithColorOnlyAndAnim()),
51
        "Methane tutorial of textured cube rendering")
52
{
53
    m_shader_uniforms.light_position = hlslpp::float3(0.F, 20.F, -25.F);
54
    m_camera.ResetOrientation({ { 13.0F, 13.0F, -13.0F }, { 0.0F, 0.0F, 0.0F }, { 0.0F, 1.0F, 0.0F } });
55

56
    m_shader_uniforms.model_matrix = hlslpp::float4x4::scale(m_cube_scale);
57

58
    // Setup animations
59
    GetAnimations().emplace_back(std::make_shared<Data::TimeAnimation>(std::bind(&TexturedCubeApp::Animate, this, std::placeholders::_1, std::placeholders::_2)));
60
}
61

62
TexturedCubeApp::~TexturedCubeApp()
63
{
64
    // Wait for GPU rendering is completed to release resources
65
    WaitForRenderComplete();
66
}
67

68
void TexturedCubeApp::Init()
69
{
70
    UserInterfaceApp::Init();
71

72
    const rhi::CommandQueue render_cmd_queue = GetRenderContext().GetRenderCommandKit().GetQueue();
73
    m_camera.Resize(GetRenderContext().GetSettings().frame_size);
74

75
    // Create vertex buffer for cube mesh
76
    const gfx::CubeMesh<CubeVertex> cube_mesh(CubeVertex::layout);
77
    const Data::Size vertex_data_size   = cube_mesh.GetVertexDataSize();
78
    const Data::Size  vertex_size       = cube_mesh.GetVertexSize();
79
    rhi::Buffer vertex_buffer = GetRenderContext().CreateBuffer(rhi::BufferSettings::ForVertexBuffer(vertex_data_size, vertex_size));
80
    vertex_buffer.SetName("Cube Vertex Buffer");
81
    vertex_buffer.SetData(render_cmd_queue, {
82
        reinterpret_cast<Data::ConstRawPtr>(cube_mesh.GetVertices().data()), // NOSONAR
83
        vertex_data_size
84
    });
85
    m_vertex_buffer_set = rhi::BufferSet(rhi::BufferType::Vertex, { vertex_buffer });
86

87
    // Create index buffer for cube mesh
88
    const Data::Size index_data_size = cube_mesh.GetIndexDataSize();
89
    const gfx::PixelFormat index_format = gfx::GetIndexFormat(cube_mesh.GetIndex(0));
90
    m_index_buffer = GetRenderContext().CreateBuffer(rhi::BufferSettings::ForIndexBuffer(index_data_size, index_format));
91
    m_index_buffer.SetName("Cube Index Buffer");
92
    m_index_buffer.SetData(render_cmd_queue, {
93
        reinterpret_cast<Data::ConstRawPtr>(cube_mesh.GetIndices().data()), // NOSONAR
94
        index_data_size
95
    });
96

97
    // Create constants buffer for frame rendering
98
    const auto constants_data_size = static_cast<Data::Size>(sizeof(m_shader_constants));
99
    m_const_buffer = GetRenderContext().CreateBuffer(rhi::BufferSettings::ForConstantBuffer(constants_data_size));
100
    m_const_buffer.SetName("Constants Buffer");
101
    m_const_buffer.SetData(render_cmd_queue, {
102
        reinterpret_cast<Data::ConstRawPtr>(&m_shader_constants), // NOSONAR
103
        constants_data_size
104
    });
105

106
    // Create render state with program
107
    m_render_state = GetRenderContext().CreateRenderState(
108
        rhi::RenderState::Settings
109
        {
110
            GetRenderContext().CreateProgram(
111
                rhi::Program::Settings
112
                {
113
                    rhi::Program::ShaderSet
114
                    {
115
                        { rhi::ShaderType::Vertex, { Data::ShaderProvider::Get(), { "TexturedCube", "CubeVS" } } },
116
                        { rhi::ShaderType::Pixel,  { Data::ShaderProvider::Get(), { "TexturedCube", "CubePS" } } },
117
                    },
118
                    rhi::ProgramInputBufferLayouts
119
                    {
120
                        rhi::Program::InputBufferLayout
121
                        {
122
                            rhi::Program::InputBufferLayout::ArgumentSemantics { cube_mesh.GetVertexLayout().GetSemantics() }
123
                        }
124
                    },
125
                    rhi::ProgramArgumentAccessors
126
                    {
127
                        { { rhi::ShaderType::All,   "g_uniforms"  }, rhi::ProgramArgumentAccessor::Type::FrameConstant },
128
                        { { rhi::ShaderType::Pixel, "g_constants" }, rhi::ProgramArgumentAccessor::Type::Constant },
129
                        { { rhi::ShaderType::Pixel, "g_texture"   }, rhi::ProgramArgumentAccessor::Type::Constant },
130
                        { { rhi::ShaderType::Pixel, "g_sampler"   }, rhi::ProgramArgumentAccessor::Type::Constant },
131
                    },
132
                    GetScreenRenderPattern().GetAttachmentFormats()
133
                }
134
            ),
135
            GetScreenRenderPattern()
136
        }
137
    );
138
    m_render_state.GetSettings().program_ptr->SetName("Textured Phong Lighting");
139
    m_render_state.SetName("Final FB Render Pipeline State");
140

141
    // Load texture image from file
142
    constexpr gfx::ImageOptionMask image_options({ gfx::ImageOption::Mipmapped, gfx::ImageOption::SrgbColorSpace });
143
    m_cube_texture = GetImageLoader().LoadImageToTexture2D(render_cmd_queue, "MethaneBubbles.jpg", image_options, "Cube Face Texture");
144

145
    // Create sampler for image texture
146
    m_texture_sampler = GetRenderContext().CreateSampler(
147
        rhi::Sampler::Settings
148
        {
149
            rhi::Sampler::Filter  { rhi::Sampler::Filter::MinMag::Linear },
150
            rhi::Sampler::Address { rhi::Sampler::Address::Mode::ClampToEdge }
151
        }
152
    );
153

154
    // Create frame buffer resources
155
    const auto uniforms_data_size = static_cast<Data::Size>(sizeof(m_shader_uniforms));
156
    for(TexturedCubeFrame& frame : GetFrames())
157
    {
158
        // Create uniforms buffer with volatile parameters for frame rendering
159
        frame.uniforms_buffer = GetRenderContext().CreateBuffer(rhi::BufferSettings::ForConstantBuffer(uniforms_data_size, false, true));
160
        frame.uniforms_buffer.SetName(fmt::format("Uniforms Buffer {}", frame.index));
161

162
        // Configure program resource bindings
163
        frame.program_bindings = m_render_state.GetProgram().CreateBindings({
164
            { { rhi::ShaderType::All,   "g_uniforms"  }, { { frame.uniforms_buffer.GetInterface() } } },
165
            { { rhi::ShaderType::Pixel, "g_constants" }, { { m_const_buffer.GetInterface()        } } },
166
            { { rhi::ShaderType::Pixel, "g_texture"   }, { { m_cube_texture.GetInterface()        } } },
167
            { { rhi::ShaderType::Pixel, "g_sampler"   }, { { m_texture_sampler.GetInterface()     } } },
168
        }, frame.index);
169
        frame.program_bindings.SetName(fmt::format("Cube Bindings {}", frame.index));
170

171
        // Create command list for rendering
172
        frame.render_cmd_list = render_cmd_queue.CreateRenderCommandList(frame.screen_pass);
173
        frame.render_cmd_list.SetName(fmt::format("Cube Rendering {}", frame.index));
174
        frame.execute_cmd_list_set = rhi::CommandListSet({ frame.render_cmd_list.GetInterface() }, frame.index);
175
    }
176

177
    UserInterfaceApp::CompleteInitialization();
178
}
179

180
bool TexturedCubeApp::Animate(double, double delta_seconds)
181
{
182
    const float rotation_angle_rad = static_cast<float>(delta_seconds * 360.F / 4.F) * gfx::ConstFloat::RadPerDeg;
183
    hlslpp::float3x3 light_rotate_matrix = hlslpp::float3x3::rotation_axis(m_camera.GetOrientation().up, rotation_angle_rad);
184
    m_shader_uniforms.light_position = hlslpp::mul(m_shader_uniforms.light_position, light_rotate_matrix);
185
    m_camera.Rotate(m_camera.GetOrientation().up, static_cast<float>(delta_seconds * 360.F / 8.F));
186
    return true;
187
}
188

189
bool TexturedCubeApp::Resize(const gfx::FrameSize& frame_size, bool is_minimized)
190
{
191
    // Resize screen color and depth textures
192
    if (!UserInterfaceApp::Resize(frame_size, is_minimized))
193
        return false;
194

195
    m_camera.Resize(frame_size);
196
    return true;
197
}
198

199
bool TexturedCubeApp::Update()
200
{
201
    if (!UserInterfaceApp::Update())
202
        return false;
203

204
    // Update Model, View, Projection matrices based on camera location
205
    m_shader_uniforms.mvp_matrix   = hlslpp::transpose(hlslpp::mul(m_shader_uniforms.model_matrix, m_camera.GetViewProjMatrix()));
206
    m_shader_uniforms.eye_position = m_camera.GetOrientation().eye;
207
    
208
    return true;
209
}
210

211
bool TexturedCubeApp::Render()
212
{
213
    if (!UserInterfaceApp::Render())
214
        return false;
215

216
    // Update uniforms buffer related to current frame
217
    const TexturedCubeFrame& frame = GetCurrentFrame();
218
    const rhi::CommandQueue& render_cmd_queue = GetRenderContext().GetRenderCommandKit().GetQueue();
219
    frame.uniforms_buffer.SetData(render_cmd_queue, m_shader_uniforms_subresource);
220

221
    // Issue commands for cube rendering
222
    META_DEBUG_GROUP_VAR(s_debug_group, "Cube Rendering");
223
    frame.render_cmd_list.ResetWithState(m_render_state, &s_debug_group);
224
    frame.render_cmd_list.SetViewState(GetViewState());
225
    frame.render_cmd_list.SetProgramBindings(frame.program_bindings);
226
    frame.render_cmd_list.SetVertexBuffers(m_vertex_buffer_set);
227
    frame.render_cmd_list.SetIndexBuffer(m_index_buffer);
228
    frame.render_cmd_list.DrawIndexed(rhi::RenderPrimitive::Triangle);
229

230
    RenderOverlay(frame.render_cmd_list);
231

232
    // Execute command list on render queue and present frame to screen
233
    frame.render_cmd_list.Commit();
234
    render_cmd_queue.Execute(frame.execute_cmd_list_set);
235
    GetRenderContext().Present();
236

237
    return true;
238
}
239

240
void TexturedCubeApp::OnContextReleased(rhi::IContext& context)
241
{
242
    m_texture_sampler = {};
243
    m_cube_texture = {};
244
    m_const_buffer = {};
245
    m_index_buffer = {};
246
    m_vertex_buffer_set = {};
247
    m_render_state = {};
248

249
    UserInterfaceApp::OnContextReleased(context);
250
}
251

252
} // namespace Methane::Tutorials
253

254
int main(int argc, const char* argv[])
255
{
256
    return Methane::Tutorials::TexturedCubeApp().Run({ argc, argv });
257
}
258

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.