123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "tr_local.h"
- idRenderProgManager renderProgManager;
- /*
- ================================================================================================
- idRenderProgManager::idRenderProgManager()
- ================================================================================================
- */
- idRenderProgManager::idRenderProgManager() {
- }
- /*
- ================================================================================================
- idRenderProgManager::~idRenderProgManager()
- ================================================================================================
- */
- idRenderProgManager::~idRenderProgManager() {
- }
- /*
- ================================================================================================
- R_ReloadShaders
- ================================================================================================
- */
- static void R_ReloadShaders( const idCmdArgs &args ) {
- renderProgManager.KillAllShaders();
- renderProgManager.LoadAllShaders();
- }
- /*
- ================================================================================================
- idRenderProgManager::Init()
- ================================================================================================
- */
- void idRenderProgManager::Init() {
- common->Printf( "----- Initializing Render Shaders -----\n" );
- for ( int i = 0; i < MAX_BUILTINS; i++ ) {
- builtinShaders[i] = -1;
- }
- struct builtinShaders_t {
- int index;
- const char * name;
- } builtins[] = {
- { BUILTIN_GUI, "gui.vfp" },
- { BUILTIN_COLOR, "color.vfp" },
- { BUILTIN_SIMPLESHADE, "simpleshade.vfp" },
- { BUILTIN_TEXTURED, "texture.vfp" },
- { BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp" },
- { BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp" },
- { BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp" },
- { BUILTIN_INTERACTION, "interaction.vfp" },
- { BUILTIN_INTERACTION_SKINNED, "interaction_skinned.vfp" },
- { BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp" },
- { BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp" },
- { BUILTIN_ENVIRONMENT, "environment.vfp" },
- { BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp" },
- { BUILTIN_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" },
- { BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyEnvironment_skinned.vfp" },
- { BUILTIN_DEPTH, "depth.vfp" },
- { BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp" },
- { BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp" },
- { BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp" },
- { BUILTIN_BLENDLIGHT, "blendlight.vfp" },
- { BUILTIN_FOG, "fog.vfp" },
- { BUILTIN_FOG_SKINNED, "fog_skinned.vfp" },
- { BUILTIN_SKYBOX, "skybox.vfp" },
- { BUILTIN_WOBBLESKY, "wobblesky.vfp" },
- { BUILTIN_POSTPROCESS, "postprocess.vfp" },
- { BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp" },
- { BUILTIN_STEREO_WARP, "stereoWarp.vfp" },
- { BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp" },
- { BUILTIN_BINK, "bink.vfp" },
- { BUILTIN_BINK_GUI, "bink_gui.vfp" },
- { BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp" },
- { BUILTIN_MOTION_BLUR, "motionBlur.vfp" },
- };
- int numBuiltins = sizeof( builtins ) / sizeof( builtins[0] );
- vertexShaders.SetNum( numBuiltins );
- fragmentShaders.SetNum( numBuiltins );
- glslPrograms.SetNum( numBuiltins );
- for ( int i = 0; i < numBuiltins; i++ ) {
- vertexShaders[i].name = builtins[i].name;
- fragmentShaders[i].name = builtins[i].name;
- builtinShaders[builtins[i].index] = i;
- LoadVertexShader( i );
- LoadFragmentShader( i );
- LoadGLSLProgram( i, i, i );
- }
- // Special case handling for fastZ shaders
- builtinShaders[BUILTIN_SHADOW] = FindVertexShader( "shadow.vp" );
- builtinShaders[BUILTIN_SHADOW_SKINNED] = FindVertexShader( "shadow_skinned.vp" );
- FindGLSLProgram( "shadow.vp", builtinShaders[BUILTIN_SHADOW], -1 );
- FindGLSLProgram( "shadow_skinned.vp", builtinShaders[BUILTIN_SHADOW_SKINNED], -1 );
- glslUniforms.SetNum( RENDERPARM_USER + MAX_GLSL_USER_PARMS, vec4_zero );
- vertexShaders[builtinShaders[BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_INTERACTION_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_INTERACTION_AMBIENT_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_ENVIRONMENT_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_BUMPY_ENVIRONMENT_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_DEPTH_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_SHADOW_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
- vertexShaders[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
- cmdSystem->AddCommand( "reloadShaders", R_ReloadShaders, CMD_FL_RENDERER, "reloads shaders" );
- }
- /*
- ================================================================================================
- idRenderProgManager::LoadAllShaders()
- ================================================================================================
- */
- void idRenderProgManager::LoadAllShaders() {
- for ( int i = 0; i < vertexShaders.Num(); i++ ) {
- LoadVertexShader( i );
- }
- for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
- LoadFragmentShader( i );
- }
- for ( int i = 0; i < glslPrograms.Num(); ++i ) {
- LoadGLSLProgram( i, glslPrograms[i].vertexShaderIndex, glslPrograms[i].fragmentShaderIndex );
- }
- }
- /*
- ================================================================================================
- idRenderProgManager::KillAllShaders()
- ================================================================================================
- */
- void idRenderProgManager::KillAllShaders() {
- Unbind();
- for ( int i = 0; i < vertexShaders.Num(); i++ ) {
- if ( vertexShaders[i].progId != INVALID_PROGID ) {
- qglDeleteShader( vertexShaders[i].progId );
- vertexShaders[i].progId = INVALID_PROGID;
- }
- }
- for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
- if ( fragmentShaders[i].progId != INVALID_PROGID ) {
- qglDeleteShader( fragmentShaders[i].progId );
- fragmentShaders[i].progId = INVALID_PROGID;
- }
- }
- for ( int i = 0; i < glslPrograms.Num(); ++i ) {
- if ( glslPrograms[i].progId != INVALID_PROGID ) {
- qglDeleteProgram( glslPrograms[i].progId );
- glslPrograms[i].progId = INVALID_PROGID;
- }
- }
- }
- /*
- ================================================================================================
- idRenderProgManager::Shutdown()
- ================================================================================================
- */
- void idRenderProgManager::Shutdown() {
- KillAllShaders();
- }
- /*
- ================================================================================================
- idRenderProgManager::FindVertexShader
- ================================================================================================
- */
- int idRenderProgManager::FindVertexShader( const char * name ) {
- for ( int i = 0; i < vertexShaders.Num(); i++ ) {
- if ( vertexShaders[i].name.Icmp( name ) == 0 ) {
- LoadVertexShader( i );
- return i;
- }
- }
- vertexShader_t shader;
- shader.name = name;
- int index = vertexShaders.Append( shader );
- LoadVertexShader( index );
- currentVertexShader = index;
- // FIXME: we should really scan the program source code for using rpEnableSkinning but at this
- // point we directly load a binary and the program source code is not available on the consoles
- if ( idStr::Icmp( name, "heatHaze.vfp" ) == 0 ||
- idStr::Icmp( name, "heatHazeWithMask.vfp" ) == 0 ||
- idStr::Icmp( name, "heatHazeWithMaskAndVertex.vfp" ) == 0 ) {
- vertexShaders[index].usesJoints = true;
- vertexShaders[index].optionalSkinning = true;
- }
- return index;
- }
- /*
- ================================================================================================
- idRenderProgManager::FindFragmentShader
- ================================================================================================
- */
- int idRenderProgManager::FindFragmentShader( const char * name ) {
- for ( int i = 0; i < fragmentShaders.Num(); i++ ) {
- if ( fragmentShaders[i].name.Icmp( name ) == 0 ) {
- LoadFragmentShader( i );
- return i;
- }
- }
- fragmentShader_t shader;
- shader.name = name;
- int index = fragmentShaders.Append( shader );
- LoadFragmentShader( index );
- currentFragmentShader = index;
- return index;
- }
- /*
- ================================================================================================
- idRenderProgManager::LoadVertexShader
- ================================================================================================
- */
- void idRenderProgManager::LoadVertexShader( int index ) {
- if ( vertexShaders[index].progId != INVALID_PROGID ) {
- return; // Already loaded
- }
- vertexShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_VERTEX_SHADER, vertexShaders[index].name, vertexShaders[index].uniforms );
- }
- /*
- ================================================================================================
- idRenderProgManager::LoadFragmentShader
- ================================================================================================
- */
- void idRenderProgManager::LoadFragmentShader( int index ) {
- if ( fragmentShaders[index].progId != INVALID_PROGID ) {
- return; // Already loaded
- }
- fragmentShaders[index].progId = ( GLuint ) LoadGLSLShader( GL_FRAGMENT_SHADER, fragmentShaders[index].name, fragmentShaders[index].uniforms );
- }
- /*
- ================================================================================================
- idRenderProgManager::LoadShader
- ================================================================================================
- */
- GLuint idRenderProgManager::LoadShader( GLenum target, const char * name, const char * startToken ) {
- idStr fullPath = "renderprogs\\gl\\";
- fullPath += name;
- common->Printf( "%s", fullPath.c_str() );
- char * fileBuffer = NULL;
- fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL );
- if ( fileBuffer == NULL ) {
- common->Printf( ": File not found\n" );
- return INVALID_PROGID;
- }
- if ( !R_IsInitialized() ) {
- common->Printf( ": Renderer not initialized\n" );
- fileSystem->FreeFile( fileBuffer );
- return INVALID_PROGID;
- }
- // vertex and fragment shaders are both be present in a single file, so
- // scan for the proper header to be the start point, and stamp a 0 in after the end
- char * start = strstr( (char *)fileBuffer, startToken );
- if ( start == NULL ) {
- common->Printf( ": %s not found\n", startToken );
- fileSystem->FreeFile( fileBuffer );
- return INVALID_PROGID;
- }
- char * end = strstr( start, "END" );
- if ( end == NULL ) {
- common->Printf( ": END not found for %s\n", startToken );
- fileSystem->FreeFile( fileBuffer );
- return INVALID_PROGID;
- }
- end[3] = 0;
- idStr program = start;
- program.Replace( "vertex.normal", "vertex.attrib[11]" );
- program.Replace( "vertex.texcoord[0]", "vertex.attrib[8]" );
- program.Replace( "vertex.texcoord", "vertex.attrib[8]" );
- GLuint progId;
- qglGenProgramsARB( 1, &progId );
- qglBindProgramARB( target, progId );
- qglGetError();
- qglProgramStringARB( target, GL_PROGRAM_FORMAT_ASCII_ARB, program.Length(), program.c_str() );
- GLenum err = qglGetError();
- GLint ofs = -1;
- qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &ofs );
- if ( ( err == GL_INVALID_OPERATION ) || ( ofs != -1 ) ) {
- if ( err == GL_INVALID_OPERATION ) {
- const GLubyte * str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
- common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str );
- } else {
- common->Printf( "\nUNKNOWN ERROR\n" );
- }
- if ( ofs < 0 ) {
- common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0\n" );
- } else if ( ofs >= program.Length() ) {
- common->Printf( "error at end of shader\n" );
- } else {
- common->Printf( "error at %i:\n%s", ofs, program.c_str() + ofs );
- }
- qglDeleteProgramsARB( 1, &progId );
- fileSystem->FreeFile( fileBuffer );
- return INVALID_PROGID;
- }
- common->Printf( "\n" );
- fileSystem->FreeFile( fileBuffer );
- return progId;
- }
- /*
- ================================================================================================
- idRenderProgManager::BindShader
- ================================================================================================
- */
- void idRenderProgManager::BindShader( int vIndex, int fIndex ) {
- if ( currentVertexShader == vIndex && currentFragmentShader == fIndex ) {
- return;
- }
- currentVertexShader = vIndex;
- currentFragmentShader = fIndex;
- // vIndex denotes the GLSL program
- if ( vIndex >= 0 && vIndex < glslPrograms.Num() ) {
- currentRenderProgram = vIndex;
- RENDERLOG_PRINTF( "Binding GLSL Program %s\n", glslPrograms[vIndex].name.c_str() );
- qglUseProgram( glslPrograms[vIndex].progId );
- }
- }
- /*
- ================================================================================================
- idRenderProgManager::Unbind
- ================================================================================================
- */
- void idRenderProgManager::Unbind() {
- currentVertexShader = -1;
- currentFragmentShader = -1;
- qglUseProgram( 0 );
- }
- /*
- ================================================================================================
- idRenderProgManager::SetRenderParms
- ================================================================================================
- */
- void idRenderProgManager::SetRenderParms( renderParm_t rp, const float * value, int num ) {
- for ( int i = 0; i < num; i++ ) {
- SetRenderParm( (renderParm_t)(rp + i), value + ( i * 4 ) );
- }
- }
- /*
- ================================================================================================
- idRenderProgManager::SetRenderParm
- ================================================================================================
- */
- void idRenderProgManager::SetRenderParm( renderParm_t rp, const float * value ) {
- SetUniformValue( rp, value );
- }
|