/** * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming * This file is in the public domain. * Contributors: Sylvain Beucler, Guus Sliepen */ #include using namespace std; #include #include /** * Store all the file's contents in memory, useful to pass shaders * source code to OpenGL. Using SDL_RWops for Android asset support. */ char* file_read(const char* filename) { SDL_RWops *rw = SDL_RWFromFile(filename, "rb"); if (rw == NULL) return NULL; Sint64 res_size = SDL_RWsize(rw); char* res = new char[res_size + 1]; Sint64 nb_read_total = 0, nb_read = 1; char* buf = res; while (nb_read_total < res_size && nb_read != 0) { nb_read = SDL_RWread(rw, buf, 1, (res_size - nb_read_total)); nb_read_total += nb_read; buf += nb_read; } SDL_RWclose(rw); if (nb_read_total != res_size) { delete[] res; return NULL; } res[nb_read_total] = '\0'; return res; } /** * Display compilation errors from the OpenGL shader compiler */ void print_log(GLuint object) { GLint log_length = 0; if (glIsShader(object)) { glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length); } else if (glIsProgram(object)) { glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length); } else { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "printlog: Not a shader or a program"); return; } char log[log_length]; if (glIsShader(object)) glGetShaderInfoLog(object, log_length, NULL, log); else if (glIsProgram(object)) glGetProgramInfoLog(object, log_length, NULL, log); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "%s\n", log); } /** * Compile the shader from file 'filename', with error handling */ GLuint create_shader(const char* filename, GLenum type) { const char* source = file_read(filename); if (source == NULL) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Error opening %s: %s", filename, SDL_GetError()); return 0; } GLuint res = glCreateShader(type); const GLchar* sources[] = { // Define GLSL version "#version 100\n" // OpenGL ES 2.0 , // Define default float precision for fragment shaders: (type == GL_FRAGMENT_SHADER) ? "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "precision highp float; \n" "#else \n" "precision mediump float; \n" "#endif \n" : "" , source }; glShaderSource(res, 3, sources, NULL); delete[] source; glCompileShader(res); GLint compile_ok = GL_FALSE; glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok); if (compile_ok == GL_FALSE) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "%s:\n", filename); print_log(res); glDeleteShader(res); return 0; } return res; } GLuint create_program(const char *vertexfile, const char *fragmentfile) { GLuint program = glCreateProgram(); GLuint shader; if(vertexfile) { shader = create_shader(vertexfile, GL_VERTEX_SHADER); if(!shader) return 0; glAttachShader(program, shader); } if(fragmentfile) { shader = create_shader(fragmentfile, GL_FRAGMENT_SHADER); if(!shader) return 0; glAttachShader(program, shader); } glLinkProgram(program); GLint link_ok = GL_FALSE; glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if (!link_ok) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "glLinkProgram:"); print_log(program); glDeleteProgram(program); return 0; } return program; } GLint get_attrib(GLuint program, const char *name) { GLint attribute = glGetAttribLocation(program, name); if(attribute == -1) SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Could not bind attribute %s", name); return attribute; } GLint get_uniform(GLuint program, const char *name) { GLint uniform = glGetUniformLocation(program, name); if(uniform == -1) SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Could not bind uniform %s", name); return uniform; } void print_opengl_info() { int major, minor, profile; SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile); const char* profile_str = ""; if (profile & SDL_GL_CONTEXT_PROFILE_CORE) profile_str = "CORE"; if (profile & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) profile_str = "COMPATIBILITY"; if (profile & SDL_GL_CONTEXT_PROFILE_ES) profile_str = "ES"; SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "OpenGL %d.%d %s", major, minor, profile_str); }