Skip to content

Instantly share code, notes, and snippets.

@japajoe
Last active January 24, 2024 11:09
Show Gist options
  • Save japajoe/62670f36b36c68f98eec599586606791 to your computer and use it in GitHub Desktop.
Save japajoe/62670f36b36c68f98eec599586606791 to your computer and use it in GitHub Desktop.
OpenGL context with X11 and Glad
//Compiling:
//g++ main.cpp -o app -lX11 -lGL -ldl
//Don't forget to add glad to your sources
#include <X11/Xlib.h>
#include "glad/glad.h"
#include <GL/glx.h>
#include <iostream>
static int CreateTriangle();
static void DestroyTriangle();
static void RenderTriangle();
GLuint vertexShader = 0;
GLuint fragmentShader = 0;
GLuint shaderProgram = 0;
GLuint VAO = 0;
GLuint VBO = 0;
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
const char *vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
)";
const char *fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(1.0, 0.5, 0.2, 1.0);
}
)";
int main()
{
Display *display;
Window window;
XEvent event;
GLXContext glContext;
// Open a connection to the X server
display = XOpenDisplay(NULL);
if (display == NULL) {
fprintf(stderr, "Unable to open display\n");
return 1;
}
// Create a window
window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 400, 300, 0, 0, None);
XSelectInput(display, window, ExposureMask | KeyPressMask | StructureNotifyMask);
XMapWindow(display, window);
// Set up GLX
int glxAttribs[] = {GLX_RGBA, GLX_DOUBLEBUFFER, None};
XVisualInfo *visualInfo = glXChooseVisual(display, DefaultScreen(display), glxAttribs);
glContext = glXCreateContext(display, visualInfo, NULL, GL_TRUE);
glXMakeCurrent(display, window, glContext);
if(!gladLoadGLLoader((GLADloadproc)glXGetProcAddress))
{
return -1;
}
CreateTriangle();
// Event loop
while (1) {
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
{
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderTriangle();
glXSwapBuffers(display, window);
break;
}
case ConfigureNotify:
{
int width = event.xconfigure.width;
int height = event.xconfigure.height;
glViewport(0, 0, width, height);
break;
}
case KeyPress:
{
break;
}
}
}
DestroyTriangle();
// Close the connection to the X server
glXMakeCurrent(display, None, NULL);
glXDestroyContext(display, glContext);
XCloseDisplay(display);
return 0;
}
int CreateTriangle()
{
// Create and compile the vertex shader
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for shader compilation errors
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(vertexShader, sizeof(infoLog), NULL, infoLog);
fprintf(stderr, "Vertex shader compilation failed:\n%s\n", infoLog);
return -1;
}
// Create and compile the fragment shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for shader compilation errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(fragmentShader, sizeof(infoLog), NULL, infoLog);
fprintf(stderr, "Fragment shader compilation failed:\n%s\n", infoLog);
return -1;
}
// Create a shader program and link the shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for shader program linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
fprintf(stderr, "Shader program linking failed:\n%s\n", infoLog);
return -1;
}
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
return 0;
}
void DestroyTriangle()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void RenderTriangle()
{
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment