new UI system
This commit is contained in:
parent
d840a81448
commit
216972e73a
82 changed files with 4837 additions and 3243 deletions
|
|
@ -1,32 +0,0 @@
|
|||
# HelloWindow Example
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates how to draw pixels to a window.
|
||||
|
||||
## Expected Result
|
||||
|
||||
A window with a green and blue colored square, when clicking on the square it logs the coordinates relative to the square.
|
||||
|
||||
## Highlighted Code Snippet
|
||||
|
||||
```cpp
|
||||
UiElement& element = window.elements.emplace_back(
|
||||
0.5,
|
||||
0.5,
|
||||
2,
|
||||
1,
|
||||
0.5f,
|
||||
0.5f,
|
||||
0.5,
|
||||
0.5,
|
||||
0,
|
||||
false
|
||||
);
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import Crafter.Event;
|
||||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
WindowWayland window(1280, 720, "Hello Input!");
|
||||
|
||||
RenderingElementScaling element(
|
||||
OpaqueType::FullyOpaque, //opaque, wether the element is opague or semi-transparant
|
||||
2, //bufferWidth: the width of this elements pixel buffer
|
||||
1, //bufferHeight: the height of this elements pixel buffer
|
||||
FractionalToMapped(0.5), //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
FractionalToMapped(0.5), //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
FractionalToMapped(0.5), //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
FractionalToMapped(0.5), //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
FractionalToMapped(0.5), //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
FractionalToMapped(0.5), //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0 //z: this elements Z position
|
||||
);
|
||||
|
||||
window.elements.push_back(&element);
|
||||
element.buffer = {{255, 0, 0 ,255}, {0, 255, 0 ,255}};
|
||||
element.UpdatePosition(window);
|
||||
|
||||
Animation<std::tuple<std::int_fast32_t>> anim({
|
||||
{std::chrono::seconds(5), FractionalToMapped(-0.5), FractionalToMapped(1.5)},
|
||||
});
|
||||
|
||||
anim.Start(std::chrono::high_resolution_clock::now());
|
||||
|
||||
EventListener<FrameTime> updateListener(&window.onUpdate, [&](FrameTime time){
|
||||
std::tuple<std::int_fast32_t> value = anim.Play(time.now);
|
||||
element.anchorX = std::get<0>(value);
|
||||
element.UpdatePosition(window);
|
||||
if(anim.currentFrame == anim.keyframes.size()) {
|
||||
anim.Start(time.now);
|
||||
}
|
||||
window.LogTiming();
|
||||
});
|
||||
|
||||
window.StartUpdate();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-timing"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# HelloWindow Example
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates how to draw pixels to a window.
|
||||
|
||||
## Expected Result
|
||||
|
||||
A window with a red colored square.
|
||||
|
||||
## Highlighted Code Snippet
|
||||
|
||||
```cpp
|
||||
for(std::uint_fast32_t x = 0; x < 1280; x++) {
|
||||
for(std::uint_fast32_t y = 0; y < 720; y++) {
|
||||
window.framebuffer[x*720+y].r = 255;
|
||||
window.framebuffer[x*720+y].g = 0;
|
||||
window.framebuffer[x*720+y].b = 0;
|
||||
window.framebuffer[x*720+y].a = 255;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
constexpr std::uint32_t width = 1280;
|
||||
constexpr std::uint32_t height = 720;
|
||||
|
||||
int main() {
|
||||
Device::Initialize();
|
||||
Window window(width, height, "Hello Drawing!");
|
||||
|
||||
for(std::uint32_t x = 0; x < width; x++) {
|
||||
for(std::uint32_t y = 0; y < height; y++) {
|
||||
window.renderer.buffer[x*height+y].r = 255;
|
||||
window.renderer.buffer[x*height+y].g = 0;
|
||||
window.renderer.buffer[x*height+y].b = 0;
|
||||
window.renderer.buffer[x*height+y].a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-debug"
|
||||
}
|
||||
],
|
||||
"debug": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# HelloGrid Example
|
||||
|
||||
This example demonstrates the usage of the GridElement class which arranges its children in configurable grid patterns.
|
||||
|
||||
## Features Shown
|
||||
|
||||
- Creating a GridElement with specified columns and rows
|
||||
- Setting spacing between grid cells
|
||||
- Adding multiple child elements to the grid
|
||||
- Automatic positioning of children in a grid layout
|
||||
- Different colored elements to visualize the grid structure
|
||||
|
||||
## How It Works
|
||||
|
||||
The GridElement automatically distributes its children across a grid defined by:
|
||||
- Number of columns and rows
|
||||
- Horizontal and vertical spacing between elements
|
||||
|
||||
Each child element is positioned in row-major order, filling the grid from left to right and top to bottom.
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
import Crafter.Event;
|
||||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
WindowWayland window(1280, 720, "Hello Grid!");
|
||||
|
||||
// Create a GridElement with 3 columns and 2 rows
|
||||
GridElement grid(
|
||||
3, // columns
|
||||
2, // rows
|
||||
FractionalToMapped(0.1), // spacingX
|
||||
FractionalToMapped(0.1), // spacingY
|
||||
FractionalToMapped(0), // anchorX
|
||||
FractionalToMapped(0), // anchorY
|
||||
FractionalToMapped(1), // relativeWidth
|
||||
FractionalToMapped(1), // relativeHeight
|
||||
FractionalToMapped(0), // anchorOffsetX
|
||||
FractionalToMapped(0), // anchorOffsetY
|
||||
0 // z
|
||||
);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
RenderingElementScaling* rendering = new RenderingElementScaling(
|
||||
OpaqueType::FullyOpaque,
|
||||
1,
|
||||
1,
|
||||
FractionalToMapped(0), // anchorX
|
||||
FractionalToMapped(0), // anchorY
|
||||
FractionalToMapped(1.0), // relativeSizeX (will be overridden by grid)
|
||||
FractionalToMapped(1.0), // relativeSizeY (will be overridden by grid)
|
||||
FractionalToMapped(0.0), // anchorOffsetX
|
||||
FractionalToMapped(0.0), // anchorOffsetY
|
||||
0 // z
|
||||
);
|
||||
|
||||
// // Set different colors for each element
|
||||
switch (i % 6) {
|
||||
case 0: rendering->buffer = {{255, 0, 0, 255}}; break; // Red
|
||||
case 1: rendering->buffer = {{0, 255, 0, 255}}; break; // Green
|
||||
case 2: rendering->buffer = {{0, 0, 255, 255}}; break; // Blue
|
||||
case 3: rendering->buffer = {{255, 255, 0, 255}}; break; // Yellow
|
||||
case 4: rendering->buffer = {{255, 0, 255, 255}}; break; // Magenta
|
||||
case 5: rendering->buffer = {{0, 255, 255, 255}}; break; // Cyan
|
||||
}
|
||||
|
||||
grid.children.push_back(rendering);
|
||||
}
|
||||
|
||||
// Add the grid to the window
|
||||
window.elements.push_back(&grid);
|
||||
|
||||
// Update positions to arrange children in grid
|
||||
grid.UpdatePosition(window);
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# HelloInput Example
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates how to handle basic input events by:
|
||||
|
||||
- Create a window using `WindowWaylandWayland`
|
||||
- Register event listeners using `EventListener<T>` for:
|
||||
- Mouse click events
|
||||
- Specific key events
|
||||
- General keypress events
|
||||
- Print formatted feedback to the console when events are triggered
|
||||
|
||||
## Expected Result
|
||||
|
||||
When you interact with the window, you might see console output like:
|
||||
|
||||
Clicked on X:450 Y:320!
|
||||
Pressed specifically the a key!
|
||||
Pressed the b key!
|
||||
|
||||
Make sure that the window has focus.
|
||||
|
||||
## Highlighted Code Snippet
|
||||
|
||||
```cpp
|
||||
EventListener<MousePoint> clickListener(&window.onMouseLeftClick, [&window](MousePoint point){
|
||||
std::cout << std::format("Clicked on X:{} Y:{}!", MappedToPixel(point.x, window.width), MappedToPixel(point.y, window.height));
|
||||
});
|
||||
|
||||
EventListener<void> keyAListener(&window.onKeyDown['a'], [](){
|
||||
std::cout << std::format("Pressed specifically the a key!");
|
||||
});
|
||||
|
||||
EventListener<char> anyKeyListener(&window.onAnyKeyDown, [](char key){
|
||||
std::cout << std::format("Pressed the {} key!", key);
|
||||
});
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import Crafter.Graphics;
|
||||
import Crafter.Event;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
WindowWayland window(1280, 720, "Hello Input!");
|
||||
|
||||
// Listen for left mouse click events on the window
|
||||
// The callback receives the MousePoint struct containing the click coordinates in float pixels from the top left corner
|
||||
EventListener<MousePoint> clickListener(&window.onMouseLeftClick, [&window](MousePoint point){
|
||||
// Print the coordinates where the user clicked, we recieve the point in mapped space so we must convert it to pixels first
|
||||
std::cout << std::format("Clicked on X:{} Y:{}!", MappedToPixelBoundless(point.x, window.width), MappedToPixelBoundless(point.y, window.height)) << std::endl;
|
||||
});
|
||||
|
||||
// Listen specifically for the 'a' key being pressed down
|
||||
// The callback takes no parameters since the key is fixed
|
||||
EventListener<void> keyAListener(&window.onKeyDown['a'], [](){
|
||||
// Print confirmation of 'a' key press
|
||||
std::cout << std::format("Pressed specifically the a key!") << std::endl;
|
||||
});
|
||||
|
||||
// Listen for any key press on the window
|
||||
// The callback receives the character of the key pressed
|
||||
EventListener<char> anyKeyListener(&window.onAnyKeyDown, [](char key){
|
||||
// Print which key was pressed
|
||||
std::cout << std::format("Pressed the {} key!", key) << std::endl;
|
||||
});
|
||||
|
||||
//Start the window event loop, unless the window is started events will not trigger.
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
import Crafter.Event;
|
||||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
WindowWayland window(200, 200, "Hello Input!");
|
||||
|
||||
RenderingElementScalingRotating2D element(
|
||||
OpaqueType::SemiOpaque, //opaque, wether the element is opague or semi-transparant
|
||||
1, //bufferWidth: the width of this elements pixel buffer
|
||||
1, //bufferHeight: the height of this elements pixel buffer
|
||||
FractionalToMappedBoundlessU(0.125),
|
||||
FractionalToMapped(0.5), //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
FractionalToMapped(0.5), //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
FractionalToMapped(0.5), //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
FractionalToMapped(0.5), //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
FractionalToMapped(0.5), //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
FractionalToMapped(0.5), //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0, //z: this elements Z position
|
||||
);
|
||||
|
||||
window.elements.push_back(&element);
|
||||
element.buffer = {{255, 0, 0 ,255}};
|
||||
element.UpdatePosition(window);
|
||||
|
||||
EventListener<FrameTime> updateListener(&window.onUpdate, [&](FrameTime time){
|
||||
element.rotation += 50000000000000000;
|
||||
std::cout << element.rotation << std::endl;
|
||||
element.UpdatePosition(window);
|
||||
window.LogTiming();
|
||||
});
|
||||
|
||||
window.StartUpdate();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-timing"
|
||||
}
|
||||
],
|
||||
"debug": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# HelloWindow Example
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates how to draw pixels to a window.
|
||||
|
||||
## Expected Result
|
||||
|
||||
A window with a green and blue colored square, when clicking on the square it logs the coordinates relative to the square.
|
||||
|
||||
## Highlighted Code Snippet
|
||||
|
||||
```cpp
|
||||
UiElement& element = window.elements.emplace_back(
|
||||
0.5,
|
||||
0.5,
|
||||
2,
|
||||
1,
|
||||
0.5f,
|
||||
0.5f,
|
||||
0.5,
|
||||
0.5,
|
||||
0,
|
||||
false
|
||||
);
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import Crafter.Event;
|
||||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
WindowWayland window(1280, 720, "Hello Input!");
|
||||
|
||||
RenderingElement<false, false, false> element(
|
||||
{
|
||||
FractionalToMapped<std::int32_t>(0), //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
FractionalToMapped<std::int32_t>(0.5), //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
FractionalToMapped<std::int32_t>(0.1), //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
FractionalToMapped<std::int32_t>(1), //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
FractionalToMapped<std::int32_t>(0), //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
FractionalToMapped<std::int32_t>(0), //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0 //z: this elements Z position
|
||||
},
|
||||
OpaqueType::FullyOpaque
|
||||
);
|
||||
|
||||
Font font("inter.ttf");
|
||||
std::string text = "testtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt";
|
||||
element.UpdatePosition(window);
|
||||
std::vector<std::string_view> lines = element.ResizeText(window, text, 200, font, TextOverflowMode::Clip, TextScaleMode::Element); // anchor.width automatically scales with our text
|
||||
element.RenderText(window, lines, 200, {0,0,0,255}, font);
|
||||
|
||||
window.elements.push_back(&element);
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
}
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-debug"
|
||||
}
|
||||
],
|
||||
"debug": true,
|
||||
"additional_files": ["inter.ttf"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# HelloWindow Example
|
||||
|
||||
## Description
|
||||
|
||||
This example demonstrates how to draw pixels to a window.
|
||||
|
||||
## Expected Result
|
||||
|
||||
A window with a green and blue colored square, when clicking on the square it logs the coordinates relative to the square.
|
||||
|
||||
## Highlighted Code Snippet
|
||||
|
||||
```cpp
|
||||
UiElement& element = window.elements.emplace_back(
|
||||
0.5,
|
||||
0.5,
|
||||
2,
|
||||
1,
|
||||
0.5f,
|
||||
0.5f,
|
||||
0.5,
|
||||
0.5,
|
||||
0,
|
||||
false
|
||||
);
|
||||
```
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
import Crafter.Event;
|
||||
import Crafter.Graphics;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
Device::Initialize();
|
||||
Window window(1280, 720, "Hello Drawing!");
|
||||
|
||||
RenderingElement2D<true, true, false> element(
|
||||
{
|
||||
0.5, //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
0.5, //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
0.5, //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
0.5, //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
0.5, //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
0.5, //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0 //z: this elements Z position
|
||||
},
|
||||
OpaqueType::FullyOpaque,
|
||||
2,
|
||||
1
|
||||
);
|
||||
|
||||
MouseElement mouse(window);
|
||||
element.children.push_back(&mouse);
|
||||
window.renderer.elements.push_back(&element);
|
||||
|
||||
element.scalingBuffer = {{255, 0, 0 ,255}, {0, 255, 0 ,255}};
|
||||
element.UpdatePosition(window.renderer);
|
||||
|
||||
EventListener<void> clickListener(&mouse.onMouseLeftClick, [&window]() {
|
||||
std::println("Clicked on X:{} Y:{}!",
|
||||
window.currentMousePos.x, window.currentMousePos.y
|
||||
);
|
||||
});
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-debug"
|
||||
}
|
||||
],
|
||||
"debug": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
# Crafter.Graphics Examples
|
||||
Welcome to the **Crafter.Graphics** examples folder!
|
||||
Here you'll find a variety of demos to help you learn and experiment with the features of the `Crafter.Graphics` library.
|
||||
|
||||
## Getting Started
|
||||
To run any example, navigate into its folder and use the following command:
|
||||
```bash
|
||||
crafter-build build executable -r
|
||||
```
|
||||
|
||||
## Hello Series
|
||||
This series explains the absolute basics.
|
||||
|
||||
1. **HelloWindow**
|
||||
Basic window creation using Crafter.Graphics.
|
||||
|
||||
2. **HelloInput**
|
||||
Handling keyboard and mouse input events.
|
||||
|
||||
3. **HelloDrawing**
|
||||
Introduction to drawing on a window.
|
||||
|
||||
4. **HelloUI**
|
||||
Creating and rendering user interface components.
|
||||
|
||||
## Vulkan Series
|
||||
This series explains the vulkan integration.
|
||||
|
||||
1. **VulkanWindow**
|
||||
HelloWindow vulkan edition.
|
||||
|
||||
2. **VulkanTraingle**
|
||||
Introduction to drawing on a window.
|
||||
|
||||
3. **VulkanCube**
|
||||
Creating a custom shader.
|
||||
|
||||
4. **VulkanShader**
|
||||
Creating a custom shader.
|
||||
|
||||
## Notes
|
||||
- Each example is self-contained and meant to be run individually.
|
||||
- Make sure your environment is correctly set up with all dependencies required by `Crafter.Graphics`.
|
||||
- A comaptible WSL envoirement can be set up by running these commands:
|
||||
```cmd
|
||||
wsl --update
|
||||
wsl --install archlinux --name crafter --no-launch
|
||||
wsl -d crafter pacman -Syu vulkan-devel vulkan-swrast clang git base-devel libpqxx onetbb boost lld glslang --noconfirm
|
||||
wsl --terminate crafter
|
||||
```
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
layout(location = 0) rayPayloadInEXT vec3 hitValue;
|
||||
hitAttributeEXT vec2 attribs;
|
||||
|
||||
void main()
|
||||
{
|
||||
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
|
||||
hitValue = barycentricCoords;
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
#include "vulkan/vulkan.h"
|
||||
|
||||
import Crafter.Graphics;
|
||||
using namespace Crafter;
|
||||
import std;
|
||||
import Crafter.Event;
|
||||
import Crafter.Math;
|
||||
|
||||
typedef VulkanShaderConst<"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR> Raygenspv;
|
||||
typedef VulkanShaderConst<"closesthit.spv", "main", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR> Closesthitspv;
|
||||
typedef VulkanShaderConst<"miss.spv", "main", VK_SHADER_STAGE_MISS_BIT_KHR> Misspv;
|
||||
typedef std::tuple<Raygenspv, Misspv, Closesthitspv> AllShaders;
|
||||
typedef std::tuple<
|
||||
ShaderGroup<0, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>,
|
||||
ShaderGroup<1, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>,
|
||||
ShaderGroup<VK_SHADER_UNUSED_KHR, 2, VK_SHADER_UNUSED_KHR, VK_SHADER_UNUSED_KHR>
|
||||
> ShaderGroups;
|
||||
typedef PipelineRTVulkanConst<AllShaders, ShaderGroups> Pipeline;
|
||||
typedef DescriptorSetLayoutVulkanConst<1, {{
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
|
||||
},
|
||||
}}> descriptorSetLayoutTlas;
|
||||
typedef DescriptorSetLayoutVulkanConst<1, {{
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
|
||||
}
|
||||
}}> descriptorSetLayoutImage;
|
||||
|
||||
int main() {
|
||||
Device::CreateDevice();
|
||||
WindowVulkan window(1280, 720, "HelloVulkan");
|
||||
VkCommandBuffer cmd = window.StartInit();
|
||||
|
||||
Raygenspv::CreateShader();
|
||||
Closesthitspv::CreateShader();
|
||||
Misspv::CreateShader();
|
||||
|
||||
ShaderBindingTableVulkanConst<AllShaders>::Init();
|
||||
|
||||
descriptorSetLayoutTlas::Init();
|
||||
descriptorSetLayoutImage::Init();
|
||||
std::array<VkDescriptorSetLayout, 4> layouts {{descriptorSetLayoutTlas::layout, descriptorSetLayoutImage::layout, descriptorSetLayoutImage::layout, descriptorSetLayoutImage::layout}};
|
||||
|
||||
DescriptorPool pool;
|
||||
pool.sets.resize(4);
|
||||
pool.BuildPool(DescriptorPool::GetPoolSizes<descriptorSetLayoutTlas, descriptorSetLayoutImage, descriptorSetLayoutImage, descriptorSetLayoutImage>(), layouts);
|
||||
|
||||
Pipeline::Init(cmd, layouts);
|
||||
window.SetPipelineRT<Pipeline>();
|
||||
|
||||
Mesh triangleMesh;
|
||||
std::array<Vector<float, 3, 3>, 3> verts {{{-150, -150, 100}, {0, 150, 100}, {150, -150, 100}}};
|
||||
std::array<std::uint32_t, 3> index {{2,1,0}};
|
||||
triangleMesh.Build(verts, index, cmd);
|
||||
|
||||
RenderingElement3D renderer = {
|
||||
.instance = {
|
||||
.instanceCustomIndex = 0,
|
||||
.mask = 0xFF,
|
||||
.instanceShaderBindingTableRecordOffset = 0,
|
||||
.flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR,
|
||||
.accelerationStructureReference = triangleMesh.blasAddr
|
||||
}
|
||||
};
|
||||
|
||||
RenderingElement3D::elements.emplace_back(&renderer);
|
||||
MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Identity();
|
||||
std::memcpy(renderer.instance.transform.matrix, transform.m, sizeof(transform.m));
|
||||
|
||||
RenderingElement3D::tlases.resize(Window::numFrames);
|
||||
RenderingElement3D::BuildTLAS(cmd, 0);
|
||||
RenderingElement3D::BuildTLAS(cmd, 1);
|
||||
RenderingElement3D::BuildTLAS(cmd, 2);
|
||||
|
||||
VkDescriptorImageInfo imageInfo[Window::numFrames] = {
|
||||
{
|
||||
.imageView = window.imageViews[0],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
},
|
||||
{
|
||||
.imageView = window.imageViews[1],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
},
|
||||
{
|
||||
.imageView = window.imageViews[2],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
||||
},
|
||||
};
|
||||
|
||||
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
|
||||
.accelerationStructureCount = 1,
|
||||
.pAccelerationStructures = &RenderingElement3D::tlases[0].accelerationStructure
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet write[4];
|
||||
|
||||
write[0] = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = &writeDescriptorSetAccelerationStructure,
|
||||
.dstSet = pool.sets[0],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
|
||||
};
|
||||
|
||||
for(std::uint32_t i = 0; i < Window::numFrames; i++) {
|
||||
write[i+1] = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = pool.sets[i+1],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.pImageInfo = &imageInfo[i]
|
||||
};
|
||||
}
|
||||
vkUpdateDescriptorSets(Device::device, 4, write, 0, nullptr);
|
||||
window.descriptorsRt = {pool.sets[0], pool.sets[1]};
|
||||
|
||||
/*
|
||||
FinishInit executes all commands recorded to StartInit.
|
||||
This must be called before the the event loops starts if you called StartInit before.
|
||||
*/
|
||||
window.FinishInit();
|
||||
|
||||
Animation<std::tuple<float>> anim({
|
||||
{std::chrono::seconds(3), -600, 600},
|
||||
});
|
||||
|
||||
anim.Start(std::chrono::high_resolution_clock::now());
|
||||
|
||||
EventListener<void> updateListener(&window.onRender, [&](){
|
||||
float value = std::get<0>(anim.Play(window.currentFrameTime.now));
|
||||
|
||||
if(anim.currentFrame == anim.keyframes.size()) {
|
||||
anim.Start(window.currentFrameTime.now);
|
||||
}
|
||||
|
||||
MatrixRowMajor<float, 4, 3, 1> transform = MatrixRowMajor<float, 4, 3, 1>::Translation(value, 0, 0);
|
||||
std::memcpy(renderer.instance.transform.matrix, transform.m, sizeof(transform.m));
|
||||
RenderingElement3D::BuildTLAS(window.drawCmdBuffers[window.currentBuffer], window.currentBuffer);
|
||||
|
||||
VkWriteDescriptorSetAccelerationStructureKHR writeDescriptorSetAccelerationStructure {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
|
||||
.accelerationStructureCount = 1,
|
||||
.pAccelerationStructures = &RenderingElement3D::tlases[window.currentBuffer].accelerationStructure
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet write = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = &writeDescriptorSetAccelerationStructure,
|
||||
.dstSet = pool.sets[0],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
|
||||
};
|
||||
vkUpdateDescriptorSets(Device::device, 1, &write, 0, nullptr);
|
||||
|
||||
window.descriptorsRt[1] = pool.sets[window.currentBuffer+1];
|
||||
});
|
||||
|
||||
window.Render();
|
||||
window.StartUpdate();
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
|
||||
layout(location = 0) rayPayloadInEXT vec3 hitValue;
|
||||
|
||||
void main()
|
||||
{
|
||||
hitValue = vec3(1, 1, 1);
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-vulkan-debug"
|
||||
}
|
||||
],
|
||||
"shaders": [
|
||||
{
|
||||
"path":"raygen.glsl",
|
||||
"type": 6,
|
||||
"entrypoint":"main"
|
||||
},
|
||||
{
|
||||
"path":"closesthit.glsl",
|
||||
"type": 9,
|
||||
"entrypoint":"main"
|
||||
},
|
||||
{
|
||||
"path":"miss.glsl",
|
||||
"type": 10,
|
||||
"entrypoint":"main"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
#extension GL_EXT_shader_image_load_formatted : enable
|
||||
|
||||
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
|
||||
layout(binding = 0, set = 1, rgba8) uniform writeonly image2D image;
|
||||
|
||||
layout(location = 0) rayPayloadEXT vec3 hitValue;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pixel coordinates
|
||||
uvec2 pixel = gl_LaunchIDEXT.xy;
|
||||
uvec2 resolution = gl_LaunchSizeEXT.xy;
|
||||
|
||||
// Normalized coordinates in range [-1, 1]
|
||||
vec2 uv = (vec2(pixel) + 0.5) / vec2(resolution);
|
||||
vec2 ndc = uv * 2.0 - 1.0;
|
||||
|
||||
// Camera parameters
|
||||
vec3 origin = vec3(0.0, 0.0, -300.0);
|
||||
|
||||
float aspect = float(resolution.x) / float(resolution.y);
|
||||
float fov = radians(60.0);
|
||||
float tanHalfFov = tan(fov * 0.5);
|
||||
|
||||
// Simple pinhole camera facing +Z
|
||||
vec3 direction = normalize(vec3(
|
||||
ndc.x * aspect * tanHalfFov,
|
||||
-ndc.y * tanHalfFov,
|
||||
1.0
|
||||
));
|
||||
|
||||
traceRayEXT(
|
||||
topLevelAS,
|
||||
gl_RayFlagsNoneEXT,
|
||||
0xff,
|
||||
0, 0, 0,
|
||||
origin,
|
||||
0.001,
|
||||
direction,
|
||||
10000.0,
|
||||
0
|
||||
);
|
||||
|
||||
imageStore(image, ivec2(pixel), vec4(hitValue, 1.0));
|
||||
}
|
||||
|
|
@ -96,6 +96,9 @@ int main() {
|
|||
|
||||
window.FinishInit();
|
||||
|
||||
auto imgSlots = descriptorHeap.AllocateImageSlots(1);
|
||||
auto bufSlots = descriptorHeap.AllocateBufferSlots(1);
|
||||
|
||||
VkDeviceAddressRangeKHR tlasRange0 = {
|
||||
.address = RenderingElement3D::tlases[0].address,
|
||||
};
|
||||
|
|
@ -161,27 +164,27 @@ int main() {
|
|||
|
||||
VkHostAddressRangeEXT destinations[6] = {
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[0].value + descriptorHeap.bufferStartOffset,
|
||||
.address = descriptorHeap.resourceHeap[0].value + descriptorHeap.BufferByteOffset(bufSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[0].value,
|
||||
.address = descriptorHeap.resourceHeap[0].value + descriptorHeap.ImageByteOffset(imgSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[1].value + descriptorHeap.bufferStartOffset,
|
||||
.address = descriptorHeap.resourceHeap[1].value + descriptorHeap.BufferByteOffset(bufSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[1].value,
|
||||
.address = descriptorHeap.resourceHeap[1].value + descriptorHeap.ImageByteOffset(imgSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[2].value + descriptorHeap.bufferStartOffset,
|
||||
.address = descriptorHeap.resourceHeap[2].value + descriptorHeap.BufferByteOffset(bufSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[2].value,
|
||||
.address = descriptorHeap.resourceHeap[2].value + descriptorHeap.ImageByteOffset(imgSlots.firstElement),
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
};
|
||||
|
|
@ -192,8 +195,9 @@ int main() {
|
|||
descriptorHeap.resourceHeap[1].FlushDevice();
|
||||
descriptorHeap.resourceHeap[2].FlushDevice();
|
||||
|
||||
window.pipeline = &pipeline;
|
||||
window.descriptorHeap = &descriptorHeap;
|
||||
RTPass rtPass(&pipeline);
|
||||
window.passes.push_back(&rtPass);
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using namespace Crafter;
|
|||
|
||||
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||||
std::vector<std::string> graphicsArgs(args.begin(), args.end());
|
||||
graphicsArgs.push_back("--vulkan");
|
||||
Configuration* graphics = LocalProject({
|
||||
.projectFile = "../../project.cpp",
|
||||
.args = graphicsArgs,
|
||||
|
|
|
|||
|
|
@ -1,133 +1,85 @@
|
|||
#include "vulkan/vulkan.h"
|
||||
#include <cassert>
|
||||
|
||||
import Crafter.Graphics;
|
||||
using namespace Crafter;
|
||||
import std;
|
||||
import Crafter.Event;
|
||||
import Crafter.Math;
|
||||
import std;
|
||||
|
||||
using namespace Crafter;
|
||||
|
||||
int main() {
|
||||
Device::Initialize();
|
||||
Window window(1280, 720, "HelloVulkan");
|
||||
VkCommandBuffer cmd = window.StartInit();
|
||||
DescriptorHeapVulkan descriptorHeap;
|
||||
descriptorHeap.Initialize(1,2,0);
|
||||
|
||||
VkSpecializationMapEntry entry = {
|
||||
.constantID = 0,
|
||||
.offset = 0,
|
||||
.size = sizeof(uint16_t)
|
||||
};
|
||||
|
||||
VkSpecializationInfo specilizationInfo = {
|
||||
.mapEntryCount = 1,
|
||||
.pMapEntries = &entry,
|
||||
.dataSize = sizeof(uint16_t),
|
||||
.pData = &descriptorHeap.bufferStartElement
|
||||
};
|
||||
|
||||
std::array<VulkanShader, 1> shaders{{
|
||||
{"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, &specilizationInfo}
|
||||
}};
|
||||
|
||||
ShaderBindingTableVulkan shaderTable;
|
||||
shaderTable.Init(shaders);
|
||||
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 1> raygenGroups {{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
|
||||
.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
|
||||
.generalShader = 0,
|
||||
.closestHitShader = VK_SHADER_UNUSED_KHR,
|
||||
.anyHitShader = VK_SHADER_UNUSED_KHR,
|
||||
.intersectionShader = VK_SHADER_UNUSED_KHR,
|
||||
},
|
||||
}};
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 0> missGroups;
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 0> hitGroups;
|
||||
|
||||
|
||||
PipelineRTVulkan pipeline;
|
||||
pipeline.Init(cmd, raygenGroups, missGroups, hitGroups, shaderTable);
|
||||
|
||||
Window window(1280, 720, "VulkanUI");
|
||||
window.StartInit();
|
||||
window.FinishInit();
|
||||
|
||||
RenderingElement2DVulkan<true, true> element(
|
||||
{
|
||||
0.5, //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
0.5, //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
0.5, //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
0.5, //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
0.5, //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
0.5, //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0 //z: this elements Z position
|
||||
},
|
||||
2,
|
||||
1
|
||||
Font font("Inter.ttf");
|
||||
|
||||
UI::Theme theme = UI::themes::default_dark();
|
||||
theme.defaultFont = &font;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// Wire the scene: it auto-creates a descriptor heap, plugs into the
|
||||
// window's pass list, hooks mouse + update events, and drives a
|
||||
// compute-shader UI pass per frame.
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
UI::UIScene scene;
|
||||
scene.Initialize(window, "ui.comp.spv");
|
||||
scene.background(UI::Color{0.06f, 0.07f, 0.10f, 1.0f});
|
||||
|
||||
scene.Root(
|
||||
UI::VStack{}
|
||||
.padding(20)
|
||||
.spacing(12)
|
||||
.children(
|
||||
UI::Text{"Crafter UI — V1"}.font(font).size(28),
|
||||
|
||||
UI::Text{}.font(font).size(14).runs(
|
||||
UI::TextRun{"Click "},
|
||||
UI::TextRun{"Quit"}.color(UI::Color{1.0f, 0.55f, 0.55f}).bold(),
|
||||
UI::TextRun{" to close the window. Tabs switch on click. "},
|
||||
UI::TextRun{"Have fun!"}.color(UI::Color{0.55f, 0.85f, 1.0f})
|
||||
),
|
||||
|
||||
UI::HStack{}
|
||||
.width(UI::Length::Frac(1))
|
||||
.spacing(8)
|
||||
.children(
|
||||
UI::Button{"Play"} .font(font).style(theme.primary) .onClick([]{ std::println(std::cerr, "[click] Play"); }),
|
||||
UI::Button{"Options"}.font(font).style(theme.secondary).onClick([]{ std::println(std::cerr, "[click] Options"); }),
|
||||
UI::Spacer{},
|
||||
UI::Button{"Quit"} .font(font).style(theme.danger) .onClick([]{ std::println(std::cerr, "[click] Quit"); std::_Exit(0); })
|
||||
),
|
||||
|
||||
UI::ProgressBar{}
|
||||
.value(0.42f)
|
||||
.size(UI::Length::Frac(1), UI::Length::Px(20))
|
||||
.foreground(theme.primary.background),
|
||||
|
||||
UI::TabView{}
|
||||
.font(font)
|
||||
.width(UI::Length::Frac(1))
|
||||
.height(UI::Length::Px(220))
|
||||
.tab("Graphics", UI::VStack{}.padding(8).spacing(8).children(
|
||||
UI::Text{"Resolution"}.font(font).size(14),
|
||||
UI::InputField{"1920x1080"}.font(font).style(theme.input),
|
||||
UI::Text{"Max lights"}.font(font).size(14),
|
||||
UI::InputField{"32"}.font(font).style(theme.input)
|
||||
))
|
||||
.tab("Input", UI::VStack{}.padding(8).spacing(8).children(
|
||||
UI::Text{"Mouse sensitivity"}.font(font).size(14),
|
||||
UI::InputField{"1.0"}.font(font).style(theme.input)
|
||||
))
|
||||
.tab("Audio", UI::VStack{}.padding(8).spacing(8).children(
|
||||
UI::Text{"Master volume"}.font(font).size(14),
|
||||
UI::InputField{"80"}.font(font).style(theme.input)
|
||||
))
|
||||
)
|
||||
);
|
||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||
reinterpret_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(element.buffers[i])->value[0] = {1, 0, 0, 1};
|
||||
reinterpret_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(element.buffers[i])->value[1] = {0, 1, 0, 1};
|
||||
reinterpret_cast<VulkanBuffer<Vector<_Float16, 4, 4>, true>*>(element.buffers[i])->FlushDevice();
|
||||
}
|
||||
RendertargetVulkan rendertarget(1280, 720, {&element});
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo0 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[0],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo1 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[1],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[2],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
std::array<VkResourceDescriptorInfoEXT, 9> infos;
|
||||
infos[0] = {
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo0 }
|
||||
};
|
||||
infos[1] = {
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo1 }
|
||||
};
|
||||
infos[2] = {
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo2 }
|
||||
};
|
||||
|
||||
std::array<VkHostAddressRangeEXT, 9> ranges;
|
||||
ranges[0] = {
|
||||
.address = descriptorHeap.resourceHeap[0].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
};
|
||||
ranges[1] = {
|
||||
.address = descriptorHeap.resourceHeap[1].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
ranges[2] = {
|
||||
.address = descriptorHeap.resourceHeap[2].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
|
||||
rendertarget.WriteDescriptors(infos, ranges, 3, descriptorHeap.bufferStartOffset, descriptorHeap);
|
||||
|
||||
window.pipeline = &pipeline;
|
||||
window.descriptorHeap = &descriptorHeap;
|
||||
|
||||
window.Render();
|
||||
window.SaveFrame("frame.png");
|
||||
|
||||
window.StartUpdate(); // continuous rendering — UIScene re-emits per frame
|
||||
window.StartSync();
|
||||
}
|
||||
|
|
|
|||
27
examples/VulkanUI/project.cpp
Normal file
27
examples/VulkanUI/project.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import std;
|
||||
import Crafter.Build;
|
||||
namespace fs = std::filesystem;
|
||||
using namespace Crafter;
|
||||
|
||||
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||||
std::vector<std::string> graphicsArgs(args.begin(), args.end());
|
||||
Configuration* graphics = LocalProject({
|
||||
.projectFile = "../../project.cpp",
|
||||
.args = graphicsArgs,
|
||||
});
|
||||
|
||||
Configuration cfg;
|
||||
cfg.path = "./";
|
||||
cfg.name = "VulkanUI";
|
||||
cfg.outputName = "VulkanUI";
|
||||
ApplyStandardArgs(cfg, args);
|
||||
cfg.dependencies = { graphics };
|
||||
|
||||
std::array<fs::path, 0> ifaces = {};
|
||||
std::array<fs::path, 1> impls = { "main" };
|
||||
cfg.GetInterfacesAndImplementations(ifaces, impls);
|
||||
|
||||
cfg.files.push_back("Inter.ttf");
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-vulkan-debug"
|
||||
}
|
||||
],
|
||||
"debug": true,
|
||||
"shaders": [
|
||||
{
|
||||
"path":"raygen.glsl",
|
||||
"type": 6,
|
||||
"entrypoint":"main"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
#extension GL_EXT_shader_image_load_formatted : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable
|
||||
#extension GL_EXT_descriptor_heap : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable
|
||||
|
||||
|
||||
struct UIScaledData{
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t sizeX;
|
||||
int16_t sizeY;
|
||||
uint16_t bufferX;
|
||||
uint16_t bufferY;
|
||||
};
|
||||
|
||||
layout(std430, descriptor_heap) buffer UIScaledDataBuffer {
|
||||
uint16_t count;
|
||||
uint16_t pad[5];
|
||||
UIScaledData data[];
|
||||
} UITransformBuffer[];
|
||||
|
||||
layout(std430, descriptor_heap) buffer UIPixelBufferr {
|
||||
f16vec4 pixels[];
|
||||
} UIPixelBuffer[];
|
||||
|
||||
layout(constant_id = 0) const uint16_t bufferStart = 0us;
|
||||
layout(descriptor_heap) uniform writeonly image2D image[];
|
||||
|
||||
void main()
|
||||
{
|
||||
uvec2 pixel = gl_LaunchIDEXT.xy;
|
||||
uvec2 resolution = gl_LaunchSizeEXT.xy;
|
||||
|
||||
vec4 hitValue = vec4(0);
|
||||
|
||||
for (uint16_t i = 1us; i < UITransformBuffer[bufferStart].count+1; i++) {
|
||||
if(pixel.x > UITransformBuffer[bufferStart].data[i].x && pixel.x < UITransformBuffer[bufferStart].data[i].x + UITransformBuffer[bufferStart].data[i].sizeX && pixel.y > UITransformBuffer[bufferStart].data[i].y && pixel.y < UITransformBuffer[bufferStart].data[i].y + UITransformBuffer[bufferStart].data[i].sizeY) {
|
||||
int16_t srcX = int16_t(float(pixel.x - UITransformBuffer[bufferStart].data[i].x) * float(UITransformBuffer[bufferStart].data[i].bufferX) / float(UITransformBuffer[bufferStart].data[i].sizeX));
|
||||
int16_t srcY = int16_t(float(pixel.y - UITransformBuffer[bufferStart].data[i].y) * float(UITransformBuffer[bufferStart].data[i].bufferY) / float(UITransformBuffer[bufferStart].data[i].sizeY));
|
||||
hitValue = vec4(UIPixelBuffer[bufferStart + 1].pixels[srcY * UITransformBuffer[bufferStart].data[i].bufferX + srcX]);
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(image[0], ivec2(pixel), hitValue);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue