diff --git a/src/Main.cpp b/src/Main.cpp index 7a89d8f..960b7d0 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -16,62 +16,8 @@ constexpr int SWAP_INTERVAL = 1; constexpr int TRANSFORMATION_COUNT = 3; -static const std::vector SIERPINSKI_TRIANGLE = { - { - 0.5f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.5f, - 0.0f, - 0.36f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.5f, - 0.0f, - 0.0f, - -0.5f, - 0.0f, - 0.5f, - 0.0f, - -0.5f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, - { - 0.5f, - 0.0f, - 0.0f, - 0.5f, - 0.0f, - 0.5f, - 0.0f, - -0.5f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f, - }, -}; +constexpr float ANIMATION_TIME = 2; +constexpr float ANIMATION_STILL_TIME = 1; class Timer { public: @@ -143,14 +89,36 @@ struct Transform { return translate; } + + Transform Blend(const Transform& other, const std::function& a_Lerp, float dt) { + return { + a_Lerp(m_ScaleX, other.m_ScaleX, dt), + a_Lerp(m_ScaleY, other.m_ScaleY, dt), + a_Lerp(m_ScaleZ, other.m_ScaleZ, dt), + a_Lerp(m_RotationX, other.m_RotationX, dt), + a_Lerp(m_RotationY, other.m_RotationY, dt), + a_Lerp(m_RotationZ, other.m_RotationZ, dt), + a_Lerp(m_ShearXY, other.m_ShearXY, dt), + a_Lerp(m_ShearXZ, other.m_ShearXZ, dt), + a_Lerp(m_ShearYX, other.m_ShearYX, dt), + a_Lerp(m_ShearYZ, other.m_ShearYZ, dt), + a_Lerp(m_ShearZX, other.m_ShearZX, dt), + a_Lerp(m_ShearZY, other.m_ShearZY, dt), + a_Lerp(m_TranslateX, other.m_TranslateX, dt), + a_Lerp(m_TranslateY, other.m_TranslateY, dt), + a_Lerp(m_TranslateZ, other.m_TranslateZ, dt), + }; + } }; -static void GenNewFractal() { +static std::vector s_T1, s_T2; + +static std::vector GenRandomFractal() { // scale, rotation, shear, translation - std::vector transformations(TRANSFORMATION_COUNT); + std::vector transforms(TRANSFORMATION_COUNT); - for (std::size_t i = 0; i < transformations.size(); i++) { + for (std::size_t i = 0; i < transforms.size(); i++) { Transform transform; transform.m_ScaleX = s_Distrib(s_Generator) * 0.4 + 0.4; transform.m_ScaleY = s_Distrib(s_Generator) * 0.4 + 0.4; @@ -171,10 +139,15 @@ static void GenNewFractal() { transform.m_TranslateY = s_Distrib(s_Generator) * 1.2f - 0.6f; transform.m_TranslateZ = s_Distrib(s_Generator) * 1.2f - 0.6f; - transformations[i] = transform.ToMatrix(); + transforms[i] = transform; } - ApplyTransforms(transformations); + return transforms; +} + +static void GenNewFractal() { + std::swap(s_T1, s_T2); + s_T2 = GenRandomFractal(); } static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { @@ -188,7 +161,7 @@ static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, i s_ComputeShader = ReloadComputeShader(s_ComputeShader, s_ComputeShaderPath); s_GraphicsShader = ReloadGraphicsShader(s_GraphicsShader, s_VertexShaderPath, s_FragmentShaderPath); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * PARTICLE_COUNT * 3, nullptr, GL_DYNAMIC_COPY); - ApplyTransforms(SIERPINSKI_TRIANGLE); + GenNewFractal(); } if (key == GLFW_KEY_T) { @@ -223,6 +196,27 @@ static void CreateGpuBuffer() { GL_DYNAMIC_COPY); // sizeof(data) only works for statically sized C/C++ arrays. } +static std::vector GetTransformMatrixBlended(float dt) { + std::vector result(TRANSFORMATION_COUNT); + + constexpr auto lerp = [](float x, float y, float t){ + return x * (1 - t) + y * t; + }; + + constexpr auto eased = [lerp](float x, float y, float t){ + return lerp(x, y, -(std::cos(3.14 * t) - 1.0f) / 2.0f); + }; + + float blendFactor = std::min(ANIMATION_TIME, dt) / ANIMATION_TIME; + + for (std::size_t i = 0; i < result.size(); i++) { + auto blended = s_T1[i].Blend(s_T2[i], eased, blendFactor); + result[i] = blended.ToMatrix(); + } + + return result; +} + static GLFWwindow* InitWindow() { glfwSetErrorCallback(ErrorCallback); @@ -282,11 +276,13 @@ int main() { int fps = 0; float secondsTimer = 0.0f; + float animationTimer = 0.0f; glBindVertexArray(vertexArray); // ApplyTransforms(SIERPINSKI_TRIANGLE); - GenNewFractal(); + s_T1 = GenRandomFractal(); + s_T2 = GenRandomFractal(); glClearColor(0.4f, 0.4f, 0.4f, 1.0f); @@ -298,18 +294,26 @@ int main() { lastTime = currentTime; secondsTimer += dt; + animationTimer += dt; if (secondsTimer >= 1.0f) { std::string title = "FPS : " + std::to_string(fps); glfwSetWindowTitle(window, title.c_str()); secondsTimer = 0.0f; fps = 0; - + } + + if (animationTimer >= ANIMATION_TIME + ANIMATION_STILL_TIME) { + animationTimer = 0; GenNewFractal(); } // Compute glUseProgram(s_ComputeShader); + + auto matricies = GetTransformMatrixBlended(animationTimer); + glUniformMatrix4fv(1, matricies.size(), false, glm::value_ptr(matricies[0])); + glDispatchCompute(PARTICLE_COUNT / WORK_GROUP_SIZE, 1, 1); // Ensure all writes to the image are complete