GRIM: Use an ARB shader to dim a screen region if possible.
This is much faster than using glReadPixels/glDrawPixels.
This commit is contained in:
parent
45ecf07bce
commit
aeedfb4aa3
2 changed files with 99 additions and 2 deletions
|
@ -57,6 +57,7 @@ PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
|
||||||
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
|
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
|
||||||
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
|
||||||
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
|
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
|
||||||
|
PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -74,6 +75,23 @@ static char fragSrc[] =
|
||||||
MOV result.depth, d.r;\n\
|
MOV result.depth, d.r;\n\
|
||||||
END\n";
|
END\n";
|
||||||
|
|
||||||
|
static char dimFragSrc[] =
|
||||||
|
"!!ARBfp1.0\n\
|
||||||
|
PARAM level = program.local[0];\n\
|
||||||
|
TEMP color;\n\
|
||||||
|
TEMP d;\n\
|
||||||
|
TEX d, fragment.texcoord[0], texture[0], 2D;\n\
|
||||||
|
TEMP sum;\n\
|
||||||
|
MOV sum, d.r;\n\
|
||||||
|
ADD sum, sum, d.g;\n\
|
||||||
|
ADD sum, sum, d.b;\n\
|
||||||
|
MUL sum, sum, 0.33;\n\
|
||||||
|
MUL sum, sum, level.x;\n\
|
||||||
|
MOV result.color.r, sum;\n\
|
||||||
|
MOV result.color.g, sum;\n\
|
||||||
|
MOV result.color.b, sum;\n\
|
||||||
|
END\n";
|
||||||
|
|
||||||
GfxOpenGL::GfxOpenGL() {
|
GfxOpenGL::GfxOpenGL() {
|
||||||
g_driver = this;
|
g_driver = this;
|
||||||
_storedDisplay = NULL;
|
_storedDisplay = NULL;
|
||||||
|
@ -89,6 +107,9 @@ GfxOpenGL::~GfxOpenGL() {
|
||||||
#ifdef GL_ARB_fragment_program
|
#ifdef GL_ARB_fragment_program
|
||||||
if (_useDepthShader)
|
if (_useDepthShader)
|
||||||
glDeleteProgramsARB(1, &_fragmentProgram);
|
glDeleteProgramsARB(1, &_fragmentProgram);
|
||||||
|
|
||||||
|
if (_useDimShader)
|
||||||
|
glDeleteProgramsARB(1, &_dimFragProgram);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +123,7 @@ byte *GfxOpenGL::setupScreen(int screenW, int screenH, bool fullscreen) {
|
||||||
|
|
||||||
_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
|
_isFullscreen = g_system->getFeatureState(OSystem::kFeatureFullscreenMode);
|
||||||
_useDepthShader = false;
|
_useDepthShader = false;
|
||||||
|
_useDimShader = false;
|
||||||
|
|
||||||
g_system->showMouse(!fullscreen);
|
g_system->showMouse(!fullscreen);
|
||||||
|
|
||||||
|
@ -148,10 +170,13 @@ void GfxOpenGL::initExtensions()
|
||||||
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)u.func_ptr;
|
glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)u.func_ptr;
|
||||||
u.obj_ptr = SDL_GL_GetProcAddress("glDeleteProgramsARB");
|
u.obj_ptr = SDL_GL_GetProcAddress("glDeleteProgramsARB");
|
||||||
glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)u.func_ptr;
|
glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)u.func_ptr;
|
||||||
|
u.obj_ptr = SDL_GL_GetProcAddress("glProgramLocalParameter4fARB");
|
||||||
|
glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC)u.func_ptr;
|
||||||
|
|
||||||
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||||
if (strstr(extensions, "ARB_fragment_program")) {
|
if (strstr(extensions, "ARB_fragment_program")) {
|
||||||
_useDepthShader = true;
|
_useDepthShader = true;
|
||||||
|
_useDimShader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_useDepthShader) {
|
if (_useDepthShader) {
|
||||||
|
@ -162,9 +187,20 @@ void GfxOpenGL::initExtensions()
|
||||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragSrc), fragSrc);
|
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragSrc), fragSrc);
|
||||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
||||||
if (errorPos != -1) {
|
if (errorPos != -1) {
|
||||||
warning("Error compiling fragment program:\n%s", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
warning("Error compiling depth fragment program:\n%s", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
||||||
_useDepthShader = false;
|
_useDepthShader = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glGenProgramsARB(1, &_dimFragProgram);
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _dimFragProgram);
|
||||||
|
|
||||||
|
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(dimFragSrc), dimFragSrc);
|
||||||
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
|
||||||
|
if (errorPos != -1) {
|
||||||
|
warning("Error compiling dim fragment program:\n%s", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
||||||
|
_useDimShader = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -780,6 +816,7 @@ void GfxOpenGL::drawBitmap(const Bitmap *bitmap, int dx, int dy) {
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
#ifdef GL_ARB_fragment_program
|
#ifdef GL_ARB_fragment_program
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _fragmentProgram);
|
||||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1303,8 +1340,66 @@ void GfxOpenGL::dimRegion(int x, int yReal, int w, int h, float level) {
|
||||||
yReal = (int)(yReal *_scaleH);
|
yReal = (int)(yReal *_scaleH);
|
||||||
w = (int)(w * _scaleW);
|
w = (int)(w * _scaleW);
|
||||||
h = (int)(h * _scaleH);
|
h = (int)(h * _scaleH);
|
||||||
|
int y = _screenHeight - yReal - h;
|
||||||
|
|
||||||
|
#ifdef GL_ARB_fragment_program
|
||||||
|
if (_useDimShader) {
|
||||||
|
GLuint texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glViewport(0, 0, _screenWidth, _screenHeight);
|
||||||
|
|
||||||
|
// copy the data over to the texture
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, x, y, w, h, 0);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0, _screenWidth, 0, _screenHeight, 0, 1);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_TEXTURE);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _dimFragProgram);
|
||||||
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, level, 0, 0, 0);
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glTexCoord2f(0, 0);
|
||||||
|
glVertex2f(x, y);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex2f(x + w, y);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex2f(x + w, y + h);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex2f(x, y + h);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
|
||||||
|
glDeleteTextures(1, &texture);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32 *data = new uint32[w * h];
|
uint32 *data = new uint32[w * h];
|
||||||
int y = _screenHeight - yReal;
|
y = _screenHeight - yReal;
|
||||||
|
|
||||||
// collect the requested area and generate the dimmed version
|
// collect the requested area and generate the dimmed version
|
||||||
glReadPixels(x, y - h, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
glReadPixels(x, y - h, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
|
@ -131,6 +131,8 @@ private:
|
||||||
byte *_storedDisplay;
|
byte *_storedDisplay;
|
||||||
bool _useDepthShader;
|
bool _useDepthShader;
|
||||||
GLuint _fragmentProgram;
|
GLuint _fragmentProgram;
|
||||||
|
bool _useDimShader;
|
||||||
|
GLuint _dimFragProgram;
|
||||||
int _maxLights;
|
int _maxLights;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue