Compare commits

...

2 Commits

22 changed files with 2288 additions and 139 deletions

View File

@ -0,0 +1,2 @@
# Blender 4.2.3 LTS MTL File: 'None'
# www.blender.org

2070
assets/models/UVSphere.obj Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,2 @@
# Blender 4.2.3 LTS MTL File: 'None'
# www.blender.org
newmtl Material
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd /home/lillian/Downloads/d41777258e68c9d7046fc03c4d1d1e89.png

View File

@ -0,0 +1,39 @@
# Blender 4.2.3 LTS
# www.blender.org
mtllib untitled.mtl
o Cube
v -6.996062 0.060240 6.002291
v -6.996062 0.123414 6.002291
v -6.996062 0.060240 -6.002291
v -6.996062 0.123414 -6.002291
v 6.996062 0.060240 6.002291
v 6.996062 0.123414 6.002291
v 6.996062 0.060240 -6.002291
v 6.996062 0.123414 -6.002291
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.561014 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.561014 0.250000
vt 0.625000 0.500000
vt 0.561014 0.500000
vt 0.625000 0.750000
vt 0.561014 0.750000
vt 0.625000 1.000000
vt 0.561014 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
s 0
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/8/4 6/7/4 2/9/4 1/10/4
f 3/11/5 7/6/5 5/8/5 1/12/5
f 8/5/6 4/13/6 2/14/6 6/7/6

View File

@ -3,6 +3,6 @@ Pos=60,60
Size=400,400
[Window][Agnosia Debug]
Pos=40,377
Pos=57,392
Size=623,438

View File

@ -23,8 +23,8 @@ void initImGuiWindow() {
}
ImGui::DragFloat3("Camera Position", Graphics::getCamPos());
ImGui::DragFloat3("Light Position", Graphics::getLightPos());
ImGui::DragFloat3("Center Position", Graphics::getCenterPos());
ImGui::DragFloat3("Up Direction", Graphics::getUpDir());
ImGui::DragFloat("Depth of Field", &Graphics::getDepthField(), 0.1f, 1.0f,
180.0f, NULL, ImGuiSliderFlags_AlwaysClamp);
ImGui::DragFloat2("Near and Far fields", Graphics::getDistanceField());

View File

@ -87,24 +87,24 @@ void createInstance() {
throw std::runtime_error("failed to create instance!");
}
}
void initVulkan() {
Material *vikingRoomMaterial =
new Material("vikingRoomMaterial", "assets/textures/viking_room.png");
void initAgnosia() {
Material *sphereMaterial =
new Material("sphereMaterial", "assets/textures/checkermap.png");
Material *stanfordDragonMaterial =
new Material("stanfordDragonMaterial", "assets/textures/checkermap.png");
Material *teapotMaterial =
new Material("teapotMaterial", "assets/textures/checkermap.png");
Model *vikingRoom =
new Model("vikingRoom", *vikingRoomMaterial,
"assets/models/viking_room.obj", glm::vec3(0.0f, 0.0f, 0.0f));
Model *uvSphere =
new Model("uvSphere", *sphereMaterial, "assets/models/UVSphere.obj",
glm::vec3(0.0f, 0.0f, 0.0f));
Model *stanfordDragon = new Model("stanfordDragon", *stanfordDragonMaterial,
"assets/models/StanfordDragon800k.obj",
glm::vec3(0.0f, 2.0f, 0.0f));
Model *teapot =
new Model("teapot", *teapotMaterial, "assets/models/teapot.obj",
glm::vec3(1.0f, -3.0f, -1.0f));
}
void initVulkan() {
// Initialize volk and continue if successful.
volkInitialize();
// Initialize vulkan and set up pipeline.
@ -122,9 +122,7 @@ void initVulkan() {
Graphics::createCommandPool();
// Image creation MUST be after command pool, because command
// buffers.
vikingRoom->populateData();
stanfordDragon->populateData();
teapot->populateData();
Model::populateModels();
Texture::createMaterialTextures(Model::getInstances());
Texture::createColorResources();
Texture::createDepthResources();
@ -150,6 +148,11 @@ void mainLoop() {
void cleanup() {
Render::cleanupSwapChain();
Graphics::destroyGraphicsPipeline();
Buffers::destroyDescriptorPool();
Model::destroyTextures();
vkDestroyDescriptorSetLayout(DeviceControl::getDevice(),
Buffers::getDescriptorSetLayout(), nullptr);
Buffers::destroyBuffers();
Render::destroyFenceSemaphores();
@ -179,6 +182,7 @@ GLFWwindow *EntryApp::getWindow() { return window; }
void EntryApp::run() {
initWindow();
initAgnosia();
initVulkan();
mainLoop();
cleanup();

View File

@ -122,6 +122,9 @@ void Buffers::createDescriptorPool() {
throw std::runtime_error("failed to create descriptor pool!");
}
}
void Buffers::destroyDescriptorPool() {
vkDestroyDescriptorPool(DeviceControl::getDevice(), descriptorPool, nullptr);
}
void Buffers::createDescriptorSet(std::vector<Model *> models) {
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;

View File

@ -19,6 +19,7 @@ public:
static void createDescriptorSetLayout();
static void createDescriptorSet(std::vector<Model *> models);
static void createDescriptorPool();
static void destroyDescriptorPool();
static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags props, VkBuffer &buffer,
VkDeviceMemory &bufferMemory);

View File

@ -13,6 +13,7 @@
#include <iostream>
#include <vulkan/vulkan_core.h>
float lightPos[4] = {5.0f, 5.0f, 5.0f, 0.44f};
float camPos[4] = {3.0f, 3.0f, 3.0f, 0.44f};
float centerPos[4] = {0.0f, 0.0f, 0.0f, 0.44f};
float upDir[4] = {0.0f, 0.0f, 1.0f, 0.44f};
@ -363,6 +364,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
Agnosia_T::GPUPushConstants pushConsts;
pushConsts.vertexBuffer = model->getBuffers().vertexBufferAddress;
pushConsts.objPosition = model->getPos();
pushConsts.lightPos = glm::vec3(lightPos[0], lightPos[1], lightPos[2]);
pushConsts.textureID = texID;
pushConsts.model =
@ -433,6 +435,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
}
float *Graphics::getCamPos() { return camPos; }
float *Graphics::getLightPos() { return lightPos; }
float *Graphics::getCenterPos() { return centerPos; }
float *Graphics::getUpDir() { return upDir; }
float &Graphics::getDepthField() { return depthField; }

View File

@ -15,6 +15,7 @@ public:
uint32_t imageIndex);
static float *getCamPos();
static float *getLightPos();
static float *getCenterPos();
static float *getUpDir();
static float &getDepthField();

View File

@ -20,15 +20,21 @@
std::vector<Model *> Model::instances;
VmaAllocator _allocator;
// chatgpt did this and the haters can WEEP fuck hash functions.
namespace std {
template <> struct hash<Agnosia_T::Vertex> {
size_t operator()(Agnosia_T::Vertex const &vertex) const {
return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec3>()(vertex.color) << 1)) >>
1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1);
size_t hashPos = hash<glm::vec3>()(vertex.pos);
size_t hashColor = hash<glm::vec3>()(vertex.color);
size_t hashUV = hash<glm::vec2>()(vertex.uv);
size_t hashNormal = hash<glm::vec3>()(vertex.normal);
// Combine all hashes
return ((hashPos ^ (hashColor << 1)) >> 1) ^ (hashUV << 1) ^
(hashNormal << 2);
}
};
} // namespace std
void Model::createMemoryAllocator(VkInstance vkInstance) {
VmaVulkanFunctions vulkanFuncs{
@ -105,7 +111,8 @@ Model::Model(const std::string &modelID, const Material &material,
instances.push_back(this);
}
void Model::populateData() {
void Model::populateModels() {
for (Model *model : getInstances()) {
std::vector<Agnosia_T::Vertex> vertices;
// Index buffer definition, showing which points to reuse.
@ -113,7 +120,7 @@ void Model::populateData() {
tinyobj::ObjReaderConfig readerConfig;
tinyobj::ObjReader reader;
if (!reader.ParseFromFile(modelPath, readerConfig)) {
if (!reader.ParseFromFile(model->modelPath, readerConfig)) {
if (!reader.Error().empty()) {
throw std::runtime_error(reader.Error());
}
@ -136,12 +143,15 @@ void Model::populateData() {
attrib.vertices[3 * index.vertex_index + 1],
attrib.vertices[3 * index.vertex_index + 2]};
vertex.normal = {attrib.normals[3 * index.normal_index + 0],
attrib.normals[3 * index.normal_index + 1],
attrib.normals[3 * index.normal_index + 2]};
// TODO: Small fix here, handle if there are no UV's unwrapped for the
// model.
// As of now, if it is not unwrapped, it segfaults on texCoord
// assignment. Obviously we should always have UV's, but it
// shouldn't crash, just unwrap in a default method.
vertex.texCoord = {attrib.texcoords[2 * index.texcoord_index + 0],
vertex.uv = {attrib.texcoords[2 * index.texcoord_index + 0],
1.0f - attrib.texcoords[2 * index.texcoord_index + 1]};
vertex.color = {1.0f, 1.0f, 1.0f};
@ -158,7 +168,8 @@ void Model::populateData() {
Agnosia_T::GPUMeshBuffers newSurface;
// Create a Vertex Buffer here, infinitely easier than the old Vulkan method!
// Create a Vertex Buffer here, infinitely easier than the old Vulkan
// method!
newSurface.vertexBuffer = createBuffer(
vertexBufferSize,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
@ -169,8 +180,8 @@ void Model::populateData() {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = newSurface.vertexBuffer.buffer,
};
newSurface.vertexBufferAddress =
vkGetBufferDeviceAddress(DeviceControl::getDevice(), &deviceAddressInfo);
newSurface.vertexBufferAddress = vkGetBufferDeviceAddress(
DeviceControl::getDevice(), &deviceAddressInfo);
// Create the index buffer to iterate over and check for duplicate vertices
newSurface.indexBuffer = createBuffer(indexBufferSize,
@ -178,9 +189,9 @@ void Model::populateData() {
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
Agnosia_T::AllocatedBuffer stagingBuffer =
createBuffer(vertexBufferSize + indexBufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
Agnosia_T::AllocatedBuffer stagingBuffer = createBuffer(
vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_CPU_ONLY);
void *data = stagingBuffer.allocation->GetMappedData();
@ -203,14 +214,25 @@ void Model::populateData() {
indexCopy.srcOffset = vertexBufferSize;
indexCopy.size = indexBufferSize;
vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.indexBuffer.buffer, 1,
&indexCopy);
vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.indexBuffer.buffer,
1, &indexCopy);
});
vmaDestroyBuffer(_allocator, stagingBuffer.buffer, stagingBuffer.allocation);
vmaDestroyBuffer(_allocator, stagingBuffer.buffer,
stagingBuffer.allocation);
this->buffers = newSurface;
this->objPosition = objPosition;
this->indiceCount = indices.size();
model->buffers = newSurface;
model->indiceCount = indices.size();
}
}
void Model::destroyTextures() {
for (Model *model : Model::getInstances()) {
vkDestroySampler(DeviceControl::getDevice(),
model->getMaterial().getTextureSampler(), nullptr);
vkDestroyImageView(DeviceControl::getDevice(),
model->getMaterial().getTextureView(), nullptr);
vkDestroyImage(DeviceControl::getDevice(),
model->getMaterial().getTextureImage(), nullptr);
}
}
std::string Model::getID() { return this->ID; }

View File

@ -28,7 +28,8 @@ public:
static void createMemoryAllocator(VkInstance instance);
static const std::vector<Model *> &getInstances();
void populateData();
static void populateModels();
static void destroyTextures();
Agnosia_T::GPUMeshBuffers getBuffers();
std::string getID();

View File

@ -4,6 +4,7 @@
struct Vertex {
vec3 pos;
vec3 normal;
vec3 color;
vec2 texCoord;
};
@ -14,6 +15,7 @@ layout(buffer_reference, scalar) readonly buffer VertexBuffer{
layout( push_constant, scalar ) uniform constants {
VertexBuffer vertBuffer;
vec3 objPos;
vec3 lightPos;
int textureID;
mat4 model;
mat4 view;

View File

@ -5,11 +5,18 @@
layout(binding = 1) uniform sampler2D texSampler[];
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 0) in vec3 v_norm;
layout(location = 1) in vec3 v_pos;
layout(location = 2) in vec2 texCoord;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(texSampler[PushConstants.textureID], fragTexCoord);
vec3 diffuseColor = texture(texSampler[PushConstants.textureID], texCoord).rgb;
vec3 ambientColor = vec3(0.05f,0.05f, 0.05f) * diffuseColor;
float lightPower = 5;
vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);
float cosTheta = dot(PushConstants.lightPos, v_norm);
float sqrDist = distance(v_pos, PushConstants.lightPos)*distance(v_pos, PushConstants.lightPos);
outColor = vec4(ambientColor + clamp(diffuseColor * lightColor * lightPower * cosTheta / sqrDist, vec3(0,0,0), vec3(1,1,1)), 1.0f);
}

View File

@ -2,14 +2,16 @@
#extension GL_GOOGLE_include_directive : enable
#include "common.glsl"
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 0) out vec3 v_norm;
layout(location = 1) out vec3 v_pos;
layout(location = 2) out vec2 texCoord;
void main() {
Vertex vertex = PushConstants.vertBuffer.vertices[gl_VertexIndex];
gl_Position = PushConstants.proj * PushConstants.view * PushConstants.model *
vec4(vertex.pos + PushConstants.objPos, 1.0f);
fragColor = vertex.color.rgb;
fragTexCoord = vertex.texCoord;
v_norm = vertex.normal;
v_pos = vertex.pos;
texCoord = vertex.texCoord;
}

View File

@ -10,12 +10,13 @@ public:
// This defines what a vertex is!
// We control the position, color and texture coordinate here!
glm::vec3 pos;
glm::vec3 normal;
glm::vec3 color;
glm::vec2 texCoord;
glm::vec2 uv;
bool operator==(const Vertex &other) const {
return pos == other.pos && color == other.color &&
texCoord == other.texCoord;
return pos == other.pos && normal == other.normal &&
color == other.color && uv == other.uv;
}
};
struct AllocatedBuffer {
@ -31,6 +32,7 @@ public:
struct GPUPushConstants {
VkDeviceAddress vertexBuffer;
glm::vec3 objPosition;
glm::vec3 lightPos;
int textureID;
glm::mat4 model;
glm::mat4 view;