#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
const char* vertex_fractal = "#version 450 core\n"
"layout(location = 0) in vec3 aPos;\n"
"out vec3 FragPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0f);\n"
" FragPos = aPos;\n"
"}\0";
const char* fragment_fractal = "#version 450 core\n"
"in vec3 FragPos;\n"
"uniform vec4 transform;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" vec2 z;\n"
" vec2 c = vec2(FragPos) * transform.zw + transform.xy;\n"
" float r = 2.0;\n"
" float iter;\n"
" int max_iter = 100;\n"
" for(iter = 0; iter < max_iter; iter++)\n"
" {\n"
" z = vec2(z.x*z.x - z.y*z.y, 2*z.x*z.y) + c;\n"
" if(length(z) > r) break;\n"
" }\n"
" if(iter == max_iter) discard;\n"
" else FragColor = vec4(iter / max_iter, 0, 0, 1);\n"
"}\0";
void Framebuffer_Size_Callback(GLFWwindow* window, int width, int height);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void GetInput(GLFWwindow* window);
unsigned int Screen_Width, Screen_Height;
const bool full_screen = false;
//past = previous time, lag = difference in time, scale = zoom amount, (xpos, ypos) = pos, zvel = zoom velocity,
//acc = acceleration, frict = frictional or oppposing force, max = maximum position
float past, lag, aspect, scale, xscale, yscale, xpos, ypos, xvel, yvel, zvel;
const float xacc = 0.1f, yacc = 0.1f, zacc = 0.01f, xfrict = 0.95f, yfrict = 0.95f, zfrict = 0.95f, xmin = -2.0f, xmax = 2.0f, ymin = -2.0f, ymax = 2.0f;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window;
if (full_screen)
{
const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
Screen_Width = mode->width;
Screen_Height = mode->height;
window = glfwCreateWindow(mode->width, mode->height, "Voxel Engine", glfwGetPrimaryMonitor(), NULL);
}
else
{
Screen_Width = 1000;
Screen_Height = 800;
window = glfwCreateWindow(Screen_Width, Screen_Height, "OpenGL1", NULL, NULL);
}
if (window == NULL)
{
std::cout << "GLFW window creation failed" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, Framebuffer_Size_Callback);
glfwSetScrollCallback(window, scroll_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Glad initialization failed" << std::endl;
glfwTerminate();
return -1;
}
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init();
//these are the vertices used to draw a rectangle covering the whole screen.
float fractal_vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
};
//this code will generate the vaos and vbos that the graphics card will use.
//the "Shader" class is a custom class.
Shader shader_fractal(vertex_fractal, fragment_fractal);
unsigned int fractal_vao, fractal_vbo;
glGenVertexArrays(1, &fractal_vao);
glGenBuffers(1, &fractal_vbo);
glBindVertexArray(fractal_vao);
glBindBuffer(GL_ARRAY_BUFFER, fractal_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(fractal_vertices), fractal_vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glm::vec4 transform;
aspect = (float)Screen_Width / (float)Screen_Height;
scale = 1.0f;
xscale = scale;
yscale = scale;
xpos = 0.0f;
ypos = 0.0f;
if (aspect > 1.0f) yscale /= aspect;
else xscale *= aspect;
while (!glfwWindowShouldClose(window))
{
GetInput(window);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
float time = (float)glfwGetTime();
lag = time - past;
past = time;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
xvel *= xfrict;
yvel *= yfrict;
zvel *= zfrict;
xpos += xvel;
ypos += yvel;
if (xpos < xmin)
{
xpos = xmin;
xvel = 0;
}
if (xpos > xmax)
{
xpos = xmax;
xvel = 0;
}
if (ypos < ymin)
{
ypos = ymin;
yvel = 0;
}
if (ypos > ymax)
{
ypos = ymax;
yvel = 0;
}
xscale *= 1 - zvel;
yscale *= 1 - zvel;
transform = glm::vec4(xpos, ypos, xscale, yscale);
shader_fractal.Use();
shader_fractal.SetVec4("transform", transform);
glBindVertexArray(fractal_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
ImGui::Begin("Settings");
if (ImGui::Button("Exit")) glfwSetWindowShouldClose(window, true);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &fractal_vao);
glDeleteBuffers(1, &fractal_vbo);
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwTerminate();
return 0;
}
void Framebuffer_Size_Callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void GetInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
yvel -= yacc * yscale * lag;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
yvel += yacc * yscale * lag;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
xvel -= xacc * xscale * lag;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
xvel += xacc * xscale * lag;
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
zvel += yoffset * zacc;
}