A little toolkit for single-quad fragment shader demos
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.1 KiB

  1. #include <memory>
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <imgui.h>
  5. #include <imgui_impl_glfw_gl3.h>
  6. #include <GL/gl3w.h>
  7. #include <GLFW/glfw3.h>
  8. #include "gui.h"
  9. #include "state.h"
  10. #include "notify.h"
  11. #define CLEAR_COLOR 0.0, 0.0, 0.0, 1.0
  12. static void glfw_error_callback(int error, const char* description) {
  13. std::cerr << "GLFW error " << error << " " << description << '\n';
  14. }
  15. // static void glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
  16. // if (key == GLFW_KEY_R && mods == GLFW_MOD_CONTROL && action == GLFW_PRESS) {
  17. // printf("...\n");
  18. // }
  19. // }
  20. int main(int argc, char* argv[]) {
  21. glfwSetErrorCallback(glfw_error_callback);
  22. if (!glfwInit()){
  23. // glfw init failed; crash out
  24. std::clog << "GLFW: init failed; exiting.\n";
  25. std::exit(-1);
  26. }
  27. // request at least OpenGL v3.3
  28. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  29. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  30. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  31. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  32. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
  33. auto window = glfwCreateWindow(1024, 768, "Zinnia", NULL, NULL);
  34. if (!window) {
  35. // window creation failed
  36. glfwTerminate();
  37. std::clog << "GLFW: failed to create window; exiting.\n";
  38. return EXIT_FAILURE;
  39. }
  40. glfwMakeContextCurrent(window);
  41. glfwSwapInterval(1);
  42. if (gl3wInit()) {
  43. std::clog << "Failed to initialize OpenGL\n";
  44. return EXIT_FAILURE;
  45. }
  46. std::cout << "[GL] OpenGL v" << glGetString(GL_VERSION)
  47. << ", GLSL v" << glGetString(GL_SHADING_LANGUAGE_VERSION) << '\n';
  48. ImGui_ImplGlfwGL3_Init(window, true);
  49. // demo state
  50. auto config = Config::from_file("../config.toml");
  51. auto state = DemoState(std::make_shared<Config>(config));
  52. auto inotify = NotifyService();
  53. // set up a GUI state
  54. auto gui = Gui(&state);
  55. if (argc == 2) {
  56. auto proj = Project::fromFile(std::string(argv[1]));
  57. inotify.watch(*proj);
  58. state.current_project = std::move(proj);
  59. }
  60. const GLfloat v_quad[][2] = {
  61. {1, 1}, {1, -1}, {-1, -1}, {-1, 1},
  62. };
  63. const GLuint i_quad[] = {
  64. 0, 1, 3,
  65. 1, 2, 3,
  66. };
  67. GLuint vao, vbo, ebo;
  68. glGenVertexArrays(1, &vao);
  69. glGenBuffers(1, &ebo);
  70. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  71. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(i_quad), i_quad, GL_STATIC_DRAW);
  72. glBindVertexArray(vao);
  73. glGenBuffers(1, &vbo);
  74. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  75. glBufferData(GL_ARRAY_BUFFER, sizeof(v_quad), v_quad, GL_STATIC_DRAW);
  76. glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
  77. glEnableVertexAttribArray(0);
  78. glBindVertexArray(0);
  79. double t, t_prev, dt;
  80. unsigned long frame_n = 0;
  81. glfwSetTime(0); t_prev = glfwGetTime();
  82. while(!glfwWindowShouldClose(window) && state.running) {
  83. t = glfwGetTime();
  84. dt = t - t_prev; t_prev = t;
  85. glfwPollEvents();
  86. ImGui_ImplGlfwGL3_NewFrame();
  87. glfwGetFramebufferSize(window, &state.width, &state.height);
  88. state.ratio = (float)state.width / (float)state.height;
  89. glViewport(0, 0, (float)state.width, (float)state.height);
  90. glClearColor(CLEAR_COLOR);
  91. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  92. if (state.current_project != nullptr) {
  93. if (state.current_project->scene_loaded) {
  94. auto prog = *state.current_project->current_scene->shader_p;
  95. auto u_resolution = glGetUniformLocation(prog, "u_Resolution");
  96. auto u_mouse = glGetUniformLocation(prog, "u_Mouse");
  97. auto u_time = glGetUniformLocation(prog, "u_Time");
  98. double m_x, m_y;
  99. glfwGetCursorPos(window, &m_x, &m_y);
  100. glUseProgram(prog);
  101. glUniform2f(u_resolution, (float)state.width, (float)state.height);
  102. glUniform4f(u_mouse, m_x, m_y, 0., 0.);
  103. glUniform1f(u_time, t);
  104. glBindVertexArray(vao);
  105. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  106. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  107. glBindVertexArray(0);
  108. }
  109. }
  110. gui.render();
  111. ImGui::Render();
  112. glfwSwapBuffers(window);
  113. if ((frame_n % 10) == 0) {
  114. inotify._poll();
  115. }
  116. std::cout << std::flush;
  117. std::cerr << std::flush;
  118. frame_n++;
  119. }
  120. ImGui_ImplGlfwGL3_Shutdown();
  121. glfwDestroyWindow(window);
  122. glfwTerminate();
  123. return 0;
  124. }