Compare commits

...

4 Commits

Author SHA1 Message Date
Alexandre
ec2955436d Added new shaders, modified logs messages, continued the tutorial. 2026-07-23 20:48:42 +02:00
Alexandre
a444a53ea7 Added build date, and version type to build id 2026-07-20 17:25:14 +02:00
Alexandre
79a73b8ceb Modified resize logic 2026-07-20 01:14:21 +02:00
Alexandre
622c0478ac Modified the default dimentions to be 1080p 2026-07-20 00:51:46 +02:00
6 changed files with 377 additions and 52 deletions

View File

@ -0,0 +1,29 @@
#version 460
layout (local_size_x = 16, local_size_y = 16) in;
layout(rgba16f,set = 0, binding = 0) uniform image2D image;
//push constants block
layout( push_constant ) uniform constants
{
vec4 data1;
vec4 data2;
vec4 data3;
vec4 data4;
} PushConstants;
void main() {
ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(image);
vec4 topColor = PushConstants.data1;
vec4 bottomColor = PushConstants.data2;
if(texelCoord.x < size.x && texelCoord.y < size.y) {
float blend = float(texelCoord.y)/(size.y);
imageStore(image, texelCoord, mix(topColor,bottomColor, blend));
}
}

91
shaders/sky.comp Normal file
View File

@ -0,0 +1,91 @@
#version 450
layout (local_size_x = 16, local_size_y = 16) in;
layout(rgba16f,set = 0, binding = 0) uniform image2D image;
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
//push constants block
layout( push_constant ) uniform constants
{
vec4 data1;
vec4 data2;
vec4 data3;
vec4 data4;
} PushConstants;
// Return random noise in the range [0.0, 1.0], as a function of x.
float Noise2d( in vec2 x )
{
float xhash = cos( x.x * 37.0 );
float yhash = cos( x.y * 57.0 );
return fract( 415.92653 * ( xhash + yhash ) );
}
// Convert Noise2d() into a "star field" by stomping everthing below fThreshhold to zero.
float NoisyStarField( in vec2 vSamplePos, float fThreshhold )
{
float StarVal = Noise2d( vSamplePos );
if ( StarVal >= fThreshhold )
StarVal = pow( (StarVal - fThreshhold)/(1.0 - fThreshhold), 6.0 );
else
StarVal = 0.0;
return StarVal;
}
// Stabilize NoisyStarField() by only sampling at integer values.
float StableStarField( in vec2 vSamplePos, float fThreshhold )
{
// Linear interpolation between four samples.
// Note: This approach has some visual artifacts.
// There must be a better way to "anti alias" the star field.
float fractX = fract( vSamplePos.x );
float fractY = fract( vSamplePos.y );
vec2 floorSample = floor( vSamplePos );
float v1 = NoisyStarField( floorSample, fThreshhold );
float v2 = NoisyStarField( floorSample + vec2( 0.0, 1.0 ), fThreshhold );
float v3 = NoisyStarField( floorSample + vec2( 1.0, 0.0 ), fThreshhold );
float v4 = NoisyStarField( floorSample + vec2( 1.0, 1.0 ), fThreshhold );
float StarVal = v1 * ( 1.0 - fractX ) * ( 1.0 - fractY )
+ v2 * ( 1.0 - fractX ) * fractY
+ v3 * fractX * ( 1.0 - fractY )
+ v4 * fractX * fractY;
return StarVal;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 iResolution = imageSize(image);
// Sky Background Color
//vec3 vColor = vec3( 0.1, 0.2, 0.4 ) * fragCoord.y / iResolution.y;
vec3 vColor = PushConstants.data1.xyz * fragCoord.y / iResolution.y;
// Note: Choose fThreshhold in the range [0.99, 0.9999].
// Higher values (i.e., closer to one) yield a sparser starfield.
float StarFieldThreshhold = PushConstants.data1.w;//0.97;
// Stars with a slow crawl.
float xRate = 0.2;
float yRate = -0.06;
vec2 vSamplePos = fragCoord.xy + vec2( xRate * float( 1 ), yRate * float( 1 ) );
float StarVal = StableStarField( vSamplePos, StarFieldThreshhold );
vColor += vec3( StarVal );
fragColor = vec4(vColor, 1.0);
}
void main()
{
vec4 value = vec4(0.0, 0.0, 0.0, 1.0);
ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(image);
if(texelCoord.x < size.x && texelCoord.y < size.y)
{
vec4 color;
mainImage(color,texelCoord);
imageStore(image, texelCoord, color);
}
}

View File

@ -17,7 +17,7 @@ class Callback {
void Callback::keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { void Callback::keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Key pressed, key {}", key); fmt::println("[Engine:Info] Key pressed, key {}", key);
#endif #endif
} }

View File

@ -2,6 +2,8 @@
#define ENGINE_H #define ENGINE_H
// Normal header // Normal header
// Current progress
// 3 - Graphics Pipeline - Setting up the render pipeline
#include "descriptors.h" // Required for public interface custom allocator #include "descriptors.h" // Required for public interface custom allocator
#include "Common/Types.h" #include "Common/Types.h"
@ -44,7 +46,7 @@ class Engine {
//========== Class Members ========== //========== Class Members ==========
bool _isInitialized { false }; bool _isInitialized { false };
int _frameNumber { 0 }; int _frameNumber { 0 };
VkExtent2D _windowExtent { 1700, 900 }; VkExtent2D _windowExtent { 1920, 1080 };
GLFWwindow *window { nullptr }; GLFWwindow *window { nullptr };
@ -204,6 +206,7 @@ void Engine::init() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Initializing the engine..."); fmt::println("[Engine:Init] Initializing the engine...");
fmt::println("[Engine:Info] Current engine version {}", BUILD_ID); fmt::println("[Engine:Info] Current engine version {}", BUILD_ID);
fmt::println("[Engine:Info] Compiled on {} at {}", __DATE__ ,__TIME__);
#endif #endif
glfwInit(); glfwInit();
@ -427,6 +430,11 @@ void Engine::run() {
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
glfwPollEvents(); glfwPollEvents();
int w, h;
glfwGetFramebufferSize(window, &w, &h);
if (w != _windowExtent.width || h != _windowExtent.height ) { _requestResize = true; };
if (_requestResize) {resizeSwapchain();}; if (_requestResize) {resizeSwapchain();};
if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) {
@ -1096,7 +1104,7 @@ void Engine::buildImgui() {
// Main ImGui things // Main ImGui things
ImGui::ShowDemoWindow(); ImGui::ShowDemoWindow();
if(ImGui::Begin("background")) { if(ImGui::Begin("Background Shader control")) {
ComputeEffect& selected = backgroundEffects[currentBackgroundEffect]; ComputeEffect& selected = backgroundEffects[currentBackgroundEffect];
ImGui::Text( ImGui::Text(
@ -1318,7 +1326,7 @@ void Engine::resizeSwapchain() {
destroySwapchain(); destroySwapchain();
int w, h; int w, h;
glfwGetWindowSize(window, &w, &h); glfwGetFramebufferSize(window, &w, &h);
_windowExtent.width = w; _windowExtent.width = w;
_windowExtent.height = h; _windowExtent.height = h;

View File

@ -69,6 +69,12 @@ namespace vkinit {
VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* colorAttachment,
VkRenderingAttachmentInfo* depthAttachment VkRenderingAttachmentInfo* depthAttachment
); );
VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo(
VkShaderStageFlagBits stage,
VkShaderModule shaderModule,
const char * entry = "main"
);
} }
@ -303,6 +309,24 @@ namespace vkinit {
}; };
return renderInfo; return renderInfo;
} }
VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo(
VkShaderStageFlagBits stage,
VkShaderModule shaderModule,
const char * entry
) {
VkPipelineShaderStageCreateInfo info {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.pNext = nullptr,
.stage = stage,
.module = shaderModule,
.pName = entry
};
return info;
}
} }
#endif #endif
#endif #endif

View File

@ -17,6 +17,36 @@ namespace vkutil {
); );
}; };
class PipelineBuilder {
public:
std::vector<VkPipelineShaderStageCreateInfo> _shaderStages;
VkPipelineInputAssemblyStateCreateInfo _inputAssembly;
VkPipelineRasterizationStateCreateInfo _rasterizer;
VkPipelineColorBlendAttachmentState _colorBlendAttachment;
VkPipelineMultisampleStateCreateInfo _multisampling;
VkPipelineLayout _pipelineLayout;
VkPipelineDepthStencilStateCreateInfo _depthStencil;
VkPipelineRenderingCreateInfo _renderInfo;
PipelineBuilder() { clear(); }
void clear();
VkPipeline buildPipeline(
VkDevice device
);
void setShaders(
VkShaderModule vertexShader,
VkShaderModule fragmentShader
);
void setInputTopology(
VkPrimitiveTopology topology
);
};
#endif #endif
#ifdef PIPELINES_IMPL #ifdef PIPELINES_IMPL
@ -29,12 +59,11 @@ namespace vkutil {
// Custom imports // Custom imports
#include "initializers.h" #include "initializers.h"
namespace vkutil { bool vkutil::loadShaderModule(
bool loadShaderModule(
const char* filePath, const char* filePath,
VkDevice device, VkDevice device,
VkShaderModule* outShaderModule VkShaderModule* outShaderModule
) { ) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Utils] Loading shader located at {}...", filePath); fmt::println("[Engine:Utils] Loading shader located at {}...", filePath);
#endif #endif
@ -88,9 +117,153 @@ namespace vkutil {
#endif #endif
return true; return true;
}
void PipelineBuilder::clear() {
#ifdef DEBUG
fmt::println("[PipelineBuilder] Clearing pipeline...");
#endif
// Clear structs
_inputAssembly = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
};
_rasterizer = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
};
_colorBlendAttachment = {};
_multisampling = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
};
_pipelineLayout = {};
_depthStencil = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
};
_renderInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO
};
_shaderStages.clear();
#ifdef DEBUG
fmt::println("[PipelineBuilder] Pipeline cleared !");
#endif
}
VkPipeline PipelineBuilder::buildPipeline (
VkDevice device
) {
#ifdef DEBUG
fmt::println("[PipelineBuilder] Building rasterisation pipeline...");
#endif
// Make the viewport state from our stored viewport and scissor
// This makes it that it won't support multiple viewports or scissors
VkPipelineViewportStateCreateInfo viewportState {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pNext = nullptr,
.viewportCount = 1,
.scissorCount = 1
};
// Setup placeholder color blending.
// Need to be changed when using transparent objects, which we aren't rn
// The blending is "no blend", but we write it to the color attachment
VkPipelineColorBlendStateCreateInfo colorBlending {
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_COPY,
.attachmentCount = 1,
.pAttachments = &_colorBlendAttachment
};
// Completely clear VertexInputStateCreateInfo, as we have no need for it
VkPipelineVertexInputStateCreateInfo _vertexInputInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
};
// Dynamic Viewport
VkDynamicState state[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = 2,
.pDynamicStates = &state[0]
};
// Build the pipeline
// Uses all the class members info structs
VkGraphicsPipelineCreateInfo pipelineInfo {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &_renderInfo,
.stageCount = (uint32_t)_shaderStages.size(),
.pStages = _shaderStages.data(),
.pVertexInputState = &_vertexInputInfo,
.pInputAssemblyState = &_inputAssembly,
.pViewportState = &viewportState,
.pRasterizationState = &_rasterizer,
.pMultisampleState = &_multisampling,
.pDepthStencilState = &_depthStencil,
.pColorBlendState = &colorBlending,
.pDynamicState = &dynamicInfo,
.layout = _pipelineLayout
};
// Check the creation of the pipeline
// I don't use the VK_CHECK()
// 'cause there might be pipeline-specific options
VkPipeline newPipeline;
if(
vkCreateGraphicsPipelines(
device,
VK_NULL_HANDLE,
1,
&pipelineInfo,
nullptr,
&newPipeline
) != VK_SUCCESS
) {
fmt::println("[PipelineBuilder] Failed to create pipeline !");
return VK_NULL_HANDLE; // Graphics pipeline failed to be created
} else {
return newPipeline;
} }
};
}
void PipelineBuilder::setShaders(
VkShaderModule vertexShader,
VkShaderModule fragmentShader
) {
_shaderStages.clear();
_shaderStages.push_back(
vkinit::pipelineShaderStageCreateInfo(
VK_SHADER_STAGE_VERTEX_BIT,
vertexShader
)
);
_shaderStages.push_back(
vkinit::pipelineShaderStageCreateInfo(
VK_SHADER_STAGE_FRAGMENT_BIT,
fragmentShader
)
);
}
#endif #endif
#endif #endif