commit c2aa6601fedb944bfdbfef3d356626cafe9db466
parent 9425d42e4ffc29df695f8ea321a230efc1b734bc
Author: bsandro <email@bsandro.tech>
Date: Thu, 16 Oct 2025 01:27:52 +0300
I'll try to figure out tesselation
Diffstat:
| M | .gitignore | | | 1 | + |
| M | Makefile | | | 10 | +++++----- |
| A | main.c | | | 107 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | main1.c | | | 1 | + |
| M | main2.c | | | 267 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
5 files changed, 265 insertions(+), 121 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,3 +3,4 @@
main3
main3o
test1
+test2
diff --git a/Makefile b/Makefile
@@ -1,12 +1,12 @@
all:
- ${CC} main1.c -std=gnu23 -Wpedantic -Os -s -fomit-frame-pointer -ffast-math -fno-stack-protector -march=native -fwrapv -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables -fmerge-all-constants -fno-ident -lm -lGL -lGLU -lX11 -Wl,--gc-sections -o test1
+ ${CC} main2.c -std=gnu23 -Wpedantic -Os -s -fomit-frame-pointer -ffast-math -fno-stack-protector -march=native -fwrapv -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables -fmerge-all-constants -fno-ident -lm -lGL -lGLU -lX11 -Wl,--gc-sections -o test2
min: all
- strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag ./test1
- upx -9 ./test1
+ strip -S --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag ./test2
+ upx -9 ./test2
clean:
- rm -f ./test1 ./main3
+ rm -f ./test1 ./test2 ./main3
main3: clean
${CC} -Os -s -fomit-frame-pointer -nostdlib main3.c -o main3o -Wl,-dynamic-linker,/usr/lib64/ld-linux-x86-64.so.2 -Wl,--no-as-needed /usr/lib64/libdl.so.2 /usr/lib64/libc.so
@@ -16,4 +16,4 @@ main3: clean
chmod +x main3
run: min
- ./test1
+ ./test2
diff --git a/main.c b/main.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+Display *dpy;
+Window win;
+Bool doubleBuffer = True;
+
+GLfloat xAngle = 42.0;
+GLfloat yAngle = 82.0;
+GLfloat zAngle = 112.0;
+
+static int sngBuf[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 12,
+ None };
+
+static int dblBuf[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 12,
+ GLX_DOUBLEBUFFER,
+ None };
+
+static void fatalError(char *str) {
+ fprintf(stderr, "%s\n", str);
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ XVisualInfo *vinfo = NULL;
+ Colormap cmap;
+ XSetWindowAttributes winattr;
+ GLXContext ctx;
+ XEvent event;
+ int dummy;
+
+ if (!(dpy = XOpenDisplay(NULL))) {
+ fatalError("cannot open display");
+ }
+
+ if (!glXQueryExtension(dpy, &dummy, &dummy)) {
+ fatalError("x server has no opengl glx extension");
+ }
+
+ if (!(vinfo = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf))) {
+ if (!(vinfo = glXChooseVisual(dpy, DefaultScreen(dpy), sngBuf))) {
+ fatalError("no rgb visual with depth buffer");
+ }
+ doubleBuffer = False;
+ }
+ if (vinfo->class != TrueColor) {
+ fatalError("TrueColor required");
+ }
+
+ if (!(ctx = glXCreateContext(dpy, vinfo, None, True))) {
+ fatalError("could not create rendering context");
+ }
+
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vinfo->screen), vinfo->visual, AllocNone);
+ winattr.colormap = cmap;
+ winattr.border_pixel = 0;
+ winattr.event_mask = ExposureMask|ButtonPressMask|StructureNotifyMask;
+ win = XCreateWindow(dpy, RootWindow(dpy, vinfo->screen),0,0,300,300,0,
+ vinfo->depth, InputOutput, vinfo->visual,
+ CWBorderPixel|CWColormap|CWEventMask, &winattr);
+ XSetStandardProperties(dpy, win, "glxsimple", "glxsimple", None, argv, argc, NULL);
+
+ glXMakeCurrent(dpy, win, ctx);
+ XMapWindow(dpy, win);
+
+ glEnable(GL_DEPTH_TEST);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
+
+ int keepRunning = 1;
+ while (keepRunning) {
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &event);
+ switch (event.type) {
+ case ButtonPress:
+ switch (event.xbutton.button) {
+ case 1: xAngle += 10.0; break;
+ case 2: yAngle += 10.0; break;
+ case 3: zAngle += 10.0; break;
+ }
+ break;
+ case ConfigureNotify:
+ glViewport(0, 0, event.xconfigure.width, event.xconfigure.height);
+ case Expose:
+ // needRedraw = True;
+ break;
+ }
+ }
+ }
+
+ printf("ok\n");
+ return 0;
+}
diff --git a/main1.c b/main1.c
@@ -1,3 +1,4 @@
+/* basic vertex+fragment shaders */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/main2.c b/main2.c
@@ -1,162 +1,197 @@
-/* tri.c - Minimal X11 + GL/GLU + GLX program drawing one triangle with shaders.
- Build:
- gcc -o tri tri.c -lX11 -lGL -lGLU
- Run:
- ./tri
-*/
-#define GL_GLEXT_PROTOTYPES 1
+/* tesselation */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
+#include <math.h>
+#include <X11/X.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
-#include <GL/glu.h>
#include <GL/glx.h>
+#include <GL/glu.h>
-static const char *vert_src =
-"#version 120\n" /* GLSL 1.10 for wide compatibility */
-"attribute vec3 pos;"
-"void main() { gl_Position = vec4(pos, 1.0); }";
+static const GLint attr[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
-static const char *frag_src =
-"#version 120\n"
-"void main() { gl_FragColor = vec4(0.8, 0.4, 0.2, 1.0); }";
+static const double current_ts() {
+ struct timespec ts;
+ timespec_get(&ts, TIME_UTC);
+ return (double)ts.tv_sec + (double)ts.tv_nsec/1e9;
+}
-static GLuint compile_shader(GLenum type, const char *src) {
- GLuint s = glCreateShader(type);
- glShaderSource(s, 1, &src, NULL);
- glCompileShader(s);
+static double t_started;
+
+//@todo move shaders to separate files
+static const GLchar *vertexSrc = " \n\
+#version 420 \n\
+in vec2 position; \n\
+in vec3 inColor; \n\
+out vec3 color; \n\
+void main() { \n\
+ gl_Position = vec4(position, 0.0, 1.0); \n\
+ color = inColor; \n\
+} \n\
+";
+
+static const GLchar *fragmentSrc = " \n\
+#version 420 \n\
+uniform double iTime; \n\
+in vec3 color; \n\
+out vec4 outColor; \n\
+void main() { \n\
+ float c1 = abs(sin(float(iTime))); \n\
+ float c2 = abs(cos(float(iTime))); \n\
+ outColor = vec4(color+c1-c2, 1.0); \n\
+} \n\
+";
+
+static GLuint mkShader(GLenum type, const GLchar *src) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &src, NULL);
+ glCompileShader(shader);
GLint ok = 0;
- glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
if (!ok) {
- char buf[1024];
- GLsizei len = 0;
- glGetShaderInfoLog(s, sizeof(buf)-1, &len, buf);
- fprintf(stderr, "Shader compile error: %.*s\n", (int)len, buf);
- exit(1);
+ static char buf[512] = {0};
+ glGetShaderInfoLog(shader, sizeof(buf)-1, NULL, buf);
+ fprintf(stderr, "Shader %d compile error: %s\n", (int)type, buf);
}
- return s;
+ return shader;
}
-static GLuint link_program(GLuint vs, GLuint fs) {
- GLuint p = glCreateProgram();
- glAttachShader(p, vs);
- glAttachShader(p, fs);
- glBindAttribLocation(p, 0, "pos"); /* ensure attribute location 0 for simplicity */
- glLinkProgram(p);
- GLint ok = 0;
- glGetProgramiv(p, GL_LINK_STATUS, &ok);
- if (!ok) {
- char buf[1024];
- GLsizei len = 0;
- glGetProgramInfoLog(p, sizeof(buf)-1, &len, buf);
- fprintf(stderr, "Program link error: %.*s\n", (int)len, buf);
- exit(1);
- }
- return p;
+static GLuint linkProgram(GLuint vertex, GLuint fragment) {
+ GLuint shaderProgram = glCreateProgram();
+ glAttachShader(shaderProgram, vertex);
+ glAttachShader(shaderProgram, fragment);
+ glBindAttribLocation(shaderProgram, 0, "position");
+ glBindFragDataLocation(shaderProgram, 0, "outColor");
+ glLinkProgram(shaderProgram);
+ return shaderProgram;
+}
+
+void __attribute__((constructor)) start() {
+ printf("start()\n");
+ t_started = current_ts();
}
-int main(void) {
+void __attribute((destructor)) end() {
+ printf("end()\n");
+}
+
+int main(int argc, char *argv[]) {
Display *dpy = XOpenDisplay(NULL);
- if (!dpy) {
- fprintf(stderr, "Unable to open X display\n");
- return 1;
+ XSetWindowAttributes swa;
+ Window win;
+ XWindowAttributes gwa;
+ XEvent xev;
+
+
+ if (dpy == NULL) {
+ printf("\n\tcannot connect to X server\n\n");
+ exit(0);
}
- /* Choose a visual */
- static int att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
- XVisualInfo *vi = glXChooseVisual(dpy, DefaultScreen(dpy), att);
- if (!vi) {
- fprintf(stderr, "No appropriate visual found\n");
- return 1;
+ Window root = DefaultRootWindow(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, 0, attr);
+
+ if (vi == NULL) {
+ printf("\n\tno appropriate visual found\n\n");
+ exit(0);
+ } else {
+ printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */
}
- Colormap cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
- XSetWindowAttributes swa;
+ Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
swa.colormap = cmap;
- swa.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask;
-
- Window win = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
- 0, 0, 640, 480, 0, vi->depth, InputOutput,
- vi->visual, CWColormap | CWEventMask, &swa);
- XStoreName(dpy, win, "Minimal GL Triangle");
+ swa.event_mask = ExposureMask | KeyPressMask;
+ win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XMapWindow(dpy, win);
-
- /* Create GLX context */
+ XStoreName(dpy, win, "OPENGL");
GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
- if (!ctx) {
- fprintf(stderr, "Failed to create GLX context\n");
- return 1;
- }
glXMakeCurrent(dpy, win, ctx);
- /* Compile shaders and link program */
- GLuint vs = compile_shader(GL_VERTEX_SHADER, vert_src);
- GLuint fs = compile_shader(GL_FRAGMENT_SHADER, frag_src);
- GLuint prog = link_program(vs, fs);
+ GLuint vao;
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
- /* Triangle vertices (preset) */
- const GLfloat verts[] = {
- 0.0f, 0.6f, 0.0f,
- -0.6f, -0.4f, 0.0f,
- 0.6f, -0.4f, 0.0f
+ // [x, y, r, g, b]
+ static const GLfloat vertices[] = {
+ 0.01f, 0.01f, 1.0f, 0.0f, 0.0f,
+ 0.8f, 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.8f, 0.0f, 0.0f, 1.0f,
+
+ -0.01f, -0.01f, 0.0f, 0.0f, 1.0f,
+ -0.8f, 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, -0.8f, 1.0f, 0.0f, 0.0f,
+
+ 0.3f, 0.3f, 1.0f, 0.0f, 0.0f,
+ 0.3f, 0.6f, 1.0f, 0.0f, 0.0f,
+ 0.6f, 0.3f, 1.0f, 0.0f, 0.0f,
+ 0.6f, 0.6f, 1.0f, 0.0f, 0.0f
+ };
+
+ static const GLuint elements[] = {
+ 0, 1, 5,
+ 3, 2, 4,
+ 6, 7, 8,
+ 7, 8, 9
};
- /* Create simple VBO */
- GLuint vbo = 0;
+ GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+ GLuint ebo;
+ glGenBuffers(1, &ebo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
- /* Set up GL state */
- glViewport(0, 0, 640, 480);
- glClearColor(0.15f, 0.18f, 0.20f, 1.0f);
+ GLuint vertex = mkShader(GL_VERTEX_SHADER, vertexSrc);
+ GLuint fragment = mkShader(GL_FRAGMENT_SHADER, fragmentSrc);
+ GLuint shaderPrg = linkProgram(vertex, fragment);
- /* Main loop */
- int running = 1;
- while (running) {
+ while (1) {
while (XPending(dpy)) {
- XEvent xe;
- XNextEvent(dpy, &xe);
- if (xe.type == Expose) {
- /* ignore */
- } else if (xe.type == ConfigureNotify) {
- XConfigureEvent *ce = (XConfigureEvent*)&xe;
+ XEvent xev;
+ XNextEvent(dpy, &xev);
+ if (xev.type == Expose) {
+ XGetWindowAttributes(dpy, win, &gwa);
+ glViewport(0, 0, gwa.width, gwa.height);
+ } else if (xev.type == KeyPress) {
+ printf("btn:%d\n", xev.xbutton.button);
+ if (xev.xbutton.button==24||xev.xbutton.button==9) {
+ glXMakeCurrent(dpy, None, NULL);
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+ exit(0);
+ }
+ } else if (xev.type == ConfigureNotify) {
+ XConfigureEvent *ce = (XConfigureEvent *)&xev;
glViewport(0, 0, ce->width, ce->height);
- } else if (xe.type == KeyPress) {
- running = 0; /* exit on any key */
- } else if (xe.type == DestroyNotify) {
- running = 0;
}
}
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClearColor(0.1f, 0.1f, 0.15f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
- glUseProgram(prog);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+ GLfloat iTime = glGetUniformLocation(shaderPrg, "iTime");
+ glUniform1d(iTime, current_ts()-t_started);
+ //printf("%f\n", fabsf(sinf(current_ts()-t_started)));
- glDrawArrays(GL_TRIANGLES, 0, 3);
+ glUseProgram(shaderPrg);
- glDisableVertexAttribArray(0);
- glUseProgram(0);
+ GLint position = glGetAttribLocation(shaderPrg, "position");
+ glEnableVertexAttribArray(position);
+ glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), 0);
+ GLint color = glGetAttribLocation(shaderPrg, "inColor");
+ glEnableVertexAttribArray(color);
+ glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void *)(2*sizeof(GLfloat)));
+ glDrawElements(GL_TRIANGLES, sizeof(elements), GL_UNSIGNED_INT, 0);
glXSwapBuffers(dpy, win);
- /* Simple CPU-side sleep to limit spin (not required) */
- usleep(1000 * 16);
+ usleep(1000*16);
}
-
- /* Cleanup */
- glDeleteBuffers(1, &vbo);
- glDeleteProgram(prog);
- glDeleteShader(vs);
- glDeleteShader(fs);
- glXMakeCurrent(dpy, None, NULL);
- glXDestroyContext(dpy, ctx);
- XDestroyWindow(dpy, win);
- XCloseDisplay(dpy);
- return 0;
}