implement TextureMatrixScale with a vertex shader
This commit is contained in:
@@ -92,6 +92,8 @@ set<string> g_glExts;
|
||||
* no GL_T2F_C4F_V3F. */
|
||||
const GLenum RageSpriteVertexFormat = GL_T2F_C4F_N3F_V3F;
|
||||
|
||||
/* If we support texture matrix scaling, a handle to the vertex program: */
|
||||
static GLhandleARB g_bTextureMatrixShader = NULL;
|
||||
|
||||
LowLevelWindow *wind;
|
||||
|
||||
@@ -348,6 +350,98 @@ RageDisplay_OGL::RageDisplay_OGL()
|
||||
wind = NULL;
|
||||
}
|
||||
|
||||
CString GetInfoLog( GLhandleARB h )
|
||||
{
|
||||
GLint iLength;
|
||||
GLExt.glGetObjectParameterivARB( h, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iLength );
|
||||
if( !iLength )
|
||||
return "";
|
||||
|
||||
GLcharARB *pInfoLog = new GLcharARB[iLength];
|
||||
GLExt.glGetInfoLogARB( h, iLength, &iLength, pInfoLog );
|
||||
CString sRet = pInfoLog;
|
||||
delete [] pInfoLog;
|
||||
return sRet;
|
||||
}
|
||||
|
||||
GLhandleARB CompileShader( GLenum ShaderType, CString sBuffer )
|
||||
{
|
||||
GLhandleARB VertexShader = GLExt.glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
|
||||
const GLcharARB *pData = sBuffer.data();
|
||||
int iLength = sBuffer.size();
|
||||
GLExt.glShaderSourceARB( VertexShader, 1, &pData, &iLength );
|
||||
|
||||
GLExt.glCompileShaderARB( VertexShader );
|
||||
|
||||
GLint bCompileStatus = GL_FALSE;
|
||||
GLExt.glGetObjectParameterivARB( VertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &bCompileStatus );
|
||||
|
||||
if( !bCompileStatus )
|
||||
{
|
||||
LOG->Trace( "Compile failure: %s", GetInfoLog( VertexShader ).c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return VertexShader;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
ATTRIB_TEXTURE_MATRIX_SCALE = 1
|
||||
};
|
||||
|
||||
/* 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 * (1-TextureMatrixScale)); \
|
||||
gl_FrontColor = gl_Color; \
|
||||
} \
|
||||
";
|
||||
|
||||
void InitScalingScript()
|
||||
{
|
||||
g_bTextureMatrixShader = NULL;
|
||||
|
||||
if( !GLExt.m_bGL_ARB_shader_objects ||
|
||||
!GLExt.m_bGL_ARB_vertex_shader ||
|
||||
!GLExt.m_bGL_ARB_shading_language_100 )
|
||||
return;
|
||||
|
||||
GLhandleARB VertexShader = CompileShader( GL_VERTEX_SHADER_ARB, g_TextureMatrixScaleShader );
|
||||
if( VertexShader == NULL )
|
||||
return;
|
||||
|
||||
g_bTextureMatrixShader = GLExt.glCreateProgramObjectARB();
|
||||
GLExt.glAttachObjectARB( g_bTextureMatrixShader, VertexShader );
|
||||
GLExt.glDeleteObjectARB( VertexShader );
|
||||
|
||||
// Bind attributes.
|
||||
GLExt.glBindAttribLocationARB( g_bTextureMatrixShader, ATTRIB_TEXTURE_MATRIX_SCALE, "TextureMatrixScale" );
|
||||
|
||||
// Link the program.
|
||||
GLExt.glLinkProgramARB( g_bTextureMatrixShader );
|
||||
GLint bLinkStatus = false;
|
||||
GLExt.glGetObjectParameterivARB( g_bTextureMatrixShader, GL_OBJECT_LINK_STATUS_ARB, &bLinkStatus );
|
||||
|
||||
if( !bLinkStatus )
|
||||
{
|
||||
LOG->Trace( "Scaling shader link failed: %s", GetInfoLog(g_bTextureMatrixShader).c_str() );
|
||||
GLExt.glDeleteObjectARB( g_bTextureMatrixShader );
|
||||
return;
|
||||
}
|
||||
|
||||
GLExt.glVertexAttrib2fARB( ATTRIB_TEXTURE_MATRIX_SCALE, 1, 1 );
|
||||
}
|
||||
|
||||
CString RageDisplay_OGL::Init( VideoModeParams p, bool bAllowUnacceleratedRenderer )
|
||||
{
|
||||
wind = MakeLowLevelWindow();
|
||||
@@ -404,6 +498,8 @@ CString RageDisplay_OGL::Init( VideoModeParams p, bool bAllowUnacceleratedRender
|
||||
glGetFloatv(GL_POINT_SIZE_RANGE, g_point_range);
|
||||
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &g_point_granularity);
|
||||
|
||||
InitScalingScript();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -797,6 +893,7 @@ public:
|
||||
m_vPosition.resize( GetTotalVertices() );
|
||||
m_vTexture.resize( GetTotalVertices() );
|
||||
m_vNormal.resize( GetTotalVertices() );
|
||||
m_vTexMatrixScale.resize( GetTotalVertices() );
|
||||
m_vTriangles.resize( GetTotalTriangles() );
|
||||
}
|
||||
void Change( const vector<msMesh> &vMeshes )
|
||||
@@ -813,6 +910,7 @@ public:
|
||||
m_vPosition[meshInfo.iVertexStart+j] = Vertices[j].p;
|
||||
m_vTexture[meshInfo.iVertexStart+j] = Vertices[j].t;
|
||||
m_vNormal[meshInfo.iVertexStart+j] = Vertices[j].n;
|
||||
m_vTexMatrixScale[meshInfo.iVertexStart+j] = Vertices[j].TextureMatrixScale;
|
||||
}
|
||||
|
||||
for( unsigned j=0; j<Triangles.size(); j++ )
|
||||
@@ -852,6 +950,7 @@ protected:
|
||||
vector<RageVector2> m_vTexture;
|
||||
vector<RageVector3> m_vNormal;
|
||||
vector<msTriangle> m_vTriangles;
|
||||
vector<RageVector2> m_vTexMatrixScale;
|
||||
};
|
||||
|
||||
class RageCompiledGeometryHWOGL : public RageCompiledGeometrySWOGL
|
||||
@@ -862,6 +961,7 @@ protected:
|
||||
GLuint m_nTextureCoords;
|
||||
GLuint m_nNormals;
|
||||
GLuint m_nTriangles;
|
||||
GLuint m_nTextureMatrixScale;
|
||||
|
||||
void AllocateBuffers();
|
||||
void UploadData();
|
||||
@@ -889,7 +989,7 @@ static void InvalidateAllGeometry()
|
||||
RageCompiledGeometryHWOGL::RageCompiledGeometryHWOGL()
|
||||
{
|
||||
g_GeometryList.insert( this );
|
||||
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = 0;
|
||||
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = m_nTextureMatrixScale = 0;
|
||||
|
||||
AllocateBuffers();
|
||||
}
|
||||
@@ -907,6 +1007,8 @@ RageCompiledGeometryHWOGL::~RageCompiledGeometryHWOGL()
|
||||
AssertNoGLError();
|
||||
GLExt.glDeleteBuffersARB( 1, &m_nTriangles );
|
||||
AssertNoGLError();
|
||||
GLExt.glDeleteBuffersARB( 1, &m_nTextureMatrixScale );
|
||||
AssertNoGLError();
|
||||
}
|
||||
|
||||
void RageCompiledGeometryHWOGL::AllocateBuffers()
|
||||
@@ -936,6 +1038,12 @@ void RageCompiledGeometryHWOGL::AllocateBuffers()
|
||||
GLExt.glGenBuffersARB( 1, &m_nTriangles );
|
||||
AssertNoGLError();
|
||||
}
|
||||
|
||||
if( !m_nTextureMatrixScale )
|
||||
{
|
||||
GLExt.glGenBuffersARB( 1, &m_nTextureMatrixScale );
|
||||
AssertNoGLError();
|
||||
}
|
||||
}
|
||||
|
||||
void RageCompiledGeometryHWOGL::UploadData()
|
||||
@@ -971,12 +1079,23 @@ void RageCompiledGeometryHWOGL::UploadData()
|
||||
&m_vTriangles[0],
|
||||
GL_STATIC_DRAW_ARB );
|
||||
// AssertNoGLError();
|
||||
|
||||
|
||||
if( m_bNeedsTextureMatrixScale )
|
||||
{
|
||||
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureMatrixScale );
|
||||
GLExt.glBufferDataARB(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
GetTotalVertices()*sizeof(RageVector2),
|
||||
&m_vTexMatrixScale[0],
|
||||
GL_STATIC_DRAW_ARB );
|
||||
}
|
||||
}
|
||||
|
||||
void RageCompiledGeometryHWOGL::Invalidate()
|
||||
{
|
||||
/* Our vertex buffers no longer exist. Reallocate and reupload. */
|
||||
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = 0;
|
||||
m_nPositions = m_nTextureCoords = m_nNormals = m_nTriangles = m_nTextureMatrixScale = 0;
|
||||
AllocateBuffers();
|
||||
UploadData();
|
||||
}
|
||||
@@ -984,7 +1103,6 @@ void RageCompiledGeometryHWOGL::Invalidate()
|
||||
void RageCompiledGeometryHWOGL::Allocate( const vector<msMesh> &vMeshes )
|
||||
{
|
||||
RageCompiledGeometrySWOGL::Allocate( vMeshes );
|
||||
|
||||
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nPositions );
|
||||
GLExt.glBufferDataARB(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
@@ -1016,6 +1134,13 @@ void RageCompiledGeometryHWOGL::Allocate( const vector<msMesh> &vMeshes )
|
||||
NULL,
|
||||
GL_STATIC_DRAW_ARB );
|
||||
AssertNoGLError();
|
||||
|
||||
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureMatrixScale );
|
||||
GLExt.glBufferDataARB(
|
||||
GL_ARRAY_BUFFER_ARB,
|
||||
GetTotalVertices()*sizeof(RageVector2),
|
||||
NULL,
|
||||
GL_STATIC_DRAW_ARB );
|
||||
}
|
||||
|
||||
void RageCompiledGeometryHWOGL::Change( const vector<msMesh> &vMeshes )
|
||||
@@ -1068,6 +1193,21 @@ void RageCompiledGeometryHWOGL::Draw( int iMeshIndex ) const
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
if( m_bNeedsTextureMatrixScale && g_bTextureMatrixShader != NULL )
|
||||
{
|
||||
/* If we're using texture matrix scales, set up that buffer, too, and enable the
|
||||
* vertex shader. This shader doesn't support all OpenGL state, so only enable it
|
||||
* if we're using it. */
|
||||
GLExt.glEnableVertexAttribArrayARB( ATTRIB_TEXTURE_MATRIX_SCALE );
|
||||
AssertNoGLError();
|
||||
GLExt.glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_nTextureMatrixScale );
|
||||
AssertNoGLError();
|
||||
GLExt.glVertexAttribPointerARB( ATTRIB_TEXTURE_MATRIX_SCALE, 2, GL_FLOAT, false, 0, NULL );
|
||||
AssertNoGLError();
|
||||
|
||||
GLExt.glUseProgramObjectARB( g_bTextureMatrixShader );
|
||||
}
|
||||
|
||||
GLExt.glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_nTriangles );
|
||||
AssertNoGLError();
|
||||
|
||||
@@ -1083,6 +1223,12 @@ void RageCompiledGeometryHWOGL::Draw( int iMeshIndex ) const
|
||||
GL_UNSIGNED_SHORT,
|
||||
BUFFER_OFFSET(meshInfo.iTriangleStart*sizeof(msTriangle)) );
|
||||
AssertNoGLError();
|
||||
|
||||
if( m_bNeedsTextureMatrixScale && g_bTextureMatrixShader != NULL )
|
||||
{
|
||||
GLExt.glDisableVertexAttribArrayARB( ATTRIB_TEXTURE_MATRIX_SCALE );
|
||||
GLExt.glUseProgramObjectARB( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
RageCompiledGeometry* RageDisplay_OGL::CreateCompiledGeometry()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "glext.h"
|
||||
|
||||
#include "RageDisplay_OGL_Extensions.h"
|
||||
#include "RageLog.h"
|
||||
#include "arch/LowLevelWindow/LowLevelWindow.h"
|
||||
|
||||
GLExt_t GLExt;
|
||||
@@ -102,4 +103,67 @@ void GLExt_t::Load( LowLevelWindow *pWind )
|
||||
|
||||
if( HasExtension("GL_EXT_draw_range_elements") )
|
||||
GLExt.glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) pWind->GetProcAddress("glDrawRangeElements");
|
||||
|
||||
m_bGL_ARB_shader_objects = HasExtension("GL_ARB_shader_objects");
|
||||
if( m_bGL_ARB_shader_objects )
|
||||
{
|
||||
func_t funcs[] = {
|
||||
F( glCreateShaderObjectARB ),
|
||||
F( glCreateShaderObjectARB ),
|
||||
F( glCreateProgramObjectARB ),
|
||||
F( glShaderSourceARB ),
|
||||
F( glCompileShaderARB ),
|
||||
F( glGetObjectParameterfvARB ),
|
||||
F( glGetObjectParameterivARB ),
|
||||
F( glGetInfoLogARB ),
|
||||
F( glAttachObjectARB ),
|
||||
F( glDeleteObjectARB ),
|
||||
F( glLinkProgramARB ),
|
||||
F( glUseProgramObjectARB ),
|
||||
F( glVertexAttrib2fARB ),
|
||||
F( glVertexAttrib3fARB ),
|
||||
F( glVertexAttrib4fARB ),
|
||||
F( glEnableVertexAttribArrayARB ),
|
||||
F( glDisableVertexAttribArrayARB ),
|
||||
F( glVertexAttribPointerARB ),
|
||||
NULL
|
||||
};
|
||||
|
||||
if( !LoadAllOrNothing(funcs, pWind) )
|
||||
m_bGL_ARB_shader_objects = false;
|
||||
}
|
||||
|
||||
m_bGL_ARB_vertex_shader = m_bGL_ARB_shader_objects && HasExtension("GL_ARB_vertex_shader");
|
||||
if( m_bGL_ARB_vertex_shader )
|
||||
{
|
||||
func_t funcs[] =
|
||||
{
|
||||
F( glBindAttribLocationARB ),
|
||||
NULL
|
||||
};
|
||||
if( !LoadAllOrNothing(funcs, pWind) )
|
||||
m_bGL_ARB_vertex_shader = false;
|
||||
}
|
||||
|
||||
m_bGL_ARB_shading_language_100 = HasExtension("GL_ARB_shading_language_100");
|
||||
if( m_bGL_ARB_shading_language_100 )
|
||||
{
|
||||
while( glGetError() != GL_NO_ERROR )
|
||||
;
|
||||
const char *pzVersion = (const char *) glGetString( GL_SHADING_LANGUAGE_VERSION );
|
||||
|
||||
GLenum glError = glGetError();
|
||||
if( glError == GL_INVALID_ENUM )
|
||||
{
|
||||
LOG->Info( "No GL_SHADING_LANGUAGE_VERSION; assuming 1.0" );
|
||||
m_iShadingLanguageVersion = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float fVersion = strtof( pzVersion, NULL );
|
||||
m_iShadingLanguageVersion = int(roundf(fVersion * 100));
|
||||
/* The version string may contain extra information beyond the version number. */
|
||||
LOG->Info( "OpenGL shading language: %s", pzVersion );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,32 @@ struct GLExt_t
|
||||
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
|
||||
PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
|
||||
|
||||
// GL_ARB_shader_objects:
|
||||
bool m_bGL_ARB_shader_objects;
|
||||
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
|
||||
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
|
||||
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
|
||||
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
|
||||
PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
|
||||
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
|
||||
PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
|
||||
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
|
||||
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
|
||||
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
|
||||
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
|
||||
PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
|
||||
PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
|
||||
PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
|
||||
PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
|
||||
|
||||
// GL_ARB_vertex_shader:
|
||||
bool m_bGL_ARB_vertex_shader;
|
||||
PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
|
||||
|
||||
bool m_bGL_ARB_shading_language_100;
|
||||
int m_iShadingLanguageVersion; /* * 100 */
|
||||
|
||||
void Load( LowLevelWindow *pWind );
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user