GL2D.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "StdInc.h"
  2. #include <SDL.h>
  3. #include <SDL_video.h>
  4. #include "SDL_syswm.h"
  5. #include <SDL_opengl.h>
  6. #include "GL2D.h"
  7. namespace GL2D
  8. {
  9. // Variables initialized by initVideo, updated by setScreenRes:
  10. static SDL_SysWMinfo wmInfo;
  11. ui32 screenWidth = 0, screenHeight = 0; // Screen/Window size
  12. // OpenGL 1.3 functions pointers
  13. PFNGLACTIVETEXTUREPROC glActiveTexture;
  14. // OpenGL 2.0 functions pointers
  15. PFNGLCREATEPROGRAMPROC glCreateProgram;
  16. PFNGLCREATESHADERPROC glCreateShader;
  17. PFNGLSHADERSOURCEPROC glShaderSource;
  18. PFNGLCOMPILESHADERPROC glCompileShader;
  19. PFNGLATTACHSHADERPROC glAttachShader;
  20. PFNGLLINKPROGRAMPROC glLinkProgram;
  21. PFNGLUSEPROGRAMPROC glUseProgram;
  22. PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
  23. PFNGLUNIFORM1IPROC glUniform1i;
  24. PFNGLUNIFORM2IPROC glUniform2i;
  25. PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
  26. PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
  27. // Shaders' sources
  28. static const char frag_palette_bitmap[] = (
  29. "uniform usampler2DRect bitmap;"
  30. "uniform sampler1D palette;"
  31. "uniform ivec2 coordOffs;"
  32. "layout (origin_upper_left) in vec4 gl_FragCoord;"
  33. "void main(){"
  34. "gl_FragColor = texelFetch(palette, int(texelFetch(bitmap, ivec2(gl_FragCoord.xy) - coordOffs).r), 0);"
  35. "}"
  36. );
  37. // Programs' handlers
  38. static GLuint currentProgram = 0;
  39. static GLuint colorizeProgram = 0;
  40. static GLuint paletteBitmapProgram = 0;
  41. // Uniforms handlers
  42. static GLint coord_uniform = -1;
  43. // Print out the information log for a shader object
  44. void printInfoLog(PFNGLGETPROGRAMINFOLOGPROC logFunc, GLuint object)
  45. {
  46. if (logFunc != nullptr)
  47. {
  48. GLsizei infoLogLength = 0;
  49. GLchar infoLog[1024];
  50. logFunc(object, sizeof(infoLog)-1, &infoLogLength, infoLog);
  51. if (infoLogLength > 0) tlog1 << infoLog;
  52. }
  53. }
  54. GLuint makeShaderProgram(const char * frg_src)
  55. {
  56. // Creating a fragment shader object
  57. GLuint shader_object = glCreateShader(GL_FRAGMENT_SHADER);
  58. glShaderSource(shader_object, 1, &frg_src, nullptr); // assigning the shader source
  59. // Compiling the shader
  60. glCompileShader(shader_object);
  61. printInfoLog(glGetShaderInfoLog, shader_object);
  62. // Creating a program object
  63. GLuint program_object = glCreateProgram();
  64. // Attaching the shader into program
  65. glAttachShader(program_object, shader_object);
  66. // Link the shaders into a complete GLSL program.
  67. glLinkProgram(program_object);
  68. printInfoLog(glGetProgramInfoLog, program_object);
  69. return program_object;
  70. }
  71. void initVideo(ui32 w, ui32 h, bool fullscreen)
  72. {
  73. SDL_VERSION(&wmInfo.version);
  74. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  75. if (!setScreenRes(w, h, fullscreen))
  76. {
  77. throw std::runtime_error("Video mode setting failed\n");
  78. }
  79. glClearColor(0, 0, 0, 0); // Black Background
  80. glClear(GL_COLOR_BUFFER_BIT);
  81. SDL_GL_SwapBuffers();
  82. // Dynamic-linked OpenGL 1.3 and 2.0 functions - required to 2D rendeing
  83. if ( (glActiveTexture = (PFNGLACTIVETEXTUREPROC) SDL_GL_GetProcAddress("glActiveTexture")) == nullptr
  84. || (glCreateProgram = (PFNGLCREATEPROGRAMPROC) SDL_GL_GetProcAddress("glCreateProgram")) == nullptr
  85. || (glCreateShader = (PFNGLCREATESHADERPROC) SDL_GL_GetProcAddress("glCreateShader")) == nullptr
  86. || (glShaderSource = (PFNGLSHADERSOURCEPROC) SDL_GL_GetProcAddress("glShaderSource")) == nullptr
  87. || (glCompileShader = (PFNGLCOMPILESHADERPROC) SDL_GL_GetProcAddress("glCompileShader")) == nullptr
  88. || (glAttachShader = (PFNGLATTACHSHADERPROC) SDL_GL_GetProcAddress("glAttachShader")) == nullptr
  89. || (glLinkProgram = (PFNGLLINKPROGRAMPROC) SDL_GL_GetProcAddress("glLinkProgram")) == nullptr
  90. || (glUseProgram = (PFNGLUSEPROGRAMPROC) SDL_GL_GetProcAddress("glUseProgram")) == nullptr
  91. || (glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) SDL_GL_GetProcAddress("glGetUniformLocation")) == nullptr
  92. || (glUniform1i = (PFNGLUNIFORM1IPROC) SDL_GL_GetProcAddress("glUniform1i")) == nullptr
  93. || (glUniform2i = (PFNGLUNIFORM2IPROC) SDL_GL_GetProcAddress("glUniform2i")) == nullptr
  94. )
  95. {
  96. tlog1 << "Error: OpenGL2 Extenstions are not available\n";
  97. tlog1 << "SDL says: " << SDL_GetError() << std::endl;
  98. throw std::runtime_error("OpenGL2 Extenstions are not available\n");
  99. }
  100. glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) SDL_GL_GetProcAddress("glGetProgramInfoLog"); // not required
  101. glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) SDL_GL_GetProcAddress("glGetShaderInfoLog"); // not required
  102. glDisable(GL_DEPTH_TEST);
  103. glDisable(GL_LIGHTING);
  104. glDisable(GL_DITHER);
  105. glDisable(GL_TEXTURE_2D);
  106. glEnable(GL_TEXTURE_RECTANGLE);
  107. glEnable(GL_BLEND);
  108. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  109. paletteBitmapProgram = makeShaderProgram(frag_palette_bitmap);
  110. GLint bitmap_uniform = glGetUniformLocation(paletteBitmapProgram, "bitmap");
  111. GLint palette_uniform = glGetUniformLocation(paletteBitmapProgram, "palette");
  112. coord_uniform = glGetUniformLocation(paletteBitmapProgram, "coordOffs");
  113. glUseProgram(currentProgram = paletteBitmapProgram);
  114. glUniform1i(bitmap_uniform, 0);
  115. glUniform1i(palette_uniform, 1);
  116. #ifdef _WIN32
  117. wglMakeCurrent(NULL, NULL);
  118. #endif
  119. }
  120. void attachToCurrentThread()
  121. {
  122. #ifdef _WIN32
  123. HDC hdc = GetDC(wmInfo.window);
  124. wglMakeCurrent(hdc, wmInfo.hglrc);
  125. #endif
  126. }
  127. bool setScreenRes(ui32 w, ui32 h, bool fullscreen)
  128. {
  129. // Try to use the best screen depth for the display
  130. int suggestedBpp = SDL_VideoModeOK(w, h, 32, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0));
  131. if(suggestedBpp == 0)
  132. {
  133. tlog1 << "Error: SDL says that " << w << "x" << h << " resolution is not available!\n";
  134. return false;
  135. }
  136. if(suggestedBpp != 32)
  137. {
  138. tlog2 << "Note: SDL suggests to use " << suggestedBpp << " bpp instead of 32 bpp\n";
  139. }
  140. if(SDL_SetVideoMode(w, h, suggestedBpp, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0)) == NULL)
  141. {
  142. tlog1 << "Error: Video mode setting failed (" << w << "x" << h << "x" << suggestedBpp << "bpp)\n";
  143. return false;
  144. }
  145. screenWidth = w; screenHeight = h;
  146. int getwm = SDL_GetWMInfo(&wmInfo);
  147. if(getwm != 1)
  148. {
  149. tlog2 << "Something went wrong, getwm=" << getwm << std::endl;
  150. tlog2 << "SDL says: " << SDL_GetError() << std::endl;
  151. return false;
  152. }
  153. glViewport(0, 0, w, h);
  154. glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
  155. glLoadIdentity(); // Reset The Projection Matrix
  156. glOrtho(0, w, h, 0, 0, 1);
  157. glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
  158. glLoadIdentity(); // Reset The Modelview Matrix
  159. glTranslatef(0.375, 0.375, 0); // Displacement trick for exact pixelization
  160. return true;
  161. }
  162. void assignTexture(ui32 slot, ui32 type, ui32 handle)
  163. {
  164. glActiveTexture(slot);
  165. glBindTexture(type, handle);
  166. }
  167. void useNoShader()
  168. {
  169. if (currentProgram != 0) {
  170. glUseProgram(currentProgram = 0);
  171. }
  172. }
  173. void useColorizeShader(const float cm[4][4])
  174. {
  175. if (currentProgram != colorizeProgram) {
  176. glUseProgram(currentProgram = colorizeProgram);
  177. }
  178. }
  179. void usePaletteBitmapShader(si32 x, si32 y)
  180. {
  181. if (currentProgram != paletteBitmapProgram) {
  182. glUseProgram(currentProgram = paletteBitmapProgram);
  183. }
  184. glUniform2i(coord_uniform, x, y);
  185. }
  186. void usePaletteBitmapShader(si32 x, si32 y, const float cm[4][4])
  187. {
  188. if (currentProgram != paletteBitmapProgram) {
  189. glUseProgram(currentProgram = paletteBitmapProgram);
  190. }
  191. glUniform2i(coord_uniform, x, y);
  192. }
  193. }