Skip to content

Instantly share code, notes, and snippets.

@giuliohome
Last active September 13, 2021 22:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save giuliohome/d841bbddae00f30e5161670e3782290f to your computer and use it in GitHub Desktop.
Save giuliohome/d841bbddae00f30e5161670e3782290f to your computer and use it in GitHub Desktop.
IMGUI + GLFW
// Include GLFW
#include <GLFW/glfw3.h>
extern GLFWwindow* window; // The "extern" keyword here is to access the variable "window" declared in tutorialXXX.cpp. This is a hack to keep the tutorials simple. Please avoid this.
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include "controls.hpp"
glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 getViewMatrix(){
return ViewMatrix;
}
glm::mat4 getProjectionMatrix(){
return ProjectionMatrix;
}
// Initial position : on +Z
glm::vec3 position = glm::vec3( 0, 0, 3 );
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 0.0f;
// Initial Field of View
float initialFoV = 45.0f;
float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;
float mydistance = 5.0f;
void computeMatricesFromImGui(
float mydistanceImGui,
float horizontalAngleImGui,
float verticalAngleImGui
){
// glfwGetTime is called only once, the first time this function is called
static double lastTime = glfwGetTime();
// Compute time difference between current and last frame
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
// Direction : Spherical coordinates to Cartesian coordinates conversion
glm::vec3 direction(
cos(verticalAngleImGui) * sin(horizontalAngleImGui),
sin(verticalAngleImGui),
cos(verticalAngleImGui) * cos(horizontalAngleImGui)
);
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngleImGui - 3.14f/2.0f),
0,
cos(horizontalAngleImGui - 3.14f/2.0f)
);
// Up vector
glm::vec3 up = glm::cross( right, direction );
float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
ViewMatrix = glm::lookAt(
- direction * vec3(mydistanceImGui,mydistanceImGui,mydistanceImGui), // Camera is here
vec3(0,0,0), // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
// For the next frame, the "last time" will be "now"
lastTime = currentTime;
}
void computeMatricesFromKeyboarInputs(){
// glfwGetTime is called only once, the first time this function is called
static double lastTime = glfwGetTime();
// Compute time difference between current and last frame
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
// vertical rotation forward
if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS){
verticalAngle += 0.01f;
}
// vertical rotation backward
if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS){
verticalAngle += - 0.01f;
}
// horizontal rotation right
if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
horizontalAngle += - 0.01f;
}
// horizontal rotation left
if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS){
horizontalAngle += 0.01f;
}
if (glfwGetKey( window, GLFW_KEY_PAGE_UP ) == GLFW_PRESS){
mydistance += 0.01f;
}
if (glfwGetKey( window, GLFW_KEY_PAGE_DOWN ) == GLFW_PRESS){
mydistance += -0.01f;
}
// Direction : Spherical coordinates to Cartesian coordinates conversion
glm::vec3 direction(
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f/2.0f),
0,
cos(horizontalAngle - 3.14f/2.0f)
);
// Up vector
glm::vec3 up = glm::cross( right, direction );
float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
ViewMatrix = glm::lookAt(
- direction * vec3(mydistance,mydistance,mydistance), // Camera is here
vec3(0,0,0), // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
// For the next frame, the "last time" will be "now"
lastTime = currentTime;
}
void computeMatricesFromInputs(){
// glfwGetTime is called only once, the first time this function is called
static double lastTime = glfwGetTime();
// Compute time difference between current and last frame
double currentTime = glfwGetTime();
float deltaTime = float(currentTime - lastTime);
// Get mouse position
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
// Reset mouse position for next frame
glfwSetCursorPos(window, 1024/2, 768/2);
// Compute new orientation
horizontalAngle += mouseSpeed * float(1024/2 - xpos );
verticalAngle += mouseSpeed * float( 768/2 - ypos );
// Direction : Spherical coordinates to Cartesian coordinates conversion
glm::vec3 direction(
cos(verticalAngle) * sin(horizontalAngle),
sin(verticalAngle),
cos(verticalAngle) * cos(horizontalAngle)
);
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f/2.0f),
0,
cos(horizontalAngle - 3.14f/2.0f)
);
// Up vector
glm::vec3 up = glm::cross( right, direction );
// Move forward
if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS){
position += direction * deltaTime * speed;
}
// Move backward
if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS){
position -= direction * deltaTime * speed;
}
// Strafe right
if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
position += right * deltaTime * speed;
}
// Strafe left
if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS){
position -= right * deltaTime * speed;
}
float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
ProjectionMatrix = glm::perspective(glm::radians(FoV), 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
ViewMatrix = glm::lookAt(
position, // Camera is here
position+direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
// For the next frame, the "last time" will be "now"
lastTime = currentTime;
}
#ifndef CONTROLS_HPP
#define CONTROLS_HPP
#include <glm/glm.hpp>
void computeMatricesFromInputs();
void computeMatricesFromKeyboarInputs();
void computeMatricesFromImGui(
float mydistance,
float horizontalAngle,
float verticalAngle
);
glm::mat4 getViewMatrix();
glm::mat4 getProjectionMatrix();
#endif
# Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
#
# You will need GLFW (http://www.glfw.org):
# Linux:
# apt-get install libglfw-dev
# Mac OS X:
# brew install glfw
# MSYS2:
# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw
#
#CXX = g++
#CXX = clang++
EXE = imgui_tut08
IMGUI_DIR = /run/media/giuliohome/Acer/Fedora/dev/gnome/imgui-master
OGL_DIR = /run/media/giuliohome/Acer/dev/c++/opengl/ogl
SOURCES = $(OGL_DIR)/common/texture.cpp $(OGL_DIR)/common/controls.cpp $(OGL_DIR)/common/shader.cpp $(OGL_DIR)/common/objloader.cpp tutorial08_imgui.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
LINUX_GL_LIBS = -lGLEW_1130 -lglfw -lz -lglut -lGL -lGLU -lgtkmm-4.0 -ldl
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/run/media/giuliohome/Acer/dev/c++/opengl/ogl/external/glew-1.13.0/include -I$(OGL_DIR) -I$(OGL_DIR)/tutorial08_basic_shading
CXXFLAGS += -g -Wall -Wformat
LIBS = -L/run/media/giuliohome/Acer/dev/c++/opengl/ogl/build/external
ECHO_MESSAGE = "$(EXE) on Linux"
LIBS += $(LINUX_GL_LIBS) `cat ../compile_libs.txt`
CXXFLAGS += `cat ../compile_libs.txt`
CFLAGS = $(CXXFLAGS)
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(OGL_DIR)/common/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(OGL_DIR)/tutorial08_basic_shading/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
all: $(EXE)
@echo Build complete for $(ECHO_MESSAGE)
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)
// Dear ImGui: standalone example application for GLFW + OpenGL 3, using programmable pipeline
#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}
int main( void )
{
// Setup window
glfwSetErrorCallback(glfw_error_callback);
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}
// GL 3.2 + GLSL 150
const char* glsl_version = "#version 150";
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 08 - Basic Shading", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
glfwSwapInterval(1); // Enable vsync
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
// Our state
bool show_demo_window = false;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 0.0f;
// zoom in&out
float mydistance = 5.0f;
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
glfwPollEvents();
glfwSetCursorPos(window, 1024/2, 768/2);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
// Cull triangles which normal is not towards the camera
glEnable(GL_CULL_FACE);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "StandardShading.vertexshader", "StandardShading.fragmentshader" );
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
GLuint ViewMatrixID = glGetUniformLocation(programID, "V");
GLuint ModelMatrixID = glGetUniformLocation(programID, "M");
// Load the texture
GLuint Texture = loadDDS("uvmap.DDS");
// Get a handle for our "myTextureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler");
// Read our .obj file
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
bool res = loadOBJ("suzanne.obj", vertices, uvs, normals);
// Load it into a VBO
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);
GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
// Get a handle for our "LightPosition" uniform
glUseProgram(programID);
GLuint LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
// IMGUI
do{
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromImGui(
mydistance,
horizontalAngle,
verticalAngle
);
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(4,4,4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
/*{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}*/
{
ImGui::Begin("Perspective Controls");
ImGui::SliderFloat("Distance", &mydistance, 3.0f, 7.0f);
ImGui::SliderFloat("Horizontal Angle", &horizontalAngle, - 3.14f, 3.14f);
ImGui::SliderFloat("Vertical Angle", &verticalAngle, - 3.14f, 3.14f);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// Rendering
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteBuffers(1, &normalbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &Texture);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment