Skip to content

Instantly share code, notes, and snippets.

@yne
Last active August 18, 2024 17:37
Show Gist options
  • Save yne/5095dbc85b1ba34ca3a2079006b9931c to your computer and use it in GitHub Desktop.
Save yne/5095dbc85b1ba34ca3a2079006b9931c to your computer and use it in GitHub Desktop.
mode7 style tilemap X11+GL (require a 32x32 ./sprite.bmp)
//c99 main.c -o ../main -lX11 -lGL -lGLU && cd .. && ./main
#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <GL/gl.h>
#include <GL/glx.h>
GLuint texture[1];
int initGL(GLfloat width,GLfloat height){
typedef uint8_t Sprite[32*32*3];
Sprite pixels[2];
FILE*f=fopen("sprite.bmp","rb");
fseek(f,122,SEEK_SET);
fread(pixels,1,sizeof(pixels),f);
fclose(f);
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, 32, 64, 0, GL_BGR, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLfloat ratio = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble fH = 0.06854;//tan(fovY/360*pi)*zNear;
GLdouble fW = fH * ratio;
glFrustum( -fW, fW, -fH, fH, 0.1f, 100.0f );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 1;
}
GLfloat xpos=.0,ypos=.0,zpos=-3.,xrot=.0,yrot=.0,zrot=.0;
int drawGLScene(GLvoid){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(xpos, ypos, zpos);
glRotatef(xrot*10,0,1,0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
typedef struct{float tx,ty,vx,vy,vz;}Node;
Node nodes[2][4]={{
{0, 0,-.5,-.5, .5},
{1, 0, .5,-.5, .5},
{1,.5, .5,-.5,-.5},
{0,.5,-.5,-.5,-.5},
},{
{0,.5,-.5,-.5, .5},
{1,.5, .5,-.5, .5},
{1, 1, .5,-.5,-.5},
{0, 1,-.5,-.5,-.5},
}};
int tex[]={
1,1,1,1,
1,0,0,1,
1,0,0,1,
1,1,1,1,
};
for(int i=0;i<16;i++){
for(Node*n=nodes[tex[i]];n<nodes[tex[i]]+(sizeof(nodes[tex[i]])/sizeof(**nodes));n++){
glTexCoord2f(n->tx, n->ty),glVertex3f(n->vx+(i%4), n->vy, n->vz+(i/4));
}
}
glEnd();
return(1);
}
int main(int argc, char *argv[]) {
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
Display*dpy = XOpenDisplay(NULL);
Window root = DefaultRootWindow(dpy);
XVisualInfo*vi = glXChooseVisual(dpy, 0, (GLint[]){GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None});
XSetWindowAttributes swa={
.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone),
.event_mask = ExposureMask | KeyPressMask
};
Window win = XCreateWindow(dpy, root, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
XMapWindow(dpy, win);
GLXContext glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
glXMakeCurrent(dpy, win, glc);
initGL(SCREEN_WIDTH,SCREEN_HEIGHT);
while(1){
XEvent xev;
if(XCheckWindowEvent(dpy, win, KeyPressMask, &xev)){
if(xev.type == KeyPress){
if(xev.xkey.keycode==9)break;
if(xev.xkey.keycode>=110 && xev.xkey.keycode<=117)
*((GLfloat*[]){&xrot,&zpos,&ypos,&xpos,&xpos,&xrot,&zpos,&ypos}[xev.xkey.keycode-110])+=xev.xkey.keycode&1?.1f:-.1f;
else
printf("unk code %i\n",xev.xkey.keycode);
printf("pos<%.2f %.2f %.2f> rot<%.2f %.2f %.2f>\n",xpos,ypos,zpos,xrot,yrot,zrot);
}else if(xev.type == Expose){
XWindowAttributes gwa;
XGetWindowAttributes(dpy, win, &gwa);
}
}
drawGLScene();
glXSwapBuffers(dpy, win);
}
glXMakeCurrent(dpy, None, NULL);
glXDestroyContext(dpy, glc);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment