Finished shader; split to targets cpu, opengl and vulkan
This commit is contained in:
parent
1b5b6d0f45
commit
8fa5172e3e
@ -2,13 +2,22 @@ cmake_minimum_required(VERSION 3.15)
|
||||
project(Informatikprojekt C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(PROJECT_SOURCES particlesystem.h particlesystem.c init.h initOpenGL.h initOpenGL.c glad/src/glad.c)
|
||||
|
||||
add_executable(Informatikprojekt cpuMain.c ${PROJECT_SOURCES})
|
||||
add_executable(Informatikprojekt_OpenGL openglMain.c ${PROJECT_SOURCES})
|
||||
add_executable(Informatikprojekt_Vulkan vulkanMain.c ${PROJECT_SOURCES})
|
||||
|
||||
# Vulkan
|
||||
find_package(Vulkan REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${Vulkan_INCLUDE_DIRS})
|
||||
|
||||
add_executable(Informatikprojekt main.c particlesystem.h particlesystem.c init.h initOpenGL.h initOpenGL.c glad/src/glad.c)
|
||||
|
||||
# GLFW
|
||||
|
||||
include_directories(./glfw/include)
|
||||
target_link_libraries(Informatikprojekt ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
|
||||
target_link_libraries(Informatikprojekt_OpenGL ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
|
||||
target_link_libraries(Informatikprojekt_Vulkan Vulkan::Vulkan ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
|
||||
|
||||
# glad
|
||||
include_directories(./glad/include)
|
||||
|
93
cpuMain.c
Normal file
93
cpuMain.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include "particlesystem.h"
|
||||
#include "initOpenGL.h"
|
||||
|
||||
#define PARTICLE_AMOUNT 1000
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 800
|
||||
|
||||
#define UPPER_AGE 250
|
||||
#define LOWER_AGE 60
|
||||
|
||||
void calcPos(particle *p, float dt);
|
||||
void calcCol(particle *p);
|
||||
|
||||
int main()
|
||||
{
|
||||
/************* INIT *************/
|
||||
// Init OpenGL and GLFW
|
||||
initGLFW();
|
||||
setErrorCallbackGL();
|
||||
|
||||
int width = WIDTH, height = HEIGHT;
|
||||
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL CPU");
|
||||
|
||||
setCurrentContextGL(window);
|
||||
setFramebufferSizeCallbackGL(window);
|
||||
|
||||
// glad
|
||||
initGlad();
|
||||
|
||||
/************* PARTICLE SYSTEM *************/
|
||||
vector3f *epos1 = initVector3f(0, 0, 0);
|
||||
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
|
||||
particle_system *ps = initParticleSystem(1);
|
||||
(ps->emitters)[0] = e1;
|
||||
initRandomParticles(e1);
|
||||
|
||||
/************* RENDER LOOP *************/
|
||||
double time, tFrame, tLast = 0;
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
time = glfwGetTime();
|
||||
tFrame = time - tLast;
|
||||
tLast = time;
|
||||
|
||||
/*** UPDATE ***/
|
||||
updateParticles((float) tFrame, ps, calcPos, calcCol);
|
||||
|
||||
/*** RENDER ***/
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
|
||||
emitter *e;
|
||||
particle *p;
|
||||
vector3f *pos;
|
||||
for (int j = 0; j < ps->eamount; j++)
|
||||
{
|
||||
e = (ps->emitters)[j];
|
||||
for (int i = 0; i < e->pamount; i++)
|
||||
{
|
||||
p = (e->particles)[i];
|
||||
pos = p->position;
|
||||
|
||||
glColor3f(p->color->x, p->color->y, p->color->z);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3f(pos->x, pos->y, pos->z);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
//END
|
||||
terminateGLFW(window);
|
||||
freeParticleSystem(ps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void calcPos(particle *p, float dt)
|
||||
{
|
||||
p->position->x += p->velocity->x * dt;
|
||||
p->position->y += p->velocity->y * dt;
|
||||
p->position->z += p->velocity->z * dt;
|
||||
}
|
||||
|
||||
void calcCol(particle *p)
|
||||
{
|
||||
p->color->x -= 0.00001f;
|
||||
p->color->y -= 0.00001f;
|
||||
p->color->z -= 0.00001f;
|
||||
}
|
334
main.c
334
main.c
@ -1,334 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "particlesystem.h"
|
||||
#include "initOpenGL.h"
|
||||
|
||||
#define PARTICLE_AMOUNT 10000
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 800
|
||||
|
||||
void printVector(vector3f *v);
|
||||
void printParticle(particle *v);
|
||||
void printEmitter(emitter *e);
|
||||
void initRandomParticles(emitter *e);
|
||||
void error_callback(int error, const char* description);
|
||||
|
||||
void calcPos(particle *p, float dt);
|
||||
void calcCol(particle *p);
|
||||
|
||||
int main()
|
||||
{
|
||||
/************* INIT *************/
|
||||
// Init OpenGL and GLFW
|
||||
initGLFW();
|
||||
setErrorCallbackGL();
|
||||
|
||||
int width = WIDTH, height = HEIGHT;
|
||||
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL");
|
||||
|
||||
setCurrentContextGL(window);
|
||||
setFramebufferSizeCallbackGL(window);
|
||||
|
||||
// glad
|
||||
initGlad();
|
||||
|
||||
/************* PARTICLE SYSTEM *************/
|
||||
vector3f *epos1 = initVector3f(0, 0, 0);
|
||||
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
|
||||
particle_system *ps = initParticleSystem(1);
|
||||
(ps->emitters)[0] = e1;
|
||||
initRandomParticles(e1);
|
||||
|
||||
/************* SHADER *************/
|
||||
const GLchar *computeShaderSource = "#version 460 core\n"
|
||||
"#extension GL_ARB_compute_shader : enable\n"
|
||||
"#extension GL_ARB_shader_storage_buffer_object : enable\n"
|
||||
"\n"
|
||||
"struct particle\n"
|
||||
"{\n"
|
||||
" vec3 pos;\n"
|
||||
" vec3 vel;\n"
|
||||
" vec3 col;\n"
|
||||
" float age;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"layout(std430, binding = 0) buffer particles\n"
|
||||
"{\n"
|
||||
" particle p[];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"uniform float dt;\n"
|
||||
"uniform vec3 resetPos;\n"
|
||||
"uniform uint seed;\n"
|
||||
"\n"
|
||||
"layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n"
|
||||
"\n"
|
||||
"float rand()\n"
|
||||
"{\n"
|
||||
" uint seedR;\n"
|
||||
" seedR = (seed * 1103515245u + 12345u);\n"
|
||||
" return float(seed) / 4294967296.0;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec3 rand3() {\n"
|
||||
" vec3 result;\n"
|
||||
" uint seedR;\n"
|
||||
" seedR = (seed * 1103515245u + 12345u);\n"
|
||||
" result.x = float(seed);\n"
|
||||
" seedR = (seed * 1103515245u + 12345u);\n"
|
||||
" result.y = float(seed);\n"
|
||||
" seedR = (seed * 1103515245u + 12345u);\n"
|
||||
" result.z = float(seed);\n"
|
||||
" return (result / 2147483648.0) - vec3(1,1,1);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" uint gid = gl_GlobalInvocationID.x;\n"
|
||||
" particle part = p[gid];\n"
|
||||
"\n"
|
||||
" if (part.age < 0 || part.pos.x > 1 || part.pos.y > 1 || part.pos.z > 1\n"
|
||||
" || part.pos.x < -1 || part.pos.y < -1 || part.pos.z < -1 )\n"
|
||||
" {\n"
|
||||
" part.pos = resetPos;\n"
|
||||
" //part.vel = rand3();\n"
|
||||
" //part.col = vec3(rand(), rand(), rand());\n"
|
||||
" //part.age = rand() * 0x7fff * 0.01f;\n"
|
||||
" \n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" part.pos += part.vel * dt;\n"
|
||||
" part.age -= 0.01f;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" p[gid] = part;\n"
|
||||
"}";
|
||||
|
||||
const GLchar *vertexShaderSource = "#version 460\n"
|
||||
"\n"
|
||||
"layout(location = 0) in vec3 pos;\n"
|
||||
"layout(location = 1) in vec3 colIn;\n"
|
||||
"\n"
|
||||
"out vec3 colV;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" colV = colIn;\n"
|
||||
" gl_Position = vec4(pos, 1);\n"
|
||||
"}";
|
||||
|
||||
const GLchar *fragmentShaderSource = "#version 460 core\n"
|
||||
"\n"
|
||||
"in vec3 colV;\n"
|
||||
"out vec4 colOut;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" colOut = vec4(colV, 1);\n"
|
||||
"}";
|
||||
|
||||
GLuint computeShader = compileShader(computeShaderSource, GL_COMPUTE_SHADER);
|
||||
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
GLuint computeShaders[] = { computeShader };
|
||||
GLuint computeShaderProgram = linkShaders(computeShaders, 1);
|
||||
glUseProgram(computeShaderProgram);
|
||||
GLint dtUniformLocation = glGetUniformLocation(computeShaderProgram, "dt");
|
||||
GLint resetPosUniformLocation = glGetUniformLocation(computeShaderProgram, "resetPos");
|
||||
GLint seedUniformLocation = glGetUniformLocation(computeShaderProgram, "seed");
|
||||
glUniform3f(resetPosUniformLocation, e1->position->x, e1->position->y, e1->position->z);
|
||||
|
||||
GLuint renderShaders[] = { vertexShader, fragmentShader };
|
||||
GLuint renderShaderProgram = linkShaders(renderShaders, 2);
|
||||
|
||||
float *particles = serializeParticlesystem(ps);
|
||||
GLsizeiptr sizeOfParticle = 3 * sizeof(vector3f) + sizeof(float);
|
||||
|
||||
GLuint particleBuffer;
|
||||
glGenBuffers(1, &particleBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, PARTICLE_AMOUNT * sizeOfParticle, particles, GL_STATIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLuint vertexArray;
|
||||
glGenVertexArrays(1, &vertexArray);
|
||||
glBindVertexArray(vertexArray);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
|
||||
// position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)0);
|
||||
// color
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)24);
|
||||
glBindVertexArray(0);
|
||||
|
||||
/************* RENDER LOOP *************/
|
||||
double time, tFrame, tLast = 0;
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
time = glfwGetTime();
|
||||
tFrame = time - tLast;
|
||||
tLast = time;
|
||||
|
||||
/*** UPDATE ***/
|
||||
glUseProgram(computeShaderProgram);
|
||||
glUniform1f(dtUniformLocation, tFrame);
|
||||
glUniform1ui(seedUniformLocation, rand());
|
||||
glDispatchCompute((PARTICLE_AMOUNT / 256) + 1, 1, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
|
||||
|
||||
/*** RENDER ***/
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glBindVertexArray(vertexArray);
|
||||
glUseProgram(renderShaderProgram);
|
||||
glDrawArrays(GL_POINTS, 0, PARTICLE_AMOUNT);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
//END
|
||||
deleteShaders(renderShaders, 2);
|
||||
deleteShaders(computeShaders, 1);
|
||||
|
||||
terminateGLFW(window);
|
||||
freeParticleSystem(ps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void calcPos(particle *p, float dt)
|
||||
{
|
||||
p->position->x += p->velocity->x * dt;
|
||||
p->position->y += p->velocity->y * dt;
|
||||
p->position->z += p->velocity->z * dt;
|
||||
}
|
||||
|
||||
void calcCol(particle *p)
|
||||
{
|
||||
// p->color->x -= 0.01f;
|
||||
// p->color->y -= 0.01f;
|
||||
// p->color->z -= 0.01f;
|
||||
}
|
||||
|
||||
/*************************************************************************************************************/
|
||||
void initRandomParticles(emitter *e)
|
||||
{
|
||||
for (int i = 0; i < e->pamount; i++)
|
||||
{
|
||||
vector3f *pos = initVector3f(e->position->x, e->position->y, e->position->z);
|
||||
vector3f *dir = initVector3f(((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
|
||||
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
|
||||
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX);
|
||||
vector3f *color = initVector3f(((float) (rand() % 255)) / 255,
|
||||
((float) (rand() % 255)) / 255,
|
||||
((float) (rand() % 255)) / 255);
|
||||
(e->particles)[i] = initParticle(pos, dir, color, rand() / 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void printParticle(particle *v)
|
||||
{
|
||||
printVector(v->position);
|
||||
printf("; ");
|
||||
printVector(v->velocity);
|
||||
printf("; ");
|
||||
printVector(v->color);
|
||||
printf("; %f\n", v->age);
|
||||
}
|
||||
|
||||
void printVector(vector3f *v)
|
||||
{
|
||||
printf("(%f, %f, %f)", v->x, v->y, v->z);
|
||||
}
|
||||
|
||||
/// VERY OLD
|
||||
// glUseProgram(shaderProgram);
|
||||
// glBindVertexArray(vao);
|
||||
// glDrawArrays(GL_POINTS, 0, particleAmount);
|
||||
|
||||
// updateParticles((float) tFrame, ps, calcPos, calcCol);
|
||||
//
|
||||
// emitter *e;
|
||||
// particle *p;
|
||||
// vector3f *pos;
|
||||
// for (int j = 0; j < ps->eamount; j++)
|
||||
// {
|
||||
// e = (ps->emitters)[j];
|
||||
// for (int i = 0; i < e->pamount; i++)
|
||||
// {
|
||||
// p = (e->particles)[i];
|
||||
// pos = p->position;
|
||||
//
|
||||
// glColor3f(p->color->x, p->color->y, p->color->z);
|
||||
// glBegin(GL_POINTS);
|
||||
// glVertex3f(pos->x, pos->y, pos->z);
|
||||
// glEnd();
|
||||
// }
|
||||
// }
|
||||
|
||||
/// FEEDBACK TRANSFORM BEFORE
|
||||
// /*************** NEW ***************/
|
||||
// float *vertexData = serializeParticlesystem(ps);
|
||||
// unsigned int currentVertexBuffer = 0, currentTransformFeedbackBuffer = 1;
|
||||
// int buffersSize = 2;
|
||||
// unsigned int particleBuffers[buffersSize], transformFeedbackBuffers[buffersSize];
|
||||
//
|
||||
// glGenTransformFeedbacks(buffersSize, transformFeedbackBuffers);
|
||||
// glGenBuffers(buffersSize, particleBuffers);
|
||||
//
|
||||
// for (int i = 0; i < buffersSize; i++)
|
||||
// {
|
||||
// glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackBuffers[i]);
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[i]);
|
||||
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW);
|
||||
// glBindBufferBase(GL_TRANSFORM_FEEDBACK, 0, particleBuffers[i]);
|
||||
// }
|
||||
|
||||
// // position attribute
|
||||
// glEnableVertexAttribArray(0);
|
||||
// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)0);
|
||||
// // velocity attribute
|
||||
// glEnableVertexAttribArray(1);
|
||||
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
// // color attribute
|
||||
// glEnableVertexAttribArray(2);
|
||||
// glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
// // age attribute
|
||||
// glEnableVertexAttribArray(3);
|
||||
// glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(9 * sizeof(float)));
|
||||
|
||||
/// TRANSFORM FEEDBACK RENDER LOOP
|
||||
///*** UPDATE PARTICLES ***/
|
||||
//glEnable(GL_RASTERIZER_DISCARD);
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currentVertexBuffer]);
|
||||
//glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackBuffers[currentTransformFeedbackBuffer]);
|
||||
//glBeginTransformFeedback(GL_POINTS);
|
||||
//if (isFirst)
|
||||
//{
|
||||
//glDrawArrays(GL_POINTS, 0, particleAmount);
|
||||
//isFirst = !isFirst;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
//glDrawTransformFeedback(GL_POINTS, transformFeedbackBuffers[currentVertexBuffer]);
|
||||
//}
|
||||
//glEndTransformFeedback();
|
||||
//
|
||||
///*** RENDER PARTICLES ***/
|
||||
//glDisable(GL_RASTERIZER_DISCARD);
|
||||
//glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currentTransformFeedbackBuffer]);
|
||||
//glDrawTransformFeedback(GL_POINTS, transformFeedbackBuffers[currentTransformFeedbackBuffer]);
|
||||
//
|
||||
///***************************************************/
|
||||
//currentVertexBuffer = currentTransformFeedbackBuffer;
|
||||
//currentTransformFeedbackBuffer = !currentTransformFeedbackBuffer;
|
216
openglMain.c
Normal file
216
openglMain.c
Normal file
@ -0,0 +1,216 @@
|
||||
#include "particlesystem.h"
|
||||
#include "initOpenGL.h"
|
||||
|
||||
#define PARTICLE_AMOUNT 1000000
|
||||
#define WIDTH 800
|
||||
#define HEIGHT 800
|
||||
|
||||
int main()
|
||||
{
|
||||
/************* INIT *************/
|
||||
// Init OpenGL and GLFW
|
||||
initGLFW();
|
||||
setErrorCallbackGL();
|
||||
|
||||
int width = WIDTH, height = HEIGHT;
|
||||
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL");
|
||||
|
||||
setCurrentContextGL(window);
|
||||
setFramebufferSizeCallbackGL(window);
|
||||
|
||||
// glad
|
||||
initGlad();
|
||||
|
||||
/************* PARTICLE SYSTEM *************/
|
||||
vector3f *epos1 = initVector3f(0, 0, 0);
|
||||
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
|
||||
particle_system *ps = initParticleSystem(1);
|
||||
(ps->emitters)[0] = e1;
|
||||
initRandomParticles(e1);
|
||||
|
||||
/************* SHADER *************/
|
||||
const GLchar *computeShaderSource = "#version 460\n"
|
||||
"\n"
|
||||
"#define FLOAT_MAX 4294967296.0f\n"
|
||||
"\n"
|
||||
"struct particle\n"
|
||||
"{\n"
|
||||
" float px, py, pz;\n"
|
||||
" float vx, vy, vz;\n"
|
||||
" float cx, cy, cz;\n"
|
||||
" float age;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"layout(std430, binding = 0) buffer particles\n"
|
||||
"{\n"
|
||||
" particle p[];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"layout(location = 0) uniform float dt;\n"
|
||||
"layout(location = 1) uniform vec3 resetPos;\n"
|
||||
"layout(location = 2) uniform uint maxParticles;\n"
|
||||
"\n"
|
||||
"layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n"
|
||||
"\n"
|
||||
"uint hash(uvec3 seed)\n"
|
||||
"{\n"
|
||||
" uint hash;\n"
|
||||
" hash = (seed.x ^ 61u) ^ (seed.y >> 16u);\n"
|
||||
" hash *= 9u;\n"
|
||||
" hash = seed.z ^ (seed.x >> 4u);\n"
|
||||
" hash *= 0x27d4eb2du;\n"
|
||||
" hash = seed.y ^ (seed.z >> 15u);\n"
|
||||
" return hash;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"uint rand(uint seed)\n"
|
||||
"{\n"
|
||||
" // Xorshift algorithm from George Marsaglia's paper\n"
|
||||
" seed ^= (seed << 13u);\n"
|
||||
" seed ^= (seed >> 17u);\n"
|
||||
" seed ^= (seed << 5u);\n"
|
||||
" return seed;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" uint gid = gl_GlobalInvocationID.x;\n"
|
||||
"\n"
|
||||
" if (gid <= maxParticles)\n"
|
||||
" {\n"
|
||||
" particle part = p[gid];\n"
|
||||
"\n"
|
||||
" uint hash1 = hash(uvec3(uint(part.px * FLOAT_MAX), uint(part.cy * FLOAT_MAX), uint(part.vz * FLOAT_MAX)));\n"
|
||||
" uint hash2 = hash(uvec3(uint(part.vx * FLOAT_MAX), uint(part.py * FLOAT_MAX), uint(part.cz * FLOAT_MAX)));\n"
|
||||
" uint hash3 = hash(uvec3(uint(part.cx * FLOAT_MAX), uint(part.vy * FLOAT_MAX), uint(part.pz * FLOAT_MAX)));\n"
|
||||
" \n"
|
||||
" if (part.age < 0 || part.px > 1 || part.py > 1 || part.pz > 1 || part.px < -1 || part.py < -1 || part.pz < -1)\n"
|
||||
" {\n"
|
||||
" part.px = resetPos.x;\n"
|
||||
" part.py = resetPos.y;\n"
|
||||
" part.pz = resetPos.z;\n"
|
||||
"\n"
|
||||
" part.age = rand(hash(uvec3(hash1, hash2, hash3))) % (250 - 60 + 1) + 60;\n"
|
||||
"\n"
|
||||
" part.vx = (rand(hash1) % 2 == 0 ? 1 : -1) * float(rand(hash2)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.vy = (rand(hash3) % 2 == 0 ? 1 : -1) * float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.vz = (rand(hash2) % 2 == 0 ? 1 : -1) * float(rand(hash3)) * (1.0f / FLOAT_MAX);\n"
|
||||
"\n"
|
||||
" part.cx = float(rand(hash3)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.cy = float(rand(hash2)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" part.px += part.vx * dt;\n"
|
||||
" part.py += part.vy * dt;\n"
|
||||
" part.pz += part.vz * dt;\n"
|
||||
"\n"
|
||||
" part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
|
||||
" part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
|
||||
"\n"
|
||||
" part.age -= 0.01f;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" p[gid] = part;\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
const GLchar *vertexShaderSource = "#version 460\n"
|
||||
"\n"
|
||||
"layout(location = 0) in vec3 pos;\n"
|
||||
"layout(location = 1) in vec3 colIn;\n"
|
||||
"\n"
|
||||
"layout(location = 0) out vec3 colV;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" colV = colIn;\n"
|
||||
" gl_Position = vec4(pos, 1);\n"
|
||||
"}";
|
||||
|
||||
const GLchar *fragmentShaderSource = "#version 460\n"
|
||||
"\n"
|
||||
"layout(location = 0) in vec3 colV;\n"
|
||||
"layout(location = 0) out vec4 colOut;\n"
|
||||
"\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" colOut = vec4(colV, 1);\n"
|
||||
"}";
|
||||
|
||||
GLuint computeShader = compileShader(computeShaderSource, GL_COMPUTE_SHADER);
|
||||
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
GLuint computeShaders[] = { computeShader };
|
||||
GLuint computeShaderProgram = linkShaders(computeShaders, 1);
|
||||
glUseProgram(computeShaderProgram);
|
||||
GLint dtUniformLocation = glGetUniformLocation(computeShaderProgram, "dt");
|
||||
GLint resetPosUniformLocation = glGetUniformLocation(computeShaderProgram, "resetPos");
|
||||
glUniform3f(resetPosUniformLocation, e1->position->x, e1->position->y, e1->position->z);
|
||||
GLint maxParticlesUniformLocation = glGetUniformLocation(computeShaderProgram, "maxParticles");
|
||||
glUniform1ui(maxParticlesUniformLocation, PARTICLE_AMOUNT);
|
||||
|
||||
GLuint renderShaders[] = { vertexShader, fragmentShader };
|
||||
GLuint renderShaderProgram = linkShaders(renderShaders, 2);
|
||||
|
||||
float *particles = serializeParticlesystem(ps);
|
||||
GLsizeiptr sizeOfParticle = 3 * sizeof(vector3f) + sizeof(float);
|
||||
|
||||
GLuint particleBuffer;
|
||||
glGenBuffers(1, &particleBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, PARTICLE_AMOUNT * sizeOfParticle, particles, GL_DYNAMIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLuint vertexArray;
|
||||
glGenVertexArrays(1, &vertexArray);
|
||||
glBindVertexArray(vertexArray);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
|
||||
// position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)0);
|
||||
// color
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)24); // 32
|
||||
glBindVertexArray(0);
|
||||
|
||||
/************* RENDER LOOP *************/
|
||||
double time, tFrame, tLast = 0;
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
time = glfwGetTime();
|
||||
tFrame = time - tLast;
|
||||
tLast = time;
|
||||
|
||||
/*** UPDATE ***/
|
||||
glUseProgram(computeShaderProgram);
|
||||
glUniform1f(dtUniformLocation, tFrame);
|
||||
glDispatchCompute(PARTICLE_AMOUNT / 256, 1, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
|
||||
|
||||
/*** RENDER ***/
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glBindVertexArray(vertexArray);
|
||||
glUseProgram(renderShaderProgram);
|
||||
glDrawArrays(GL_POINTS, 0, PARTICLE_AMOUNT);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
//END
|
||||
deleteShaders(renderShaders, 2);
|
||||
deleteShaders(computeShaders, 1);
|
||||
|
||||
terminateGLFW(window);
|
||||
freeParticleSystem(ps);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "particlesystem.h"
|
||||
|
||||
@ -158,7 +159,7 @@ float *serializeParticlesystem(particle_system *ps)
|
||||
}
|
||||
|
||||
unsigned long particleBytesAmount = sizeof(vector3f) * 3 + sizeof(float);
|
||||
float *vert = malloc(particleBytesAmount * particleAmount);
|
||||
float *vert = malloc(particleAmount * particleBytesAmount);
|
||||
|
||||
emitter *e;
|
||||
particle *p;
|
||||
@ -168,6 +169,7 @@ float *serializeParticlesystem(particle_system *ps)
|
||||
for (int x = 0; x < e->pamount; x++)
|
||||
{
|
||||
p = e->particles[x];
|
||||
|
||||
// Position
|
||||
vert[j++] = p->position->x;
|
||||
vert[j++] = p->position->y;
|
||||
@ -190,3 +192,21 @@ float *serializeParticlesystem(particle_system *ps)
|
||||
|
||||
return vert;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inits random particles
|
||||
*/
|
||||
void initRandomParticles(emitter *e)
|
||||
{
|
||||
for (int i = 0; i < e->pamount; i++)
|
||||
{
|
||||
vector3f *pos = initVector3f(e->position->x, e->position->y, e->position->z);
|
||||
vector3f *dir = initVector3f(((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
|
||||
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
|
||||
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX);
|
||||
vector3f *color = initVector3f(((float) (rand() % 255)) / 255,
|
||||
((float) (rand() % 255)) / 255,
|
||||
((float) (rand() % 255)) / 255);
|
||||
(e->particles)[i] = initParticle(pos, dir, color, (float) (rand() % (UPPER_AGE - LOWER_AGE + 1) + LOWER_AGE));
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
#define UPPER_AGE 250
|
||||
#define LOWER_AGE 60
|
||||
|
||||
/*
|
||||
* A vector with three floats
|
||||
*/
|
||||
@ -107,4 +110,9 @@ void freeParticleSystem(particle_system *ps);
|
||||
/*
|
||||
* Creates float array out of a particle system
|
||||
*/
|
||||
float *serializeParticlesystem(particle_system *ps);
|
||||
float *serializeParticlesystem(particle_system *ps);
|
||||
|
||||
/*
|
||||
* Inits random particle
|
||||
*/
|
||||
void initRandomParticles(emitter *e);
|
@ -1,64 +0,0 @@
|
||||
#version 460 core
|
||||
#extension GL_ARB_compute_shader : enable
|
||||
#extension GL_ARB_shader_storage_buffer_object : enable
|
||||
|
||||
struct particle
|
||||
{
|
||||
vec3 pos;
|
||||
vec3 vel;
|
||||
vec3 col;
|
||||
float age;
|
||||
};
|
||||
|
||||
layout(std430, binding = 0) buffer particles
|
||||
{
|
||||
particle p[];
|
||||
};
|
||||
|
||||
uniform float dt;
|
||||
uniform vec3 resetPos;
|
||||
uniform uint seed;
|
||||
|
||||
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
float rand()
|
||||
{
|
||||
uint seedR;
|
||||
seedR = (seed * 1103515245u + 12345u);
|
||||
return float(seed) / 4294967296.0;
|
||||
}
|
||||
|
||||
vec3 rand3() {
|
||||
vec3 result;
|
||||
uint seedR;
|
||||
seedR = (seed * 1103515245u + 12345u);
|
||||
result.x = float(seed);
|
||||
seedR = (seed * 1103515245u + 12345u);
|
||||
result.y = float(seed);
|
||||
seedR = (seed * 1103515245u + 12345u);
|
||||
result.z = float(seed);
|
||||
return (result / 2147483648.0) - vec3(1,1,1);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint gid = gl_GlobalInvocationID.x;
|
||||
particle part = p[gid];
|
||||
|
||||
if (part.age < 0 || part.pos.x > 1 || part.pos.y > 1 || part.pos.z > 1
|
||||
|| part.pos.x < -1 || part.pos.y < -1 || part.pos.z < -1 )
|
||||
{
|
||||
part.pos = resetPos;
|
||||
part.vel = rand3();
|
||||
part.col = vec3(rand(), rand(), rand());
|
||||
part.age = rand() * 0x7fff * 0.01f;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
part.pos += part.vel * dt;
|
||||
part.age -= 0.01f;
|
||||
}
|
||||
|
||||
p[gid] = part;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
in vec3 colV;
|
||||
out vec4 colOut;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
colOut = vec4(colV, 1);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
layout(points) in;
|
||||
layout(points, max_vertices = 256) out;
|
||||
|
||||
in vec3 colV;
|
||||
out vec3 colG;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
colG = colV;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
layout (points) in;
|
||||
layout (points) out;
|
||||
layout (max_vertices = 40) out;
|
||||
|
||||
in vec3 pos0[];
|
||||
in vec3 vel0[];
|
||||
in vec3 col0[];
|
||||
in float age0[];
|
||||
|
||||
out vec3 posOut;
|
||||
out vec3 velOut;
|
||||
out vec3 colOut;
|
||||
out float ageOut;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (age0[0] < 0)
|
||||
{
|
||||
posOut = vec3(0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
posOut = pos0[0];
|
||||
velOut = vel0[0];
|
||||
colOut = col0[0];
|
||||
ageOut = age0[0] - 0.01f;
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#version 460 core
|
||||
|
||||
layout (location = 0) in vec3 pos; // the position variable has attribute position 0
|
||||
layout (location = 1) in vec3 vel; // the velocity variable has attribute position 1
|
||||
layout (location = 2) in vec3 col; // the color variable has attribute position 2
|
||||
layout (location = 3) in float age; // the age variable has attribute position 3
|
||||
|
||||
out vec3 pos0;
|
||||
out vec3 vel0;
|
||||
out vec3 col0;
|
||||
out float age0;
|
||||
|
||||
void main()
|
||||
{
|
||||
pos0 = pos;
|
||||
vel0 = vel;
|
||||
col0 = col;
|
||||
age0 = age;
|
||||
}
|
87
shaders/opengl/ComputeShader.glsl
Normal file
87
shaders/opengl/ComputeShader.glsl
Normal file
@ -0,0 +1,87 @@
|
||||
#version 460
|
||||
|
||||
#define FLOAT_MAX 4294967296.0f
|
||||
|
||||
struct particle
|
||||
{
|
||||
float px, py, pz;
|
||||
float vx, vy, vz;
|
||||
float cx, cy, cz;
|
||||
float age;
|
||||
};
|
||||
|
||||
layout(std430, binding = 0) buffer particles
|
||||
{
|
||||
particle p[];
|
||||
};
|
||||
|
||||
layout(location = 0) uniform float dt;
|
||||
layout(location = 1) uniform vec3 resetPos;
|
||||
layout(location = 2) uniform uint maxParticles;
|
||||
|
||||
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
uint hash(uvec3 seed)
|
||||
{
|
||||
uint hash;
|
||||
hash = (seed.x ^ 61u) ^ (seed.y >> 16u);
|
||||
hash *= 9u;
|
||||
hash = seed.z ^ (seed.x >> 4u);
|
||||
hash *= 0x27d4eb2du;
|
||||
hash = seed.y ^ (seed.z >> 15u);
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint rand(uint seed)
|
||||
{
|
||||
// Xorshift algorithm from George Marsaglia's paper
|
||||
seed ^= (seed << 13u);
|
||||
seed ^= (seed >> 17u);
|
||||
seed ^= (seed << 5u);
|
||||
return seed;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint gid = gl_GlobalInvocationID.x;
|
||||
|
||||
if (gid <= maxParticles)
|
||||
{
|
||||
particle part = p[gid];
|
||||
|
||||
uint hash1 = hash(uvec3(uint(part.px * FLOAT_MAX), uint(part.cy * FLOAT_MAX), uint(part.vz * FLOAT_MAX)));
|
||||
uint hash2 = hash(uvec3(uint(part.vx * FLOAT_MAX), uint(part.py * FLOAT_MAX), uint(part.cz * FLOAT_MAX)));
|
||||
uint hash3 = hash(uvec3(uint(part.cx * FLOAT_MAX), uint(part.vy * FLOAT_MAX), uint(part.pz * FLOAT_MAX)));
|
||||
|
||||
if (part.age < 0 || part.px > 1 || part.py > 1 || part.pz > 1 || part.px < -1 || part.py < -1 || part.pz < -1)
|
||||
{
|
||||
part.px = resetPos.x;
|
||||
part.py = resetPos.y;
|
||||
part.pz = resetPos.z;
|
||||
|
||||
part.age = rand(hash(uvec3(hash1, hash2, hash3))) % (250 - 60 + 1) + 60;
|
||||
|
||||
part.vx = (rand(hash1) % 2 == 0 ? 1 : -1) * float(rand(hash2)) * (1.0f / FLOAT_MAX);
|
||||
part.vy = (rand(hash3) % 2 == 0 ? -1 : 1) * float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
part.vz = (rand(hash2) % 2 == 0 ? 1 : -1) * float(rand(hash3)) * (1.0f / FLOAT_MAX);
|
||||
|
||||
part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
part.px += part.vx * dt;
|
||||
part.py += part.vy * dt;
|
||||
part.pz += part.vz * dt;
|
||||
|
||||
part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);
|
||||
|
||||
part.age -= 0.01f;
|
||||
}
|
||||
|
||||
p[gid] = part;
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
#version 460 core
|
||||
#version 460
|
||||
|
||||
layout(location = 0) in vec3 pos;
|
||||
layout(location = 1) in vec3 colIn;
|
||||
|
||||
out vec3 colV;
|
||||
layout(location = 0) out vec3 colV;
|
||||
|
||||
void main(void)
|
||||
{
|
368
vulkanMain.c
Normal file
368
vulkanMain.c
Normal file
@ -0,0 +1,368 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
#define APP_NAME "Vulkan Tutorial"
|
||||
#define APP_VERSION VK_MAKE_VERSION(0, 0, 0)
|
||||
#define ENGINE_NAME "Memobio Game Engine"
|
||||
#define ENGINE_VERSION VK_MAKE_VERSION(0, 0, 0)
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
#define ASSERT_SUCCESS(res)\
|
||||
if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; }
|
||||
#define ASSERT_GLFW_SUCCESS(res)\
|
||||
if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; }
|
||||
#define ASSERT_VK_SUCCESS(res)\
|
||||
if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; }
|
||||
#define BOOL_LITERAL(val)\
|
||||
val ? "True" : "False"
|
||||
#define HUMAN_READABLE(val)\
|
||||
val * 9.313226e-10
|
||||
|
||||
#define WIDTH 500
|
||||
#define HEIGHT 500
|
||||
|
||||
int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window,
|
||||
VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t *amountImages);
|
||||
void initAppInfo(VkApplicationInfo *appInfo);
|
||||
void initCreateInfo(VkApplicationInfo *appInfo, VkInstanceCreateInfo *instanceInfo);
|
||||
void initQueueInfo(VkDeviceQueueCreateInfo *queueInfo);
|
||||
void initDeviceInfo(VkDeviceQueueCreateInfo *queueInfo, VkDeviceCreateInfo *deviceInfo, VkPhysicalDeviceFeatures *features);
|
||||
void initImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChainImages, int index);
|
||||
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface);
|
||||
|
||||
void initSwapChainInfo(VkSwapchainCreateInfoKHR *swapChainCreateInfo, VkSurfaceKHR *surface);
|
||||
|
||||
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
|
||||
VkImageView *imageViews, uint32_t amountImages);
|
||||
|
||||
void shutdownGLFW(GLFWwindow *window);
|
||||
|
||||
int main()
|
||||
{
|
||||
VkInstance vkInstance;
|
||||
VkDevice device;
|
||||
VkSurfaceKHR surface;
|
||||
VkSwapchainKHR swapChain;
|
||||
VkImageView *imageViews = NULL;
|
||||
uint32_t amountImages;
|
||||
|
||||
// GLFW
|
||||
ASSERT_GLFW_SUCCESS(glfwInit())
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan Particlesystem", NULL, NULL);
|
||||
|
||||
// Init Vulkan
|
||||
ASSERT_SUCCESS(initVulkan(&vkInstance, &device, &surface, window, &swapChain, imageViews, &amountImages))
|
||||
|
||||
// Render Loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
// Stop Vulkan
|
||||
shutdownVulkan(&vkInstance, &device, &surface, &swapChain, imageViews, amountImages);
|
||||
|
||||
// Stop GLFW
|
||||
shutdownGLFW(window);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window,
|
||||
VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t *amountImages)
|
||||
{
|
||||
// VkApplicationInfo
|
||||
VkApplicationInfo appInfo;
|
||||
initAppInfo(&appInfo);
|
||||
|
||||
// VkInstanceCreateInfo
|
||||
uint32_t amountOfLayers;
|
||||
vkEnumerateInstanceLayerProperties(&amountOfLayers, NULL);
|
||||
VkLayerProperties layers[amountOfLayers];
|
||||
vkEnumerateInstanceLayerProperties(&amountOfLayers, layers);
|
||||
|
||||
VkInstanceCreateInfo instanceInfo;
|
||||
initCreateInfo(&appInfo, &instanceInfo);
|
||||
|
||||
// Vulkan Instance
|
||||
ASSERT_VK_SUCCESS(vkCreateInstance(&instanceInfo, NULL, vkInstance))
|
||||
|
||||
// Get physical device
|
||||
uint32_t amountOfPhysicalDevices = 0;
|
||||
ASSERT_VK_SUCCESS(vkEnumeratePhysicalDevices(*vkInstance, &amountOfPhysicalDevices, NULL)) // Let fill amount first automatically
|
||||
VkPhysicalDevice physicalDevices[amountOfPhysicalDevices]; // create array for physical devices
|
||||
ASSERT_VK_SUCCESS(vkEnumeratePhysicalDevices(*vkInstance, &amountOfPhysicalDevices, physicalDevices)) // Call again with array
|
||||
|
||||
// Create Window Surface
|
||||
ASSERT_VK_SUCCESS(glfwCreateWindowSurface(*vkInstance, window, NULL, surface))
|
||||
|
||||
printStats(&physicalDevices[0], surface);
|
||||
|
||||
// Queue info
|
||||
VkDeviceQueueCreateInfo queueInfo;
|
||||
initQueueInfo(&queueInfo);
|
||||
|
||||
// Device info
|
||||
VkPhysicalDeviceFeatures usedFeatures = {};
|
||||
VkDeviceCreateInfo deviceInfo;
|
||||
initDeviceInfo(&queueInfo, &deviceInfo, &usedFeatures);
|
||||
|
||||
// Logical device
|
||||
ASSERT_VK_SUCCESS(vkCreateDevice(physicalDevices[0], &deviceInfo, NULL, device))
|
||||
|
||||
// Queue
|
||||
VkQueue queue;
|
||||
vkGetDeviceQueue(*device, 0, 0, &queue);
|
||||
|
||||
// Swap chain support
|
||||
VkBool32 swapChainSupport;
|
||||
ASSERT_VK_SUCCESS(vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevices[0], 0, *surface, &swapChainSupport))
|
||||
if (!swapChainSupport)
|
||||
{
|
||||
printf("Swap chain not supported!");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Swap chain info
|
||||
VkSwapchainCreateInfoKHR swapChainCreateInfo;
|
||||
initSwapChainInfo(&swapChainCreateInfo, surface);
|
||||
|
||||
// Swap chain
|
||||
ASSERT_VK_SUCCESS(vkCreateSwapchainKHR(*device, &swapChainCreateInfo, NULL, swapChain))
|
||||
|
||||
// Swap chain images
|
||||
vkGetSwapchainImagesKHR(*device, *swapChain, amountImages, NULL);
|
||||
VkImage swapChainImages[*amountImages];
|
||||
ASSERT_VK_SUCCESS(vkGetSwapchainImagesKHR(*device, *swapChain, amountImages, swapChainImages))
|
||||
|
||||
// Image view
|
||||
imageViews = malloc(*amountImages * sizeof(VkImageView));
|
||||
VkImageViewCreateInfo imageViewInfo;
|
||||
for (int i = 0; i < *amountImages; i++)
|
||||
{
|
||||
initImageViewInfo(&imageViewInfo, swapChainImages, i);
|
||||
ASSERT_VK_SUCCESS(vkCreateImageView(*device, &imageViewInfo, NULL, &imageViews[i]))
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void initAppInfo(VkApplicationInfo *appInfo)
|
||||
{
|
||||
appInfo->sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo->pNext = NULL;
|
||||
appInfo->pApplicationName = APP_NAME;
|
||||
appInfo->applicationVersion = APP_VERSION;
|
||||
appInfo->pEngineName = ENGINE_NAME;
|
||||
appInfo->engineVersion = ENGINE_VERSION;
|
||||
appInfo->apiVersion = VK_API_VERSION_1_1;
|
||||
}
|
||||
|
||||
void initCreateInfo(VkApplicationInfo *appInfo, VkInstanceCreateInfo *instanceInfo)
|
||||
{
|
||||
GLuint amountOfGLFWExtensions;
|
||||
const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&amountOfGLFWExtensions);
|
||||
|
||||
instanceInfo->sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
instanceInfo->pNext = NULL;
|
||||
instanceInfo->flags = 0;
|
||||
instanceInfo->pApplicationInfo = appInfo;
|
||||
instanceInfo->enabledLayerCount = 0;
|
||||
instanceInfo->ppEnabledLayerNames = NULL;
|
||||
instanceInfo->enabledExtensionCount = amountOfGLFWExtensions;
|
||||
instanceInfo->ppEnabledExtensionNames = glfwExtensions;
|
||||
}
|
||||
|
||||
void initQueueInfo(VkDeviceQueueCreateInfo *queueInfo)
|
||||
{
|
||||
queueInfo->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueInfo->pNext = NULL;
|
||||
queueInfo->flags = 0;
|
||||
queueInfo->queueFamilyIndex = 0;
|
||||
queueInfo->queueCount = 1;
|
||||
queueInfo->pQueuePriorities = NULL;
|
||||
}
|
||||
|
||||
void initDeviceInfo(VkDeviceQueueCreateInfo *queueInfo, VkDeviceCreateInfo *deviceInfo, VkPhysicalDeviceFeatures *features)
|
||||
{
|
||||
const char *deviceExtensions[1] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
|
||||
deviceInfo->sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceInfo->pNext = NULL;
|
||||
deviceInfo->flags = 0;
|
||||
deviceInfo->queueCreateInfoCount = 1;
|
||||
deviceInfo->pQueueCreateInfos = queueInfo;
|
||||
deviceInfo->enabledLayerCount = 0;
|
||||
deviceInfo->ppEnabledLayerNames = NULL;
|
||||
deviceInfo->enabledExtensionCount = 1;
|
||||
deviceInfo->ppEnabledExtensionNames = deviceExtensions;
|
||||
deviceInfo->pEnabledFeatures = features;
|
||||
}
|
||||
|
||||
void initSwapChainInfo(VkSwapchainCreateInfoKHR *swapChainCreateInfo, VkSurfaceKHR *surface)
|
||||
{
|
||||
VkExtent2D imageExtent = { WIDTH, HEIGHT };
|
||||
|
||||
swapChainCreateInfo->sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swapChainCreateInfo->pNext = NULL;
|
||||
swapChainCreateInfo->flags = 0;
|
||||
swapChainCreateInfo->surface = *surface;
|
||||
swapChainCreateInfo->minImageCount = 1;
|
||||
swapChainCreateInfo->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
swapChainCreateInfo->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
swapChainCreateInfo->imageExtent = imageExtent;
|
||||
swapChainCreateInfo->imageArrayLayers = 1;
|
||||
swapChainCreateInfo->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapChainCreateInfo->imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapChainCreateInfo->queueFamilyIndexCount = 0;
|
||||
swapChainCreateInfo->pQueueFamilyIndices = NULL;
|
||||
swapChainCreateInfo->preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
swapChainCreateInfo->compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapChainCreateInfo->presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
swapChainCreateInfo->clipped = VK_FALSE;
|
||||
swapChainCreateInfo->oldSwapchain = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void initImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChainImages, int index)
|
||||
{
|
||||
VkComponentMapping componentMapping = {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY
|
||||
};
|
||||
VkImageSubresourceRange subresourceRange = {
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,0, 1, 0, 1
|
||||
};
|
||||
|
||||
imageViewInfo->sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewInfo->pNext = NULL;
|
||||
imageViewInfo->flags = 0;
|
||||
imageViewInfo->image = swapChainImages[index];
|
||||
imageViewInfo->viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewInfo->format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
imageViewInfo->components = componentMapping;
|
||||
imageViewInfo->subresourceRange = subresourceRange;
|
||||
}
|
||||
|
||||
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
|
||||
VkImageView *imageViews, uint32_t amountImages)
|
||||
{
|
||||
vkDeviceWaitIdle(*device);
|
||||
|
||||
for (int i = 0; i < amountImages; i++)
|
||||
{
|
||||
vkDestroyImageView(*device, imageViews[i], NULL);
|
||||
}
|
||||
|
||||
vkDestroySwapchainKHR(*device, *swapChain, NULL);
|
||||
vkDestroySurfaceKHR(*vkInstance, *surface, NULL);
|
||||
vkDestroyDevice(*device, NULL);
|
||||
vkDestroyInstance(*vkInstance, NULL);
|
||||
}
|
||||
|
||||
void shutdownGLFW(GLFWwindow *window)
|
||||
{
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface)
|
||||
{
|
||||
// Device Properties
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(*physicalDevice, &properties);
|
||||
|
||||
printf("--------- DEVICE PROPERTIES ---------\n");
|
||||
uint32_t apiVersion = properties.apiVersion;
|
||||
printf("Name: %s\n", properties.deviceName);
|
||||
printf("API Version: %d.%d.%d\n", VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion));
|
||||
|
||||
// Features
|
||||
VkPhysicalDeviceFeatures features;
|
||||
vkGetPhysicalDeviceFeatures(*physicalDevice, &features);
|
||||
|
||||
printf("\n--------- FEATURES ---------\n");
|
||||
printf("Geometry Shader: %s\n", (BOOL_LITERAL(features.geometryShader)));
|
||||
printf("Tessellation Shader: %s\n", (BOOL_LITERAL(features.tessellationShader)));
|
||||
|
||||
// Memory Properties
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(*physicalDevice, &memoryProperties);
|
||||
|
||||
printf("\n--------- MEMORY PROPERTIES ---------\n");
|
||||
printf("Heapsize: %llu Byte / %f GiB\n", memoryProperties.memoryHeaps->size,
|
||||
(HUMAN_READABLE(memoryProperties.memoryHeaps->size)));
|
||||
|
||||
// Queue Properties
|
||||
uint32_t amountQueueFamilies = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &amountQueueFamilies, NULL);
|
||||
VkQueueFamilyProperties familyProperties[amountQueueFamilies];
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &amountQueueFamilies, familyProperties);
|
||||
|
||||
printf("\n--------- QUEUE PROPERTIES ---------\n");
|
||||
printf("Queue Families Amount: %d\n", amountQueueFamilies);
|
||||
|
||||
for (int i = 0; i < amountQueueFamilies; i++)
|
||||
{
|
||||
printf("-- Queue Family #%d --\n", i);
|
||||
printf(" Graphics bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)));
|
||||
printf(" Compute bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)));
|
||||
printf(" Transfer bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)));
|
||||
printf(" Sparse Binding bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0)));
|
||||
printf(" Queue Count: %d\n", familyProperties[i].queueCount);
|
||||
}
|
||||
|
||||
// Surface Capabilities
|
||||
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(*physicalDevice, *surface, &surfaceCapabilities);
|
||||
printf("\n--------- SURFACE CAPABILITIES ---------\n");
|
||||
printf(" Min Image Count: %d\n", surfaceCapabilities.minImageCount);
|
||||
printf(" Max Image Count: %d\n", surfaceCapabilities.maxImageCount);
|
||||
printf(" Current Extent: (%d; %d)\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height);
|
||||
printf(" Min Image Extent: (%d; %d)\n", surfaceCapabilities.minImageExtent.width, surfaceCapabilities.minImageExtent.height);
|
||||
printf(" Max Image Extent: (%d; %d)\n", surfaceCapabilities.maxImageExtent.width, surfaceCapabilities.maxImageExtent.height);
|
||||
printf(" Max Image Array Layers: %d\n", surfaceCapabilities.maxImageArrayLayers);
|
||||
printf(" Supported Transforms: %d\n", surfaceCapabilities.supportedTransforms);
|
||||
printf(" Current Transform: %d\n", surfaceCapabilities.currentTransform);
|
||||
printf(" Supported Composite Alpha: %d\n", surfaceCapabilities.supportedCompositeAlpha);
|
||||
printf(" Supported Usage Flags: %d\n", surfaceCapabilities.supportedUsageFlags);
|
||||
|
||||
// Surface Formats
|
||||
uint32_t amountFormats;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(*physicalDevice, *surface, &amountFormats, NULL);
|
||||
VkSurfaceFormatKHR formats[amountFormats];
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(*physicalDevice, *surface, &amountFormats, formats);
|
||||
|
||||
printf("\n--------- SURFACE FORMATS ---------\n");
|
||||
printf("Surface Formats Amount: %d\n", amountFormats);
|
||||
|
||||
for (int i = 0; i < amountFormats; i++)
|
||||
{
|
||||
printf("-- Surface Format #%d --\n", i);
|
||||
printf(" Format: %d\n", formats[i].format);
|
||||
}
|
||||
|
||||
// Presentation Modes
|
||||
uint32_t amountPresentModes;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(*physicalDevice, *surface, &amountPresentModes, NULL);
|
||||
VkPresentModeKHR presentModes[amountPresentModes];
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(*physicalDevice, *surface, &amountPresentModes, presentModes);
|
||||
|
||||
printf("\n--------- PRESENTATION MODES ---------\n");
|
||||
printf("Presentation Modes Amount: %d\n", amountPresentModes);
|
||||
|
||||
for (int i = 0; i < amountPresentModes; ++i)
|
||||
{
|
||||
printf("-- Present Mode #%d --\n", i);
|
||||
printf(" Mode: %d\n", presentModes[i]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user