mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
New namespaces: GL2D (low-level OpenGL functions), Gfx (images and animation objects cooperating with the interface GL2D)
This commit is contained in:
242
client/UIFramework/GL2D.cpp
Normal file
242
client/UIFramework/GL2D.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
#include "StdInc.h"
|
||||
#include <SDL.h>
|
||||
#include <SDL_video.h>
|
||||
#include "SDL_syswm.h"
|
||||
#include <SDL_opengl.h>
|
||||
#include "GL2D.h"
|
||||
|
||||
|
||||
namespace GL2D
|
||||
{
|
||||
|
||||
// Variables initialized by initVideo, updated by setScreenRes:
|
||||
static SDL_SysWMinfo wmInfo;
|
||||
ui32 screenWidth = 0, screenHeight = 0; // Screen/Window size
|
||||
|
||||
// OpenGL 1.3 functions pointers
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||
// OpenGL 2.0 functions pointers
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||
PFNGLCREATESHADERPROC glCreateShader;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader;
|
||||
PFNGLATTACHSHADERPROC glAttachShader;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||
PFNGLUNIFORM1IPROC glUniform1i;
|
||||
PFNGLUNIFORM2IPROC glUniform2i;
|
||||
|
||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||
|
||||
|
||||
// Shaders' sources
|
||||
static const char frag_palette_bitmap[] = (
|
||||
"uniform usampler2DRect bitmap;"
|
||||
"uniform sampler1D palette;"
|
||||
"uniform ivec2 coordOffs;"
|
||||
"layout (origin_upper_left) in vec4 gl_FragCoord;"
|
||||
|
||||
"void main(){"
|
||||
"gl_FragColor = texelFetch(palette, int(texelFetch(bitmap, ivec2(gl_FragCoord.xy) - coordOffs).r), 0);"
|
||||
"}"
|
||||
);
|
||||
|
||||
|
||||
// Programs' handlers
|
||||
static GLuint currentProgram = 0;
|
||||
static GLuint colorizeProgram = 0;
|
||||
static GLuint paletteBitmapProgram = 0;
|
||||
|
||||
// Uniforms handlers
|
||||
static GLint coord_uniform = -1;
|
||||
|
||||
|
||||
// Print out the information log for a shader object
|
||||
void printInfoLog(PFNGLGETPROGRAMINFOLOGPROC logFunc, GLuint object)
|
||||
{
|
||||
if (logFunc != nullptr)
|
||||
{
|
||||
GLsizei infoLogLength = 0;
|
||||
GLchar infoLog[1024];
|
||||
logFunc(object, sizeof(infoLog)-1, &infoLogLength, infoLog);
|
||||
|
||||
if (infoLogLength > 0) tlog1 << infoLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLuint makeShaderProgram(const char * frg_src)
|
||||
{
|
||||
// Creating a fragment shader object
|
||||
GLuint shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(shader_object, 1, &frg_src, nullptr); // assigning the shader source
|
||||
// Compiling the shader
|
||||
glCompileShader(shader_object);
|
||||
printInfoLog(glGetShaderInfoLog, shader_object);
|
||||
|
||||
// Creating a program object
|
||||
GLuint program_object = glCreateProgram();
|
||||
// Attaching the shader into program
|
||||
glAttachShader(program_object, shader_object);
|
||||
|
||||
// Link the shaders into a complete GLSL program.
|
||||
glLinkProgram(program_object);
|
||||
printInfoLog(glGetProgramInfoLog, program_object);
|
||||
|
||||
return program_object;
|
||||
}
|
||||
|
||||
|
||||
void initVideo(ui32 w, ui32 h, bool fullscreen)
|
||||
{
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
if (!setScreenRes(w, h, fullscreen))
|
||||
{
|
||||
throw std::runtime_error("Video mode setting failed\n");
|
||||
}
|
||||
glClearColor(0, 0, 0, 0); // Black Background
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
SDL_GL_SwapBuffers();
|
||||
|
||||
// Dynamic-linked OpenGL 1.3 and 2.0 functions - required to 2D rendeing
|
||||
if ( (glActiveTexture = (PFNGLACTIVETEXTUREPROC) SDL_GL_GetProcAddress("glActiveTexture")) == nullptr
|
||||
|| (glCreateProgram = (PFNGLCREATEPROGRAMPROC) SDL_GL_GetProcAddress("glCreateProgram")) == nullptr
|
||||
|| (glCreateShader = (PFNGLCREATESHADERPROC) SDL_GL_GetProcAddress("glCreateShader")) == nullptr
|
||||
|| (glShaderSource = (PFNGLSHADERSOURCEPROC) SDL_GL_GetProcAddress("glShaderSource")) == nullptr
|
||||
|| (glCompileShader = (PFNGLCOMPILESHADERPROC) SDL_GL_GetProcAddress("glCompileShader")) == nullptr
|
||||
|| (glAttachShader = (PFNGLATTACHSHADERPROC) SDL_GL_GetProcAddress("glAttachShader")) == nullptr
|
||||
|| (glLinkProgram = (PFNGLLINKPROGRAMPROC) SDL_GL_GetProcAddress("glLinkProgram")) == nullptr
|
||||
|| (glUseProgram = (PFNGLUSEPROGRAMPROC) SDL_GL_GetProcAddress("glUseProgram")) == nullptr
|
||||
|| (glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) SDL_GL_GetProcAddress("glGetUniformLocation")) == nullptr
|
||||
|| (glUniform1i = (PFNGLUNIFORM1IPROC) SDL_GL_GetProcAddress("glUniform1i")) == nullptr
|
||||
|| (glUniform2i = (PFNGLUNIFORM2IPROC) SDL_GL_GetProcAddress("glUniform2i")) == nullptr
|
||||
)
|
||||
{
|
||||
tlog1 << "Error: OpenGL2 Extenstions are not available\n";
|
||||
tlog1 << "SDL says: " << SDL_GetError() << std::endl;
|
||||
throw std::runtime_error("OpenGL2 Extenstions are not available\n");
|
||||
}
|
||||
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) SDL_GL_GetProcAddress("glGetProgramInfoLog"); // not required
|
||||
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) SDL_GL_GetProcAddress("glGetShaderInfoLog"); // not required
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DITHER);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_TEXTURE_RECTANGLE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
paletteBitmapProgram = makeShaderProgram(frag_palette_bitmap);
|
||||
GLint bitmap_uniform = glGetUniformLocation(paletteBitmapProgram, "bitmap");
|
||||
GLint palette_uniform = glGetUniformLocation(paletteBitmapProgram, "palette");
|
||||
coord_uniform = glGetUniformLocation(paletteBitmapProgram, "coordOffs");
|
||||
|
||||
glUseProgram(currentProgram = paletteBitmapProgram);
|
||||
glUniform1i(bitmap_uniform, 0);
|
||||
glUniform1i(palette_uniform, 1);
|
||||
|
||||
#ifdef _WIN32
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void attachToCurrentThread()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HDC hdc = GetDC(wmInfo.window);
|
||||
wglMakeCurrent(hdc, wmInfo.hglrc);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool setScreenRes(ui32 w, ui32 h, bool fullscreen)
|
||||
{
|
||||
// Try to use the best screen depth for the display
|
||||
int suggestedBpp = SDL_VideoModeOK(w, h, 32, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0));
|
||||
if(suggestedBpp == 0)
|
||||
{
|
||||
tlog1 << "Error: SDL says that " << w << "x" << h << " resolution is not available!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(suggestedBpp != 32)
|
||||
{
|
||||
tlog2 << "Note: SDL suggests to use " << suggestedBpp << " bpp instead of 32 bpp\n";
|
||||
}
|
||||
|
||||
if(SDL_SetVideoMode(w, h, suggestedBpp, SDL_OPENGL | SDL_ANYFORMAT | (fullscreen?SDL_FULLSCREEN:0)) == NULL)
|
||||
{
|
||||
tlog1 << "Error: Video mode setting failed (" << w << "x" << h << "x" << suggestedBpp << "bpp)\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
screenWidth = w; screenHeight = h;
|
||||
|
||||
int getwm = SDL_GetWMInfo(&wmInfo);
|
||||
if(getwm != 1)
|
||||
{
|
||||
tlog2 << "Something went wrong, getwm=" << getwm << std::endl;
|
||||
tlog2 << "SDL says: " << SDL_GetError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
|
||||
glLoadIdentity(); // Reset The Projection Matrix
|
||||
glOrtho(0, w, h, 0, 0, 1);
|
||||
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
|
||||
glLoadIdentity(); // Reset The Modelview Matrix
|
||||
glTranslatef(0.375, 0.375, 0); // Displacement trick for exact pixelization
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void assignTexture(ui32 slot, ui32 type, ui32 handle)
|
||||
{
|
||||
glActiveTexture(slot);
|
||||
glBindTexture(type, handle);
|
||||
}
|
||||
|
||||
|
||||
void useNoShader()
|
||||
{
|
||||
if (currentProgram != 0) {
|
||||
glUseProgram(currentProgram = 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void useColorizeShader(const float cm[4][4])
|
||||
{
|
||||
if (currentProgram != colorizeProgram) {
|
||||
glUseProgram(currentProgram = colorizeProgram);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void usePaletteBitmapShader(si32 x, si32 y)
|
||||
{
|
||||
if (currentProgram != paletteBitmapProgram) {
|
||||
glUseProgram(currentProgram = paletteBitmapProgram);
|
||||
}
|
||||
glUniform2i(coord_uniform, x, y);
|
||||
}
|
||||
|
||||
|
||||
void usePaletteBitmapShader(si32 x, si32 y, const float cm[4][4])
|
||||
{
|
||||
if (currentProgram != paletteBitmapProgram) {
|
||||
glUseProgram(currentProgram = paletteBitmapProgram);
|
||||
}
|
||||
glUniform2i(coord_uniform, x, y);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user