-
Notifications
You must be signed in to change notification settings - Fork 0
first draft #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
first draft #1
Changes from all commits
e929bc2
9d3da9a
0ab7072
1b1d1dc
7d5064d
16a1594
caf29af
77c4882
43aeeb9
92e52ee
28921b8
aff36b5
d6bb6d3
abd74bd
16428d2
67bb65f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| BasedOnStyle: Google | ||
| IndentWidth: 4 | ||
| AccessModifierOffset: -4 | ||
| ColumnLimit: 100 | ||
| AllowShortFunctionsOnASingleLine: None | ||
| AllowShortIfStatementsOnASingleLine: false | ||
| AllowShortLoopsOnASingleLine: false | ||
| DerivePointerAlignment: true | ||
| KeepEmptyLinesAtTheStartOfBlocks: true | ||
| SeparateDefinitionBlocks: Always | ||
| EmptyLineBeforeAccessModifier: LogicalBlock | ||
| SortIncludes: false | ||
| InsertNewlineAtEOF : true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| --- | ||
| Checks: '-*,cppcoreguidelines-avoid-goto,cppcoreguidelines-pro-type-const-cast, google-readability-casting, modernize-replace-random-shuffle, readability-braces-around-statements, readability-container-size-empty, readability-redundant-control-flow, readability-redundant-string-init, modernize-use-nullptr, readability-identifier-naming, google-build-using-namespace' | ||
| HeaderFilterRegex: '\.h$' | ||
| WarningsAsErrors: '*' | ||
| CheckOptions: | ||
| - key: readability-identifier-naming.NamespaceCase | ||
| value: lower_case | ||
| - key: readability-identifier-naming.ClassCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.TypedefCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.TypedefIgnoredRegexp | ||
| value: (allocator_type|size_type|key_type|value_type|mapped_type|difference_type|pointer|const_pointer|reference|const_reference|iterator_category|const_iterator|iterator|reverse_iterator|const_reverse_iterator|key_compare) | ||
| - key: readability-identifier-naming.TypeAliasCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.PrivateMemberSuffix | ||
| value: '_' | ||
| - key: readability-identifier-naming.StructCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.FunctionCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.VariableCase | ||
| value: lower_case | ||
| - key: readability-identifier-naming.PrivateMemberCase | ||
| value: lower_case | ||
| - key: readability-identifier-naming.ParameterCase | ||
| value: lower_case | ||
| - key: readability-identifier-naming.GlobalConstantPrefix | ||
| value: k | ||
| - key: readability-identifier-naming.GlobalConstantCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.StaticConstantPrefix | ||
| value: k | ||
| - key: readability-identifier-naming.StaticConstantCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.ConstexprVariableCase | ||
| value: CamelCase | ||
| - key: readability-identifier-naming.ConstexprVariablePrefix | ||
| value: k | ||
| - key: google-runtime-int.TypeSuffix | ||
| value: _t |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,3 +30,12 @@ | |
| *.exe | ||
| *.out | ||
| *.app | ||
|
|
||
| # Build files | ||
| /build/ | ||
| /build_debug/ | ||
| compile_commands.json | ||
| /.cache/ | ||
|
|
||
| # 3D Models | ||
| /data/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [submodule "submodules/stb"] | ||
| path = submodules/stb | ||
| url = https://github.com/nothings/stb.git |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| cmake_minimum_required(VERSION 3.5) | ||
| project(3d-renderer) | ||
|
|
||
| set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||
| set(CMAKE_CXX_STANDARD 20) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED True) | ||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) | ||
|
|
||
| add_subdirectory(src) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # 3D Renderer | ||
| Курсовой проект по имплементации 3D рендерера с нуля. | ||
| ## Скачивание | ||
| ```shell | ||
| git clone --recurse-submodules git@github.com:rualss/3d-renderer.git | ||
| git checkout dev | ||
| git submodule update --init --recursive | ||
| ``` | ||
| ## Сборка и запуск | ||
| Перед сборкой нужно установить зависимости SFML. Все остальные библиотеки подтянутся сами | ||
| ```shell | ||
| sudo apt update && sudo apt install \ | ||
| libxrandr-dev \ | ||
| libxcursor-dev \ | ||
| libxi-dev \ | ||
| libudev-dev \ | ||
| libflac-dev \ | ||
| libvorbis-dev \ | ||
| libgl1-mesa-dev \ | ||
| libegl1-mesa-dev \ | ||
| libdrm-dev \ | ||
| libgbm-dev | ||
| ``` | ||
| Далее в корне репозитория нужно выполнить | ||
| ```shell | ||
| mkdir build | ||
| cd build | ||
| cmake -DCMAKE_BUILD_TYPE=Release .. | ||
| cmake --build . --parallel <количество потоков у процессора> | ||
| ./renderer | ||
| ``` | ||
| ## Управление | ||
| + **W** - переместить камеру вперёд | ||
| + **A** - переместить камеру влево | ||
| + **S** - переместить камеру назад | ||
| + **D** - переместить камеру вправо | ||
| + **Up** - повернуть камеру вверх | ||
| + **Down** - повернуть камеру вниз | ||
| + **Right** - повернуть камеру вправо | ||
| + **Left** - повернуть камеру влево | ||
| + **Q** - наклонить камеру влево | ||
| + **E** - наклонить камеру вправо | ||
|
|
||
| ## Пример работы | ||
|  |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| project(3d-renderer) | ||
|
|
||
| include(sources.cmake) | ||
|
|
||
| add_subdirectory(app) | ||
|
|
||
| include(FetchContent) | ||
| FetchContent_Declare( | ||
| assimp | ||
| GIT_REPOSITORY https://github.com/assimp/assimp.git | ||
| GIT_TAG master | ||
| ) | ||
| FetchContent_MakeAvailable(assimp) | ||
|
|
||
| FetchContent_Declare( | ||
| glm | ||
| GIT_REPOSITORY https://github.com/g-truc/glm.git | ||
| GIT_TAG master | ||
| ) | ||
| FetchContent_MakeAvailable(glm) | ||
|
|
||
| target_include_directories(3d_pipeline_lib PRIVATE ${CMAKE_SOURCE_DIR}/submodules/stb) | ||
| target_link_libraries(3d_pipeline_lib PUBLIC glm::glm assimp::assimp) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #pragma once | ||
|
|
||
| #include <cstdint> | ||
| namespace renderer { | ||
|
|
||
| enum class Axis { X, Y, Z }; | ||
|
|
||
| enum Height : int32_t; | ||
| enum Width : int32_t; | ||
|
|
||
| } // namespace renderer |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| project(3d-renderer) | ||
|
|
||
| include(FetchContent) | ||
| FetchContent_Declare(SFML | ||
| GIT_REPOSITORY https://github.com/SFML/SFML.git | ||
| GIT_TAG 3.0.0 | ||
| GIT_SHALLOW ON | ||
| EXCLUDE_FROM_ALL | ||
| SYSTEM) | ||
| FetchContent_MakeAvailable(SFML) | ||
|
|
||
| add_executable( | ||
| renderer | ||
| main.cpp | ||
| application.cpp | ||
| timer.cpp | ||
| ) | ||
|
|
||
| target_include_directories(renderer PUBLIC ${CMAKE_SOURCE_DIR}/src) | ||
| target_link_libraries(renderer PRIVATE 3d_pipeline_lib SFML::Graphics) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| #include "application.h" | ||
| #include <SFML/Graphics/RenderWindow.hpp> | ||
| #include <SFML/Window/Keyboard.hpp> | ||
| #include "camera.h" | ||
| #include "color.h" | ||
| #include "light.h" | ||
| #include "linalg.h" | ||
| #include "material.h" | ||
| #include "model_loader.h" | ||
| #include "object_3d.h" | ||
| #include "picture.h" | ||
| #include "polygon.h" | ||
| #include "world.h" | ||
| #include <SFML/Window/VideoMode.hpp> | ||
| #include <glm/ext/matrix_transform.hpp> | ||
| #include <glm/trigonometric.hpp> | ||
|
|
||
| namespace renderer { | ||
|
|
||
| namespace { | ||
|
|
||
| World ExampleScene() { | ||
| ModelLoader loader; | ||
| loader.Open("../data/floppa2.fbx"); | ||
| Object3D floppa = loader.GetObject(); | ||
| floppa.ApplyMatrix(glm::scale(Mat4(1.), {0.01, 0.01, 0.01})); | ||
| World world; | ||
| world.AddObject(floppa); | ||
| world.AddLight(DirectionalLight{}); | ||
| return world; | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| Application::Application() | ||
| : world_(ExampleScene()), | ||
| window_(sf::VideoMode({static_cast<Index>(picture_.GetWidth()), | ||
| static_cast<Index>(picture_.GetHeight())}), | ||
| kDefaultName) { | ||
| } | ||
|
|
||
| void Application::Run() { | ||
| while (window_.isOpen()) { | ||
| window_.clear(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нарушение уровня абстракции. Это низкоуровневая фигня, которая является частью отрисовки фрейма, непонятно зачем это тут зовется. Это должно быть внутри функции draw frame. |
||
| HandleEvents(); | ||
| HandleKeyboard(); | ||
| RenderFrame(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+45
to
+47
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ну это просто феерия черных ящиков. Прям три закрытые шкатулки, угадайте где лежит миллион рублей. Блять, ты что в Поле Чудес переиграл? Как вообще понять, какой тут поток данных? Ты просто манипулируешь скрыто состоянием объекта Application и все. Не делай так. |
||
| } | ||
| } | ||
|
|
||
| void Application::HandleEvents() { | ||
| while (const std::optional event = window_.pollEvent()) { | ||
| if (event->is<sf::Event::Closed>()) { | ||
| window_.close(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Странно, что после этого ты не останавливаешь run-time loop, а делаешь вызовы к двух других функций. |
||
| } | ||
| } | ||
| } | ||
|
|
||
| void Application::HandleKeyboard() { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Плохая функция, ты в ней смешиваешь две совершенно разные задачи:
Time elapsed = timer_.passed();
auto motion = read_input(); // это что-то, что понимает как двигать камеру
// теперь подвинуть камеру либо так
// camera_ = moveCamera(motion * elapsed, movement_speed, rotation_speed_, std::move(camera));
// либо так
camera_.move(motion * elapsed, movement_speed_, rotation_speed_);
// оба варианта так себе, но иначе нужен большой редизайн.
frame = renderer_.render(scnene_, camera_, std::move(frame));
drawFrame(frame);И вот таким макаром у тебя понятно какие данные как текут, какие объекты какую работу делают и взаимодействие с пользователям отделено от обработки логики ядра приложения. |
||
| Time elapsed = timer_.Elapsed(); | ||
| CoordType move_distance = movement_speed_ * elapsed.ToSeconds(); | ||
| CoordType rotate_angle = rotation_speed_ * elapsed.ToSeconds(); | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. У тебя тут магические константы -- имена клавиш. По-хорошему надо хранить таблицу с биндами имен клавишь на действия и тут транслировать эти действия. За это должен отвечать отдельный объект. Но этим НЕ надо сейчас заниматься. |
||
| camera_.Move(camera_.GetForwardDirection() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A)) { | ||
| camera_.Move(-camera_.GetRightDirecton() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) { | ||
| camera_.Move(-camera_.GetForwardDirection() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) { | ||
| camera_.Move(camera_.GetRightDirecton() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Space)) { | ||
| camera_.Move(camera_.GetUpDirection() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Z)) { | ||
| camera_.Move(-camera_.GetUpDirection() * move_distance); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Up)) { | ||
| camera_.Rotate(Axis::X, rotate_angle); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Down)) { | ||
| camera_.Rotate(Axis::X, -rotate_angle); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left)) { | ||
| camera_.Rotate(Axis::Y, rotate_angle); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right)) { | ||
| camera_.Rotate(Axis::Y, -rotate_angle); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::E)) { | ||
| camera_.Rotate(Axis::Z, rotate_angle); | ||
| } | ||
| if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Q)) { | ||
| camera_.Rotate(Axis::Z, -rotate_angle); | ||
| } | ||
| } | ||
|
|
||
| void Application::RenderFrame() { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Название метода врет. |
||
| renderer_.Render(world_, camera_, &picture_); | ||
| pixels_.clear(); | ||
| for (size_t x = 0; x < picture_.GetWidth(); ++x) { | ||
| for (size_t y = 0; y < picture_.GetHeight(); ++y) { | ||
| DiscreteColor color = picture_(x, y); | ||
| if (color != kBlackDiscrete) { | ||
| pixels_.emplace_back(sf::Vector2f(x, y), sf::Color(color.x, color.y, color.z)); | ||
| } | ||
| } | ||
| } | ||
| window_.draw(pixels_.data(), pixels_.size(), sf::PrimitiveType::Points); | ||
| window_.display(); | ||
|
Comment on lines
+112
to
+113
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вот это вместе с windows_.clear() является одним вызовом метода draw. Так же конвертация picture в pixels является деталью метода drawFrame. |
||
| } | ||
|
|
||
| } // namespace renderer | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #pragma once | ||
|
|
||
| #include <SFML/Graphics.hpp> | ||
| #include <SFML/Window.hpp> | ||
| #include "camera.h" | ||
| #include "linalg.h" | ||
| #include "picture.h" | ||
| #include "renderer.h" | ||
| #include "world.h" | ||
| #include "timer.h" | ||
|
|
||
| namespace renderer { | ||
|
|
||
| class Application { | ||
| using Window = sf::RenderWindow; | ||
| using Index = uint32_t; // SFML default size type, there is no sf::size_type | ||
|
|
||
| public: | ||
| Application(); | ||
| void Run(); | ||
|
|
||
| private: | ||
| void HandleEvents(); | ||
| void HandleKeyboard(); | ||
| void RenderFrame(); | ||
|
|
||
| static constexpr CoordType kDefaultMovementSpeed = 50.; | ||
| static constexpr CoordType kDefaultRotationSpeed = 80.; | ||
| static constexpr std::string kDefaultName = "3D renderer"; | ||
|
|
||
| Renderer renderer_; | ||
| Camera camera_; | ||
| World world_; | ||
| Picture picture_; | ||
| Window window_; | ||
| CoordType movement_speed_ = kDefaultMovementSpeed; | ||
| CoordType rotation_speed_ = kDefaultRotationSpeed; | ||
| std::vector<sf::Vertex> pixels_; | ||
| Timer timer_; | ||
| }; | ||
|
|
||
| } // namespace renderer |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #include <exception> | ||
| #include <iostream> | ||
|
|
||
| #include "application.h" | ||
|
|
||
| using namespace renderer; | ||
|
|
||
| int main() { | ||
| try { | ||
| Application app; | ||
| app.Run(); | ||
| } catch (std::exception& e) { | ||
| std::cout << e.what() << '\n'; | ||
| } catch (...) { | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Добавь строчку
set(CMAKE_CXX_STANDARD_REQUIRED True)А то cmake разрешено откатиться на более низкий стандарт.