#include "jshader.h" #include #ifdef __APPLE__ #include "CoreFoundation/CoreFoundation.h" #include #if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 #include #else #include #endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 #else #include #include #endif namespace shader { SDL_Window *win = nullptr; SDL_Renderer *renderer = nullptr; GLuint programId = 0; SDL_Texture* backBuffer = nullptr; SDL_FRect window = {0, 0, 640, 480}; SDL_FPoint tex_size = {320, 240}; float aspect_ratio = 1; bool can_use_opengl = false; bool using_opengl = false; GLuint texture_number; GLuint nose; #ifndef __APPLE__ // I'm avoiding the use of GLEW or some extensions handler, but that // doesn't mean you should... PFNGLCREATESHADERPROC glCreateShader; PFNGLSHADERSOURCEPROC glShaderSource; PFNGLCOMPILESHADERPROC glCompileShader; PFNGLGETSHADERIVPROC glGetShaderiv; PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; PFNGLDELETESHADERPROC glDeleteShader; PFNGLATTACHSHADERPROC glAttachShader; PFNGLCREATEPROGRAMPROC glCreateProgram; PFNGLDELETEPROGRAMPROC glDeleteProgram; PFNGLLINKPROGRAMPROC glLinkProgram; PFNGLVALIDATEPROGRAMPROC glValidateProgram; PFNGLGETPROGRAMIVPROC glGetProgramiv; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; PFNGLUSEPROGRAMPROC glUseProgram; PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; bool initGLExtensions() { glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"); glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"); glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"); glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"); glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"); glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"); glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"); glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"); glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram"); glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"); glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram"); glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"); glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog"); glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"); glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation"); return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv && glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram && glDeleteProgram && glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog && glUseProgram && glGetUniformLocation; } #endif GLuint compileShader(const char* source, GLuint shaderType) { // Create ID for shader GLuint result = glCreateShader(shaderType); // Add define depending on shader type const char *sources[2] = { shaderType==GL_VERTEX_SHADER?"#define VERTEX\n":"#define FRAGMENT\n", source }; // Define shader text glShaderSource(result, 2, sources, NULL); // Compile shader glCompileShader(result); //Check vertex shader for errors GLint shaderCompiled = GL_FALSE; glGetShaderiv( result, GL_COMPILE_STATUS, &shaderCompiled ); if (shaderCompiled != GL_TRUE) { std::cout << "Error en la compilación: " << result << "!" << std::endl; GLint logLength; glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar*)malloc(logLength); glGetShaderInfoLog(result, logLength, &logLength, log); std::cout << "Shader compile log:" << log << std::endl; //std::cout << source << std::endl; free(log); } glDeleteShader(result); result = 0; } return result; } GLuint compileProgram(const char* vertexShaderSource, const char* fragmentShaderSource) { GLuint programId = 0; GLuint vtxShaderId, fragShaderId; if (programId != 0) glDeleteProgram(programId); programId = glCreateProgram(); vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER); fragShaderId = compileShader(fragmentShaderSource?fragmentShaderSource:vertexShaderSource, GL_FRAGMENT_SHADER); if(vtxShaderId && fragShaderId) { // Associate shader with program glAttachShader(programId, vtxShaderId); glAttachShader(programId, fragShaderId); glLinkProgram(programId); glValidateProgram(programId); // Check the status of the compile/link GLint logLen; glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char* log = (char*) malloc(logLen * sizeof(char)); // Show any errors as appropriate glGetProgramInfoLog(programId, logLen, &logLen, log); std::cout << "Prog Info Log: " << std::endl << log << std::endl; free(log); } } if (vtxShaderId) glDeleteShader(vtxShaderId); if (fragShaderId) glDeleteShader(fragShaderId); return programId; } const bool init(SDL_Window* win, SDL_Texture* backBuffer, const char* vertexShader, const char* fragmentShader) { shader::win = win; shader::renderer = SDL_GetRenderer(win); shader::backBuffer = backBuffer; int w, h; SDL_GetWindowSize(win, &w, &h); if (w * aspect_ratio > h) { window.y = 0; window.h = h; window.w = h/aspect_ratio; window.x = (w - window.w)/2; } else { window.x = 0; window.w = w; window.h = w*aspect_ratio; window.y = (h - window.h)/2; } SDL_GetTextureSize(backBuffer, &tex_size.x, &tex_size.y); printf("tex size: %fx%f\n", tex_size.x, tex_size.y); SDL_PropertiesID props = SDL_GetTextureProperties(backBuffer); texture_number = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER, -1); printf("texture number: %i\n", texture_number); int access = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_ACCESS_NUMBER, -1); nose = SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER, -1); printf("texture target number: %i\n", nose); if (access != SDL_TEXTUREACCESS_TARGET) { std::cout << "ERROR FATAL: La textura per al render ha de tindre SDL_TEXTUREACCESS_TARGET definit." << std::endl; exit(1); } const char * renderer_name = SDL_GetRendererName(renderer); printf("rendererInfo.name: %s\n", renderer_name); if(!strncmp(renderer_name, "opengl", 6)) { #ifndef __APPLE__ static bool gl_extensions_initialized = false; if (!gl_extensions_initialized) { if (!initGLExtensions()) { std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl; can_use_opengl = false; return false; } gl_extensions_initialized = true; } #endif // Compilar el shader y dejarlo listo para usar. if (!vertexShader) { can_use_opengl = false; return false; } programId = compileProgram(vertexShader, fragmentShader); } else { std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl; can_use_opengl = false; return false; } can_use_opengl = true; return true; } unsigned char pixels[512*240*4]; void enable() { if (can_use_opengl) using_opengl = true; } void disable() { using_opengl = false; } void setAspectRatio(const float ratio) { aspect_ratio = ratio; } void render() { SDL_FlushRenderer(renderer); SDL_SetRenderTarget(renderer, NULL); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); SDL_FlushRenderer(renderer); if (using_opengl) { GLint oldProgramId; if (programId != 0) { glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId); glUseProgram(programId); } glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 1); //glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels); //if (glGetError()) { printf("GLGETERROR!\n"); exit(1);} //GLint param; //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, ¶m); //printf("tex width: %i\n", param); glViewport(window.x, window.y, window.w, window.h); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(tex_size.x, 0.0f); glVertex2f(1.0f, -1.0f); glTexCoord2f(0.0f, tex_size.y); glVertex2f(-1.0f, 1.0f); glTexCoord2f(tex_size.x, tex_size.y); glVertex2f(1.0f, 1.0f); glEnd(); SDL_GL_SwapWindow(win); if (programId != 0) glUseProgram(oldProgramId); } else { SDL_RenderTexture(renderer, backBuffer, NULL, &window); SDL_RenderPresent(renderer); } if (glGetError()) { printf("GLERROR!\n"); exit(1); } } }