Skip to content

Instantly share code, notes, and snippets.

@neuro-sys
Created November 22, 2019 17:36
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 neuro-sys/866fc1a47e3a2c2cc0675cc33babd02e to your computer and use it in GitHub Desktop.
Save neuro-sys/866fc1a47e3a2c2cc0675cc33babd02e to your computer and use it in GitHub Desktop.
// Compile: cc minimal.c `pkg-config glew sdl2 SDL2_image --libs --cflags` -lm
// Download: https://0fps.files.wordpress.com/2013/07/terrain.png
#include <stdio.h>
#include <GL/glew.h>
#include <SDL.h>
#include <SDL_render.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
const char* vertexShaderSource =
"#version 130\n"
"in vec3 position;\n"
"in vec2 texCoord;\n"
"uniform vec3 translate;\n"
"out vec2 outTexCoord;\n"
"void main()\n"
"{\n"
"outTexCoord = texCoord;\n"
"gl_Position = vec4(vec3(position + translate), 1.0);\n"
"}\n";
const char* fragmentShaderSource =
"#version 130\n"
"in vec2 outTexCoord;\n"
"uniform sampler2D tex;\n"
"void main()\n"
"{\n"
"vec4 c = texture(tex, outTexCoord);\n"
/* "if (c.a < 0.1) { discard; }\n" */
"gl_FragColor = c;\n"
"}\n";
int main()
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_GLContext glContext;
SDL_Surface *texture_atlas;
int width = 800, height = 800;
if (SDL_Init(SDL_INIT_VIDEO)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Init error.", "Unable to initialize SDL.", NULL);
exit(0);
}
if (!(window = SDL_CreateWindow("Game", 50, 50, width, height, SDL_WINDOW_OPENGL))) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Init error.", "Unable to create window.", NULL);
exit(0);
}
if (!(renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED))) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Init error.", "Unable to create renderer.", NULL);
exit(0);
}
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
if (!(glContext = SDL_GL_CreateContext(window))) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Init error.", "Unable to create gl context.", NULL);
exit(0);
};
if (!(texture_atlas = IMG_Load("terrain.png"))) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Init error.", "Unable to load texture.", NULL);
exit(0);
}
glewInit();
int maj;
int min;
glGetIntegerv(GL_MAJOR_VERSION, &maj);
glGetIntegerv(GL_MINOR_VERSION, &min);
printf("OpenGL Version: %d,%d\n", maj, min);
glEnable(GL_DEPTH);
glEnable(GL_DEPTH_TEST);
// Create Shaders
GLuint shaderProgram;
GLuint vertexShader;
GLuint fragmentShader;
// Compile Vertex Shader
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Compile Fragment Shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Link Shader Program
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Create textures
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_atlas->w, texture_atlas->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_atlas->pixels);
// Create VAO
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
// Create VBO
GLfloat VBOData[] = {
-1.0 / 8.0, -1.0 / 8.0, 0.0,
-1.0 / 8.0, 1.0 / 8.0, 0.0,
1.0 / 8.0, 1.0 / 8.0, 0.0,
-1.0 / 8.0, -1.0 / 8.0, 0.0,
1.0 / 8.0, -1.0 / 8.0, 0.0,
1.0 / 8.0, 1.0 / 8.0, 0.0,
};
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(VBOData), VBOData, GL_STATIC_DRAW);
GLint positionAttrib = glGetAttribLocation(shaderProgram, "position");
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(positionAttrib);
GLfloat TBOData[] = {
0.0 / 16.0, 1.0 / 16.0,
0.0 / 16.0, 0.0 / 16.0,
1.0 / 16.0, 0.0 / 16.0,
0.0 / 16.0, 1.0 / 16.0,
1.0 / 16.0, 1.0 / 16.0,
1.0 / 16.0, 0.0 / 16.0,
};
GLuint TBO;
glGenBuffers(1, &TBO);
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(TBOData), TBOData, GL_DYNAMIC_DRAW);
GLint textureAttrib = glGetAttribLocation(shaderProgram, "texCoord");
glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(textureAttrib);
int sprite_x = 0;
int sprite_y = 0;
unsigned int t1 = SDL_GetTicks();
int alpha_sprite_x = 12;
int alpha_sprite_y = 0;
GLfloat TBOSubData[sizeof(TBOData) / sizeof(TBOData[0])];
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (1) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
exit(0);
}
}
glClearColor(0.1, 0.1, 0.1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable VAO
glBindVertexArray(VAO);
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(shaderProgram);
GLint translate = glGetUniformLocation(shaderProgram, "translate");
unsigned int t2 = SDL_GetTicks();
float x = sin(t2 / 1000.0) * 0.5;
float y = cos(t2 / 1000.0) * 0.5;
GLfloat spritePos[] = { x, y, 0.0 };
for (int i = 0; i < sizeof(TBOData) / sizeof(TBOData[0]); i += 2) {
TBOSubData[i + 0] = TBOData[i + 0] + sprite_x * 1.0 / 16.0;
TBOSubData[i + 1] = TBOData[i + 1] + sprite_y * 1.0 / 16.0;
}
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(TBOSubData), TBOSubData);
glUniform3fv(translate, 1, spritePos);
glDrawArrays(GL_TRIANGLES, 0, 6);
for (int i = 0; i < sizeof(TBOData) / sizeof(TBOData[0]); i += 2) {
TBOSubData[i + 0] = TBOData[i + 0] + alpha_sprite_x * 1.0 / 16.0;
TBOSubData[i + 1] = TBOData[i + 1] + alpha_sprite_y * 1.0 / 16.0;
}
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(TBOSubData), TBOSubData);
spritePos[2] = -1e-3;
glUniform3fv(translate, 1, spritePos);
glDrawArrays(GL_TRIANGLES, 0, 6);
SDL_GL_SwapWindow(window);
// Every second update texture coordinates to display a different sprite
if (t1 + 1000 < SDL_GetTicks()) {
t1 = SDL_GetTicks();
sprite_x += 1;
if (sprite_x >= 16) {
sprite_x = 0;
}
sprite_y += 1;
if (sprite_y >= 16) {
sprite_y = 0;
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment