Skip to content

Instantly share code, notes, and snippets.

@computermouth
Last active April 27, 2023 16:51
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 computermouth/3ccf270148e7e7b1dc7f511c8230212f to your computer and use it in GitHub Desktop.
Save computermouth/3ccf270148e7e7b1dc7f511c8230212f to your computer and use it in GitHub Desktop.
#include <GLES2/gl2.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_error.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_opengles2.h>
#include <SDL2/SDL_render.h>
#define WINDOW_W 320
#define WINDOW_H 180
///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader(const GLchar *shaderSrc, GLenum type)
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader(type);
if(shader == 0)
return 0;
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
// Compile the shader
glCompileShader(shader);
// Check the compile status
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
printf("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
///
// Initialize the shader and program object
//
GLuint Init()
{
GLchar vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
GLchar fShaderStr[] =
"precision mediump float; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = LoadShader(vShaderStr, GL_VERTEX_SHADER);
fragmentShader = LoadShader(fShaderStr, GL_FRAGMENT_SHADER);
// Create the program object
programObject = glCreateProgram();
if(programObject == 0)
return 0;
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
// Bind vPosition to attribute 0
glBindAttribLocation(programObject, 0, "vPosition");
// Link the program
glLinkProgram(programObject);
// Check the link status
glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint infoLen = 0;
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
printf("Error linking program:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
return 0;
}
// Store the program object
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
return programObject;
}
///
// Draw a triangle using the shader pair created in Init()
//
void Draw(GLuint program)
{
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
// Set the viewport
glViewport(0, 0, WINDOW_W, WINDOW_H);
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(program);
// Load the vertex data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
// Requires at least OpenGL ES 2.0
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_Window* window = SDL_CreateWindow("sdl2 gles2 triangle",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
WINDOW_W, WINDOW_H,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
SDL_GL_CreateContext(window);
GLuint program = Init();
GLint fbo = 0;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
// glGenFramebuffers(1, &fbo);
// glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// GLuint tex;
// glGenTextures(1, &tex);
// glBindTexture(GL_TEXTURE_2D, tex);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_W, WINDOW_H, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
// GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// if (status != GL_FRAMEBUFFER_COMPLETE) {
// handle framebuffer creation error
// }
// SDL_Renderer * sdl_renderer = SDL_GetRenderer(window);
// SDL_Renderer * sdl_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// SDL_Texture * sdl_tex = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, WINDOW_W, WINDOW_H);
unsigned int pb_w = WINDOW_W;
unsigned int pb_h = WINDOW_H;
unsigned char * pixbuf = calloc(sizeof(char), pb_w * pb_h * 4);
while (1) {
SDL_Event e;
unsigned int new_w = WINDOW_W;
unsigned int new_h = WINDOW_H;
while(SDL_PollEvent(&e))
{
if(e.type == SDL_QUIT)
goto quit;
// if(e.type == SDL_WINDOWEVENT_SIZE_CHANGED) {
// new_w = e.window.data1;
// new_h = e.window.data1;
// }
}
// resize buffer to match window size
// if (new_w != pb_w || new_h != pb_h) {
// pb_w = new_w;
// pb_h = new_h;
// free(pixbuf);
// pixbuf = calloc(sizeof(char), pb_w * pb_h);
// }
Draw(program);
glReadPixels(
// read from (0,0)
0, 0,
pb_w, pb_h,
GL_RGBA, GL_UNSIGNED_BYTE,
pixbuf);
for(int i = 0; i < pb_w * pb_h; i++){
printf("0x%x ", pixbuf[i]);
}
SDL_GL_SwapWindow(window);
const char * serror = SDL_GetError();
while ( strcmp(serror, "") ) {
printf("sdlerror: %s\n", serror);
SDL_ClearError();
serror = SDL_GetError();
}
GLenum gerror = glGetError();
while (gerror != GL_NO_ERROR) {
printf("glerror: %x\n", gerror);
gerror = glGetError();
}
}
quit:
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment