comments + fixed dragging

This commit is contained in:
Lauchmelder 2022-02-19 14:43:01 +01:00
parent 4bb7c3fcbe
commit d245c7fbf5
No known key found for this signature in database
GPG key ID: C2403C69D78F011D
4 changed files with 78 additions and 44 deletions

View file

@ -3,7 +3,7 @@
#
cmake_minimum_required (VERSION 3.8)
project ("Mandelbrot")
project ("Julia")
set(IMGUI_SOURCE_DIR "${CMAKE_SOURCE_DIR}/vendor/imgui")

View file

@ -10,17 +10,21 @@
Application::Application() :
window(new Window(1280, 720, "Julia Sets")), canvas(nullptr)
{
// Make the window's context the current one
window->MakeContextCurrent();
// Load OpenGL functions
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
throw std::runtime_error("GLAD failed to initialize.");
}
// Set viewport
glViewport(0, 0, 1280, 720);
canvas = new Canvas();
// Set up ImGUI
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
@ -30,17 +34,19 @@ Application::Application() :
ImGui::StyleColorsDark();
// Set UserData
data.lastMousePos = { 0.0, 0.0 };
data.mouseDelta = { 0.0, 0.0 };
data.wheel = { 0.0, 0.0 };
// set user data pointer and install callbacks
GLFWwindow* nativeHandle = window->GetHandle();
glfwSetWindowUserPointer(nativeHandle, (void*)&data);
if (glfwRawMouseMotionSupported())
glfwSetInputMode(nativeHandle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
// Just store scroll wheel info in the user pointer
glfwSetScrollCallback(nativeHandle,
[] (GLFWwindow* window, double x, double y)
{
@ -63,6 +69,7 @@ void Application::Launch()
{
while (!window->ShouldClose())
{
// Recalculate the julia set
canvas->CalculateJuliaSet();
glfwPollEvents();
@ -73,51 +80,26 @@ void Application::Launch()
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Render julia set
canvas->Render();
// Get julia set properties & recalculate aspect ratio
JuliaProperties& props = canvas->GetProperties();
int width, height;
window->GetWindowSize(width, height);
props.aspectRatio = (float)height / (float)width;
double mouseX, mouseY;
glfwGetCursorPos(window->GetHandle(), &mouseX, &mouseY);
data.mouseDelta.x = mouseX - data.lastMousePos.x;
data.mouseDelta.y = mouseY - data.lastMousePos.y;
data.lastMousePos.x = mouseX;
data.lastMousePos.y = mouseY;
float xSize = props.xBounds[1] - props.xBounds[0];
if (glfwGetMouseButton(window->GetHandle(), GLFW_MOUSE_BUTTON_LEFT))
{
float stepSize = xSize / (float)width;
props.xBounds[0] -= data.mouseDelta.x * stepSize;
props.xBounds[1] -= data.mouseDelta.x * stepSize;
props.yCenter += data.mouseDelta.y * stepSize;
}
if (data.wheel.y != 0.0)
{
props.xBounds[0] += data.wheel.y * (xSize / 10.0f);
props.xBounds[1] -= data.wheel.y * (xSize / 10.0f);
}
data.wheel = { 0.0, 0.0 };
// Properties of the GPUs work capabilities
const WorkProperties& workProps = canvas->GetWorkProperties();
// Render ImGui window
ImGui::Begin("Julia Set Properties");
ImGui::SliderInt("max iterations", (int*)&props.maxIterations, 10, 1000);
ImGui::SliderFloat("max color", &props.iterationColorCutoff, 10, 1000);
ImGui::SliderInt("texture width", (int*)&props.textureWidth, 480, 2560);
ImGui::SliderFloat2("c param", props.c, -1.5f, 1.5f);
ImGui::SliderInt("Max Iterations", (int*)&props.maxIterations, 10, 1000);
ImGui::SliderFloat("Color Threshold", &props.iterationColorCutoff, 10, 1000);
ImGui::SliderInt("Texture Width", (int*)&props.textureWidth, 480, 2560);
ImGui::SliderFloat2("c", props.c, -1.5f, 1.5f);
if (ImGui::Button(props.doublePrecision ? "Double Precision" : "Single Precision"))
props.doublePrecision = !props.doublePrecision;
@ -128,6 +110,42 @@ void Application::Launch()
ImGui::Text("Max group sizes - x: %i, y: %i, z: %i", workProps.groupSize[0], workProps.groupSize[1], workProps.groupSize[2]);
ImGui::Text("Max invocations - %i", workProps.maxInvocations);
// calculate mouse delta
double mouseX, mouseY;
glfwGetCursorPos(window->GetHandle(), &mouseX, &mouseY);
data.mouseDelta.x = mouseX - data.lastMousePos.x;
data.mouseDelta.y = mouseY - data.lastMousePos.y;
data.lastMousePos.x = mouseX;
data.lastMousePos.y = mouseY;
// Size of the domain (x direction)
float xSize = props.xBounds[1] - props.xBounds[0];
// Camera panning handling
ImVec2 min = ImGui::GetWindowPos();
ImVec2 max = { min.x + ImGui::GetWindowWidth(), min.y + ImGui::GetWindowHeight() };
if (!ImGui::IsMouseHoveringRect(min, max) && glfwGetMouseButton(window->GetHandle(), GLFW_MOUSE_BUTTON_LEFT))
{
float stepSize = xSize / (float)width;
props.xBounds[0] -= data.mouseDelta.x * stepSize;
props.xBounds[1] -= data.mouseDelta.x * stepSize;
props.yCenter += data.mouseDelta.y * stepSize;
}
// Zooming
if (data.wheel.y != 0.0)
{
props.xBounds[0] += data.wheel.y * (xSize / 10.0f);
props.xBounds[1] -= data.wheel.y * (xSize / 10.0f);
}
data.wheel = { 0.0, 0.0 };
ImGui::End();
ImGui::Render();

View file

@ -4,19 +4,19 @@
cmake_minimum_required (VERSION 3.8)
# Add source to this project's executable.
add_executable (Mandelbrot "main.cpp" "Window.cpp" "Application.cpp" "Canvas.cpp" "Shader.cpp")
add_executable (julia "main.cpp" "Window.cpp" "Application.cpp" "Canvas.cpp" "Shader.cpp")
target_sources(Mandelbrot PRIVATE
target_sources(julia PRIVATE
${IMGUI_SOURCE_FILES}
)
target_include_directories(Mandelbrot PRIVATE
target_include_directories(julia PRIVATE
glfw
glad
${IMGUI_INCLUDE_DIRS}
)
target_link_libraries(Mandelbrot
target_link_libraries(julia
glfw
glad
)

View file

@ -15,6 +15,7 @@ double Map(double fromMin, double fromMax, double toMin, double toMax, double va
Canvas::Canvas() :
vao(0), vbo(0), texture(0)
{
// Default Julia properties
properties.xBounds[0] = -2.5f;
properties.xBounds[1] = 2.5f;
properties.yCenter = 0.0f;
@ -47,8 +48,10 @@ Canvas::~Canvas()
void Canvas::Render()
{
// Wait for compute shader to finish
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
// Render texture to screen
shader.Use();
glBindTexture(GL_TEXTURE_2D, texture);
@ -58,44 +61,54 @@ void Canvas::Render()
void Canvas::CalculateJuliaSet()
{
// Wait for previous calculation to finish
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
// width and height of the target texture
int width = properties.textureWidth;
int height = properties.textureWidth * properties.aspectRatio;
// domain in y direction
float yLength = (properties.xBounds[1] - properties.xBounds[0]) * properties.aspectRatio;
float yMin = properties.yCenter - 0.5f * yLength;
float yMax = properties.yCenter + 0.5f * yLength;
// Bind our texture object
glBindTexture(GL_TEXTURE_2D, texture);
// Set texture properties (linear filtering)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Re-create empty texture with right dimensions
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
glGenerateMipmap(GL_TEXTURE_2D);
// Prepare texture for use in the compute shader
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
// Decide whether to use single- or double precision shader
if (properties.doublePrecision)
doubleComputeShader.Use();
else
computeShader.Use();
// Set uniforms for shader
glUniform2f(1, properties.xBounds[0], properties.xBounds[1]);
glUniform2f(2, yMin, yMax);
glUniform2f(3, properties.c[0], properties.c[1]);
glUniform1i(4, properties.maxIterations);
glUniform1f(5, properties.iterationColorCutoff);
// Calculate Julia set
glDispatchCompute(width, height, 1);
// delete[] image;
}
void Canvas::CreateVertexArrayObject()
{
// Create simple quad
float vertices[4 * (2 + 2)] = {
-1.0f, -1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
@ -119,6 +132,8 @@ void Canvas::CreateVertexArrayObject()
void Canvas::CreateShaderProgram()
{
// Create the render shader
// It simply renders the texture to a quad
std::string vertexShaderSource = R"(
#version 460 core
@ -157,6 +172,7 @@ void Canvas::CreateCompueShader()
{
QueryWorkGroupInfo();
// Create compute shader
std::string shaderSource = R"(
#version 460 core
@ -209,6 +225,7 @@ void Canvas::CreateCompueShader()
doubleComputeShader.AttachComputeShader(shaderSource);
doubleComputeShader.Link();
// Single precision shader is the exact same, except different datatypes
shaderSource = std::regex_replace(shaderSource, std::regex("double"), "float");
shaderSource = std::regex_replace(shaderSource, std::regex("dvec2"), "vec2");
computeShader.AttachComputeShader(shaderSource);
@ -218,12 +235,11 @@ void Canvas::CreateCompueShader()
void Canvas::CreateTexture()
{
glGenTextures(1, &texture);
// CalculateJuliaSet();
}
void Canvas::QueryWorkGroupInfo()
{
// Get infor about the GPUs work group props
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &workProperties.groupCount[0]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &workProperties.groupCount[1]);
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &workProperties.groupCount[2]);