more sensible shader handling, incomplete but functional
add mixing modes
This commit is contained in:
+121
-126
@@ -4,6 +4,7 @@
|
|||||||
#include "RageDisplay_OGL_Helpers.h"
|
#include "RageDisplay_OGL_Helpers.h"
|
||||||
using namespace RageDisplay_OGL_Helpers;
|
using namespace RageDisplay_OGL_Helpers;
|
||||||
|
|
||||||
|
#include "RageFile.h"
|
||||||
#include "RageSurface.h"
|
#include "RageSurface.h"
|
||||||
#include "RageSurfaceUtils.h"
|
#include "RageSurfaceUtils.h"
|
||||||
#include "RageUtil.h"
|
#include "RageUtil.h"
|
||||||
@@ -260,140 +261,124 @@ RString GetInfoLog( GLhandleARB h )
|
|||||||
GLExt.glGetInfoLogARB( h, iLength, &iLength, pInfoLog );
|
GLExt.glGetInfoLogARB( h, iLength, &iLength, pInfoLog );
|
||||||
RString sRet = pInfoLog;
|
RString sRet = pInfoLog;
|
||||||
delete [] pInfoLog;
|
delete [] pInfoLog;
|
||||||
|
TrimRight( sRet );
|
||||||
return sRet;
|
return sRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLhandleARB CompileShader( GLenum ShaderType, RString sBuffer )
|
GLhandleARB CompileShader( GLenum ShaderType, RString sFile, vector<RString> asDefines )
|
||||||
{
|
{
|
||||||
GLhandleARB VertexShader = GLExt.glCreateShaderObjectARB( ShaderType );
|
RString sBuffer;
|
||||||
const GLcharARB *pData = sBuffer.data();
|
{
|
||||||
int iLength = sBuffer.size();
|
RageFile file;
|
||||||
GLExt.glShaderSourceARB( VertexShader, 1, &pData, (GLint*)&iLength );
|
if( !file.Open(sFile) )
|
||||||
|
{
|
||||||
|
LOG->Warn( "Error compiling shader %s: %s", sFile.c_str(), file.GetError().c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
GLExt.glCompileShaderARB( VertexShader );
|
if( file.Read(sBuffer, file.GetFileSize()) == -1 )
|
||||||
|
{
|
||||||
|
LOG->Warn( "Error compiling shader %s: %s", sFile.c_str(), file.GetError().c_str() );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG->Trace( "Compiling shader %s", sFile.c_str() );
|
||||||
|
GLhandleARB hShader = GLExt.glCreateShaderObjectARB( ShaderType );
|
||||||
|
vector<const GLcharARB *> apData;
|
||||||
|
vector<GLint> aiLength;
|
||||||
|
FOREACH( RString, asDefines, s )
|
||||||
|
{
|
||||||
|
*s = ssprintf( "#define %s\n", s->c_str() );
|
||||||
|
apData.push_back( s->data() );
|
||||||
|
aiLength.push_back( s->size() );
|
||||||
|
}
|
||||||
|
apData.push_back( "#line 1\n" );
|
||||||
|
aiLength.push_back( 8 );
|
||||||
|
|
||||||
|
apData.push_back( sBuffer.data() );
|
||||||
|
aiLength.push_back( sBuffer.size() );
|
||||||
|
GLExt.glShaderSourceARB( hShader, apData.size(), &apData[0], &aiLength[0] );
|
||||||
|
|
||||||
|
GLExt.glCompileShaderARB( hShader );
|
||||||
|
|
||||||
|
RString sInfo = GetInfoLog( hShader );
|
||||||
|
|
||||||
GLint bCompileStatus = GL_FALSE;
|
GLint bCompileStatus = GL_FALSE;
|
||||||
GLExt.glGetObjectParameterivARB( VertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompileStatus );
|
GLExt.glGetObjectParameterivARB( hShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompileStatus );
|
||||||
|
|
||||||
if( !bCompileStatus )
|
if( !bCompileStatus )
|
||||||
{
|
{
|
||||||
LOG->Trace( "Compile failure: %s", GetInfoLog( VertexShader ).c_str() );
|
LOG->Warn( "Error compiling shader %s:\n%s", sFile.c_str(), sInfo.c_str() );
|
||||||
|
GLExt.glDeleteObjectARB( hShader );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VertexShader;
|
if( !sInfo.empty() )
|
||||||
|
LOG->Trace( "Messages compiling shader %s:\n%s", sFile.c_str(), sInfo.c_str() );
|
||||||
|
|
||||||
|
return hShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
int g_iAttribTextureMatrixScale;
|
GLhandleARB LoadShader( GLenum ShaderType, RString sFile, vector<RString> asDefines )
|
||||||
|
|
||||||
/* XXX: How should we include these? Doing them like this is ugly. Linking them in
|
|
||||||
* from another file as a text symbol would be ideal, but that's completely different
|
|
||||||
* on each platform, so it'd be a maintenance nightmare. Reading them from a file would
|
|
||||||
* be annoying, too. */
|
|
||||||
const GLcharARB *g_TextureMatrixScaleShader =
|
|
||||||
" \
|
|
||||||
attribute vec4 TextureMatrixScale; \
|
|
||||||
void main( void ) \
|
|
||||||
{ \
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \
|
|
||||||
vec4 multiplied_tex_coord = gl_TextureMatrix[0] * gl_MultiTexCoord0; \
|
|
||||||
gl_TexCoord[0] = (multiplied_tex_coord * TextureMatrixScale) + \
|
|
||||||
(gl_MultiTexCoord0 * (vec4(1)-TextureMatrixScale)); \
|
|
||||||
gl_FrontColor = gl_Color; \
|
|
||||||
} \
|
|
||||||
";
|
|
||||||
|
|
||||||
void InitScalingScript()
|
|
||||||
{
|
{
|
||||||
g_bTextureMatrixShader = 0;
|
if( !GLExt.m_bGL_ARB_fragment_shader && ShaderType == GL_FRAGMENT_SHADER_ARB )
|
||||||
|
return 0;
|
||||||
|
if( !GLExt.m_bGL_ARB_vertex_shader && ShaderType == GL_VERTEX_SHADER_ARB )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if( !GLExt.m_bGL_ARB_shader_objects ||
|
GLhandleARB hShader = CompileShader( ShaderType, sFile, asDefines );
|
||||||
!GLExt.m_bGL_ARB_vertex_shader ||
|
if( hShader == 0 )
|
||||||
!GLExt.m_bGL_ARB_shading_language_100 )
|
return 0;
|
||||||
return;
|
|
||||||
|
|
||||||
GLhandleARB VertexShader = CompileShader( GL_VERTEX_SHADER_ARB, g_TextureMatrixScaleShader );
|
GLhandleARB hProgram = GLExt.glCreateProgramObjectARB();
|
||||||
if( VertexShader == 0 )
|
GLExt.glAttachObjectARB( hProgram, hShader );
|
||||||
return;
|
GLExt.glDeleteObjectARB( hShader );
|
||||||
|
|
||||||
g_bTextureMatrixShader = GLExt.glCreateProgramObjectARB();
|
|
||||||
GLExt.glAttachObjectARB( g_bTextureMatrixShader, VertexShader );
|
|
||||||
GLExt.glDeleteObjectARB( VertexShader );
|
|
||||||
|
|
||||||
// Link the program.
|
// Link the program.
|
||||||
GLExt.glLinkProgramARB( g_bTextureMatrixShader );
|
GLExt.glLinkProgramARB( hProgram );
|
||||||
GLint bLinkStatus = false;
|
GLint bLinkStatus = false;
|
||||||
GLExt.glGetObjectParameterivARB( g_bTextureMatrixShader, GL_OBJECT_LINK_STATUS_ARB, &bLinkStatus );
|
GLExt.glGetObjectParameterivARB( hProgram, GL_OBJECT_LINK_STATUS_ARB, &bLinkStatus );
|
||||||
|
|
||||||
if( !bLinkStatus )
|
if( !bLinkStatus )
|
||||||
{
|
{
|
||||||
LOG->Trace( "Scaling shader link failed: %s", GetInfoLog(g_bTextureMatrixShader).c_str() );
|
LOG->Warn( "Error linking shader %s: %s", sFile.c_str(), GetInfoLog(hProgram).c_str() );
|
||||||
GLExt.glDeleteObjectARB( g_bTextureMatrixShader );
|
GLExt.glDeleteObjectARB( hProgram );
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return hProgram;
|
||||||
// Bind attributes.
|
|
||||||
g_iAttribTextureMatrixScale = GLExt.glGetAttribLocationARB( g_bTextureMatrixShader, "TextureMatrixScale" );
|
|
||||||
if( g_iAttribTextureMatrixScale == -1 )
|
|
||||||
{
|
|
||||||
LOG->Trace( "Scaling shader link failed: couldn't bind attribute \"TextureMatrixScale\"" );
|
|
||||||
GLExt.glDeleteObjectARB( g_bTextureMatrixShader );
|
|
||||||
g_bTextureMatrixShader = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLExt.glVertexAttrib2fARB( g_iAttribTextureMatrixScale, 1, 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLcharARB *g_ColorBurnFragmentShader = " \
|
static int g_iAttribTextureMatrixScale;
|
||||||
uniform sampler2D Texture1; \
|
|
||||||
uniform sampler2D Texture2; \
|
|
||||||
void main(void) \
|
|
||||||
{ \
|
|
||||||
vec4 color1 = texture2DProj( Texture1, gl_TexCoord[0] ); \
|
|
||||||
vec4 color2 = texture2DProj( Texture2, gl_TexCoord[0] ); \
|
|
||||||
\
|
|
||||||
/* Threshold to prevent division by zero: */ \
|
|
||||||
vec4 threshold = vec4(0.00001, 0.00001, 0.00001, 0.00001); \
|
|
||||||
vec4 color = 1-((1-color1) / max(color2, threshold)); \
|
|
||||||
color = (color * color1[3]) + (color2 * (1-color1[3]) ); \
|
|
||||||
color[3] = color2[3]; \
|
|
||||||
gl_FragColor = color; \
|
|
||||||
} \
|
|
||||||
";
|
|
||||||
|
|
||||||
static GLhandleARB g_bColorBurnShader = 0;
|
static GLhandleARB g_bColorBurnShader = 0;
|
||||||
void InitColorBurnScript()
|
static GLhandleARB g_bColorDodgeShader = 0;
|
||||||
|
static GLhandleARB g_bVividLightShader = 0;
|
||||||
|
static GLhandleARB g_hHardMixShader = 0;
|
||||||
|
|
||||||
|
void InitShaders()
|
||||||
{
|
{
|
||||||
g_bColorBurnShader = 0;
|
vector<RString> asDefines;
|
||||||
|
g_bTextureMatrixShader = LoadShader( GL_VERTEX_SHADER_ARB, "Data/Shaders/GLSL/Texture matrix scaling.vert", asDefines );
|
||||||
|
g_bColorBurnShader = LoadShader( GL_FRAGMENT_SHADER_ARB, "Data/Shaders/GLSL/Color burn.frag", asDefines );
|
||||||
|
g_bColorDodgeShader = LoadShader( GL_FRAGMENT_SHADER_ARB, "Data/Shaders/GLSL/Color dodge.frag", asDefines );
|
||||||
|
g_bVividLightShader = LoadShader( GL_FRAGMENT_SHADER_ARB, "Data/Shaders/GLSL/Vivid light.frag", asDefines );
|
||||||
|
g_hHardMixShader = LoadShader( GL_FRAGMENT_SHADER_ARB, "Data/Shaders/GLSL/Hard mix.frag", asDefines );
|
||||||
|
|
||||||
if( !GLExt.m_bGL_ARB_shader_objects ||
|
// Bind attributes.
|
||||||
!GLExt.m_bGL_ARB_fragment_shader ||
|
if( g_bTextureMatrixShader )
|
||||||
!GLExt.m_bGL_ARB_shading_language_100 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
GLhandleARB FragmentShader = CompileShader( GL_FRAGMENT_SHADER_ARB, g_ColorBurnFragmentShader );
|
|
||||||
if( FragmentShader == 0 )
|
|
||||||
{
|
{
|
||||||
GLExt.glDeleteObjectARB( FragmentShader );
|
g_iAttribTextureMatrixScale = GLExt.glGetAttribLocationARB( g_bTextureMatrixShader, "TextureMatrixScale" );
|
||||||
return;
|
if( g_iAttribTextureMatrixScale == -1 )
|
||||||
}
|
{
|
||||||
AssertNoGLError();
|
LOG->Trace( "Scaling shader link failed: couldn't bind attribute \"TextureMatrixScale\"" );
|
||||||
|
GLExt.glDeleteObjectARB( g_bTextureMatrixShader );
|
||||||
g_bColorBurnShader = GLExt.glCreateProgramObjectARB();
|
g_bTextureMatrixShader = 0;
|
||||||
GLExt.glAttachObjectARB( g_bColorBurnShader, FragmentShader );
|
}
|
||||||
GLExt.glDeleteObjectARB( FragmentShader );
|
else
|
||||||
|
{
|
||||||
// Link the program.
|
GLExt.glVertexAttrib2fARB( g_iAttribTextureMatrixScale, 1, 1 );
|
||||||
GLExt.glLinkProgramARB( g_bColorBurnShader );
|
AssertNoGLError();
|
||||||
GLint bLinkStatus = false;
|
}
|
||||||
GLExt.glGetObjectParameterivARB( g_bColorBurnShader, GL_OBJECT_LINK_STATUS_ARB, &bLinkStatus );
|
|
||||||
|
|
||||||
if( !bLinkStatus )
|
|
||||||
{
|
|
||||||
LOG->Trace( "Color burn shader link failed: %s", GetInfoLog(g_bColorBurnShader).c_str() );
|
|
||||||
GLExt.glDeleteObjectARB( g_bColorBurnShader );
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +407,6 @@ RString RageDisplay_OGL::Init( const VideoModeParams &p, bool bAllowUnaccelerate
|
|||||||
const char *szExtensionString = (const char *) glGetString(GL_EXTENSIONS);
|
const char *szExtensionString = (const char *) glGetString(GL_EXTENSIONS);
|
||||||
vector<RString> asExtensions;
|
vector<RString> asExtensions;
|
||||||
split( szExtensionString, " ", asExtensions );
|
split( szExtensionString, " ", asExtensions );
|
||||||
sort( asExtensions.begin(), asExtensions.end() );
|
|
||||||
size_t iNextToPrint = 0;
|
size_t iNextToPrint = 0;
|
||||||
while( iNextToPrint < asExtensions.size() )
|
while( iNextToPrint < asExtensions.size() )
|
||||||
{
|
{
|
||||||
@@ -707,8 +691,7 @@ RString RageDisplay_OGL::TryVideoMode( const VideoModeParams &p, bool &bNewDevic
|
|||||||
/* Recreate all vertex buffers. */
|
/* Recreate all vertex buffers. */
|
||||||
InvalidateAllGeometry();
|
InvalidateAllGeometry();
|
||||||
|
|
||||||
InitScalingScript();
|
InitShaders();
|
||||||
InitColorBurnScript();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set vsync the Windows way, if we can. (What other extensions are there
|
/* Set vsync the Windows way, if we can. (What other extensions are there
|
||||||
@@ -827,6 +810,14 @@ static void SetupVertices( const RageSpriteVertex v[], int iNumVerts )
|
|||||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
glTexCoordPointer( 2, GL_FLOAT, 0, Texture );
|
glTexCoordPointer( 2, GL_FLOAT, 0, Texture );
|
||||||
|
|
||||||
|
if( GLExt.glClientActiveTextureARB != NULL )
|
||||||
|
{
|
||||||
|
GLExt.glClientActiveTextureARB( GL_TEXTURE1_ARB );
|
||||||
|
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
|
glTexCoordPointer( 2, GL_FLOAT, 0, Texture );
|
||||||
|
GLExt.glClientActiveTextureARB( GL_TEXTURE0_ARB );
|
||||||
|
}
|
||||||
|
|
||||||
glEnableClientState( GL_NORMAL_ARRAY );
|
glEnableClientState( GL_NORMAL_ARRAY );
|
||||||
glNormalPointer( GL_FLOAT, 0, Normal );
|
glNormalPointer( GL_FLOAT, 0, Normal );
|
||||||
}
|
}
|
||||||
@@ -1554,35 +1545,39 @@ void RageDisplay_OGL::SetTextureFiltering( TextureUnit tu, bool b )
|
|||||||
|
|
||||||
void RageDisplay_OGL::SetEffectMode( EffectMode effect )
|
void RageDisplay_OGL::SetEffectMode( EffectMode effect )
|
||||||
{
|
{
|
||||||
|
if( GLExt.glUseProgramObjectARB == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
GLhandleARB hShader = 0;
|
||||||
switch( effect )
|
switch( effect )
|
||||||
{
|
{
|
||||||
case EffectMode_Normal:
|
case EffectMode_Normal: hShader = 0; break;
|
||||||
if( GLExt.glUseProgramObjectARB != NULL )
|
case EffectMode_ColorBurn: hShader = g_bColorBurnShader; break;
|
||||||
GLExt.glUseProgramObjectARB( 0 );
|
case EffectMode_ColorDodge: hShader = g_bColorDodgeShader; break;
|
||||||
break;
|
case EffectMode_VividLight: hShader = g_bVividLightShader; break;
|
||||||
case EffectMode_ColorBurn:
|
case EffectMode_HardMix: hShader = g_hHardMixShader; break;
|
||||||
if( !g_bColorBurnShader )
|
|
||||||
break; // unsupported
|
|
||||||
|
|
||||||
FlushGLErrors();
|
|
||||||
GLExt.glUseProgramObjectARB( g_bColorBurnShader );
|
|
||||||
GLint g_bColorBurnShaderTexture1 = GLExt.glGetUniformLocationARB( g_bColorBurnShader, "Texture1" );
|
|
||||||
GLint g_bColorBurnShaderTexture2 = GLExt.glGetUniformLocationARB( g_bColorBurnShader, "Texture2" );
|
|
||||||
GLExt.glUniform1iARB( g_bColorBurnShaderTexture1, 0 );
|
|
||||||
GLExt.glUniform1iARB( g_bColorBurnShaderTexture2, 1 );
|
|
||||||
AssertNoGLError();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlushGLErrors();
|
||||||
|
GLExt.glUseProgramObjectARB( hShader );
|
||||||
|
if( hShader == 0 )
|
||||||
|
return;
|
||||||
|
GLint iTexture1 = GLExt.glGetUniformLocationARB( hShader, "Texture1" );
|
||||||
|
GLint iTexture2 = GLExt.glGetUniformLocationARB( hShader, "Texture2" );
|
||||||
|
GLExt.glUniform1iARB( iTexture1, 0 );
|
||||||
|
GLExt.glUniform1iARB( iTexture2, 1 );
|
||||||
|
AssertNoGLError();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RageDisplay_OGL::IsEffectModeSupported( EffectMode effect )
|
bool RageDisplay_OGL::IsEffectModeSupported( EffectMode effect )
|
||||||
{
|
{
|
||||||
switch( effect )
|
switch( effect )
|
||||||
{
|
{
|
||||||
case EffectMode_Normal:
|
case EffectMode_Normal: return true;
|
||||||
return true;
|
case EffectMode_ColorBurn: return g_bColorBurnShader != 0;
|
||||||
case EffectMode_ColorBurn:
|
case EffectMode_ColorDodge: return g_bColorDodgeShader != 0;
|
||||||
return g_bColorBurnShader != 0;
|
case EffectMode_VividLight: return g_bVividLightShader != 0;
|
||||||
|
case EffectMode_HardMix: return g_hHardMixShader != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -96,8 +96,11 @@ static const char *EffectModeNames[] =
|
|||||||
/* Normal blending. All supported texture modes have their standard effects. */
|
/* Normal blending. All supported texture modes have their standard effects. */
|
||||||
"Normal",
|
"Normal",
|
||||||
|
|
||||||
/* Color burn blending. */
|
/* Layered blending. */
|
||||||
"ColorBurn",
|
"ColorBurn",
|
||||||
|
"ColorDodge",
|
||||||
|
"VividLight",
|
||||||
|
"HardMix",
|
||||||
};
|
};
|
||||||
XToString( EffectMode );
|
XToString( EffectMode );
|
||||||
LuaXType( EffectMode );
|
LuaXType( EffectMode );
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ enum EffectMode
|
|||||||
{
|
{
|
||||||
EffectMode_Normal,
|
EffectMode_Normal,
|
||||||
EffectMode_ColorBurn,
|
EffectMode_ColorBurn,
|
||||||
|
EffectMode_ColorDodge,
|
||||||
|
EffectMode_VividLight,
|
||||||
|
EffectMode_HardMix,
|
||||||
NUM_EffectMode,
|
NUM_EffectMode,
|
||||||
EffectMode_Invalid
|
EffectMode_Invalid
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user