Refactoring basic text rendering
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
|
||||||
|
// such as names of functions and macros.
|
||||||
|
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
|
||||||
|
#define DECLARE_REF(x)
|
||||||
+19
-37
@@ -1,39 +1,21 @@
|
|||||||
import Common;
|
import Common;
|
||||||
|
|
||||||
struct GlyphData
|
|
||||||
{
|
|
||||||
float4 bearingSize;
|
|
||||||
};
|
|
||||||
struct TextData
|
|
||||||
{
|
|
||||||
float4 textColor;
|
|
||||||
float scale;
|
|
||||||
}
|
|
||||||
struct GlyphSampler
|
|
||||||
{
|
|
||||||
SamplerState s;
|
|
||||||
}
|
|
||||||
ParameterBlock<GlyphSampler> glyphSampler;
|
|
||||||
//layout(set = 1)
|
|
||||||
//ShaderBuffer<GlyphData> glyphData;
|
|
||||||
struct GlyphTextures
|
|
||||||
{
|
|
||||||
Texture2D[256] textures;
|
|
||||||
}
|
|
||||||
ParameterBlock<GlyphTextures> pGlyphTextures;
|
|
||||||
|
|
||||||
struct GlyphInstanceData
|
struct GlyphInstanceData
|
||||||
{
|
{
|
||||||
float2 position;
|
float x;
|
||||||
float2 widthHeight;
|
float y;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
uint glyphIndex;
|
uint glyphIndex;
|
||||||
};
|
};
|
||||||
struct TextRender
|
|
||||||
|
struct TextData
|
||||||
{
|
{
|
||||||
StructuredBuffer<GlyphInstanceData> instances;
|
StructuredBuffer<GlyphInstanceData> glyphs;
|
||||||
TextData textData;
|
SamplerState glyphSampler;
|
||||||
}
|
Texture2D<float> glyphTextures[];
|
||||||
ParameterBlock<TextRender> pRender;
|
};
|
||||||
|
ParameterBlock<TextData> pText;
|
||||||
|
|
||||||
struct VertexInput
|
struct VertexInput
|
||||||
{
|
{
|
||||||
@@ -51,23 +33,23 @@ struct VertexOutput
|
|||||||
[shader("vertex")]
|
[shader("vertex")]
|
||||||
VertexOutput vertexMain(VertexInput input)
|
VertexOutput vertexMain(VertexInput input)
|
||||||
{
|
{
|
||||||
float xpos = pRender.instances[input.instanceId].position.x;
|
float xpos = pText.glyphs[input.instanceId].x;
|
||||||
float ypos = pRender.instances[input.instanceId].position.y;
|
float ypos = pText.glyphs[input.instanceId].y;
|
||||||
|
|
||||||
float w = pRender.instances[input.instanceId].widthHeight.x;
|
float w = pText.glyphs[input.instanceId].width;
|
||||||
float h = pRender.instances[input.instanceId].widthHeight.y;
|
float h = pText.glyphs[input.instanceId].height;
|
||||||
|
|
||||||
float4 coordinates[4] = {
|
const float4 coordinates[4] = {
|
||||||
float4(xpos, ypos, 0, 1),
|
float4(xpos, ypos, 0, 1),
|
||||||
float4(xpos, ypos + h, 0, 0),
|
float4(xpos, ypos + h, 0, 0),
|
||||||
float4(xpos + w, ypos, 1, 1),
|
float4(xpos + w, ypos, 1, 1),
|
||||||
float4(xpos + w, ypos + h, 1, 0)
|
float4(xpos + w, ypos + h, 1, 0),
|
||||||
};
|
};
|
||||||
float4 vertex = coordinates[input.vertexId];
|
float4 vertex = coordinates[input.vertexId];
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
output.texCoords = vertex.zw;
|
output.texCoords = vertex.zw;
|
||||||
output.position = mul(pViewParams.projectionMatrix, float4(vertex.xy, 0, 1));
|
output.position = mul(pViewParams.projectionMatrix, float4(vertex.xy, 0, 1));
|
||||||
output.glyphIndex = pRender.instances[input.instanceId].glyphIndex;
|
output.glyphIndex = pText.glyphs[input.instanceId].glyphIndex;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,5 +60,5 @@ float4 fragmentMain(
|
|||||||
uint glyphIndex : GLYPHINDEX
|
uint glyphIndex : GLYPHINDEX
|
||||||
) : SV_Target
|
) : SV_Target
|
||||||
{
|
{
|
||||||
return pRender.textData.textColor * pGlyphTextures.textures[glyphIndex].Sample(glyphSampler.s, texCoords);
|
return float4(1, 0, 0, pText.glyphTextures[glyphIndex].Sample(pText.glyphSampler, texCoords));
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ VertexOutput vertexMain(uint vertexId : SV_VertexID, RenderElementStyle style)
|
|||||||
float4(xMax, yMax, 1, 1)
|
float4(xMax, yMax, 1, 1)
|
||||||
};
|
};
|
||||||
VertexOutput output;
|
VertexOutput output;
|
||||||
output.position = mul(pViewData.projectionMatrix, float4(coordinates[vertexId].xy, style.position.z, 1));
|
output.position = mul(pViewParams.projectionMatrix, float4(coordinates[vertexId].xy, style.position.z, 1));
|
||||||
output.texCoords = coordinates[vertexId].zw;
|
output.texCoords = coordinates[vertexId].zw;
|
||||||
output.style = style;
|
output.style = style;
|
||||||
return output;
|
return output;
|
||||||
@@ -62,9 +62,5 @@ float4 fragmentMain(
|
|||||||
{
|
{
|
||||||
float4 bgTextureColor = float4(1, 1, 1, 1);
|
float4 bgTextureColor = float4(1, 1, 1, 1);
|
||||||
uint imageIndex = style.backgroundImageIndex;
|
uint imageIndex = style.backgroundImageIndex;
|
||||||
if(imageIndex < numBackgroundTextures)
|
return float4(0, 1, 0, 1);
|
||||||
{
|
|
||||||
bgTextureColor = pParams.backgroundTextures[imageIndex].Sample(pParams.backgroundSampler, texCoords);
|
|
||||||
}
|
|
||||||
return float4(style.backgroundColor, style.opacity) * bgTextureColor;
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
target_sources(AssetViewer
|
target_sources(AssetViewer
|
||||||
PRIVATE
|
PRIVATE
|
||||||
main.cpp)
|
main.cpp "../../tests/Engine/UI/Element.cpp")
|
||||||
@@ -2,4 +2,4 @@ target_sources(Benchmark
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
main.cpp
|
main.cpp
|
||||||
PlayView.h
|
PlayView.h
|
||||||
PlayView.cpp)
|
PlayView.cpp "../../tests/Engine/UI/Element.cpp")
|
||||||
@@ -9,4 +9,4 @@ target_sources(Editor
|
|||||||
MeshLoader.h
|
MeshLoader.h
|
||||||
MeshLoader.cpp
|
MeshLoader.cpp
|
||||||
TextureLoader.h
|
TextureLoader.h
|
||||||
TextureLoader.cpp)
|
TextureLoader.cpp "../../../tests/Engine/UI/Element.cpp")
|
||||||
@@ -30,7 +30,6 @@ void FontLoader::importAsset(FontImportArgs args) {
|
|||||||
|
|
||||||
// in case of the space character there is no bitmap
|
// in case of the space character there is no bitmap
|
||||||
// so we create a single pixel empty texture
|
// so we create a single pixel empty texture
|
||||||
uint8 transparentPixel = 0;
|
|
||||||
void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
||||||
FT_Library ft;
|
FT_Library ft;
|
||||||
FT_Error error = FT_Init_FreeType(&ft);
|
FT_Error error = FT_Init_FreeType(&ft);
|
||||||
@@ -39,7 +38,6 @@ void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
|||||||
error = FT_New_Face(ft, args.filePath.string().c_str(), 0, &face);
|
error = FT_New_Face(ft, args.filePath.string().c_str(), 0, &face);
|
||||||
assert(!error);
|
assert(!error);
|
||||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||||
Array<Gfx::OTexture2D> usedTextures;
|
|
||||||
for (uint32 c = 0; c < 256; ++c) {
|
for (uint32 c = 0; c < 256; ++c) {
|
||||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
||||||
std::cout << "error loading " << (char)c << std::endl;
|
std::cout << "error loading " << (char)c << std::endl;
|
||||||
@@ -49,28 +47,17 @@ void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
|||||||
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||||
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||||
glyph.advance = face->glyph->advance.x;
|
glyph.advance = face->glyph->advance.x;
|
||||||
TextureCreateInfo imageData;
|
glyph.textureData.resize(glyph.size.x * glyph.size.y);
|
||||||
imageData.format = Gfx::SE_FORMAT_R8_UINT;
|
if (glyph.textureData.size() == 0) {
|
||||||
imageData.width = face->glyph->bitmap.width;
|
|
||||||
imageData.height = face->glyph->bitmap.rows;
|
|
||||||
imageData.sourceData.data = face->glyph->bitmap.buffer;
|
|
||||||
imageData.sourceData.size = imageData.width * imageData.height;
|
|
||||||
if (imageData.width == 0 || imageData.height == 0) {
|
|
||||||
glyph.size.x = 1;
|
glyph.size.x = 1;
|
||||||
glyph.size.y = 1;
|
glyph.size.y = 1;
|
||||||
glyph.bearing.x = 0;
|
glyph.textureData.add(0); // load a single transparent pixel, so that we dont have to handle empty textures later
|
||||||
glyph.bearing.y = 0;
|
} else {
|
||||||
imageData.width = 1;
|
std::memcpy(glyph.textureData.data(), face->glyph->bitmap.buffer, glyph.textureData.size());
|
||||||
imageData.height = 1;
|
|
||||||
imageData.sourceData.size = sizeof(uint8);
|
|
||||||
imageData.sourceData.data = &transparentPixel;
|
|
||||||
}
|
}
|
||||||
glyph.textureIndex = usedTextures.size();
|
|
||||||
usedTextures.add(graphics->createTexture2D(imageData));
|
|
||||||
}
|
}
|
||||||
FT_Done_Face(face);
|
FT_Done_Face(face);
|
||||||
FT_Done_FreeType(ft);
|
FT_Done_FreeType(ft);
|
||||||
asset->setUsedTextures(std::move(usedTextures));
|
|
||||||
|
|
||||||
AssetRegistry::saveAsset(asset, FontAsset::IDENTIFIER, asset->getFolderPath(), asset->getName());
|
AssetRegistry::saveAsset(asset, FontAsset::IDENTIFIER, asset->getFolderPath(), asset->getName());
|
||||||
|
|
||||||
|
|||||||
@@ -3,40 +3,31 @@
|
|||||||
#include "Asset/AssetRegistry.h"
|
#include "Asset/AssetRegistry.h"
|
||||||
#include "Asset/FontLoader.h"
|
#include "Asset/FontLoader.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "UI/System.h"
|
#include "UI/Element/Text.h"
|
||||||
#include "Window/Window.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Editor;
|
using namespace Seele::Editor;
|
||||||
|
|
||||||
InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo)
|
InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo)
|
||||||
: View(graphics, std::move(window), std::move(createInfo), "InspectorView")
|
: View(graphics, window, createInfo, "InspectorView"), uiSystem(new UI::System(new UI::Text("Test"))) {
|
||||||
//, renderGraph(RenderGraphBuilder::build(
|
renderGraph.addPass(new UIPass(graphics, uiSystem));
|
||||||
// UIPass(graphics),
|
renderGraph.setViewport(viewport);
|
||||||
// TextPass(graphics)
|
renderGraph.createRenderPass();
|
||||||
//))
|
|
||||||
,
|
|
||||||
uiSystem(new UI::System()) {
|
|
||||||
// renderGraph.updateViewport(viewport);
|
|
||||||
uiSystem->updateViewport(viewport);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InspectorView::~InspectorView() {}
|
InspectorView::~InspectorView() {}
|
||||||
|
|
||||||
void InspectorView::beginUpdate() {
|
void InspectorView::beginUpdate() {}
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorView::update() {
|
void InspectorView::update() {}
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InspectorView::commitUpdate() {}
|
void InspectorView::commitUpdate() {}
|
||||||
|
|
||||||
void InspectorView::prepareRender() {}
|
void InspectorView::prepareRender() {}
|
||||||
|
|
||||||
void InspectorView::render() {}
|
void InspectorView::render() { renderGraph.render(Component::Camera()); }
|
||||||
|
|
||||||
|
void InspectorView::applyArea(URect area) {}
|
||||||
|
|
||||||
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) {}
|
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/RenderPass/RenderGraph.h"
|
#include "Graphics/RenderPass/RenderGraph.h"
|
||||||
#include "Graphics/RenderPass/TextPass.h"
|
|
||||||
#include "Graphics/RenderPass/UIPass.h"
|
#include "Graphics/RenderPass/UIPass.h"
|
||||||
#include "UI/Elements/Panel.h"
|
|
||||||
#include "Window/View.h"
|
#include "Window/View.h"
|
||||||
|
#include "UI/System.h"
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
DECLARE_REF(Actor)
|
DECLARE_REF(Actor)
|
||||||
@@ -20,11 +18,13 @@ class InspectorView : public View {
|
|||||||
|
|
||||||
virtual void prepareRender() override;
|
virtual void prepareRender() override;
|
||||||
virtual void render() override;
|
virtual void render() override;
|
||||||
void selectActor();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void applyArea(URect area) override;
|
||||||
UI::PSystem uiSystem;
|
UI::PSystem uiSystem;
|
||||||
PActor selectedActor;
|
RenderGraph renderGraph;
|
||||||
|
Component::Camera cam;
|
||||||
|
|
||||||
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override;
|
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override;
|
||||||
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
||||||
|
|||||||
+48
-37
@@ -11,6 +11,7 @@
|
|||||||
#include "Graphics/Vulkan/Graphics.h"
|
#include "Graphics/Vulkan/Graphics.h"
|
||||||
#endif
|
#endif
|
||||||
#include "Graphics/StaticMeshVertexData.h"
|
#include "Graphics/StaticMeshVertexData.h"
|
||||||
|
#include "Window/InspectorView.h"
|
||||||
#include "Window/PlayView.h"
|
#include "Window/PlayView.h"
|
||||||
#include "Window/WindowManager.h"
|
#include "Window/WindowManager.h"
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
@@ -36,9 +37,9 @@ Array<Halfedge> generateEdges() {
|
|||||||
Array<Halfedge> edges;
|
Array<Halfedge> edges;
|
||||||
for (auto ind : indices) {
|
for (auto ind : indices) {
|
||||||
uint32 baseIndex = edges.size();
|
uint32 baseIndex = edges.size();
|
||||||
edges.add(Halfedge{ind.x, baseIndex+1, baseIndex+2, UINT32_MAX});
|
edges.add(Halfedge{ind.x, baseIndex + 1, baseIndex + 2, UINT32_MAX});
|
||||||
edges.add(Halfedge{ind.y, baseIndex+2, baseIndex, UINT32_MAX});
|
edges.add(Halfedge{ind.y, baseIndex + 2, baseIndex, UINT32_MAX});
|
||||||
edges.add(Halfedge{ind.z, baseIndex, baseIndex+1, UINT32_MAX});
|
edges.add(Halfedge{ind.z, baseIndex, baseIndex + 1, UINT32_MAX});
|
||||||
}
|
}
|
||||||
for (uint32 i = 0; i < edges.size(); ++i) {
|
for (uint32 i = 0; i < edges.size(); ++i) {
|
||||||
if (edges[i].twinID == UINT32_MAX) {
|
if (edges[i].twinID == UINT32_MAX) {
|
||||||
@@ -83,9 +84,9 @@ int main() {
|
|||||||
OWindowManager windowManager = new WindowManager();
|
OWindowManager windowManager = new WindowManager();
|
||||||
AssetRegistry::init(sourcePath / "Assets", graphics);
|
AssetRegistry::init(sourcePath / "Assets", graphics);
|
||||||
AssetImporter::init(graphics);
|
AssetImporter::init(graphics);
|
||||||
// AssetImporter::importFont(FontImportArgs{
|
AssetImporter::importFont(FontImportArgs{
|
||||||
// .filePath = "./fonts/Calibri.ttf",
|
.filePath = "./fonts/arial.ttf",
|
||||||
// });
|
});
|
||||||
AssetImporter::importMesh(MeshImportArgs{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
.filePath = sourcePath / "import/models/cube.fbx",
|
.filePath = sourcePath / "import/models/cube.fbx",
|
||||||
});
|
});
|
||||||
@@ -100,35 +101,35 @@ int main() {
|
|||||||
// .filePath = sourcePath / "import/models/ship.fbx",
|
// .filePath = sourcePath / "import/models/ship.fbx",
|
||||||
// .importPath = "ship",
|
// .importPath = "ship",
|
||||||
// });
|
// });
|
||||||
//AssetImporter::importTexture(TextureImportArgs{
|
// AssetImporter::importTexture(TextureImportArgs{
|
||||||
// .filePath = sourcePath / "import/textures/azeroth.png",
|
// .filePath = sourcePath / "import/textures/azeroth.png",
|
||||||
//});
|
//});
|
||||||
//AssetImporter::importTexture(TextureImportArgs{
|
// AssetImporter::importTexture(TextureImportArgs{
|
||||||
// .filePath = sourcePath / "import/textures/azeroth_height.png",
|
// .filePath = sourcePath / "import/textures/azeroth_height.png",
|
||||||
//});
|
//});
|
||||||
//AssetImporter::importTexture(TextureImportArgs{
|
// AssetImporter::importTexture(TextureImportArgs{
|
||||||
// .filePath = sourcePath / "import/textures/wgen.png",
|
// .filePath = sourcePath / "import/textures/wgen.png",
|
||||||
//});
|
//});
|
||||||
AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
|
||||||
.importPath = "Whitechapel",
|
|
||||||
});
|
|
||||||
//AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
// .filePath = sourcePath / "import/models/plane.obj",
|
|
||||||
// .importPath = "",
|
|
||||||
//});
|
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
|
|
||||||
// .importPath = "suburbs",
|
|
||||||
// });
|
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
// .filePath = sourcePath / "import/models/minecraft-medieval-city.fbx",
|
|
||||||
// .importPath = "minecraft",
|
|
||||||
// });
|
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
// AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/Volvo/Volvo.fbx",
|
// .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
||||||
// .importPath = "Volvo",
|
// .importPath = "Whitechapel",
|
||||||
|
//});
|
||||||
|
// AssetImporter::importMesh(MeshImportArgs{
|
||||||
|
// .filePath = sourcePath / "import/models/plane.obj",
|
||||||
|
// .importPath = "",
|
||||||
// });
|
// });
|
||||||
|
// AssetImporter::importMesh(MeshImportArgs{
|
||||||
|
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
|
||||||
|
// .importPath = "suburbs",
|
||||||
|
// });
|
||||||
|
// AssetImporter::importMesh(MeshImportArgs{
|
||||||
|
// .filePath = sourcePath / "import/models/minecraft-medieval-city.fbx",
|
||||||
|
// .importPath = "minecraft",
|
||||||
|
// });
|
||||||
|
// AssetImporter::importMesh(MeshImportArgs{
|
||||||
|
// .filePath = sourcePath / "import/models/Volvo/Volvo.fbx",
|
||||||
|
// .importPath = "Volvo",
|
||||||
|
// });
|
||||||
getThreadPool().waitIdle();
|
getThreadPool().waitIdle();
|
||||||
vd->commitMeshes();
|
vd->commitMeshes();
|
||||||
WindowCreateInfo mainWindowInfo = {
|
WindowCreateInfo mainWindowInfo = {
|
||||||
@@ -138,16 +139,26 @@ int main() {
|
|||||||
.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB,
|
.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB,
|
||||||
};
|
};
|
||||||
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
||||||
ViewportCreateInfo sceneViewInfo = {
|
// ViewportCreateInfo sceneViewInfo = {
|
||||||
.dimensions =
|
// .dimensions =
|
||||||
{
|
// {
|
||||||
.size = {1920, 1080},
|
// .size = {1920, 1080},
|
||||||
.offset = {0, 0},
|
// .offset = {0, 0},
|
||||||
},
|
// },
|
||||||
.numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT,
|
// .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT,
|
||||||
};
|
// };
|
||||||
OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string());
|
// OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string());
|
||||||
sceneView->setFocused();
|
// sceneView->setFocused();
|
||||||
|
OInspectorView inspectorView = new Editor::InspectorView(graphics, window,
|
||||||
|
ViewportCreateInfo{
|
||||||
|
.dimensions =
|
||||||
|
{
|
||||||
|
.size = {1920, 1080},
|
||||||
|
.offset = {0, 0},
|
||||||
|
},
|
||||||
|
.fieldOfView = 0,
|
||||||
|
.numSamples = Gfx::SE_SAMPLE_COUNT_1_BIT,
|
||||||
|
});
|
||||||
|
|
||||||
while (windowManager->isActive() && getGlobals().running) {
|
while (windowManager->isActive() && getGlobals().running) {
|
||||||
windowManager->render();
|
windowManager->render();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "FontAsset.h"
|
#include "FontAsset.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Graphics/Texture.h"
|
#include "Graphics/Texture.h"
|
||||||
#include <ktx.h>
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -11,106 +10,31 @@ FontAsset::FontAsset(std::string_view folderPath, std::string_view name) : Asset
|
|||||||
|
|
||||||
FontAsset::~FontAsset() {}
|
FontAsset::~FontAsset() {}
|
||||||
|
|
||||||
void FontAsset::save(ArchiveBuffer& buffer) const {
|
void FontAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, glyphs); }
|
||||||
Serialization::save(buffer, glyphs);
|
|
||||||
Serialization::save(buffer, usedTextures.size());
|
|
||||||
for (uint32 x = 0; x < usedTextures.size(); ++x) {
|
|
||||||
Array<uint8> textureData;
|
|
||||||
ktxTexture2* kTexture;
|
|
||||||
ktxTextureCreateInfo createInfo = {
|
|
||||||
.glInternalformat = 0,
|
|
||||||
.vkFormat = (uint32_t)usedTextures[x]->getFormat(),
|
|
||||||
.pDfd = nullptr,
|
|
||||||
.baseWidth = usedTextures[x]->getWidth(),
|
|
||||||
.baseHeight = usedTextures[x]->getHeight(),
|
|
||||||
.baseDepth = usedTextures[x]->getDepth(),
|
|
||||||
.numDimensions = usedTextures[x]->getDepth() > 1 ? 3u
|
|
||||||
: usedTextures[x]->getHeight() > 1 ? 2u
|
|
||||||
: 1u,
|
|
||||||
.numLevels = usedTextures[x]->getMipLevels(),
|
|
||||||
.numLayers = usedTextures[x]->getDepth(),
|
|
||||||
.numFaces = usedTextures[x]->getNumFaces(),
|
|
||||||
.isArray = false,
|
|
||||||
.generateMipmaps = false,
|
|
||||||
};
|
|
||||||
ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE, &kTexture);
|
|
||||||
|
|
||||||
for (uint32 depth = 0; depth < usedTextures[x]->getDepth(); ++depth) {
|
void FontAsset::load(ArchiveBuffer& buffer) { Serialization::load(buffer, glyphs); }
|
||||||
for (uint32 face = 0; face < usedTextures[x]->getNumFaces(); ++face) {
|
|
||||||
// technically, downloading cant be const, because we have to allocate temporary buffers and change layouts
|
|
||||||
// but practically the texture stays the same
|
|
||||||
const_cast<Gfx::Texture2D*>(*(usedTextures[x]))->download(0, depth, face, textureData);
|
|
||||||
ktxTexture_SetImageFromMemory(ktxTexture(kTexture), 0, depth, face, textureData.data(), textureData.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char writer[100];
|
|
||||||
snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1");
|
|
||||||
ktxHashList_AddKVPair(&kTexture->kvDataHead, KTX_WRITER_KEY, (ktx_uint32_t)strlen(writer) + 1, writer);
|
|
||||||
|
|
||||||
ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_ASTC_4x4_RGBA, 0);
|
|
||||||
|
|
||||||
ktx_uint8_t* texData;
|
|
||||||
ktx_size_t texSize;
|
|
||||||
ktxTexture_WriteToMemory(ktxTexture(kTexture), &texData, &texSize);
|
|
||||||
|
|
||||||
Array<uint8> rawData(texSize);
|
|
||||||
std::memcpy(rawData.data(), texData, texSize);
|
|
||||||
|
|
||||||
free(texData);
|
|
||||||
|
|
||||||
Serialization::save(buffer, rawData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontAsset::load(ArchiveBuffer& buffer) {
|
|
||||||
Serialization::load(buffer, glyphs);
|
|
||||||
size_t numTextures;
|
|
||||||
Serialization::load(buffer, numTextures);
|
|
||||||
for (uint64 x = 0; x < numTextures; ++x) {
|
|
||||||
Array<uint8> rawTex;
|
|
||||||
Serialization::load(buffer, rawTex);
|
|
||||||
|
|
||||||
ktxTexture2* kTexture;
|
|
||||||
ktxTexture2_CreateFromMemory(rawTex.data(), rawTex.size(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &kTexture);
|
|
||||||
|
|
||||||
ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_BC7_RGBA, 0);
|
|
||||||
|
|
||||||
TextureCreateInfo createInfo = {
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = ktxTexture_GetDataSize(ktxTexture(kTexture)),
|
|
||||||
.data = ktxTexture_GetData(ktxTexture(kTexture)),
|
|
||||||
.owner = Gfx::QueueType::GRAPHICS,
|
|
||||||
},
|
|
||||||
.format = (Gfx::SeFormat)kTexture->vkFormat,
|
|
||||||
.width = kTexture->baseWidth,
|
|
||||||
.height = kTexture->baseHeight,
|
|
||||||
.depth = kTexture->baseDepth,
|
|
||||||
.layers = kTexture->numFaces,
|
|
||||||
.elements = kTexture->numLayers,
|
|
||||||
.useMip = true,
|
|
||||||
.usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
|
|
||||||
};
|
|
||||||
|
|
||||||
Gfx::OTexture2D texture = buffer.getGraphics()->createTexture2D(createInfo);
|
|
||||||
usedTextures.add(std::move(texture));
|
|
||||||
|
|
||||||
ktxTexture_Destroy(ktxTexture(kTexture));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Seele::FontAsset::setUsedTextures(Array<Gfx::OTexture2D> _usedTextures) { usedTextures = std::move(_usedTextures); }
|
|
||||||
|
|
||||||
void FontAsset::Glyph::save(ArchiveBuffer& buffer) const {
|
void FontAsset::Glyph::save(ArchiveBuffer& buffer) const {
|
||||||
Serialization::save(buffer, textureIndex);
|
|
||||||
Serialization::save(buffer, size);
|
Serialization::save(buffer, size);
|
||||||
Serialization::save(buffer, bearing);
|
Serialization::save(buffer, bearing);
|
||||||
Serialization::save(buffer, advance);
|
Serialization::save(buffer, advance);
|
||||||
|
Serialization::save(buffer, textureData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAsset::Glyph::load(ArchiveBuffer& buffer) {
|
void FontAsset::Glyph::load(ArchiveBuffer& buffer) {
|
||||||
Serialization::load(buffer, textureIndex);
|
|
||||||
Serialization::load(buffer, size);
|
Serialization::load(buffer, size);
|
||||||
Serialization::load(buffer, bearing);
|
Serialization::load(buffer, bearing);
|
||||||
Serialization::load(buffer, advance);
|
Serialization::load(buffer, advance);
|
||||||
|
Serialization::load(buffer, textureData);
|
||||||
|
texture = buffer.getGraphics()->createTexture2D(TextureCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = textureData.size(),
|
||||||
|
.data = textureData.data(),
|
||||||
|
},
|
||||||
|
.format = Gfx::SE_FORMAT_R8_UNORM,
|
||||||
|
.width = size.x,
|
||||||
|
.height = size.y,
|
||||||
|
.name = "FontGlyph",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Asset.h"
|
#include "Asset.h"
|
||||||
#include "Containers/Map.h"
|
#include "Containers/Map.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
#include <freetype/freetype.h>
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
DECLARE_NAME_REF(Gfx, Texture2D)
|
DECLARE_NAME_REF(Gfx, Texture2D)
|
||||||
@@ -15,19 +16,17 @@ class FontAsset : public Asset {
|
|||||||
virtual void load(ArchiveBuffer& buffer) override;
|
virtual void load(ArchiveBuffer& buffer) override;
|
||||||
|
|
||||||
struct Glyph {
|
struct Glyph {
|
||||||
uint32 textureIndex;
|
UVector2 size = {};
|
||||||
IVector2 size;
|
UVector2 bearing = {};
|
||||||
IVector2 bearing;
|
uint32 advance = 0;
|
||||||
uint32 advance;
|
Array<uint8> textureData;
|
||||||
|
Gfx::OTexture2D texture = nullptr;
|
||||||
void save(ArchiveBuffer& buffer) const;
|
void save(ArchiveBuffer& buffer) const;
|
||||||
void load(ArchiveBuffer& buffer);
|
void load(ArchiveBuffer& buffer);
|
||||||
};
|
};
|
||||||
const Map<uint32, Glyph> getGlyphData() const { return glyphs; }
|
const Glyph& getGlyphData(char c) const { return glyphs[c]; }
|
||||||
Gfx::PTexture2D getTexture(uint32 index) { return usedTextures[index]; }
|
|
||||||
void setUsedTextures(Array<Gfx::OTexture2D> _usedTextures);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Array<Gfx::OTexture2D> usedTextures;
|
|
||||||
Map<uint32, Glyph> glyphs;
|
Map<uint32, Glyph> glyphs;
|
||||||
friend class FontLoader;
|
friend class FontLoader;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Graphics/Mesh.h"
|
#include "Graphics/Mesh.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
MeshAsset::MeshAsset() {}
|
MeshAsset::MeshAsset() {}
|
||||||
@@ -14,7 +13,8 @@ MeshAsset::~MeshAsset() {}
|
|||||||
|
|
||||||
void MeshAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, meshes); }
|
void MeshAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, meshes); }
|
||||||
|
|
||||||
void MeshAsset::load(ArchiveBuffer& buffer) { Serialization::load(buffer, meshes);
|
void MeshAsset::load(ArchiveBuffer& buffer) {
|
||||||
|
Serialization::load(buffer, meshes);
|
||||||
byteSize = 0;
|
byteSize = 0;
|
||||||
for (const auto& mesh : meshes) {
|
for (const auto& mesh : meshes) {
|
||||||
byteSize += mesh->getCPUSize();
|
byteSize += mesh->getCPUSize();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ target_sources(Engine
|
|||||||
Game.h
|
Game.h
|
||||||
MinimalEngine.h
|
MinimalEngine.h
|
||||||
ThreadPool.h
|
ThreadPool.h
|
||||||
ThreadPool.cpp)
|
ThreadPool.cpp "../../tests/Engine/UI/Element.cpp")
|
||||||
|
|
||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ class Graphics {
|
|||||||
|
|
||||||
virtual void copyBuffer(Gfx::PShaderBuffer src, Gfx::PShaderBuffer dst) = 0;
|
virtual void copyBuffer(Gfx::PShaderBuffer src, Gfx::PShaderBuffer dst) = 0;
|
||||||
|
|
||||||
bool supportMeshShading() const { return meshShadingEnabled; }
|
constexpr bool supportMeshShading() const { return meshShadingEnabled; }
|
||||||
|
constexpr bool supportRayTracing() const { return rayTracingEnabled; }
|
||||||
|
|
||||||
// Ray Tracing
|
// Ray Tracing
|
||||||
virtual OBottomLevelAS createBottomLevelAccelerationStructure(const BottomLevelASCreateInfo& createInfo) = 0;
|
virtual OBottomLevelAS createBottomLevelAccelerationStructure(const BottomLevelASCreateInfo& createInfo) = 0;
|
||||||
@@ -122,6 +123,7 @@ class Graphics {
|
|||||||
QueueFamilyMapping queueMapping;
|
QueueFamilyMapping queueMapping;
|
||||||
OShaderCompiler shaderCompiler;
|
OShaderCompiler shaderCompiler;
|
||||||
bool meshShadingEnabled = false;
|
bool meshShadingEnabled = false;
|
||||||
|
bool rayTracingEnabled = false;
|
||||||
friend class Window;
|
friend class Window;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Graphics)
|
DEFINE_REF(Graphics)
|
||||||
|
|||||||
@@ -30,10 +30,12 @@ void Mesh::load(ArchiveBuffer& buffer) {
|
|||||||
referencedMaterial = AssetRegistry::findMaterialInstance(refFolder, refId);
|
referencedMaterial = AssetRegistry::findMaterialInstance(refFolder, refId);
|
||||||
id = vertexData->allocateVertexData(vertexCount);
|
id = vertexData->allocateVertexData(vertexCount);
|
||||||
byteSize = vertexData->deserializeMesh(id, buffer);
|
byteSize = vertexData->deserializeMesh(id, buffer);
|
||||||
blas = buffer.getGraphics()->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{
|
if (buffer.getGraphics()->supportRayTracing()) {
|
||||||
.mesh = this,
|
blas = buffer.getGraphics()->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo{
|
||||||
});
|
.mesh = this,
|
||||||
vertexData->registerBottomLevelAccelerationStructure(blas);
|
});
|
||||||
|
vertexData->registerBottomLevelAccelerationStructure(blas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 Mesh::getCPUSize() const {
|
uint64 Mesh::getCPUSize() const {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void Seele::addDebugVertex(DebugVertex vert) { gDebugVertices.add(vert); }
|
|||||||
|
|
||||||
void Seele::addDebugVertices(Array<DebugVertex> verts) { gDebugVertices.addAll(verts); }
|
void Seele::addDebugVertices(Array<DebugVertex> verts) { gDebugVertices.addAll(verts); }
|
||||||
|
|
||||||
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
|
||||||
//waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout);
|
//waterRenderer = new WaterRenderer(graphics, scene, viewParamsLayout);
|
||||||
basePassLayout = graphics->createPipelineLayout("BasePassLayout");
|
basePassLayout = graphics->createPipelineLayout("BasePassLayout");
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ class BasePass : public RenderPass {
|
|||||||
} skyboxData;
|
} skyboxData;
|
||||||
Gfx::OUniformBuffer skyboxBuffer;
|
Gfx::OUniformBuffer skyboxBuffer;
|
||||||
Component::Skybox skybox;
|
Component::Skybox skybox;
|
||||||
|
PScene scene;
|
||||||
};
|
};
|
||||||
DEFINE_REF(BasePass)
|
DEFINE_REF(BasePass)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ target_sources(Engine
|
|||||||
RenderPass.cpp
|
RenderPass.cpp
|
||||||
TerrainRenderer.h
|
TerrainRenderer.h
|
||||||
TerrainRenderer.cpp
|
TerrainRenderer.cpp
|
||||||
TextPass.h
|
|
||||||
TextPass.cpp
|
|
||||||
UIPass.h
|
UIPass.h
|
||||||
UIPass.cpp
|
UIPass.cpp
|
||||||
VisibilityPass.h
|
VisibilityPass.h
|
||||||
@@ -38,6 +36,5 @@ target_sources(Engine
|
|||||||
RenderGraphResources.h
|
RenderGraphResources.h
|
||||||
RenderPass.h
|
RenderPass.h
|
||||||
TerrainRenderer.h
|
TerrainRenderer.h
|
||||||
TextPass.h
|
|
||||||
UIPass.h
|
UIPass.h
|
||||||
VisibilityPass.h)
|
VisibilityPass.h)
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
|
||||||
depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout");
|
depthPrepassLayout = graphics->createPipelineLayout("CachedDepthLayout");
|
||||||
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
|
depthPrepassLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
|
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class CachedDepthPass : public RenderPass {
|
|||||||
Gfx::OTimestampQuery timestamps;
|
Gfx::OTimestampQuery timestamps;
|
||||||
|
|
||||||
Gfx::PShaderBuffer cullingBuffer;
|
Gfx::PShaderBuffer cullingBuffer;
|
||||||
|
PScene scene;
|
||||||
};
|
};
|
||||||
DEFINE_REF(CachedDepthPass)
|
DEFINE_REF(CachedDepthPass)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
|
||||||
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
||||||
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class DepthCullingPass : public RenderPass {
|
|||||||
Gfx::PComputePipeline depthReduceLevel;
|
Gfx::PComputePipeline depthReduceLevel;
|
||||||
|
|
||||||
Gfx::PShaderBuffer cullingBuffer;
|
Gfx::PShaderBuffer cullingBuffer;
|
||||||
|
PScene scene;
|
||||||
};
|
};
|
||||||
DEFINE_REF(DepthCullingPass)
|
DEFINE_REF(DepthCullingPass)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
|
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {}
|
||||||
|
|
||||||
LightCullingPass::~LightCullingPass() {}
|
LightCullingPass::~LightCullingPass() {}
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ class LightCullingPass : public RenderPass {
|
|||||||
Gfx::PComputePipeline cullingEnabledPipeline;
|
Gfx::PComputePipeline cullingEnabledPipeline;
|
||||||
Gfx::OPipelineStatisticsQuery query;
|
Gfx::OPipelineStatisticsQuery query;
|
||||||
Gfx::PTimestampQuery timestamps;
|
Gfx::PTimestampQuery timestamps;
|
||||||
|
|
||||||
|
PScene scene;
|
||||||
};
|
};
|
||||||
DEFINE_REF(LightCullingPass)
|
DEFINE_REF(LightCullingPass)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct SampleParams {
|
|||||||
uint32 samplesPerPixel;
|
uint32 samplesPerPixel;
|
||||||
};
|
};
|
||||||
|
|
||||||
RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
|
||||||
paramsLayout = graphics->createDescriptorLayout("pRayTracingParams");
|
paramsLayout = graphics->createDescriptorLayout("pRayTracingParams");
|
||||||
paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
paramsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ class RayTracingPass : public RenderPass {
|
|||||||
Gfx::OMissShader miss;
|
Gfx::OMissShader miss;
|
||||||
Gfx::PRayTracingPipeline pipeline;
|
Gfx::PRayTracingPipeline pipeline;
|
||||||
Gfx::OTopLevelAS tlas;
|
Gfx::OTopLevelAS tlas;
|
||||||
|
PScene scene;
|
||||||
};
|
};
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
RenderPass::RenderPass(Gfx::PGraphics graphics, PScene scene) : graphics(graphics), scene(scene) {
|
RenderPass::RenderPass(Gfx::PGraphics graphics) : graphics(graphics) {
|
||||||
viewParamsLayout = graphics->createDescriptorLayout("pViewParams");
|
viewParamsLayout = graphics->createDescriptorLayout("pViewParams");
|
||||||
viewParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
viewParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ DECLARE_NAME_REF(Gfx, Graphics)
|
|||||||
DECLARE_NAME_REF(Gfx, RenderPass)
|
DECLARE_NAME_REF(Gfx, RenderPass)
|
||||||
class RenderPass {
|
class RenderPass {
|
||||||
public:
|
public:
|
||||||
RenderPass(Gfx::PGraphics graphics, PScene scene);
|
RenderPass(Gfx::PGraphics graphics);
|
||||||
RenderPass(RenderPass&&) = default;
|
RenderPass(RenderPass&&) = default;
|
||||||
RenderPass& operator=(RenderPass&&) = default;
|
RenderPass& operator=(RenderPass&&) = default;
|
||||||
virtual ~RenderPass();
|
virtual ~RenderPass();
|
||||||
@@ -71,7 +71,6 @@ class RenderPass {
|
|||||||
Gfx::ORenderPass renderPass;
|
Gfx::ORenderPass renderPass;
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
Gfx::PViewport viewport;
|
Gfx::PViewport viewport;
|
||||||
PScene scene;
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(RenderPass)
|
DEFINE_REF(RenderPass)
|
||||||
template <typename RP>
|
template <typename RP>
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
#include "TextPass.h"
|
|
||||||
#include "Graphics/Command.h"
|
|
||||||
#include "Graphics/Enums.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
|
||||||
#include "Graphics/RenderTarget.h"
|
|
||||||
#include "RenderGraph.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
|
|
||||||
TextPass::TextPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
|
|
||||||
|
|
||||||
TextPass::~TextPass() {}
|
|
||||||
|
|
||||||
void TextPass::beginFrame(const Component::Camera& cam) {
|
|
||||||
RenderPass::beginFrame(cam);
|
|
||||||
for (TextRender& render : texts) {
|
|
||||||
FontData& fd = getFontData(render.font);
|
|
||||||
TextResources& res = textResources[render.font].add();
|
|
||||||
Array<GlyphInstanceData> instanceData;
|
|
||||||
float x = render.position.x;
|
|
||||||
float y = render.position.y;
|
|
||||||
for (uint32 c : render.text) {
|
|
||||||
const GlyphData& glyph = fd.glyphDataSet[fd.characterToGlyphIndex[c]];
|
|
||||||
Vector2 bearing = glyph.bearing;
|
|
||||||
Vector2 size = glyph.size;
|
|
||||||
float xpos = x + bearing.x * render.scale;
|
|
||||||
float ypos = y - (size.y - bearing.y) * render.scale;
|
|
||||||
|
|
||||||
float w = size.x * render.scale;
|
|
||||||
float h = size.y * render.scale;
|
|
||||||
|
|
||||||
instanceData.add(GlyphInstanceData{
|
|
||||||
.position = Vector2(xpos, ypos),
|
|
||||||
.widthHeight = Vector2(w, h),
|
|
||||||
.glyphIndex = fd.characterToGlyphIndex[c],
|
|
||||||
});
|
|
||||||
x += (glyph.advance >> 6) * render.scale;
|
|
||||||
}
|
|
||||||
res.instanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = static_cast<uint32>(instanceData.size() * sizeof(GlyphInstanceData)),
|
|
||||||
.data = reinterpret_cast<uint8*>(instanceData.data()),
|
|
||||||
},
|
|
||||||
.numElements = instanceData.size(),
|
|
||||||
});
|
|
||||||
|
|
||||||
res.textureArraySet = fd.textureArraySet;
|
|
||||||
|
|
||||||
res.textData = {
|
|
||||||
.textColor = render.textColor,
|
|
||||||
.scale = render.scale,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
auto proj = viewport->getProjectionMatrix();
|
|
||||||
projectionBuffer->updateContents(0, sizeof(Matrix4), &proj);
|
|
||||||
generalSet->updateBuffer(1, 0, projectionBuffer);
|
|
||||||
generalSet->writeChanges();
|
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextPass::render() {
|
|
||||||
graphics->beginRenderPass(renderPass);
|
|
||||||
Array<Gfx::ORenderCommand> commands;
|
|
||||||
for (const auto& [fontAsset, res] : textResources) {
|
|
||||||
Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
|
|
||||||
command->setViewport(viewport);
|
|
||||||
command->bindPipeline(pipeline);
|
|
||||||
for (const auto& resource : res) {
|
|
||||||
command->bindDescriptor({generalSet, resource.textureArraySet});
|
|
||||||
// command->bindVertexBuffer({resource.vertexBuffer});
|
|
||||||
|
|
||||||
command->pushConstants(Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(TextData),
|
|
||||||
&resource.textData);
|
|
||||||
// command->draw(4, static_cast<uint32>(resource.vertexBuffer->getNumVertices()), 0, 0);
|
|
||||||
}
|
|
||||||
commands.add(std::move(command));
|
|
||||||
}
|
|
||||||
graphics->executeCommands(std::move(commands));
|
|
||||||
graphics->endRenderPass();
|
|
||||||
textResources.clear();
|
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextPass::endFrame() {
|
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TextPass::publishOutputs() {}
|
|
||||||
|
|
||||||
void TextPass::createRenderPass() {
|
|
||||||
renderTarget = resources->requestRenderTarget("UIPASS_COLOR");
|
|
||||||
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "TextVertex",
|
|
||||||
.modules = {"TextPass"},
|
|
||||||
.entryPoints = {{"vertexMain", "TextPass"}, {"fragmentMain", "TextFragment"}},
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
vertexShader = graphics->createVertexShader({0});
|
|
||||||
fragmentShader = graphics->createFragmentShader({1});
|
|
||||||
|
|
||||||
generalLayout = graphics->createDescriptorLayout("pRender");
|
|
||||||
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.uniformLength = sizeof(Matrix4),
|
|
||||||
});
|
|
||||||
generalLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 1,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
|
||||||
});
|
|
||||||
generalLayout->create();
|
|
||||||
|
|
||||||
textureArrayLayout = graphics->createDescriptorLayout("pGlyphTextures");
|
|
||||||
textureArrayLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY,
|
|
||||||
.descriptorCount = 256,
|
|
||||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,
|
|
||||||
});
|
|
||||||
textureArrayLayout->create();
|
|
||||||
|
|
||||||
projectionBuffer = graphics->createUniformBuffer({
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = sizeof(Matrix4),
|
|
||||||
.data = nullptr,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
glyphSampler = graphics->createSampler({
|
|
||||||
.magFilter = Gfx::SE_FILTER_LINEAR,
|
|
||||||
.minFilter = Gfx::SE_FILTER_LINEAR,
|
|
||||||
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
|
||||||
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
|
||||||
});
|
|
||||||
|
|
||||||
generalSet = generalLayout->allocateDescriptorSet();
|
|
||||||
generalSet->updateBuffer(0, 0, projectionBuffer);
|
|
||||||
generalSet->updateSampler(1, 0, glyphSampler);
|
|
||||||
generalSet->writeChanges();
|
|
||||||
|
|
||||||
pipelineLayout = graphics->createPipelineLayout();
|
|
||||||
pipelineLayout->addDescriptorLayout(generalLayout);
|
|
||||||
pipelineLayout->addDescriptorLayout(textureArrayLayout);
|
|
||||||
pipelineLayout->addPushConstants(
|
|
||||||
{.stageFlags = Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, .offset = 0, .size = sizeof(TextData)});
|
|
||||||
pipelineLayout->create();
|
|
||||||
|
|
||||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{.colorAttachments = {renderTarget}, .depthAttachment = depthAttachment};
|
|
||||||
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
|
|
||||||
|
|
||||||
Gfx::LegacyPipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.vertexShader = vertexShader;
|
|
||||||
pipelineInfo.fragmentShader = fragmentShader;
|
|
||||||
pipelineInfo.renderPass = renderPass;
|
|
||||||
pipelineInfo.pipelineLayout = pipelineLayout;
|
|
||||||
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
|
|
||||||
pipelineInfo.colorBlend.attachmentCount = 1;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].blendEnable = true;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].colorWriteMask =
|
|
||||||
Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT | Gfx::SE_COLOR_COMPONENT_A_BIT;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ZERO;
|
|
||||||
pipelineInfo.colorBlend.blendAttachments[0].alphaBlendOp = Gfx::SE_BLEND_OP_ADD;
|
|
||||||
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
|
||||||
|
|
||||||
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
|
||||||
}
|
|
||||||
TextPass::FontData& TextPass::getFontData(PFontAsset font) {
|
|
||||||
if (fontData.exists(font)) {
|
|
||||||
return fontData[font];
|
|
||||||
}
|
|
||||||
const auto& fontGlyphs = font->getGlyphData();
|
|
||||||
FontData& fd = fontData[font];
|
|
||||||
Array<GlyphData> glyphData;
|
|
||||||
Array<Gfx::PTexture2D> textures;
|
|
||||||
glyphData.reserve(fontGlyphs.size());
|
|
||||||
for (const auto& [key, value] : fontGlyphs) {
|
|
||||||
fd.characterToGlyphIndex[key] = static_cast<uint32>(glyphData.size());
|
|
||||||
GlyphData& gd = glyphData.add();
|
|
||||||
gd.bearing = value.bearing;
|
|
||||||
gd.size = value.size;
|
|
||||||
gd.advance = value.advance;
|
|
||||||
textures.add(font->getTexture(value.textureIndex));
|
|
||||||
}
|
|
||||||
fd.glyphDataSet = glyphData;
|
|
||||||
|
|
||||||
textureArrayLayout->reset();
|
|
||||||
fd.textureArraySet = textureArrayLayout->allocateDescriptorSet();
|
|
||||||
for (uint32 i = 0; i < textures.size(); ++i) {
|
|
||||||
fd.textureArraySet->updateTexture(0, i, textures[i]);
|
|
||||||
}
|
|
||||||
fd.textureArraySet->writeChanges();
|
|
||||||
return fontData[font];
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Asset/FontAsset.h"
|
|
||||||
#include "Graphics/Shader.h"
|
|
||||||
#include "RenderPass.h"
|
|
||||||
#include "UI/RenderHierarchy.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
DECLARE_NAME_REF(Gfx, Texture2D)
|
|
||||||
DECLARE_NAME_REF(Gfx, ShaderBuffer)
|
|
||||||
struct TextRender {
|
|
||||||
std::string text;
|
|
||||||
PFontAsset font;
|
|
||||||
Vector4 textColor;
|
|
||||||
Vector2 position;
|
|
||||||
float scale;
|
|
||||||
};
|
|
||||||
class TextPass : public RenderPass {
|
|
||||||
public:
|
|
||||||
TextPass(Gfx::PGraphics graphics, PScene scene);
|
|
||||||
TextPass(TextPass&&) = default;
|
|
||||||
TextPass& operator=(TextPass&&) = default;
|
|
||||||
virtual ~TextPass();
|
|
||||||
virtual void beginFrame(const Component::Camera& cam) override;
|
|
||||||
virtual void render() override;
|
|
||||||
virtual void endFrame() override;
|
|
||||||
virtual void publishOutputs() override;
|
|
||||||
virtual void createRenderPass() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct GlyphData {
|
|
||||||
Vector2 bearing;
|
|
||||||
Vector2 size;
|
|
||||||
uint32 advance;
|
|
||||||
};
|
|
||||||
struct GlyphInstanceData {
|
|
||||||
Vector2 position;
|
|
||||||
Vector2 widthHeight;
|
|
||||||
uint32 glyphIndex;
|
|
||||||
};
|
|
||||||
struct TextData {
|
|
||||||
Vector4 textColor;
|
|
||||||
float scale;
|
|
||||||
};
|
|
||||||
struct FontData {
|
|
||||||
Gfx::PDescriptorSet textureArraySet;
|
|
||||||
Array<GlyphData> glyphDataSet;
|
|
||||||
Map<uint32, uint32> characterToGlyphIndex;
|
|
||||||
};
|
|
||||||
FontData& getFontData(PFontAsset font);
|
|
||||||
Map<PFontAsset, FontData> fontData;
|
|
||||||
|
|
||||||
struct TextResources {
|
|
||||||
Gfx::PShaderBuffer instanceBuffer;
|
|
||||||
Gfx::PDescriptorSet textureArraySet;
|
|
||||||
TextData textData;
|
|
||||||
};
|
|
||||||
Map<PFontAsset, Array<TextResources>> textResources;
|
|
||||||
|
|
||||||
Gfx::RenderTargetAttachment renderTarget;
|
|
||||||
Gfx::RenderTargetAttachment depthAttachment;
|
|
||||||
|
|
||||||
Gfx::ODescriptorLayout generalLayout;
|
|
||||||
Gfx::ODescriptorLayout textureArrayLayout;
|
|
||||||
|
|
||||||
Gfx::PDescriptorSet generalSet;
|
|
||||||
|
|
||||||
Gfx::OUniformBuffer projectionBuffer;
|
|
||||||
Gfx::OSampler glyphSampler;
|
|
||||||
|
|
||||||
Gfx::OVertexShader vertexShader;
|
|
||||||
Gfx::OFragmentShader fragmentShader;
|
|
||||||
Gfx::OPipelineLayout pipelineLayout;
|
|
||||||
Gfx::PGraphicsPipeline pipeline;
|
|
||||||
Array<TextRender> texts;
|
|
||||||
};
|
|
||||||
DEFINE_REF(TextPass);
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "UIPass.h"
|
#include "UIPass.h"
|
||||||
|
#include "Asset/AssetRegistry.h"
|
||||||
#include "Graphics/Command.h"
|
#include "Graphics/Command.h"
|
||||||
#include "Graphics/Enums.h"
|
#include "Graphics/Enums.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
@@ -7,53 +8,100 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
UIPass::UIPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
|
UIPass::UIPass(Gfx::PGraphics graphics, UI::PSystem system) : RenderPass(graphics) {
|
||||||
|
glyphInstanceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.name = "GlyphInstanceBuffer"});
|
||||||
|
textDescriptorLayout = graphics->createDescriptorLayout("pText");
|
||||||
|
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.binding = 0,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
});
|
||||||
|
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.binding = 1,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
|
});
|
||||||
|
textDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.binding = 2,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.descriptorCount = 1024,
|
||||||
|
});
|
||||||
|
textPipelineLayout = graphics->createPipelineLayout("TextPipeline");
|
||||||
|
textPipelineLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
textPipelineLayout->addDescriptorLayout(textDescriptorLayout);
|
||||||
|
|
||||||
|
uiPipelineLayout = graphics->createPipelineLayout("UIPipeline");
|
||||||
|
uiPipelineLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
// todo:
|
||||||
|
texts.add(TextRender{
|
||||||
|
.text = "TestText123",
|
||||||
|
.font = AssetRegistry::findFont("", "arial"),
|
||||||
|
.fontSize = 12,
|
||||||
|
.position = Vector2(0, 100),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
UIPass::~UIPass() {}
|
UIPass::~UIPass() {}
|
||||||
|
|
||||||
void UIPass::beginFrame(const Component::Camera& cam) {
|
void UIPass::beginFrame(const Component::Camera& cam) {
|
||||||
RenderPass::beginFrame(cam);
|
RenderPass::beginFrame(cam);
|
||||||
VertexBufferCreateInfo info = {
|
glyphs.clear();
|
||||||
.sourceData =
|
usedTextures.clear();
|
||||||
{
|
for (TextRender& render : texts) {
|
||||||
.size = (uint32)(sizeof(UI::RenderElementStyle) * renderElements.size()),
|
TextResources& res = textResources[render.font].add();
|
||||||
.data = (uint8*)renderElements.data(),
|
float x = render.position.x * viewport->getContentScaleX();
|
||||||
},
|
float y = (viewport->getHeight() - render.position.y) * viewport->getContentScaleY();
|
||||||
.vertexSize = sizeof(UI::RenderElementStyle),
|
for (uint32 c : render.text) {
|
||||||
.numVertices = (uint32)renderElements.size(),
|
const FontAsset::Glyph& glyph = render.font->getGlyphData(c);
|
||||||
};
|
Vector2 bearing = Vector2(glyph.bearing) * viewport->getContentScaleX();
|
||||||
elementBuffer = graphics->createVertexBuffer(info);
|
Vector2 size = Vector2(glyph.size) * viewport->getContentScaleY();
|
||||||
uint32 numTextures = static_cast<uint32>(usedTextures.size());
|
float xpos = x + glyph.bearing.x;
|
||||||
numTexturesBuffer->updateContents(0, sizeof(uint32), &numTextures);
|
float ypos = y + (size.y - bearing.y);
|
||||||
descriptorSet->updateBuffer(2, 0, numTexturesBuffer);
|
|
||||||
for (uint32 i = 0; i < usedTextures.size(); ++i) {
|
float w = size.x;
|
||||||
descriptorSet->updateTexture(3, i, usedTextures[i]);
|
float h = size.y;
|
||||||
|
|
||||||
|
glyphs.add(GlyphInstanceData{
|
||||||
|
.x = xpos,
|
||||||
|
.y = ypos,
|
||||||
|
.width = w,
|
||||||
|
.height = h,
|
||||||
|
.glyphIndex = (uint32)usedTextures.size(),
|
||||||
|
});
|
||||||
|
usedTextures.add(glyph.texture);
|
||||||
|
x += glyph.advance >> 6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
descriptorSet->writeChanges();
|
glyphInstanceBuffer->rotateBuffer(sizeof(GlyphInstanceData) * glyphs.size());
|
||||||
// co_return;
|
glyphInstanceBuffer->updateContents(0, sizeof(GlyphInstanceData) * glyphs.size(), glyphs.data());
|
||||||
|
glyphInstanceBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
|
||||||
|
textDescriptorLayout->reset();
|
||||||
|
textDescriptorSet = textDescriptorLayout->allocateDescriptorSet();
|
||||||
|
textDescriptorSet->updateBuffer(0, 0, glyphInstanceBuffer);
|
||||||
|
textDescriptorSet->updateSampler(1, 0, glyphSampler);
|
||||||
|
for (uint32 i = 0; i < usedTextures.size(); ++i) {
|
||||||
|
textDescriptorSet->updateTexture(2, i, usedTextures[i]);
|
||||||
|
}
|
||||||
|
textDescriptorSet->writeChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIPass::render() {
|
void UIPass::render() {
|
||||||
graphics->beginRenderPass(renderPass);
|
graphics->beginRenderPass(renderPass);
|
||||||
Gfx::ORenderCommand command = graphics->createRenderCommand("UIPassCommand");
|
|
||||||
command->setViewport(viewport);
|
|
||||||
command->bindPipeline(pipeline);
|
|
||||||
command->bindVertexBuffer({elementBuffer});
|
|
||||||
command->bindDescriptor(descriptorSet);
|
|
||||||
command->draw(4, static_cast<uint32>(renderElements.size()), 0, 0);
|
|
||||||
Array<Gfx::ORenderCommand> commands;
|
Array<Gfx::ORenderCommand> commands;
|
||||||
|
Gfx::ORenderCommand command = graphics->createRenderCommand("TextPassCommand");
|
||||||
|
command->setViewport(viewport);
|
||||||
|
command->bindPipeline(textPipeline);
|
||||||
|
command->bindDescriptor({viewParamsSet, textDescriptorSet});
|
||||||
|
command->draw(4, glyphs.size(), 0, 0);
|
||||||
commands.add(std::move(command));
|
commands.add(std::move(command));
|
||||||
graphics->executeCommands(std::move(commands));
|
graphics->executeCommands(std::move(commands));
|
||||||
graphics->endRenderPass();
|
graphics->endRenderPass();
|
||||||
|
|
||||||
// co_return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIPass::endFrame() {
|
void UIPass::endFrame() {}
|
||||||
// co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIPass::publishOutputs() {
|
void UIPass::publishOutputs() {}
|
||||||
|
|
||||||
|
void UIPass::createRenderPass() {
|
||||||
TextureCreateInfo depthBufferInfo = {
|
TextureCreateInfo depthBufferInfo = {
|
||||||
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
.format = Gfx::SE_FORMAT_D32_SFLOAT,
|
||||||
.width = viewport->getWidth(),
|
.width = viewport->getWidth(),
|
||||||
@@ -65,98 +113,69 @@ void UIPass::publishOutputs() {
|
|||||||
depthAttachment =
|
depthAttachment =
|
||||||
Gfx::RenderTargetAttachment(depthBuffer, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
Gfx::RenderTargetAttachment(depthBuffer, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||||
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||||
resources->registerRenderPassOutput("UIPASS_DEPTH", depthAttachment);
|
depthAttachment.clear.depthStencil.depth = 0;
|
||||||
|
|
||||||
TextureCreateInfo colorBufferInfo = {
|
colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
.format = Gfx::SE_FORMAT_R16G16B16A16_SFLOAT,
|
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
||||||
.width = viewport->getWidth(),
|
colorAttachment.clear.color = {{1.0f, 1.0f, 1.0f, 1.0f}};
|
||||||
.height = viewport->getHeight(),
|
|
||||||
.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
|
||||||
|
.colorAttachments = {colorAttachment},
|
||||||
|
.depthAttachment = depthAttachment,
|
||||||
};
|
};
|
||||||
colorBuffer = graphics->createTexture2D(colorBufferInfo);
|
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport, "TextPass");
|
||||||
renderTarget = Gfx::RenderTargetAttachment(colorBuffer, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR,
|
|
||||||
Gfx::SE_ATTACHMENT_STORE_OP_STORE);
|
|
||||||
renderTarget.clear.color = {{0.0f, 0.0f, 0.0f, 1.0f}};
|
|
||||||
resources->registerRenderPassOutput("UIPASS_COLOR", renderTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIPass::createRenderPass() {
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
ShaderCompilationInfo createInfo = {
|
.name = "TextVertex",
|
||||||
|
.modules = {"TextPass"},
|
||||||
|
.entryPoints = {{"vertexMain", "TextPass"}, {"fragmentMain", "TextPass"}},
|
||||||
|
.rootSignature = textPipelineLayout,
|
||||||
|
});
|
||||||
|
textPipelineLayout->create();
|
||||||
|
textVertexShader = graphics->createVertexShader({0});
|
||||||
|
textFragmentShader = graphics->createFragmentShader({1});
|
||||||
|
|
||||||
|
glyphSampler = graphics->createSampler({
|
||||||
|
.magFilter = Gfx::SE_FILTER_LINEAR,
|
||||||
|
.minFilter = Gfx::SE_FILTER_LINEAR,
|
||||||
|
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
|
});
|
||||||
|
|
||||||
|
Gfx::LegacyPipelineCreateInfo pipelineInfo = {
|
||||||
|
.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
||||||
|
.vertexShader = textVertexShader,
|
||||||
|
.fragmentShader = textFragmentShader,
|
||||||
|
.renderPass = renderPass,
|
||||||
|
.pipelineLayout = textPipelineLayout,
|
||||||
|
.rasterizationState =
|
||||||
|
{
|
||||||
|
.cullMode = Gfx::SE_CULL_MODE_NONE,
|
||||||
|
},
|
||||||
|
.colorBlend =
|
||||||
|
{
|
||||||
|
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.blendAttachments = {{
|
||||||
|
.blendEnable = true,
|
||||||
|
.srcColorBlendFactor = Gfx::SE_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
.dstColorBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.srcAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.dstAlphaBlendFactor = Gfx::SE_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaBlendOp = Gfx::SE_BLEND_OP_ADD,
|
||||||
|
.colorWriteMask = Gfx::SE_COLOR_COMPONENT_R_BIT | Gfx::SE_COLOR_COMPONENT_G_BIT | Gfx::SE_COLOR_COMPONENT_B_BIT |
|
||||||
|
Gfx::SE_COLOR_COMPONENT_A_BIT,
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
textPipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||||
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
.name = "UIVertex",
|
.name = "UIVertex",
|
||||||
.modules = {"UIPass"},
|
.modules = {"UIPass"},
|
||||||
.entryPoints =
|
.entryPoints = {{"vertexMain", "UIPass"}, {"fragmentMain", "UIPass"}},
|
||||||
{
|
.rootSignature = uiPipelineLayout,
|
||||||
{"vertexMain", "UIPass"},
|
|
||||||
{"fragmentMain", "UIFragment"},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
vertexShader = graphics->createVertexShader({0});
|
|
||||||
fragmentShader = graphics->createFragmentShader({1});
|
|
||||||
|
|
||||||
descriptorLayout = graphics->createDescriptorLayout("pParams");
|
|
||||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 0,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.uniformLength = sizeof(Matrix4),
|
|
||||||
});
|
});
|
||||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
uiVertexShader = graphics->createVertexShader({0});
|
||||||
.binding = 1,
|
uiFragmentShader = graphics->createFragmentShader({1});
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
|
||||||
});
|
|
||||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 2,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.uniformLength = sizeof(uint32)
|
|
||||||
});
|
|
||||||
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.binding = 3,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D_ARRAY,
|
|
||||||
.descriptorCount = 256,
|
|
||||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
|
||||||
});
|
|
||||||
descriptorLayout->create();
|
|
||||||
|
|
||||||
Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
|
|
||||||
|
|
||||||
Gfx::OUniformBuffer uniformBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = sizeof(Matrix4),
|
|
||||||
.data = (uint8*)&projectionMatrix,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Gfx::OSampler backgroundSampler = graphics->createSampler({});
|
|
||||||
|
|
||||||
numTexturesBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
|
||||||
.sourceData =
|
|
||||||
{
|
|
||||||
.size = sizeof(uint32),
|
|
||||||
.data = nullptr,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
descriptorSet = descriptorLayout->allocateDescriptorSet();
|
|
||||||
descriptorSet->updateBuffer(0, 0, uniformBuffer);
|
|
||||||
descriptorSet->updateSampler(1, 0, backgroundSampler);
|
|
||||||
descriptorSet->writeChanges();
|
|
||||||
|
|
||||||
pipelineLayout = graphics->createPipelineLayout();
|
|
||||||
pipelineLayout->addDescriptorLayout(descriptorLayout);
|
|
||||||
pipelineLayout->create();
|
|
||||||
|
|
||||||
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{.colorAttachments = {renderTarget}, .depthAttachment = depthAttachment};
|
|
||||||
renderPass = graphics->createRenderPass(std::move(layout), {}, viewport);
|
|
||||||
|
|
||||||
Gfx::LegacyPipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.vertexShader = vertexShader;
|
|
||||||
pipelineInfo.fragmentShader = fragmentShader;
|
|
||||||
pipelineInfo.renderPass = renderPass;
|
|
||||||
pipelineInfo.pipelineLayout = pipelineLayout;
|
|
||||||
pipelineInfo.rasterizationState.cullMode = Gfx::SE_CULL_MODE_NONE;
|
|
||||||
pipelineInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
|
|
||||||
|
|
||||||
pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/Shader.h"
|
#include "Graphics/Shader.h"
|
||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "UI/RenderHierarchy.h"
|
#include "Asset/FontAsset.h"
|
||||||
|
#include "UI/System.h"
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
DECLARE_NAME_REF(Gfx, Texture2D)
|
DECLARE_NAME_REF(Gfx, Texture2D)
|
||||||
DECLARE_NAME_REF(Gfx, RenderTargetAttachment)
|
DECLARE_NAME_REF(Gfx, RenderTargetAttachment)
|
||||||
|
struct TextRender {
|
||||||
|
std::string text;
|
||||||
|
PFontAsset font;
|
||||||
|
uint32 fontSize;
|
||||||
|
Vector4 textColor;
|
||||||
|
Vector2 position;
|
||||||
|
};
|
||||||
class UIPass : public RenderPass {
|
class UIPass : public RenderPass {
|
||||||
public:
|
public:
|
||||||
UIPass(Gfx::PGraphics graphics, PScene scene);
|
UIPass(Gfx::PGraphics graphics, UI::PSystem system);
|
||||||
UIPass(UIPass&&) = default;
|
UIPass(UIPass&&) = default;
|
||||||
UIPass& operator=(UIPass&&) = default;
|
UIPass& operator=(UIPass&&) = default;
|
||||||
virtual ~UIPass();
|
virtual ~UIPass();
|
||||||
@@ -20,23 +27,54 @@ class UIPass : public RenderPass {
|
|||||||
virtual void createRenderPass() override;
|
virtual void createRenderPass() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gfx::RenderTargetAttachment renderTarget;
|
struct GlyphData {
|
||||||
Gfx::OTexture2D colorBuffer;
|
Vector2 bearing;
|
||||||
|
Vector2 size;
|
||||||
|
uint32 advance;
|
||||||
|
};
|
||||||
|
struct GlyphInstanceData {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
uint32 glyphIndex;
|
||||||
|
};
|
||||||
|
struct TextData {
|
||||||
|
Vector4 textColor;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TextResources {
|
||||||
|
Gfx::PShaderBuffer instanceBuffer;
|
||||||
|
Gfx::PDescriptorSet textureArraySet;
|
||||||
|
TextData textData;
|
||||||
|
};
|
||||||
|
Map<PFontAsset, Array<TextResources>> textResources;
|
||||||
|
|
||||||
|
Gfx::RenderTargetAttachment colorAttachment;
|
||||||
Gfx::RenderTargetAttachment depthAttachment;
|
Gfx::RenderTargetAttachment depthAttachment;
|
||||||
Gfx::OTexture2D depthBuffer;
|
Gfx::OTexture2D depthBuffer;
|
||||||
|
|
||||||
Gfx::ODescriptorLayout descriptorLayout;
|
Gfx::ODescriptorLayout textDescriptorLayout;
|
||||||
Gfx::PDescriptorSet descriptorSet;
|
Gfx::PDescriptorSet textDescriptorSet;
|
||||||
|
|
||||||
Gfx::OUniformBuffer numTexturesBuffer;
|
Gfx::OVertexShader textVertexShader;
|
||||||
Gfx::OVertexBuffer elementBuffer;
|
Gfx::OFragmentShader textFragmentShader;
|
||||||
|
Gfx::OPipelineLayout textPipelineLayout;
|
||||||
|
Gfx::PGraphicsPipeline textPipeline;
|
||||||
|
|
||||||
Gfx::OVertexShader vertexShader;
|
Gfx::ODescriptorLayout uiDescriptorLayout;
|
||||||
Gfx::OFragmentShader fragmentShader;
|
Gfx::PDescriptorSet uiDescriptorSet;
|
||||||
Gfx::PGraphicsPipeline pipeline;
|
|
||||||
Gfx::OPipelineLayout pipelineLayout;
|
|
||||||
|
|
||||||
Array<UI::RenderElementStyle> renderElements;
|
Gfx::OVertexShader uiVertexShader;
|
||||||
|
Gfx::OFragmentShader uiFragmentShader;
|
||||||
|
Gfx::OPipelineLayout uiPipelineLayout;
|
||||||
|
Gfx::PGraphicsPipeline uiPipeline;
|
||||||
|
|
||||||
|
Array<TextRender> texts;
|
||||||
|
Array<GlyphInstanceData> glyphs;
|
||||||
|
Gfx::OShaderBuffer glyphInstanceBuffer;
|
||||||
|
Gfx::OSampler glyphSampler;
|
||||||
Array<Gfx::PTexture2D> usedTextures;
|
Array<Gfx::PTexture2D> usedTextures;
|
||||||
};
|
};
|
||||||
DEFINE_REF(UIPass);
|
DEFINE_REF(UIPass);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {}
|
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {}
|
||||||
|
|
||||||
VisibilityPass::~VisibilityPass() {}
|
VisibilityPass::~VisibilityPass() {}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
namespace Seele {
|
namespace Seele {
|
||||||
class VisibilityPass : public RenderPass {
|
class VisibilityPass : public RenderPass {
|
||||||
public:
|
public:
|
||||||
VisibilityPass(Gfx::PGraphics graphics, PScene scene);
|
VisibilityPass(Gfx::PGraphics graphics);
|
||||||
VisibilityPass(VisibilityPass&&) = default;
|
VisibilityPass(VisibilityPass&&) = default;
|
||||||
VisibilityPass& operator=(VisibilityPass&&) = default;
|
VisibilityPass& operator=(VisibilityPass&&) = default;
|
||||||
virtual ~VisibilityPass();
|
virtual ~VisibilityPass();
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ Graphics::~Graphics() {
|
|||||||
|
|
||||||
void Graphics::init(GraphicsInitializer initInfo) {
|
void Graphics::init(GraphicsInitializer initInfo) {
|
||||||
initInstance(initInfo);
|
initInstance(initInfo);
|
||||||
|
//setupDebugCallback();
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
createDevice(initInfo);
|
createDevice(initInfo);
|
||||||
VmaAllocatorCreateInfo createInfo = {
|
VmaAllocatorCreateInfo createInfo = {
|
||||||
@@ -437,6 +438,8 @@ Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLev
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::buildBottomLevelAccelerationStructures(Array<Gfx::PBottomLevelAS> data) {
|
void Graphics::buildBottomLevelAccelerationStructures(Array<Gfx::PBottomLevelAS> data) {
|
||||||
|
if (!supportRayTracing())
|
||||||
|
return;
|
||||||
Gfx::PShaderBuffer verticesBuffer = StaticMeshVertexData::getInstance()->getPositionBuffer();
|
Gfx::PShaderBuffer verticesBuffer = StaticMeshVertexData::getInstance()->getPositionBuffer();
|
||||||
Gfx::PIndexBuffer indexBuffer = StaticMeshVertexData::getInstance()->getIndexBuffer();
|
Gfx::PIndexBuffer indexBuffer = StaticMeshVertexData::getInstance()->getIndexBuffer();
|
||||||
|
|
||||||
@@ -790,14 +793,12 @@ void Graphics::pickPhysicalDevice() {
|
|||||||
};
|
};
|
||||||
meshShaderFeatures = {
|
meshShaderFeatures = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
|
||||||
.pNext = &accelerationFeatures,
|
|
||||||
.taskShader = true,
|
.taskShader = true,
|
||||||
.meshShader = true,
|
.meshShader = true,
|
||||||
.meshShaderQueries = true,
|
.meshShaderQueries = true,
|
||||||
};
|
};
|
||||||
features12 = {
|
features12 = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||||
.pNext = &meshShaderFeatures,
|
|
||||||
.storageBuffer8BitAccess = true,
|
.storageBuffer8BitAccess = true,
|
||||||
.uniformAndStorageBuffer8BitAccess = true,
|
.uniformAndStorageBuffer8BitAccess = true,
|
||||||
.shaderBufferInt64Atomics = true,
|
.shaderBufferInt64Atomics = true,
|
||||||
@@ -836,17 +837,36 @@ void Graphics::pickPhysicalDevice() {
|
|||||||
.inheritedQueries = true,
|
.inheritedQueries = true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (Gfx::useMeshShading) {
|
bool rayTracingPipelineSupport = false;
|
||||||
uint32 count = 0;
|
bool accelerationStructureSupport = false;
|
||||||
vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr);
|
uint32 count = 0;
|
||||||
Array<VkExtensionProperties> extensionProps(count);
|
vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr);
|
||||||
vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, extensionProps.data());
|
Array<VkExtensionProperties> extensionProps(count);
|
||||||
for (size_t i = 0; i < count; ++i) {
|
vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, extensionProps.data());
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
if (Gfx::useMeshShading) {
|
||||||
if (std::strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extensionProps[i].extensionName) == 0) {
|
if (std::strcmp(VK_EXT_MESH_SHADER_EXTENSION_NAME, extensionProps[i].extensionName) == 0) {
|
||||||
meshShadingEnabled = true;
|
meshShadingEnabled = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (std::strcmp(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME, extensionProps[i].extensionName) == 0) {
|
||||||
|
rayTracingPipelineSupport = true;
|
||||||
|
}
|
||||||
|
if (std::strcmp(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, extensionProps[i].extensionName) == 0) {
|
||||||
|
accelerationStructureSupport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rayTracingEnabled = rayTracingPipelineSupport && accelerationStructureSupport;
|
||||||
|
if (meshShadingEnabled) {
|
||||||
|
features12.pNext = &meshShaderFeatures;
|
||||||
|
}
|
||||||
|
if (rayTracingEnabled) {
|
||||||
|
if (meshShadingEnabled) {
|
||||||
|
meshShaderFeatures.pNext = &accelerationFeatures;
|
||||||
|
} else {
|
||||||
|
features12.pNext = &accelerationFeatures;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,12 +940,14 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
|
|||||||
if (supportMeshShading()) {
|
if (supportMeshShading()) {
|
||||||
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
|
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
if (supportRayTracing()) {
|
||||||
|
initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
|
||||||
|
initializer.deviceExtensions.add(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
|
||||||
|
initializer.deviceExtensions.add(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
||||||
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
initializer.deviceExtensions.add("VK_KHR_portability_subset");
|
initializer.deviceExtensions.add("VK_KHR_portability_subset");
|
||||||
#endif
|
#endif
|
||||||
initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
|
|
||||||
initializer.deviceExtensions.add(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
|
|
||||||
initializer.deviceExtensions.add(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
|
|
||||||
VkDeviceCreateInfo deviceInfo = {
|
VkDeviceCreateInfo deviceInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pNext = &features,
|
.pNext = &features,
|
||||||
@@ -963,15 +985,17 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
|
|||||||
cmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT");
|
cmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT");
|
||||||
cmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT");
|
cmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT");
|
||||||
|
|
||||||
createAccelerationStructure = (PFN_vkCreateAccelerationStructureKHR)vkGetDeviceProcAddr(handle, "vkCreateAccelerationStructureKHR");
|
if (rayTracingEnabled) {
|
||||||
cmdBuildAccelerationStructures =
|
createAccelerationStructure = (PFN_vkCreateAccelerationStructureKHR)vkGetDeviceProcAddr(handle, "vkCreateAccelerationStructureKHR");
|
||||||
(PFN_vkCmdBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(handle, "vkCmdBuildAccelerationStructuresKHR");
|
cmdBuildAccelerationStructures =
|
||||||
getAccelerationStructureBuildSize =
|
(PFN_vkCmdBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(handle, "vkCmdBuildAccelerationStructuresKHR");
|
||||||
(PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureBuildSizesKHR");
|
getAccelerationStructureBuildSize =
|
||||||
createRayTracingPipelines = (PFN_vkCreateRayTracingPipelinesKHR)vkGetDeviceProcAddr(handle, "vkCreateRayTracingPipelinesKHR");
|
(PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureBuildSizesKHR");
|
||||||
getRayTracingShaderGroupHandles =
|
createRayTracingPipelines = (PFN_vkCreateRayTracingPipelinesKHR)vkGetDeviceProcAddr(handle, "vkCreateRayTracingPipelinesKHR");
|
||||||
(PFN_vkGetRayTracingShaderGroupHandlesKHR)vkGetDeviceProcAddr(handle, "vkGetRayTracingShaderGroupHandlesKHR");
|
getRayTracingShaderGroupHandles =
|
||||||
cmdTraceRays = (PFN_vkCmdTraceRaysKHR)vkGetDeviceProcAddr(handle, "vkCmdTraceRaysKHR");
|
(PFN_vkGetRayTracingShaderGroupHandlesKHR)vkGetDeviceProcAddr(handle, "vkGetRayTracingShaderGroupHandlesKHR");
|
||||||
getAccelerationStructureDeviceAddress =
|
cmdTraceRays = (PFN_vkCmdTraceRaysKHR)vkGetDeviceProcAddr(handle, "vkCmdTraceRaysKHR");
|
||||||
(PFN_vkGetAccelerationStructureDeviceAddressKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureDeviceAddressKHR");
|
getAccelerationStructureDeviceAddress =
|
||||||
|
(PFN_vkGetAccelerationStructureDeviceAddressKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureDeviceAddressKHR");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,10 +57,9 @@ void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
|
|||||||
|
|
||||||
Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
||||||
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
||||||
float xscale, yscale;
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
||||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &xscale, &yscale);
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
GLFWwindow* handle = glfwCreateWindow(createInfo.width / xscale, createInfo.height / yscale, createInfo.title, nullptr, nullptr);
|
GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr);
|
||||||
windowHandle = handle;
|
windowHandle = handle;
|
||||||
glfwSetWindowUserPointer(handle, this);
|
glfwSetWindowUserPointer(handle, this);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,6 @@ Matrix4 Viewport::getProjectionMatrix() const {
|
|||||||
//);
|
//);
|
||||||
return glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), 0.1f, 1000.0f);
|
return glm::perspective(fieldOfView, sizeX / static_cast<float>(sizeY), 0.1f, 1000.0f);
|
||||||
} else {
|
} else {
|
||||||
return glm::ortho(0.0f, (float)sizeX, (float)sizeY, 0.0f);
|
return glm::ortho(0.0f, (float)sizeX, 0.0f, (float)sizeY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,12 +24,16 @@ class Window {
|
|||||||
constexpr SeFormat getSwapchainFormat() const { return framebufferFormat; }
|
constexpr SeFormat getSwapchainFormat() const { return framebufferFormat; }
|
||||||
constexpr uint32 getFramebufferWidth() const { return framebufferWidth; }
|
constexpr uint32 getFramebufferWidth() const { return framebufferWidth; }
|
||||||
constexpr uint32 getFramebufferHeight() const { return framebufferHeight; }
|
constexpr uint32 getFramebufferHeight() const { return framebufferHeight; }
|
||||||
|
constexpr float getContentScaleX() const { return contentScaleX; }
|
||||||
|
constexpr float getContentScaleY() const { return contentScaleY; }
|
||||||
constexpr bool isPaused() const { return paused; }
|
constexpr bool isPaused() const { return paused; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SeFormat framebufferFormat;
|
SeFormat framebufferFormat;
|
||||||
uint32 framebufferWidth;
|
uint32 framebufferWidth;
|
||||||
uint32 framebufferHeight;
|
uint32 framebufferHeight;
|
||||||
|
float contentScaleX;
|
||||||
|
float contentScaleY;
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Window)
|
DEFINE_REF(Window)
|
||||||
@@ -45,6 +49,8 @@ class Viewport {
|
|||||||
constexpr uint32 getHeight() const { return sizeY; }
|
constexpr uint32 getHeight() const { return sizeY; }
|
||||||
constexpr uint32 getOffsetX() const { return offsetX; }
|
constexpr uint32 getOffsetX() const { return offsetX; }
|
||||||
constexpr uint32 getOffsetY() const { return offsetY; }
|
constexpr uint32 getOffsetY() const { return offsetY; }
|
||||||
|
constexpr float getContentScaleX() const { return owner->getContentScaleX(); }
|
||||||
|
constexpr float getContentScaleY() const { return owner->getContentScaleY(); }
|
||||||
constexpr Gfx::SeSampleCountFlags getSamples() const { return samples; }
|
constexpr Gfx::SeSampleCountFlags getSamples() const { return samples; }
|
||||||
Matrix4 getProjectionMatrix() const;
|
Matrix4 getProjectionMatrix() const;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,14 @@ template <std::integral T> static void save(ArchiveBuffer& buffer, const T& type
|
|||||||
template <std::integral T> static void load(ArchiveBuffer& buffer, T& type) { buffer.readBytes(&type, sizeof(type)); }
|
template <std::integral T> static void load(ArchiveBuffer& buffer, T& type) { buffer.readBytes(&type, sizeof(type)); }
|
||||||
template <std::floating_point T> static void save(ArchiveBuffer& buffer, const T& type) { buffer.writeBytes(&type, sizeof(type)); }
|
template <std::floating_point T> static void save(ArchiveBuffer& buffer, const T& type) { buffer.writeBytes(&type, sizeof(type)); }
|
||||||
template <std::floating_point T> static void load(ArchiveBuffer& buffer, T& type) { buffer.readBytes(&type, sizeof(type)); }
|
template <std::floating_point T> static void load(ArchiveBuffer& buffer, T& type) { buffer.readBytes(&type, sizeof(type)); }
|
||||||
|
static void save(ArchiveBuffer& buffer, const UVector2& vec) {
|
||||||
|
save(buffer, vec.x);
|
||||||
|
save(buffer, vec.y);
|
||||||
|
}
|
||||||
|
static void load(ArchiveBuffer& buffer, UVector2& vec) {
|
||||||
|
load(buffer, vec.x);
|
||||||
|
load(buffer, vec.y);
|
||||||
|
}
|
||||||
static void save(ArchiveBuffer& buffer, const IVector2& vec) {
|
static void save(ArchiveBuffer& buffer, const IVector2& vec) {
|
||||||
save(buffer, vec.x);
|
save(buffer, vec.x);
|
||||||
save(buffer, vec.y);
|
save(buffer, vec.y);
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
struct Attributes {
|
||||||
|
std::function<void()> onClick;
|
||||||
|
};
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -1,24 +1,17 @@
|
|||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PRIVATE
|
PRIVATE
|
||||||
HorizontalLayout.h
|
Attributes.h
|
||||||
HorizontalLayout.cpp
|
Element.h
|
||||||
Layout.h
|
Element.cpp
|
||||||
Layout.cpp
|
|
||||||
RenderHierarchy.h
|
)
|
||||||
RenderHierarchy.cpp
|
|
||||||
System.h
|
|
||||||
System.cpp
|
|
||||||
VerticalLayout.h
|
|
||||||
VerticalLayout.cpp)
|
|
||||||
|
|
||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
FILES
|
FILES
|
||||||
HorizontalLayout.h
|
Attributes.h
|
||||||
Layout.h
|
Element.h
|
||||||
RenderHierarchy.h
|
)
|
||||||
System.h
|
|
||||||
VerticalLayout.h)
|
|
||||||
|
|
||||||
|
add_subdirectory(Style/)
|
||||||
add_subdirectory(Elements/)
|
add_subdirectory(Element/)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include "Element.h"
|
||||||
|
#include "System.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
using namespace Seele::UI;
|
||||||
|
|
||||||
|
Array<RenderElement> Element::render() {
|
||||||
|
RenderElement result;
|
||||||
|
result.position = UVector2(0, 0);
|
||||||
|
result.size = UVector2(style.width, style.height);
|
||||||
|
result.backgroundColor = style.backgroundColor;
|
||||||
|
result.fontSize = style.fontSize;
|
||||||
|
result.fontFamily = style.fontFamily;
|
||||||
|
return {result};
|
||||||
|
}
|
||||||
|
|
||||||
|
Element::Element(Attributes attr, Array<OElement> children) : attr(attr), children(std::move(children)) {}
|
||||||
|
|
||||||
|
Element::~Element() {}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Attributes.h"
|
||||||
|
#include "Containers/Array.h"
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Style/Style.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
struct RenderElement;
|
||||||
|
DECLARE_REF(Element)
|
||||||
|
class Element {
|
||||||
|
public:
|
||||||
|
Element(Attributes attr, Array<OElement> children);
|
||||||
|
virtual ~Element();
|
||||||
|
virtual void calcStyle(Style parentStyle) = 0;
|
||||||
|
Array<RenderElement> render();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Style style;
|
||||||
|
Attributes attr;
|
||||||
|
Array<OElement> children;
|
||||||
|
};
|
||||||
|
DEFINE_REF(Element)
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
target_sources(Engine
|
||||||
|
PRIVATE
|
||||||
|
Div.h
|
||||||
|
Text.h)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "UI/Element.h"
|
||||||
|
#include "UI/Style/Class.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
template<StyleClass... classes>
|
||||||
|
class Div : public Element {
|
||||||
|
public:
|
||||||
|
Div(Attributes attr, std::initializer_list<OElement> children) : Element(attr, children) { style.displayType = DisplayType::Block; }
|
||||||
|
virtual ~Div() {}
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "UI/Element.h"
|
||||||
|
#include "UI/Style/Class.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
class Text : public Element {
|
||||||
|
public:
|
||||||
|
Text(std::string text) : Element({}, {}), text(text) {}
|
||||||
|
virtual void calcStyle(Style parentStyle) override { style = parentStyle; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string text;
|
||||||
|
};
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#include "Button.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Element.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
class Button : public Element {};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
target_sources(Engine
|
|
||||||
PRIVATE
|
|
||||||
Button.h
|
|
||||||
Button.cpp
|
|
||||||
Element.h
|
|
||||||
Element.cpp
|
|
||||||
Label.h
|
|
||||||
Label.cpp
|
|
||||||
Panel.h
|
|
||||||
Panel.cpp)
|
|
||||||
|
|
||||||
target_sources(Engine
|
|
||||||
PUBLIC FILE_SET HEADERS
|
|
||||||
FILES
|
|
||||||
Button.h
|
|
||||||
Element.h
|
|
||||||
Label.h
|
|
||||||
Panel.h)
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#include "Element.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
|
||||||
#include "UI/System.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
Element::Element() : dirty(false), enabled(false) {}
|
|
||||||
|
|
||||||
Element::~Element() {}
|
|
||||||
|
|
||||||
void Element::setParent(PElement element) {
|
|
||||||
if (parent != nullptr) {
|
|
||||||
parent->removeChild(this);
|
|
||||||
}
|
|
||||||
parent = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
PElement Element::getParent() const { return parent; }
|
|
||||||
|
|
||||||
void Element::addChild(PElement element) { children.add(element); }
|
|
||||||
|
|
||||||
void Element::removeChild(PElement element) { children.remove(element, false); }
|
|
||||||
|
|
||||||
const Array<PElement> Element::getChildren() { return children; }
|
|
||||||
|
|
||||||
void Element::clear() { children.clear(); }
|
|
||||||
|
|
||||||
void Element::setEnabled(bool newEnabled) { enabled = newEnabled; }
|
|
||||||
|
|
||||||
bool Element::isEnabled() const { return enabled; }
|
|
||||||
|
|
||||||
Rect& Element::getBoundingBox() { return boundingBox; }
|
|
||||||
|
|
||||||
const Rect Element::getBoundingBox() const { return boundingBox; }
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Containers/Array.h"
|
|
||||||
#include "Math/Math.h"
|
|
||||||
#include "MinimalEngine.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
// Element defines any part of the UI
|
|
||||||
DECLARE_REF(Element)
|
|
||||||
DECLARE_REF(System)
|
|
||||||
class Element {
|
|
||||||
public:
|
|
||||||
Element();
|
|
||||||
virtual ~Element();
|
|
||||||
void setParent(PElement element);
|
|
||||||
PElement getParent() const;
|
|
||||||
void addChild(PElement element);
|
|
||||||
void removeChild(PElement element);
|
|
||||||
const Array<PElement> getChildren();
|
|
||||||
void clear();
|
|
||||||
void setEnabled(bool newEnabled);
|
|
||||||
bool isEnabled() const;
|
|
||||||
// maybe not the healthiest inteface
|
|
||||||
// non-const version
|
|
||||||
Rect& getBoundingBox();
|
|
||||||
// The bounding box describes the relative size of any Element
|
|
||||||
// relative to the total view, meaning a bounding box of (0,0), (1,1)
|
|
||||||
// would take up the entire view
|
|
||||||
const Rect getBoundingBox() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Rect boundingBox;
|
|
||||||
bool dirty;
|
|
||||||
|
|
||||||
bool enabled;
|
|
||||||
PSystem system;
|
|
||||||
PElement parent;
|
|
||||||
Array<PElement> children;
|
|
||||||
friend class RenderElement;
|
|
||||||
};
|
|
||||||
DEFINE_REF(Element)
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Element.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
class Label : public Element {
|
|
||||||
public:
|
|
||||||
Label();
|
|
||||||
~Label();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string text;
|
|
||||||
};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include "Panel.h"
|
|
||||||
#include "UI/Layout.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
Panel::Panel() {}
|
|
||||||
|
|
||||||
Panel::~Panel() {}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Element.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
DECLARE_REF(Layout)
|
|
||||||
class Panel : Element {
|
|
||||||
public:
|
|
||||||
Panel();
|
|
||||||
virtual ~Panel();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PLayout activeLayout;
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFINE_REF(Panel);
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#include "HorizontalLayout.h"
|
|
||||||
#include "Elements/Element.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
HorizontalLayout::HorizontalLayout(PElement element) : Layout(element) {}
|
|
||||||
|
|
||||||
HorizontalLayout::~HorizontalLayout() {}
|
|
||||||
|
|
||||||
void HorizontalLayout::apply() {
|
|
||||||
Array<PElement> children = element->getChildren();
|
|
||||||
const Rect parent = element->getBoundingBox();
|
|
||||||
float xOffset = parent.offset.x;
|
|
||||||
float yOffset = parent.offset.y;
|
|
||||||
float xSize = parent.size.x / children.size();
|
|
||||||
float ySize = parent.size.y;
|
|
||||||
for (uint32 index = 0; index < children.size(); ++index) {
|
|
||||||
Rect& child = children[index]->getBoundingBox();
|
|
||||||
child.offset.x = xOffset + (index * xSize);
|
|
||||||
child.offset.y = yOffset;
|
|
||||||
child.size.x = xSize;
|
|
||||||
child.size.y = ySize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Layout.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
class HorizontalLayout : Layout {
|
|
||||||
public:
|
|
||||||
HorizontalLayout(PElement element);
|
|
||||||
~HorizontalLayout();
|
|
||||||
virtual void apply() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include "Layout.h"
|
|
||||||
#include "Elements/Element.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
Layout::Layout(PElement element) : element(element) {}
|
|
||||||
|
|
||||||
Layout::~Layout() {}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "MinimalEngine.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
DECLARE_REF(Element);
|
|
||||||
class Layout {
|
|
||||||
public:
|
|
||||||
Layout(PElement element);
|
|
||||||
virtual ~Layout();
|
|
||||||
virtual void apply() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PElement element;
|
|
||||||
};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#include "RenderHierarchy.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
void AddElementRenderHierarchyUpdate::apply(Array<RenderElement>& elements) {
|
|
||||||
auto parentIt = elements.find([this](RenderElement e) { return e.parent == parent; });
|
|
||||||
parentIt->referencedElement->addChild(addedElement);
|
|
||||||
addedElement->setParent(parentIt->referencedElement);
|
|
||||||
|
|
||||||
elements.emplace(parentIt->referencedElement, addedElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveElementRenderHierarchyUpdate::apply(Array<RenderElement>& elements) {
|
|
||||||
auto elementIt = elements.find([this](RenderElement e) { return e.referencedElement == element; });
|
|
||||||
if (!removeChildren) {
|
|
||||||
for (auto child : elementIt->referencedElement->getChildren()) {
|
|
||||||
child->setParent(elementIt->referencedElement->getParent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elementIt->referencedElement->setParent(nullptr);
|
|
||||||
|
|
||||||
elements.remove(elementIt);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderHierarchy::RenderHierarchy() {}
|
|
||||||
|
|
||||||
RenderHierarchy::~RenderHierarchy() {}
|
|
||||||
|
|
||||||
void RenderHierarchy::addElement(PElement addedElement) {
|
|
||||||
std::scoped_lock lock(updateLock);
|
|
||||||
updates.add(new AddElementRenderHierarchyUpdate{addedElement.getHandle(), addedElement->getParent().getHandle()});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderHierarchy::removeElement(PElement elementToRemove) {
|
|
||||||
std::scoped_lock lock(updateLock);
|
|
||||||
updates.add(new RemoveElementRenderHierarchyUpdate{
|
|
||||||
elementToRemove.getHandle(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderHierarchy::moveElement(PElement elementToMove, PElement newParent) {
|
|
||||||
std::scoped_lock lock(updateLock);
|
|
||||||
updates.add(new AddElementRenderHierarchyUpdate{elementToMove.getHandle(), newParent.getHandle()});
|
|
||||||
updates.add(new RemoveElementRenderHierarchyUpdate{elementToMove.getHandle()});
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderHierarchy::updateHierarchy() {
|
|
||||||
List<RenderHierarchyUpdate*> localUpdates;
|
|
||||||
{ // make a local copy of the updates so we dont hold the lock for too long
|
|
||||||
std::scoped_lock lock(updateLock);
|
|
||||||
localUpdates = updates;
|
|
||||||
updates.clear();
|
|
||||||
}
|
|
||||||
for (auto update : localUpdates) {
|
|
||||||
update->apply(drawElements);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Containers/List.h"
|
|
||||||
#include "Elements/Element.h"
|
|
||||||
#include "Graphics/Resources.h"
|
|
||||||
#include "Graphics/Texture.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
struct RenderElementStyle {
|
|
||||||
Vector position = Vector(0, 0, 0);
|
|
||||||
uint32 backgroundImageIndex = UINT32_MAX;
|
|
||||||
Vector backgroundColor = Vector(1, 1, 1);
|
|
||||||
float opacity = 1.0f;
|
|
||||||
// Vector4 borderBottomColor = Vector4(1, 1, 1, 1);
|
|
||||||
// Vector4 borderLeftColor = Vector4(1, 1, 1, 1);
|
|
||||||
// Vector4 borderRightColor = Vector4(1, 1, 1, 1);
|
|
||||||
// Vector4 borderTopColor = Vector4(1, 1, 1, 1);
|
|
||||||
// float borderBottomLeftRadius = 0;
|
|
||||||
// float borderBottomRightRadius = 0;
|
|
||||||
// float borderTopLeftRadius = 0;
|
|
||||||
// float borderTopRightRadius = 0;
|
|
||||||
Vector2 dimensions = Vector2(1, 1);
|
|
||||||
};
|
|
||||||
class RenderElement {
|
|
||||||
public:
|
|
||||||
RenderElement() = default;
|
|
||||||
RenderElement(Element* parent, Element* referencedElement) : parent(parent), referencedElement(referencedElement) {}
|
|
||||||
~RenderElement() = default;
|
|
||||||
Element* parent;
|
|
||||||
Element* referencedElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RenderHierarchyUpdate {
|
|
||||||
virtual void apply(Array<RenderElement>& elements) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AddElementRenderHierarchyUpdate : public RenderHierarchyUpdate {
|
|
||||||
Element* addedElement;
|
|
||||||
Element* parent;
|
|
||||||
AddElementRenderHierarchyUpdate(Element* addedElement, Element* parent) : addedElement(addedElement), parent(parent) {}
|
|
||||||
virtual void apply(Array<RenderElement>& elements) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RemoveElementRenderHierarchyUpdate : public RenderHierarchyUpdate {
|
|
||||||
Element* element;
|
|
||||||
bool removeChildren;
|
|
||||||
RemoveElementRenderHierarchyUpdate(Element* elementToRemove, bool removeChildren = false)
|
|
||||||
: element(elementToRemove), removeChildren(removeChildren) {}
|
|
||||||
virtual void apply(Array<RenderElement>& elements) override;
|
|
||||||
};
|
|
||||||
class RenderHierarchy {
|
|
||||||
public:
|
|
||||||
RenderHierarchy();
|
|
||||||
~RenderHierarchy();
|
|
||||||
// logic thread interface, queue hierarchy changes
|
|
||||||
void addElement(PElement addedElement);
|
|
||||||
void removeElement(PElement elementToRemove);
|
|
||||||
void moveElement(PElement elementToMove, PElement newParent);
|
|
||||||
|
|
||||||
// render thread interface, apply changes
|
|
||||||
void updateHierarchy();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static_assert(std::is_trivially_copyable_v<RenderElement>);
|
|
||||||
// List of all drawable elements in draw order
|
|
||||||
Array<RenderElement> drawElements;
|
|
||||||
// Shader data used for styling elements
|
|
||||||
Array<RenderElementStyle> elementStyles;
|
|
||||||
Array<Gfx::PTexture> usedTextures;
|
|
||||||
|
|
||||||
List<RenderHierarchyUpdate*> updates;
|
|
||||||
std::mutex updateLock;
|
|
||||||
};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
target_sources(Engine
|
||||||
|
PRIVATE
|
||||||
|
Class.h
|
||||||
|
Style.h)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Style.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
template <typename C>
|
||||||
|
concept StyleClass = requires(C c, Style& s) { c.apply(s); };
|
||||||
|
|
||||||
|
template <uint32 w, DimensionType widthType> struct WidthClass {
|
||||||
|
static void apply(Style& s) {
|
||||||
|
s.width = w;
|
||||||
|
s.widthType = widthType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using W_Full = WidthClass<100, DimensionType::Percent>;
|
||||||
|
using W_1 = WidthClass<2, DimensionType::Pixel>;
|
||||||
|
|
||||||
|
template <DisplayType displayType> struct DisplayClass {
|
||||||
|
static void apply(Style& s) { s.displayType = displayType; }
|
||||||
|
};
|
||||||
|
using Hidden = DisplayClass<DisplayType::Hidden>;
|
||||||
|
using Block = DisplayClass<DisplayType::Block>;
|
||||||
|
using Flex = DisplayClass<DisplayType::Flex>;
|
||||||
|
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Math/Vector.h"
|
||||||
|
#include "Asset/FontAsset.h"
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace UI {
|
||||||
|
enum class DimensionType {
|
||||||
|
Pixel,
|
||||||
|
Percent, // EM, PEM, etc...
|
||||||
|
};
|
||||||
|
enum class PositionType {
|
||||||
|
Relative,
|
||||||
|
Static,
|
||||||
|
Absolute,
|
||||||
|
Sticky,
|
||||||
|
};
|
||||||
|
enum class DisplayType {
|
||||||
|
Inline,
|
||||||
|
Hidden,
|
||||||
|
Block,
|
||||||
|
Flex,
|
||||||
|
Grid,
|
||||||
|
};
|
||||||
|
struct Style {
|
||||||
|
DimensionType widthType = DimensionType::Pixel;
|
||||||
|
uint32 width = 0;
|
||||||
|
DimensionType heightType = DimensionType::Pixel;
|
||||||
|
uint32 height = 0;
|
||||||
|
uint32 z = 0;
|
||||||
|
Vector backgroundColor = Vector(1, 1, 1);
|
||||||
|
DisplayType displayType = DisplayType::Inline;
|
||||||
|
PositionType position = PositionType::Relative;
|
||||||
|
PFontAsset fontFamily;
|
||||||
|
uint32 lineHeight = 12;
|
||||||
|
uint32 fontSize = 12;
|
||||||
|
uint32 fontWeight = 0;
|
||||||
|
uint32 paddingTop = 0;
|
||||||
|
uint32 paddingBottom = 0;
|
||||||
|
uint32 paddingLeft = 0;
|
||||||
|
uint32 paddingRight = 0;
|
||||||
|
uint32 marginTop = 0;
|
||||||
|
uint32 marginBottom = 0;
|
||||||
|
uint32 marginLeft = 0;
|
||||||
|
uint32 marginRight = 0;
|
||||||
|
uint32 gap = 0;
|
||||||
|
};
|
||||||
|
} // namespace UI
|
||||||
|
} // namespace Seele
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#include "System.h"
|
|
||||||
#include "Asset/AssetRegistry.h"
|
|
||||||
#include "Asset/TextureAsset.h"
|
|
||||||
#include "Elements/Panel.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
System::System() {}
|
|
||||||
|
|
||||||
System::~System() {}
|
|
||||||
|
|
||||||
void System::update() {}
|
|
||||||
|
|
||||||
void System::updateViewport(Gfx::PViewport) {
|
|
||||||
// TODO set viewport FoV to 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Component::Camera System::getVirtualCamera() const { return virtualCamera; }
|
|
||||||
+21
-15
@@ -1,26 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/RenderPass/TextPass.h"
|
#include "Element.h"
|
||||||
#include "Graphics/RenderPass/UIPass.h"
|
|
||||||
#include "MinimalEngine.h"
|
|
||||||
#include "RenderHierarchy.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
namespace UI {
|
namespace UI {
|
||||||
DECLARE_REF(Panel)
|
struct RenderElement {
|
||||||
|
// position relative to target viewport in pixels
|
||||||
|
UVector2 position;
|
||||||
|
// size relative to target viewport in pixels
|
||||||
|
UVector2 size;
|
||||||
|
// background color of area
|
||||||
|
Vector backgroundColor;
|
||||||
|
// text to render
|
||||||
|
std::string text;
|
||||||
|
// font size in pixels
|
||||||
|
uint32 fontSize;
|
||||||
|
// font family
|
||||||
|
PFontAsset fontFamily;
|
||||||
|
};
|
||||||
class System {
|
class System {
|
||||||
public:
|
public:
|
||||||
System();
|
System(OElement rootElement) : rootElement(std::move(rootElement)) {}
|
||||||
virtual ~System();
|
~System();
|
||||||
void update();
|
Array<RenderElement> render(UVector2 viewport) {
|
||||||
void updateViewport(Gfx::PViewport viewport);
|
}
|
||||||
Component::Camera getVirtualCamera() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Component::Camera virtualCamera;
|
OElement rootElement;
|
||||||
PPanel rootPanel;
|
|
||||||
RenderHierarchy hierarchy;
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(System)
|
DEFINE_REF(System)
|
||||||
} // namespace UI
|
} // namespace UI
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#include "VerticalLayout.h"
|
|
||||||
#include "Elements/Element.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
using namespace Seele::UI;
|
|
||||||
|
|
||||||
VerticalLayout::VerticalLayout(PElement element) : Layout(element) {}
|
|
||||||
|
|
||||||
VerticalLayout::~VerticalLayout() {}
|
|
||||||
|
|
||||||
void VerticalLayout::apply() {
|
|
||||||
Array<PElement> children = element->getChildren();
|
|
||||||
const Rect parent = element->getBoundingBox();
|
|
||||||
float xOffset = parent.offset.x;
|
|
||||||
float yOffset = parent.offset.y;
|
|
||||||
float xSize = parent.size.x;
|
|
||||||
float ySize = parent.size.y / children.size();
|
|
||||||
for (uint32 index = 0; index < children.size(); ++index) {
|
|
||||||
Rect& child = children[index]->getBoundingBox();
|
|
||||||
child.offset.x = xOffset;
|
|
||||||
child.offset.y = yOffset + (index * ySize);
|
|
||||||
child.size.x = xSize;
|
|
||||||
child.size.y = ySize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Layout.h"
|
|
||||||
|
|
||||||
namespace Seele {
|
|
||||||
namespace UI {
|
|
||||||
class VerticalLayout : Layout {
|
|
||||||
public:
|
|
||||||
VerticalLayout(PElement element);
|
|
||||||
~VerticalLayout();
|
|
||||||
virtual void apply() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
} // namespace UI
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -25,15 +25,17 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
|||||||
reloadGame();
|
reloadGame();
|
||||||
renderGraph.addPass(new CachedDepthPass(graphics, scene));
|
renderGraph.addPass(new CachedDepthPass(graphics, scene));
|
||||||
renderGraph.addPass(new DepthCullingPass(graphics, scene));
|
renderGraph.addPass(new DepthCullingPass(graphics, scene));
|
||||||
renderGraph.addPass(new VisibilityPass(graphics, scene));
|
renderGraph.addPass(new VisibilityPass(graphics));
|
||||||
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||||
renderGraph.addPass(new BasePass(graphics, scene));
|
renderGraph.addPass(new BasePass(graphics, scene));
|
||||||
renderGraph.setViewport(viewport);
|
renderGraph.setViewport(viewport);
|
||||||
renderGraph.createRenderPass();
|
renderGraph.createRenderPass();
|
||||||
|
if (graphics->supportRayTracing()) {
|
||||||
rayTracingGraph.addPass(new RayTracingPass(graphics, scene));
|
rayTracingGraph.addPass(new RayTracingPass(graphics, scene));
|
||||||
rayTracingGraph.setViewport(viewport);
|
rayTracingGraph.setViewport(viewport);
|
||||||
rayTracingGraph.createRenderPass();
|
rayTracingGraph.createRenderPass();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GameView::~GameView() {}
|
GameView::~GameView() {}
|
||||||
@@ -67,7 +69,7 @@ void GameView::render() {
|
|||||||
if (c.mainCamera)
|
if (c.mainCamera)
|
||||||
cam = c;
|
cam = c;
|
||||||
});
|
});
|
||||||
if (getGlobals().useRayTracing) {
|
if (getGlobals().useRayTracing && graphics->supportRayTracing()) {
|
||||||
rayTracingGraph.render(cam);
|
rayTracingGraph.render(cam);
|
||||||
} else {
|
} else {
|
||||||
renderGraph.render(cam);
|
renderGraph.render(cam);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "Label.h"
|
#include "UI/Style/Class.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::UI;
|
using namespace Seele::UI;
|
||||||
Reference in New Issue
Block a user