2004-10-19 15:56:22 +00:00
/*
Copyright ( C ) 2002 - 2003 Victor Luchits
This program 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 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2010-11-26 06:58:48 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-10-19 15:56:22 +00:00
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// r_shader.c - based on code by Stephen C. Taylor
2010-07-11 02:22:39 +00:00
// Ported to FTE from qfusion, there are numerous changes since then.
2004-10-19 15:56:22 +00:00
# include "quakedef.h"
2009-11-04 21:16:50 +00:00
# ifndef SERVERONLY
2004-10-19 15:56:22 +00:00
# include "glquake.h"
# include "shader.h"
2004-11-23 01:23:45 +00:00
# include "hash.h"
2004-10-19 15:56:22 +00:00
2004-12-09 23:42:00 +00:00
# include <ctype.h>
2011-09-03 03:49:43 +00:00
# ifdef D3DQUAKE
# include <d3d9.h>
extern LPDIRECT3DDEVICE9 pD3DDev9 ;
# endif
2009-11-04 21:16:50 +00:00
extern texid_t missing_texture ;
2012-02-12 05:18:31 +00:00
texid_t r_whiteimage ;
2009-11-04 21:16:50 +00:00
static qboolean shader_reload_needed ;
2010-07-11 02:22:39 +00:00
static qboolean shader_rescan_needed ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
//cvars that affect shader generation
2011-12-05 15:23:40 +00:00
cvar_t r_vertexlight = CVARFD ( " r_vertexlight " , " 0 " , CVAR_SHADERSYSTEM , " Hack loaded shaders to remove detail pass and lightmap sampling for faster rendering. " ) ;
2012-01-17 07:57:46 +00:00
extern cvar_t r_glsl_offsetmapping_reliefmapping ;
2011-04-30 17:21:10 +00:00
extern cvar_t r_deluxemapping ;
2010-07-11 02:22:39 +00:00
extern cvar_t r_fastturb , r_fastsky , r_skyboxname ;
2009-11-04 21:16:50 +00:00
extern cvar_t r_drawflat ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
//backend fills this in to say the max pass count
int be_maxpasses ;
2004-10-19 15:56:22 +00:00
# define Q_stricmp stricmp
2011-12-23 03:12:29 +00:00
# define Q_strnicmp strnicmp
2006-03-06 01:41:09 +00:00
# define Com_sprintf snprintf
2004-10-19 15:56:22 +00:00
# define clamp(v,min, max) (v) = (((v)<(min))?(min):(((v)>(max))?(max):(v)));
typedef union {
float f ;
unsigned int i ;
} float_int_t ;
qbyte FloatToByte ( float x )
{
static float_int_t f2i ;
// shift float to have 8bit fraction at base of number
f2i . f = x + 32768.0f ;
// then read as integer and kill float bits...
return ( qbyte ) min ( f2i . i & 0x7FFFFF , 255 ) ;
}
cvar_t r_detailtextures ;
# define MAX_TOKEN_CHARS 1024
char * COM_ParseExt ( char * * data_p , qboolean nl )
{
int c ;
int len ;
char * data ;
qboolean newlines = false ;
data = * data_p ;
len = 0 ;
com_token [ 0 ] = 0 ;
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
if ( ! data )
{
* data_p = NULL ;
return " " ;
}
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
// skip whitespace
skipwhite :
2009-11-04 21:16:50 +00:00
while ( ( c = * data ) < = ' ' )
2004-10-19 15:56:22 +00:00
{
if ( c = = 0 )
{
* data_p = NULL ;
return " " ;
}
if ( c = = ' \n ' )
newlines = true ;
data + + ;
}
2009-11-04 21:16:50 +00:00
if ( newlines & & ! nl )
{
2004-10-19 15:56:22 +00:00
* data_p = data ;
return com_token ;
}
// skip // comments
if ( c = = ' / ' & & data [ 1 ] = = ' / ' )
{
while ( * data & & * data ! = ' \n ' )
data + + ;
goto skipwhite ;
}
// handle quoted strings specially
if ( c = = ' \" ' )
{
data + + ;
while ( 1 )
{
c = * data + + ;
if ( c = = ' \" ' | | ! c )
{
com_token [ len ] = 0 ;
* data_p = data ;
return com_token ;
}
if ( len < MAX_TOKEN_CHARS )
{
com_token [ len ] = c ;
len + + ;
}
}
}
// parse a regular word
do
{
if ( len < MAX_TOKEN_CHARS )
{
com_token [ len ] = c ;
len + + ;
}
data + + ;
c = * data ;
2011-02-25 04:22:14 +00:00
if ( c = = ' , ' & & len )
break ;
2004-10-19 15:56:22 +00:00
} while ( c > 32 ) ;
if ( len = = MAX_TOKEN_CHARS )
{
// Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
len = 0 ;
}
com_token [ len ] = 0 ;
* data_p = data ;
return com_token ;
}
# define HASH_SIZE 128
typedef struct shaderkey_s
{
char * keyword ;
void ( * func ) ( shader_t * shader , shaderpass_t * pass , char * * ptr ) ;
} shaderkey_t ;
typedef struct shadercache_s {
char name [ MAX_QPATH ] ;
char * path ;
unsigned int offset ;
struct shadercache_s * hash_next ;
} shadercache_t ;
2010-05-01 22:47:47 +00:00
static shadercache_t * * shader_hash ;
2005-03-28 00:11:59 +00:00
static char shaderbuf [ MAX_QPATH * 256 ] ;
int shaderbuflen ;
2004-10-19 15:56:22 +00:00
2011-12-05 15:23:40 +00:00
static enum {
SPM_DEFAULT , /*quake3/fte internal*/
SPM_DOOM3 ,
} shaderparsemode ;
2010-05-01 22:47:47 +00:00
shader_t * r_shaders ;
2010-07-11 02:22:39 +00:00
static hashtable_t shader_active_hash ;
void * shader_active_hash_mem ;
2004-10-19 15:56:22 +00:00
2004-12-09 23:42:00 +00:00
//static char r_skyboxname[MAX_QPATH];
//static float r_skyheight;
2004-10-19 15:56:22 +00:00
char * Shader_Skip ( char * ptr ) ;
static qboolean Shader_Parsetok ( shader_t * shader , shaderpass_t * pass , shaderkey_t * keys ,
char * token , char * * ptr ) ;
static void Shader_ParseFunc ( char * * args , shaderfunc_t * func ) ;
static void Shader_MakeCache ( char * path ) ;
static void Shader_GetPathAndOffset ( char * name , char * * path , unsigned int * offset ) ;
2011-12-05 15:23:40 +00:00
static void Shader_ReadShader ( shader_t * s , char * shadersource , int parsemode ) ;
2004-10-19 15:56:22 +00:00
//===========================================================================
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
static qboolean Shader_EvaluateCondition ( char * * ptr )
{
char * token ;
cvar_t * cv ;
qboolean conditiontrue = true ;
token = COM_ParseExt ( ptr , false ) ;
if ( * token = = ' ! ' )
{
conditiontrue = false ;
token + + ;
}
if ( * token = = ' $ ' )
{
token + + ;
2011-09-03 03:49:43 +00:00
if ( ! Q_stricmp ( token , " lpp " ) )
2011-12-23 03:12:29 +00:00
conditiontrue = conditiontrue = = r_lightprepass . ival ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " lightmap " ) )
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
conditiontrue = conditiontrue = = ! r_fullbright . value ;
else if ( ! Q_stricmp ( token , " deluxmap " ) )
2011-10-27 16:16:29 +00:00
conditiontrue = conditiontrue = = r_deluxemapping . ival ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
//normalmaps are generated if they're not already known.
else if ( ! Q_stricmp ( token , " normalmap " ) )
2011-10-27 16:16:29 +00:00
conditiontrue = conditiontrue = = r_loadbumpmapping ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
2011-05-20 04:10:46 +00:00
else if ( ! Q_stricmp ( token , " gles " ) )
{
# ifdef GLQUAKE
conditiontrue = conditiontrue = = ( ( qrenderer = = QR_OPENGL ) & & ! ! gl_config . gles ) ;
# else
conditiontrue = conditiontrue = = false ;
# endif
}
else if ( ! Q_stricmp ( token , " nofixed " ) )
{
# ifdef GLQUAKE
conditiontrue = conditiontrue = = ( ( qrenderer = = QR_OPENGL ) & & ! ! gl_config . nofixedfunc ) ;
# else
conditiontrue = conditiontrue = = false ;
# endif
}
2011-03-12 13:51:40 +00:00
else if ( ! Q_stricmp ( token , " glsl " ) )
{
# ifdef GLQUAKE
conditiontrue = conditiontrue = = ( ( qrenderer = = QR_OPENGL ) & & gl_config . arb_shader_objects ) ;
# else
conditiontrue = conditiontrue = = false ;
# endif
}
else if ( ! Q_stricmp ( token , " hlsl " ) )
{
# ifdef D3DQUAKE
conditiontrue = conditiontrue = = false ; //((qrenderer == QR_DIRECT3D) && gl_config.arb_shader_objects);
# else
conditiontrue = conditiontrue = = false ;
# endif
2011-10-27 16:16:29 +00:00
2011-03-12 13:51:40 +00:00
2010-12-09 08:52:33 +00:00
// GCC hates these within if statements "error: expected '}' before 'else'"
2011-10-27 16:16:29 +00:00
# ifdef warningmsg
# pragma warningmsg("shader fixme")
2010-11-26 06:58:48 +00:00
# endif
2011-10-27 16:16:29 +00:00
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
else if ( ! Q_stricmp ( token , " diffuse " ) )
conditiontrue = conditiontrue = = true ;
else if ( ! Q_stricmp ( token , " specular " ) )
conditiontrue = conditiontrue = = false ;
else if ( ! Q_stricmp ( token , " fullbright " ) )
conditiontrue = conditiontrue = = false ;
else if ( ! Q_stricmp ( token , " topoverlay " ) )
conditiontrue = conditiontrue = = false ;
else if ( ! Q_stricmp ( token , " loweroverlay " ) )
conditiontrue = conditiontrue = = false ;
else
2011-03-12 13:51:40 +00:00
{
Con_Printf ( " Unrecognised builtin shader condition '%s' \n " , token ) ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
conditiontrue = conditiontrue = = false ;
2011-03-12 13:51:40 +00:00
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
}
else
{
cv = Cvar_Get ( token , " " , 0 , " Shader Conditions " ) ;
2010-11-10 03:32:47 +00:00
token = COM_ParseExt ( ptr , false ) ;
if ( * token )
{
float rhs ;
char cmp [ 4 ] ;
memcpy ( cmp , token , 4 ) ;
token = COM_ParseExt ( ptr , false ) ;
rhs = atof ( token ) ;
if ( ! strcmp ( cmp , " != " ) )
conditiontrue = cv - > value ! = rhs ;
else if ( ! strcmp ( cmp , " == " ) )
conditiontrue = cv - > value = = rhs ;
else if ( ! strcmp ( cmp , " < " ) )
conditiontrue = cv - > value < rhs ;
else if ( ! strcmp ( cmp , " <= " ) )
conditiontrue = cv - > value < = rhs ;
else if ( ! strcmp ( cmp , " > " ) )
conditiontrue = cv - > value > rhs ;
else if ( ! strcmp ( cmp , " >= " ) )
conditiontrue = cv - > value > = rhs ;
else
conditiontrue = false ;
}
else
{
if ( cv )
conditiontrue = conditiontrue = = ! ! cv - > value ;
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
}
2011-03-12 13:51:40 +00:00
token = COM_ParseExt ( ptr , false ) ;
if ( ! strcmp ( token , " && " ) )
return Shader_EvaluateCondition ( ptr ) & & conditiontrue ;
if ( ! strcmp ( token , " || " ) )
return Shader_EvaluateCondition ( ptr ) | | conditiontrue ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
return conditiontrue ;
}
2004-10-19 15:56:22 +00:00
static char * Shader_ParseString ( char * * ptr )
{
char * token ;
if ( ! ptr | | ! ( * ptr ) ) {
return " " ;
}
if ( ! * * ptr | | * * ptr = = ' } ' ) {
return " " ;
}
token = COM_ParseExt ( ptr , false ) ;
2005-01-24 23:47:32 +00:00
Q_strlwr ( token ) ;
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
return token ;
}
2010-07-11 02:22:39 +00:00
static char * Shader_ParseSensString ( char * * ptr )
{
char * token ;
if ( ! ptr | | ! ( * ptr ) ) {
return " " ;
}
if ( ! * * ptr | | * * ptr = = ' } ' ) {
return " " ;
}
token = COM_ParseExt ( ptr , false ) ;
2010-11-26 06:58:48 +00:00
2010-07-11 02:22:39 +00:00
return token ;
}
2010-11-22 02:03:28 +00:00
static float Shader_ParseFloat ( char * * ptr )
2004-10-19 15:56:22 +00:00
{
2010-11-22 02:03:28 +00:00
char * token ;
if ( ! ptr | | ! ( * ptr ) )
{
2004-10-19 15:56:22 +00:00
return 0 ;
}
2010-11-22 02:03:28 +00:00
if ( ! * * ptr | | * * ptr = = ' } ' )
{
2004-10-19 15:56:22 +00:00
return 0 ;
}
2010-11-22 02:03:28 +00:00
token = COM_ParseExt ( ptr , false ) ;
if ( * token = = ' $ ' )
{
cvar_t * var ;
var = Cvar_FindVar ( token + 1 ) ;
if ( var )
return var - > value ;
}
return atof ( token ) ;
2004-10-19 15:56:22 +00:00
}
static void Shader_ParseVector ( char * * ptr , vec3_t v )
{
2009-11-04 21:16:50 +00:00
char * scratch ;
2004-10-19 15:56:22 +00:00
char * token ;
qboolean bracket ;
token = Shader_ParseString ( ptr ) ;
2009-11-04 21:16:50 +00:00
if ( * token = = ' $ ' )
{
cvar_t * var ;
var = Cvar_FindVar ( token + 1 ) ;
if ( ! var )
{
v [ 0 ] = 1 ;
v [ 1 ] = 1 ;
v [ 2 ] = 1 ;
return ;
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
var - > flags | = CVAR_SHADERSYSTEM ;
2009-11-04 21:16:50 +00:00
ptr = & scratch ;
scratch = var - > string ;
2010-07-11 02:22:39 +00:00
token = Shader_ParseString ( ptr ) ;
2009-11-04 21:16:50 +00:00
}
2004-10-19 15:56:22 +00:00
if ( ! Q_stricmp ( token , " ( " ) ) {
bracket = true ;
token = Shader_ParseString ( ptr ) ;
} else if ( token [ 0 ] = = ' ( ' ) {
bracket = true ;
token = & token [ 1 ] ;
} else {
bracket = false ;
}
v [ 0 ] = atof ( token ) ;
v [ 1 ] = Shader_ParseFloat ( ptr ) ;
token = Shader_ParseString ( ptr ) ;
if ( ! token [ 0 ] ) {
v [ 2 ] = 0 ;
} else if ( token [ strlen ( token ) - 1 ] = = ' ) ' ) {
token [ strlen ( token ) - 1 ] = 0 ;
v [ 2 ] = atof ( token ) ;
} else {
v [ 2 ] = atof ( token ) ;
if ( bracket ) {
Shader_ParseString ( ptr ) ;
}
}
2009-11-04 21:16:50 +00:00
if ( v [ 0 ] > 5 | | v [ 1 ] > 5 | | v [ 2 ] > 5 )
{
VectorScale ( v , 1.0f / 255 , v ) ;
}
2004-10-19 15:56:22 +00:00
}
2010-07-11 02:22:39 +00:00
qboolean Shader_ParseSkySides ( char * shadername , char * texturename , texid_t * images )
2004-10-19 15:56:22 +00:00
{
2010-07-11 02:22:39 +00:00
qboolean allokay = true ;
2009-11-04 21:16:50 +00:00
int i , ss , sp ;
2004-10-19 15:56:22 +00:00
char path [ MAX_QPATH ] ;
2009-11-04 21:16:50 +00:00
static char * skyname_suffix [ ] [ 6 ] = {
{ " rt " , " bk " , " lf " , " ft " , " up " , " dn " } ,
{ " px " , " py " , " nx " , " ny " , " pz " , " nz " } ,
{ " posx " , " posy " , " negx " , " negy " , " posz " , " negz " } ,
{ " _px " , " _py " , " _nx " , " _ny " , " _pz " , " _nz " } ,
{ " _posx " , " _posy " , " _negx " , " _negy " , " _posz " , " _negz " } ,
{ " _rt " , " _bk " , " _lf " , " _ft " , " _up " , " _dn " }
} ;
static char * skyname_pattern [ ] = {
" %s_%s " ,
" %s%s " ,
" env/%s%s " ,
" gfx/env/%s%s "
} ;
2004-10-19 15:56:22 +00:00
2010-07-11 02:22:39 +00:00
if ( * texturename = = ' $ ' )
2009-11-04 21:16:50 +00:00
{
cvar_t * v ;
2010-07-11 02:22:39 +00:00
v = Cvar_FindVar ( texturename + 1 ) ;
2009-11-04 21:16:50 +00:00
if ( v )
2010-07-11 02:22:39 +00:00
texturename = v - > string ;
2009-11-04 21:16:50 +00:00
}
2010-07-11 02:22:39 +00:00
if ( ! * texturename )
texturename = " - " ;
2004-10-19 15:56:22 +00:00
for ( i = 0 ; i < 6 ; i + + )
{
2010-07-11 02:22:39 +00:00
if ( texturename [ 0 ] = = ' - ' )
{
2009-11-04 21:16:50 +00:00
images [ i ] = r_nulltex ;
2010-07-11 02:22:39 +00:00
}
else
{
2009-11-04 21:16:50 +00:00
for ( sp = 0 ; sp < sizeof ( skyname_pattern ) / sizeof ( skyname_pattern [ 0 ] ) ; sp + + )
{
for ( ss = 0 ; ss < sizeof ( skyname_suffix ) / sizeof ( skyname_suffix [ 0 ] ) ; ss + + )
{
2010-07-11 02:22:39 +00:00
Com_sprintf ( path , sizeof ( path ) , skyname_pattern [ sp ] , texturename , skyname_suffix [ ss ] [ i ] ) ;
2009-11-04 21:16:50 +00:00
images [ i ] = R_LoadHiResTexture ( path , NULL , IF_NOALPHA ) ;
if ( TEXVALID ( images [ i ] ) )
break ;
}
if ( TEXVALID ( images [ i ] ) )
break ;
}
if ( ! TEXVALID ( images [ i ] ) )
2009-01-15 04:58:12 +00:00
{
2010-07-11 02:22:39 +00:00
Con_Printf ( " Sky \" %s \" missing texture: %s \n " , shadername , path ) ;
2006-01-12 22:24:06 +00:00
images [ i ] = missing_texture ;
2010-07-11 02:22:39 +00:00
allokay = false ;
2009-01-15 04:58:12 +00:00
}
2004-10-19 15:56:22 +00:00
}
}
2010-07-11 02:22:39 +00:00
return allokay ;
2004-10-19 15:56:22 +00:00
}
2005-04-16 16:21:27 +00:00
2004-10-19 15:56:22 +00:00
static void Shader_ParseFunc ( char * * ptr , shaderfunc_t * func )
{
char * token ;
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " sin " ) ) {
func - > type = SHADER_FUNC_SIN ;
} else if ( ! Q_stricmp ( token , " triangle " ) ) {
func - > type = SHADER_FUNC_TRIANGLE ;
} else if ( ! Q_stricmp ( token , " square " ) ) {
func - > type = SHADER_FUNC_SQUARE ;
} else if ( ! Q_stricmp ( token , " sawtooth " ) ) {
func - > type = SHADER_FUNC_SAWTOOTH ;
} else if ( ! Q_stricmp ( token , " inversesawtooth " ) ) {
func - > type = SHADER_FUNC_INVERSESAWTOOTH ;
} else if ( ! Q_stricmp ( token , " noise " ) ) {
func - > type = SHADER_FUNC_NOISE ;
}
func - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
func - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
func - > args [ 2 ] = Shader_ParseFloat ( ptr ) ;
func - > args [ 3 ] = Shader_ParseFloat ( ptr ) ;
}
//===========================================================================
2011-12-23 03:12:29 +00:00
static int Shader_SetImageFlags ( shader_t * shader , char * * name )
2004-10-19 15:56:22 +00:00
{
int flags = 0 ;
2011-12-23 03:12:29 +00:00
while ( name )
{
if ( ! Q_strnicmp ( * name , " $3d: " , 4 ) )
{
* name + = 4 ;
flags | = IF_3DMAP ;
}
else
name = NULL ;
}
2009-11-04 21:16:50 +00:00
// if (shader->flags & SHADER_SKY)
// flags |= IF_SKY;
if ( shader - > flags & SHADER_NOMIPMAPS )
flags | = IF_NOMIPMAP ;
if ( shader - > flags & SHADER_NOPICMIP )
flags | = IF_NOPICMIP ;
2004-10-19 15:56:22 +00:00
return flags ;
}
2009-11-04 21:16:50 +00:00
static texid_t Shader_FindImage ( char * name , int flags )
2004-10-19 15:56:22 +00:00
{
2011-12-05 15:23:40 +00:00
if ( shaderparsemode = = SPM_DOOM3 )
{
if ( ! Q_stricmp ( name , " _default " ) )
return r_whiteimage ; /*fixme*/
if ( ! Q_stricmp ( name , " _white " ) )
return r_whiteimage ;
if ( ! Q_stricmp ( name , " _black " ) )
{
int wibuf [ 16 ] = { 0 } ;
2011-12-23 03:12:29 +00:00
return R_LoadTexture ( " $blackimage " , 4 , 4 , TF_RGBA32 , wibuf , IF_NOMIPMAP | IF_NOPICMIP | IF_NEAREST | IF_NOGAMMA ) ;
2011-12-05 15:23:40 +00:00
}
}
2009-11-04 21:16:50 +00:00
else
2011-12-05 15:23:40 +00:00
{
if ( ! Q_stricmp ( name , " $whiteimage " ) )
return r_whiteimage ;
}
return R_LoadHiResTexture ( name , NULL , flags ) ;
2004-10-19 15:56:22 +00:00
}
/****************** shader keyword functions ************************/
static void Shader_Cull ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
shader - > flags & = ~ ( SHADER_CULL_FRONT | SHADER_CULL_BACK ) ;
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " disable " ) | | ! Q_stricmp ( token , " none " ) | | ! Q_stricmp ( token , " twosided " ) ) {
} else if ( ! Q_stricmp ( token , " front " ) ) {
shader - > flags | = SHADER_CULL_FRONT ;
} else if ( ! Q_stricmp ( token , " back " ) | | ! Q_stricmp ( token , " backside " ) | | ! Q_stricmp ( token , " backsided " ) ) {
shader - > flags | = SHADER_CULL_BACK ;
} else {
shader - > flags | = SHADER_CULL_FRONT ;
}
}
static void Shader_NoMipMaps ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = ( SHADER_NOMIPMAPS | SHADER_NOPICMIP ) ;
}
static void Shader_NoPicMip ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = SHADER_NOPICMIP ;
}
static void Shader_DeformVertexes ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
deformv_t * deformv ;
if ( shader - > numdeforms > = SHADER_DEFORM_MAX ) {
return ;
}
deformv = & shader - > deforms [ shader - > numdeforms ] ;
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " wave " ) ) {
deformv - > type = DEFORMV_WAVE ;
deformv - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
if ( deformv - > args [ 0 ] ) {
deformv - > args [ 0 ] = 1.0f / deformv - > args [ 0 ] ;
}
Shader_ParseFunc ( ptr , & deformv - > func ) ;
} else if ( ! Q_stricmp ( token , " normal " ) ) {
deformv - > type = DEFORMV_NORMAL ;
deformv - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
deformv - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
} else if ( ! Q_stricmp ( token , " bulge " ) ) {
deformv - > type = DEFORMV_BULGE ;
Shader_ParseVector ( ptr , deformv - > args ) ;
shader - > flags | = SHADER_DEFORMV_BULGE ;
} else if ( ! Q_stricmp ( token , " move " ) ) {
deformv - > type = DEFORMV_MOVE ;
Shader_ParseVector ( ptr , deformv - > args ) ;
Shader_ParseFunc ( ptr , & deformv - > func ) ;
} else if ( ! Q_stricmp ( token , " autosprite " ) ) {
deformv - > type = DEFORMV_AUTOSPRITE ;
shader - > flags | = SHADER_AUTOSPRITE ;
} else if ( ! Q_stricmp ( token , " autosprite2 " ) ) {
deformv - > type = DEFORMV_AUTOSPRITE2 ;
shader - > flags | = SHADER_AUTOSPRITE ;
} else if ( ! Q_stricmp ( token , " projectionShadow " ) ) {
deformv - > type = DEFORMV_PROJECTION_SHADOW ;
} else {
return ;
}
shader - > numdeforms + + ;
}
2010-07-11 02:22:39 +00:00
static void Shader_SkyParms ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
skydome_t * skydome ;
float skyheight ;
2010-07-11 02:22:39 +00:00
char * boxname ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
if ( shader - > skydome )
{
2010-07-11 02:22:39 +00:00
Z_Free ( shader - > skydome ) ;
2004-10-19 15:56:22 +00:00
}
2010-07-11 02:22:39 +00:00
skydome = ( skydome_t * ) Z_Malloc ( sizeof ( skydome_t ) ) ;
2004-10-19 15:56:22 +00:00
shader - > skydome = skydome ;
2010-07-11 02:22:39 +00:00
boxname = Shader_ParseString ( ptr ) ;
Shader_ParseSkySides ( shader - > name , boxname , skydome - > farbox_textures ) ;
2004-10-19 15:56:22 +00:00
2010-07-11 02:22:39 +00:00
skyheight = Shader_ParseFloat ( ptr ) ;
if ( ! skyheight )
{
2004-10-19 15:56:22 +00:00
skyheight = 512.0f ;
}
2010-07-11 02:22:39 +00:00
boxname = Shader_ParseString ( ptr ) ;
Shader_ParseSkySides ( shader - > name , boxname , skydome - > nearbox_textures ) ;
2004-10-19 15:56:22 +00:00
shader - > flags | = SHADER_SKY ;
shader - > sort = SHADER_SORT_SKY ;
}
static void Shader_FogParms ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
float div ;
vec3_t color , fcolor ;
// if ( !r_ignorehwgamma->value )
// div = 1.0f / pow(2, max(0, floor(r_overbrightbits->value)));
// else
div = 1.0f ;
Shader_ParseVector ( ptr , color ) ;
VectorScale ( color , div , color ) ;
ColorNormalize ( color , fcolor ) ;
shader - > fog_color [ 0 ] = FloatToByte ( fcolor [ 0 ] ) ;
shader - > fog_color [ 1 ] = FloatToByte ( fcolor [ 1 ] ) ;
shader - > fog_color [ 2 ] = FloatToByte ( fcolor [ 2 ] ) ;
2010-11-26 06:58:48 +00:00
shader - > fog_color [ 3 ] = 255 ;
2004-10-19 15:56:22 +00:00
shader - > fog_dist = Shader_ParseFloat ( ptr ) ;
if ( shader - > fog_dist < = 0.0f ) {
shader - > fog_dist = 128.0f ;
}
shader - > fog_dist = 1.0f / shader - > fog_dist ;
}
2005-05-26 12:55:34 +00:00
static void Shader_SurfaceParm ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " nodraw " ) )
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
shader - > flags | = SHADER_NODRAW ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " nodlight " ) )
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
shader - > flags | = SHADER_NODLIGHT ;
2005-05-26 12:55:34 +00:00
}
2004-10-19 15:56:22 +00:00
static void Shader_Sort ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
token = Shader_ParseString ( ptr ) ;
2011-09-03 03:49:43 +00:00
if ( ! Q_stricmp ( token , " portal " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_PORTAL ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " sky " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_SKY ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " opaque " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_OPAQUE ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " decal " ) )
2010-07-11 02:22:39 +00:00
shader - > sort = SHADER_SORT_DECAL ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " seethrough " ) )
2010-07-11 02:22:39 +00:00
shader - > sort = SHADER_SORT_SEETHROUGH ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " banner " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_BANNER ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " additive " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_ADDITIVE ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " underwater " ) )
2010-07-11 02:22:39 +00:00
shader - > sort = SHADER_SORT_UNDERWATER ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " nearest " ) )
2004-10-19 15:56:22 +00:00
shader - > sort = SHADER_SORT_NEAREST ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " blend " ) )
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
shader - > sort = SHADER_SORT_BLEND ;
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( token , " lpp_light " ) )
shader - > sort = SHADER_SORT_PRELIGHT ;
else
{
2004-10-19 15:56:22 +00:00
shader - > sort = atoi ( token ) ;
clamp ( shader - > sort , SHADER_SORT_NONE , SHADER_SORT_NEAREST ) ;
}
}
2011-09-03 03:49:43 +00:00
static void Shader_Prelight ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > sort = SHADER_SORT_PRELIGHT ;
}
2004-10-19 15:56:22 +00:00
static void Shader_Portal ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > sort = SHADER_SORT_PORTAL ;
}
static void Shader_PolygonOffset ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
2009-11-04 21:16:50 +00:00
/*the q3 defaults*/
shader - > polyoffset . factor = - 0.05 ;
shader - > polyoffset . unit = - 25 ;
2004-10-19 15:56:22 +00:00
}
static void Shader_EntityMergable ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = SHADER_ENTITY_MERGABLE ;
}
2011-12-23 03:12:29 +00:00
static void Shader_ProgAutoFields ( program_t * prog , char * * cvarnames , int * cvartypes ) ;
2011-01-23 03:44:49 +00:00
/*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/
2012-01-16 06:22:06 +00:00
static qboolean Shader_LoadPermutations ( char * name , program_t * prog , char * script , int qrtype , int ver )
2010-08-28 17:14:38 +00:00
{
2011-01-23 03:44:49 +00:00
static char * permutationname [ ] =
{
2010-08-28 17:14:38 +00:00
" #define BUMP \n " ,
" #define SPECULAR \n " ,
2011-01-23 03:44:49 +00:00
" #define FULLBRIGHT \n " ,
" #define LOWER \n " ,
" #define UPPER \n " ,
" #define OFFSETMAPPING \n " ,
2011-07-30 14:14:56 +00:00
" #define SKELETAL \n " ,
2011-12-23 03:12:29 +00:00
" #define FOG \n " ,
2011-01-23 03:44:49 +00:00
NULL
} ;
2012-01-17 07:57:46 +00:00
char * permutationdefines [ sizeof ( permutationname ) / sizeof ( permutationname [ 0 ] ) + 64 + 1 ] ;
2011-01-23 03:44:49 +00:00
unsigned int nopermutation = ~ 0u ;
2011-12-27 08:35:19 +00:00
int nummodifiers ;
2011-01-23 03:44:49 +00:00
int p , n , pn ;
char * end ;
2011-12-23 03:12:29 +00:00
char * cvarnames [ 64 ] ;
int cvartypes [ 64 ] ;
int cvarcount = 0 ;
2012-01-17 07:57:46 +00:00
qboolean onefailed = false ;
2011-04-30 17:21:10 +00:00
2011-12-23 03:12:29 +00:00
cvarnames [ cvarcount ] = NULL ;
2011-04-30 17:21:10 +00:00
2011-01-23 03:44:49 +00:00
for ( ; ; )
{
while ( * script = = ' ' | | * script = = ' \r ' | | * script = = ' \n ' | | * script = = ' \t ' )
script + + ;
2011-04-30 17:21:10 +00:00
if ( ! strncmp ( script , " !!cvarf " , 7 ) )
{
script + = 7 ;
while ( * script = = ' ' | | * script = = ' \t ' )
script + + ;
end = script ;
while ( ( * end > = ' A ' & & * end < = ' Z ' ) | | ( * end > = ' a ' & & * end < = ' z ' ) | | ( * end > = ' 0 ' & & * end < = ' 9 ' ) | | * end = = ' _ ' )
end + + ;
2011-12-23 03:12:29 +00:00
if ( cvarcount + 1 ! = sizeof ( cvarnames ) / sizeof ( cvarnames [ 0 ] ) )
{
cvartypes [ cvarcount ] = SP_CVARF ;
cvarnames [ cvarcount + + ] = script ;
cvarnames [ cvarcount ] = NULL ;
}
script = end ;
}
else if ( ! strncmp ( script , " !!cvarv " , 7 ) )
{
script + = 7 ;
while ( * script = = ' ' | | * script = = ' \t ' )
script + + ;
end = script ;
while ( ( * end > = ' A ' & & * end < = ' Z ' ) | | ( * end > = ' a ' & & * end < = ' z ' ) | | ( * end > = ' 0 ' & & * end < = ' 9 ' ) | | * end = = ' _ ' )
end + + ;
if ( cvarcount + 1 ! = sizeof ( cvarnames ) / sizeof ( cvarnames [ 0 ] ) )
{
cvartypes [ cvarcount ] = SP_CVAR3F ;
cvarnames [ cvarcount + + ] = script ;
cvarnames [ cvarcount ] = NULL ;
}
2011-04-30 17:21:10 +00:00
script = end ;
}
else if ( ! strncmp ( script , " !!permu " , 7 ) )
2011-01-23 03:44:49 +00:00
{
script + = 7 ;
2011-04-30 17:21:10 +00:00
while ( * script = = ' ' | | * script = = ' \t ' )
2011-01-23 03:44:49 +00:00
script + + ;
end = script ;
while ( ( * end > = ' A ' & & * end < = ' Z ' ) | | ( * end > = ' a ' & & * end < = ' z ' ) | | ( * end > = ' 0 ' & & * end < = ' 9 ' ) | | * end = = ' _ ' )
end + + ;
for ( p = 0 ; permutationname [ p ] ; p + + )
{
if ( ! strncmp ( permutationname [ p ] + 8 , script , end - script ) & & permutationname [ p ] [ 8 + end - script ] = = ' \n ' )
nopermutation & = ~ ( 1u < < p ) ;
}
script = end ;
}
2011-05-26 16:46:43 +00:00
else if ( ! strncmp ( script , " !!ver " , 5 ) )
{
script + = 5 ;
while ( * script = = ' ' | | * script = = ' \t ' )
script + + ;
end = script ;
while ( ( * end > = ' A ' & & * end < = ' Z ' ) | | ( * end > = ' a ' & & * end < = ' z ' ) | | ( * end > = ' 0 ' & & * end < = ' 9 ' ) | | * end = = ' _ ' )
end + + ;
ver = strtol ( script , NULL , 0 ) ;
script = end ;
}
2011-01-23 03:44:49 +00:00
else
break ;
2010-08-28 17:14:38 +00:00
} ;
2011-02-25 04:22:14 +00:00
memset ( prog - > handle , 0 , sizeof ( * prog - > handle ) * PERMUTATIONS ) ;
2011-12-27 08:35:19 +00:00
nummodifiers = 0 ;
for ( end = strchr ( name , ' # ' ) ; end & & * end ; )
{
char * start = end + 1 ;
end = strchr ( start , ' # ' ) ;
if ( ! end )
end = start + strlen ( start ) ;
2012-01-17 07:57:46 +00:00
if ( nummodifiers < 64 )
{
permutationdefines [ nummodifiers ] = malloc ( 10 + end - start ) ;
memcpy ( permutationdefines [ nummodifiers ] , " #define " , 8 ) ;
memcpy ( permutationdefines [ nummodifiers ] + 8 , start , end - start ) ;
memcpy ( permutationdefines [ nummodifiers ] + 8 + ( end - start ) , " \n " , 2 ) ;
for ( start = permutationdefines [ nummodifiers ] + 8 ; * start ; start + + )
* start = toupper ( * start ) ;
nummodifiers + + ;
permutationdefines [ nummodifiers ] = NULL ;
}
2011-12-27 08:35:19 +00:00
}
2012-01-17 07:57:46 +00:00
2010-08-28 17:14:38 +00:00
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
2012-01-17 07:57:46 +00:00
if ( nopermutation & p )
{
continue ;
}
pn = nummodifiers ;
for ( n = 0 ; permutationname [ n ] ; n + + )
{
if ( p & ( 1u < < n ) )
permutationdefines [ pn + + ] = permutationname [ n ] ;
}
if ( r_glsl_offsetmapping_reliefmapping . ival & & ( p & PERMUTATION_OFFSET ) )
permutationdefines [ pn + + ] = " #define RELIEFMAPPING \n " ;
permutationdefines [ pn + + ] = NULL ;
2010-08-28 17:14:38 +00:00
if ( qrenderer ! = qrtype )
{
}
2011-03-31 02:32:32 +00:00
# ifdef GLQUAKE
2010-08-28 17:14:38 +00:00
else if ( qrenderer = = QR_OPENGL )
2011-01-23 03:44:49 +00:00
{
2012-01-17 07:57:46 +00:00
prog - > handle [ p ] . glsl = GLSlang_CreateProgram ( name , ( ( ( p & PERMUTATION_SKELETAL ) & & ver < 120 ) ? 120 : ver ) , permutationdefines , script , script , onefailed ) ;
if ( ! prog - > handle [ p ] . glsl )
onefailed = true ;
2012-01-16 06:22:06 +00:00
if ( ! p & & ! prog - > handle [ p ] . glsl )
break ;
2011-01-23 03:44:49 +00:00
}
2011-03-31 02:32:32 +00:00
# endif
# ifdef D3DQUAKE
else if ( qrenderer = = QR_DIRECT3D )
{
2012-01-16 06:22:06 +00:00
if ( ! D3DShader_CreateProgram ( prog , p , permutationdefines , script , script ) )
break ;
2011-03-31 02:32:32 +00:00
}
# endif
2010-08-28 17:14:38 +00:00
}
2011-12-27 08:35:19 +00:00
while ( nummodifiers )
free ( permutationdefines [ - - nummodifiers ] ) ;
2011-02-25 04:22:14 +00:00
2011-12-23 03:12:29 +00:00
Shader_ProgAutoFields ( prog , cvarnames , cvartypes ) ;
2012-01-16 06:22:06 +00:00
if ( p = = PERMUTATIONS )
return true ;
return false ;
2010-08-28 17:14:38 +00:00
}
2011-01-23 03:44:49 +00:00
typedef struct sgeneric_s
{
struct sgeneric_s * next ;
2012-01-01 02:26:42 +00:00
char * name ;
2011-02-25 04:22:14 +00:00
qboolean failed ;
program_t prog ;
2011-01-23 03:44:49 +00:00
} sgeneric_t ;
static sgeneric_t * sgenerics ;
struct sbuiltin_s
{
int qrtype ;
int apiver ;
char name [ MAX_QPATH ] ;
char * body ;
2011-05-15 13:23:13 +00:00
} sbuiltins [ ] =
2011-01-23 03:44:49 +00:00
{
2011-01-23 03:51:27 +00:00
# ifdef GLQUAKE
/*a quick note on glsl versions:
gl versioning started with 110
gles versioning started at 100 and only had a single one defined
with gl3 ' s combined support , gl3 supports 130 + and 100 , but 110 requries compat extension
with gl4 , versions are meant to match the gl version more closely , so gl4 .0 uses 400. */
2011-02-06 20:56:39 +00:00
/*glsl es shaders require precisions to be defined for fragment shader variables
more precision for shaders would be a good candidate for a cvar */
2011-06-05 23:53:33 +00:00
/*defaultfill is a simple shader for block-filling with vertex colours. note that the blendfunc stuff is done after the shader anyway.*/
{ QR_OPENGL /*ES*/ , 100 , " defaultfill " ,
" #ifdef VERTEX_SHADER \n "
" attribute vec4 v_colour; \n "
" varying vec4 vc; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-06-05 23:53:33 +00:00
" { \n "
" vc = v_colour; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
2011-06-07 23:54:58 +00:00
" varying lowp vec4 vc; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-06-05 23:53:33 +00:00
" { \n "
" gl_FragColor = vc; \n "
" } \n "
" #endif \n "
} ,
/*default2d is a simple shader to draw the 2d elements. simple copying of a texture image to its dest (with vertex colour blending)*/
2011-01-23 03:44:49 +00:00
{ QR_OPENGL /*ES*/ , 100 , " default2d " ,
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec4 v_colour; \n "
" varying vec2 tc; \n "
" varying vec4 vc; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" tc = v_texcoord; \n "
" vc = v_colour; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
2011-02-06 20:56:39 +00:00
" varying mediump vec2 tc; \n "
" varying lowp vec4 vc; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" gl_FragColor = texture2D(s_t0, tc) * vc; \n "
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " default2d " ,
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec4 v_colour; \n "
" varying vec2 tc; \n "
" varying vec4 vc; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" tc = v_texcoord; \n "
" vc = v_colour; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" in vec2 tc; \n "
" varying vec4 vc; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" gl_FragColor = texture2D(s_t0, tc) * vc; \n "
" } \n "
" #endif \n "
} ,
2011-12-23 03:12:29 +00:00
{ QR_OPENGL , 110 , " defaultsprite " ,
" !!permu FOG \n "
" #include \" sys/fog.h \" \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec4 v_colour; \n "
" varying vec2 tc; \n "
" varying vec4 vc; \n "
" void main () \n "
" { \n "
" tc = v_texcoord; \n "
" vc = v_colour; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" in vec2 tc; \n "
" varying vec4 vc; \n "
2012-02-12 05:18:31 +00:00
" uniform vec4 e_colourident; \n "
2011-12-23 03:12:29 +00:00
" void main () \n "
" { \n "
" gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc); \n "
2012-02-12 05:18:31 +00:00
" gl_FragColor = gl_FragColor * e_colourident; \n "
2011-12-23 03:12:29 +00:00
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " defaultadditivesprite " ,
" !!permu FOG \n "
" #include \" sys/fog.h \" \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec4 v_colour; \n "
" varying vec2 tc; \n "
" varying vec4 vc; \n "
" void main () \n "
" { \n "
" tc = v_texcoord; \n "
" vc = v_colour; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" in vec2 tc; \n "
" varying vec4 vc; \n "
2012-02-12 05:18:31 +00:00
" uniform vec4 e_colourident; \n "
2011-12-23 03:12:29 +00:00
" void main () \n "
" { \n "
" gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc); \n "
2012-02-12 05:18:31 +00:00
" gl_FragColor = gl_FragColor * e_colourident; \n "
2011-12-23 03:12:29 +00:00
" } \n "
" #endif \n "
} ,
2011-06-05 23:53:33 +00:00
/*draws a wall, with lightmap.*/
2011-05-30 21:48:32 +00:00
{ QR_OPENGL /*ES*/ , 100 , " defaultwall " ,
2011-01-23 03:44:49 +00:00
" #ifdef VERTEX_SHADER \n "
2011-05-20 04:10:46 +00:00
" attribute vec2 v_texcoord; \n "
" attribute vec2 v_lmcoord; \n "
" varying vec2 tc, lm; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" tc = v_texcoord; \n "
" lm = v_lmcoord; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n " /*tex_diffuse*/
" uniform sampler2D s_t1; \n " /*tex_lightmap*/
//"uniform sampler2D s_t2;\n" /*tex_normalmap*/
//"uniform sampler2D s_t3;\n" /*tex_deluxmap*/
//"uniform sampler2D s_t4;\n" /*tex_fullbright*/
2011-05-30 21:48:32 +00:00
" varying mediump vec2 tc, lm; \n "
2012-01-17 07:57:46 +00:00
" uniform mediump vec4 e_lmscale; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2012-01-17 07:57:46 +00:00
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale; \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
} ,
2011-05-30 21:48:32 +00:00
{ QR_OPENGL , 110 , " defaultwall " ,
2011-12-26 15:19:13 +00:00
" !!permu OFFSETMAPPING \n "
" !!permu FULLBRIGHT \n "
2011-12-23 03:12:29 +00:00
" !!permu FOG \n "
2011-12-26 15:19:13 +00:00
" !!cvarf r_glsl_offsetmapping_scale \n "
2011-12-23 03:12:29 +00:00
" #include \" sys/fog.h \" \n "
2011-12-26 15:19:13 +00:00
" #if defined(OFFSETMAPPING) \n "
" varying vec3 eyevector; \n "
" #endif \n "
2011-01-23 03:44:49 +00:00
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec2 v_lmcoord; \n "
" varying vec2 tc, lm; \n "
2011-12-26 15:19:13 +00:00
" #if defined(OFFSETMAPPING) \n "
" uniform vec3 e_eyepos; \n "
" attribute vec3 v_normal; \n "
" attribute vec3 v_svector; \n "
" attribute vec3 v_tvector; \n "
" #endif \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-12-26 15:19:13 +00:00
" #if defined(OFFSETMAPPING) \n "
" vec3 eyeminusvertex = e_eyepos - v_position.xyz; \n "
" eyevector.x = dot(eyeminusvertex, v_svector.xyz); \n "
" eyevector.y = -dot(eyeminusvertex, v_tvector.xyz); \n "
" eyevector.z = dot(eyeminusvertex, v_normal.xyz); \n "
" #endif \n "
2011-01-23 03:44:49 +00:00
" tc = v_texcoord; \n "
" lm = v_lmcoord; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n " /*tex_diffuse*/
" uniform sampler2D s_t1; \n " /*tex_lightmap*/
2011-12-26 15:19:13 +00:00
" #ifdef OFFSETMAPPING \n "
" uniform sampler2D s_t2; \n " /*tex_normalmap*/
" #endif \n "
2011-01-23 03:44:49 +00:00
//"uniform sampler2D s_t3;\n" /*tex_deluxmap*/
2011-12-26 15:19:13 +00:00
" #ifdef FULLBRIGHT \n "
" uniform sampler2D s_t4; \n " /*tex_fullbright*/
" #endif \n "
2011-05-30 21:48:32 +00:00
" varying vec2 tc, lm; \n "
2012-01-17 07:57:46 +00:00
" uniform vec4 e_lmscale; \n "
2012-02-12 05:18:31 +00:00
" uniform vec4 e_colourident; \n "
2011-12-26 15:19:13 +00:00
" #ifdef OFFSETMAPPING \n "
2012-01-17 07:57:46 +00:00
" #include \" sys/offsetmapping.h \" \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-12-26 15:19:13 +00:00
" #ifdef OFFSETMAPPING \n "
2012-01-17 07:57:46 +00:00
" vec2 tcoffsetmap = offsetmap(s_t2, tc, eyevector); \n "
" #define tc tcoffsetmap \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
2012-01-17 07:57:46 +00:00
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale; \n "
2011-12-26 15:19:13 +00:00
" #ifdef FULLBRIGHT \n "
" gl_FragColor.rgb += texture2D(s_t4, tc).rgb; \n "
" #endif \n "
" #ifdef FOG \n "
" gl_FragColor = fog4(gl_FragColor); \n "
" #endif \n "
2012-02-12 05:18:31 +00:00
" gl_FragColor = gl_FragColor * e_colourident; \n "
2011-12-23 03:12:29 +00:00
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " drawflat_wall " ,
" !!cvarv r_floorcolor \n "
" !!cvarv r_wallcolor \n "
" !!permu FOG \n "
" #include \" sys/fog.h \" \n "
" varying vec4 col; \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec3 v_normal; \n "
" attribute vec2 v_lmcoord; \n "
" varying vec2 lm; \n "
" uniform vec3 cvar_r_wallcolor; \n "
" uniform vec3 cvar_r_floorcolor; \n "
2012-01-17 07:57:46 +00:00
" uniform vec4 e_lmscale; \n "
2011-12-23 03:12:29 +00:00
" void main () \n "
" { \n "
2012-01-17 07:57:46 +00:00
" col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a); \n "
2011-12-23 03:12:29 +00:00
" lm = v_lmcoord; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n " /*tex_lightmap*/
" varying vec2 lm; \n "
" void main () \n "
" { \n "
" gl_FragColor = fog4(col * texture2D(s_t0, lm)); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
} ,
2011-06-05 23:53:33 +00:00
/*defaultwarp: draws a water surface*/
2011-01-23 03:44:49 +00:00
{ QR_OPENGL /*ES*/ , 100 , " defaultwarp " ,
2011-04-30 17:21:10 +00:00
" !!cvarf r_wateralpha \n "
2011-02-06 20:56:39 +00:00
" varying mediump vec2 tc; \n "
2011-01-23 03:44:49 +00:00
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" tc = v_texcoord; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
2011-06-02 15:16:05 +00:00
" uniform sampler2D s_t0; \n "
2011-02-06 20:56:39 +00:00
" uniform mediump float e_time; \n "
2011-05-20 04:10:46 +00:00
" uniform lowp float cvar_r_wateralpha; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-02-06 20:56:39 +00:00
" mediump vec2 ntc; \n "
2011-01-23 03:44:49 +00:00
" ntc.s = tc.s + sin(tc.t+e_time)*0.125; \n "
" ntc.t = tc.t + sin(tc.s+e_time)*0.125; \n "
2011-06-02 15:16:05 +00:00
" lowp vec3 ts = vec3(texture2D(s_t0, ntc)); \n "
2011-01-23 03:44:49 +00:00
2011-05-20 04:10:46 +00:00
" gl_FragColor = vec4(ts, cvar_r_wateralpha); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " defaultwarp " ,
2011-04-30 17:21:10 +00:00
" !!cvarf r_wateralpha \n "
2011-12-23 03:12:29 +00:00
" !!permu FOG \n "
" #include \" sys/fog.h \" \n "
2011-01-23 03:44:49 +00:00
" varying vec2 tc; \n "
" #ifdef VERTEX_SHADER \n "
2011-05-20 04:10:46 +00:00
" attribute vec2 v_texcoord; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-05-20 04:10:46 +00:00
" tc = v_texcoord.st; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" uniform float e_time; \n "
2011-05-20 04:10:46 +00:00
" uniform float cvar_r_wateralpha; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" vec2 ntc; \n "
" ntc.s = tc.s + sin(tc.t+e_time)*0.125; \n "
" ntc.t = tc.t + sin(tc.s+e_time)*0.125; \n "
" vec3 ts = vec3(texture2D(s_t0, ntc)); \n "
2011-12-23 03:12:29 +00:00
" gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha)); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
} ,
2011-10-27 16:16:29 +00:00
{ QR_OPENGL , 110 , " underwaterwarp " ,
/*
inputs :
texcoords : edge points
coords : vertex coords ( duh )
time
ampscale ( cvar = r_waterwarp )
use ifs instead of an edge map ?
*/
" !!cvarf r_waterwarp \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" varying vec2 v_stc; \n "
" varying vec2 v_warp; \n "
" varying vec2 v_edge; \n "
" uniform float e_time; \n "
" void main () \n "
" { \n "
" gl_Position = ftetransform(); \n "
" v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0; \n "
" v_warp.s = e_time * 0.25 + v_texcoord.s; \n "
" v_warp.t = e_time * 0.25 + v_texcoord.t; \n "
" v_edge = v_texcoord.xy; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" varying vec2 v_stc; \n "
" varying vec2 v_warp; \n "
" varying vec2 v_edge; \n "
" uniform sampler2D s_t0;/*$currentrender*/ \n "
" uniform sampler2D s_t1;/*warp image*/ \n "
" uniform sampler2D s_t2;/*edge image*/ \n "
" uniform vec3 e_rendertexturescale; \n "
" uniform float cvar_r_waterwarp; \n "
" void main () \n "
" { \n "
" float amptemp; \n "
" vec3 edge; \n "
" edge = texture2D( s_t2, v_edge ).rgb; \n "
" amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x; \n "
" vec3 offset; \n "
" offset = texture2D( s_t1, v_warp ).rgb; \n "
" offset.x = (offset.x - 0.5) * 2.0; \n "
" offset.y = (offset.y - 0.5) * 2.0; \n "
" vec2 temp; \n "
" temp.x = v_stc.x + offset.x * amptemp; \n "
" temp.y = v_stc.y + offset.y * amptemp; \n "
" gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st ); \n "
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " postproc_panorama " ,
" !!cvarf ffov \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" varying vec2 texcoord; \n "
" void main() \n "
" { \n "
" texcoord = v_texcoord.xy; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform samplerCube s_t0; \n "
" varying vec2 texcoord; \n "
" uniform float cvar_ffov; \n "
" void main() \n "
" { \n "
" vec3 tc; \n "
" float ang; \n "
" ang = texcoord.x*-radians(cvar_ffov); \n "
" tc.x = sin(ang); \n "
" tc.y = -texcoord.y; \n "
" tc.z = cos(ang); \n "
" gl_FragColor = textureCube(s_t0, tc); \n "
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " postproc_fisheye " ,
" !!cvarf ffov \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" varying vec2 texcoord; \n "
" void main() \n "
" { \n "
" texcoord = v_texcoord.xy; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform samplerCube s_t0; \n "
" varying vec2 texcoord; \n "
" uniform float cvar_ffov; \n "
" void main() \n "
" { \n "
" vec3 tc; \n "
" vec2 d; \n "
" vec2 ang; \n "
" d = texcoord; \n "
" ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n "
" ang.y = -atan(d.y, d.x); \n "
" tc.x = sin(ang.x) * cos(ang.y); \n "
" tc.y = sin(ang.x) * sin(ang.y); \n "
" tc.z = cos(ang.x); \n "
" gl_FragColor = textureCube(s_t0, tc); \n "
" } \n "
" #endif \n "
} ,
2011-06-05 23:53:33 +00:00
/*defautsky projects the texture in order to match q1 skies, along with two separate layers scrolling at separate speeds*/
2011-01-23 03:44:49 +00:00
{ QR_OPENGL /*ES*/ , 100 , " defaultsky " ,
" #ifdef VERTEX_SHADER \n "
" varying vec3 pos; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" pos = v_position.xyz; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" uniform sampler2D s_t1; \n "
2011-02-06 20:56:39 +00:00
" uniform mediump float e_time; \n "
2011-03-31 02:32:32 +00:00
" uniform mediump vec3 e_eyepos; \n "
2011-02-06 20:56:39 +00:00
" varying mediump vec3 pos; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-02-06 20:56:39 +00:00
" mediump vec2 tccoord; \n "
2011-01-23 03:44:49 +00:00
2011-03-31 02:32:32 +00:00
" mediump vec3 dir = pos - e_eyepos; \n "
2011-01-23 03:44:49 +00:00
" dir.z *= 3.0; \n "
" dir.xy /= 0.5*length(dir); \n "
" tccoord = (dir.xy + e_time*0.03125); \n "
2011-02-06 20:56:39 +00:00
" lowp vec3 solid = vec3(texture2D(s_t0, tccoord)); \n "
2011-01-23 03:44:49 +00:00
" tccoord = (dir.xy + e_time*0.0625); \n "
2011-02-06 20:56:39 +00:00
" lowp vec4 clouds = texture2D(s_t1, tccoord); \n "
2011-01-23 03:44:49 +00:00
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb); \n "
// " gl_FragColor.rgb = solid.rgb;/*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n"
" } \n "
" #endif \n "
} ,
2011-09-03 03:49:43 +00:00
{ QR_OPENGL , 110 , " defaultsky " ,
2011-01-23 03:44:49 +00:00
" #ifdef VERTEX_SHADER \n "
" varying vec3 pos; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-05-20 04:10:46 +00:00
" pos = v_position.xyz; \n "
2011-06-05 23:53:33 +00:00
" gl_Position = ftetransform(); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform float e_time; \n "
2011-03-31 02:32:32 +00:00
" uniform vec3 e_eyepos; \n "
2011-01-23 03:44:49 +00:00
" varying vec3 pos; \n "
" uniform sampler2D s_t0; \n "
" uniform sampler2D s_t1; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
" vec2 tccoord; \n "
2011-03-31 02:32:32 +00:00
" vec3 dir = pos - e_eyepos; \n "
2011-01-23 03:44:49 +00:00
" dir.z *= 3.0; \n "
" dir.xy /= 0.5*length(dir); \n "
" tccoord = (dir.xy + e_time*0.03125); \n "
" vec3 solid = vec3(texture2D(s_t0, tccoord)); \n "
" tccoord = (dir.xy + e_time*0.0625); \n "
" vec4 clouds = texture2D(s_t1, tccoord); \n "
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb); \n "
" } \n "
" #endif \n "
} ,
2011-06-05 23:53:33 +00:00
/*draws a model. there's lots of extra stuff for light shading calcs and upper/lower textures*/
2011-01-23 03:44:49 +00:00
{ QR_OPENGL /*ES*/ , 100 , " defaultskin " ,
" !!permu FULLBRIGHT \n "
" !!permu LOWER \n "
" !!permu UPPER \n "
2011-07-30 14:14:56 +00:00
" !!permu SKELETAL \n "
2011-01-23 03:44:49 +00:00
" #ifdef VERTEX_SHADER \n "
2011-10-27 16:16:29 +00:00
" #include \" sys/skeletal.h \" \n "
2011-01-23 03:44:49 +00:00
" attribute vec2 v_texcoord; \n "
" varying vec2 tc; \n "
" uniform vec3 e_light_dir; \n "
" uniform vec3 e_light_mul; \n "
" uniform vec3 e_light_ambient; \n "
" varying vec3 light; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-10-27 16:16:29 +00:00
" vec3 n; \n "
" gl_Position = skeletaltransform_n(n); \n "
" light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul); \n "
2011-01-23 03:44:49 +00:00
" tc = v_texcoord; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n " /*tex_diffuse*/
" #ifdef LOWER \n "
" uniform sampler2D s_t1; \n " /*tex_lower*/
2011-02-06 20:56:39 +00:00
" uniform lowp vec3 e_lowercolour; \n "
2011-01-23 03:44:49 +00:00
" #endif \n "
" #ifdef UPPER \n "
" uniform sampler2D s_t2; \n " /*tex_upper*/
2011-02-06 20:56:39 +00:00
" uniform lowp vec3 e_uppercolour; \n "
2011-01-23 03:44:49 +00:00
" #endif \n "
" #ifdef FULLBRIGHT \n "
" uniform sampler2D s_t3; \n " /*tex_fullbright*/
" #endif \n "
2011-02-06 20:56:39 +00:00
" varying mediump vec2 tc; \n "
" varying lowp vec3 light; \n "
2011-05-30 21:48:32 +00:00
" uniform lowp vec4 e_colourident; \n "
2011-01-23 03:44:49 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-02-25 04:22:14 +00:00
" { \n "
2011-05-30 21:48:32 +00:00
" lowp vec4 col; \n "
2011-04-25 03:25:22 +00:00
" col = texture2D(s_t0, tc); \n "
2011-02-25 04:22:14 +00:00
" #ifdef UPPER \n "
2011-05-30 21:48:32 +00:00
" lowp vec4 uc = texture2D(s_t2, tc); \n "
2011-04-25 03:25:22 +00:00
" col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a); \n "
2011-02-25 04:22:14 +00:00
" #endif \n "
" #ifdef LOWER \n "
2011-05-30 21:48:32 +00:00
" lowp vec4 lc = texture2D(s_t1, tc); \n "
2011-04-25 03:25:22 +00:00
" col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a); \n "
2011-02-25 04:22:14 +00:00
" #endif \n "
2011-04-25 03:25:22 +00:00
" col.rgb *= light; \n "
2011-02-25 04:22:14 +00:00
" #ifdef FULLBRIGHT \n "
2011-05-30 21:48:32 +00:00
" lowp vec4 fb = texture2D(s_t3, tc); \n "
2011-04-25 03:25:22 +00:00
" col.rgb = mix(col.rgb, fb.rgb, fb.a); \n "
2011-02-25 04:22:14 +00:00
" #endif \n "
2011-05-15 13:23:13 +00:00
" gl_FragColor = col * e_colourident; \n "
2011-02-25 04:22:14 +00:00
" } \n "
" #endif \n "
} ,
2011-10-27 16:16:29 +00:00
{ QR_OPENGL , 110 , " defaultskin " ,
2011-02-25 04:22:14 +00:00
" !!permu FULLBRIGHT \n "
" !!permu LOWER \n "
" !!permu UPPER \n "
2011-07-30 14:14:56 +00:00
" !!permu SKELETAL \n "
2011-12-23 03:12:29 +00:00
" !!permu FOG \n "
2011-10-27 16:16:29 +00:00
" varying vec2 tc; \n "
" varying vec3 light; \n "
2011-02-25 04:22:14 +00:00
" #ifdef VERTEX_SHADER \n "
2011-10-27 16:16:29 +00:00
" #include \" sys/skeletal.h \" \n "
2011-02-25 04:22:14 +00:00
" attribute vec2 v_texcoord; \n "
" uniform vec3 e_light_dir; \n "
" uniform vec3 e_light_mul; \n "
" uniform vec3 e_light_ambient; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-02-25 04:22:14 +00:00
" { \n "
2011-10-27 16:16:29 +00:00
" vec3 n; \n "
" gl_Position = skeletaltransform_n(n); \n "
" light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul); \n "
2011-02-25 04:22:14 +00:00
" tc = v_texcoord; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
2011-12-23 03:12:29 +00:00
" #include \" sys/fog.h \" \n "
2011-02-25 04:22:14 +00:00
" uniform sampler2D s_t0; \n " /*tex_diffuse*/
" #ifdef LOWER \n "
" uniform sampler2D s_t1; \n " /*tex_lower*/
" uniform vec3 e_lowercolour; \n "
" #endif \n "
" #ifdef UPPER \n "
" uniform sampler2D s_t2; \n " /*tex_upper*/
" uniform vec3 e_uppercolour; \n "
" #endif \n "
" #ifdef FULLBRIGHT \n "
" uniform sampler2D s_t3; \n " /*tex_fullbright*/
" #endif \n "
2011-04-30 17:21:10 +00:00
" uniform vec4 e_colourident; \n "
2011-02-25 04:22:14 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-01-23 03:44:49 +00:00
" { \n "
2011-04-25 03:25:22 +00:00
" vec4 col, sp; \n "
" col = texture2D(s_t0, tc); \n "
2011-01-23 03:44:49 +00:00
" #ifdef UPPER \n "
2011-04-25 03:25:22 +00:00
" vec4 uc = texture2D(s_t2, tc); \n "
" col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a); \n "
2011-01-23 03:44:49 +00:00
" #endif \n "
" #ifdef LOWER \n "
2011-04-25 03:25:22 +00:00
" vec4 lc = texture2D(s_t1, tc); \n "
" col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a); \n "
2011-01-23 03:44:49 +00:00
" #endif \n "
2011-04-25 03:25:22 +00:00
" col.rgb *= light; \n "
2011-01-23 03:44:49 +00:00
" #ifdef FULLBRIGHT \n "
2011-04-25 03:25:22 +00:00
" vec4 fb = texture2D(s_t3, tc); \n "
" col.rgb = mix(col.rgb, fb.rgb, fb.a); \n "
2011-01-23 03:44:49 +00:00
" #endif \n "
2011-12-23 03:12:29 +00:00
" gl_FragColor = fog4(col * e_colourident); \n "
2011-01-23 03:44:49 +00:00
" } \n "
" #endif \n "
} ,
2011-09-03 03:49:43 +00:00
{ QR_OPENGL , 110 , " lpp_depthnorm " ,
" !!permu BUMP \n "
2011-10-27 16:16:29 +00:00
" !!permu SKELETAL \n "
2011-09-03 03:49:43 +00:00
" varying vec3 norm, tang, bitang; \n "
" #if defined(BUMP) \n "
" varying vec2 tc; \n "
" #endif \n "
" #ifdef VERTEX_SHADER \n "
2011-10-27 16:16:29 +00:00
" #include \" sys/skeletal.h \" \n "
2011-09-03 03:49:43 +00:00
" attribute vec2 v_texcoord; \n "
2011-10-27 16:16:29 +00:00
" void main() \n "
2011-09-03 03:49:43 +00:00
" { \n "
" #if defined(BUMP) \n "
2011-10-27 16:16:29 +00:00
" gl_Position = skeletaltransform_nst(norm, tang, bitang); \n "
2011-09-03 03:49:43 +00:00
" tc = v_texcoord; \n "
2011-10-27 16:16:29 +00:00
" #else \n "
" gl_Position = skeletaltransform_n(norm); \n "
2011-09-03 03:49:43 +00:00
" #endif \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" #if defined(BUMP) \n "
" uniform sampler2D s_t0; \n "
" #endif \n "
2011-10-27 16:16:29 +00:00
" void main() \n "
2011-09-03 03:49:43 +00:00
" { \n "
" vec3 onorm; \n "
" #if defined(BUMP) \n "
/*transform by the normalmap*/
" vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0; \n "
" onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm); \n "
" #else \n "
" onorm = norm; \n "
" #endif \n "
2011-12-23 03:12:29 +00:00
" gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w); \n "
2011-09-03 03:49:43 +00:00
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " lpp_light " ,
" varying vec4 tf; \n "
" #ifdef VERTEX_SHADER \n "
2011-10-27 16:16:29 +00:00
" void main() \n "
2011-09-03 03:49:43 +00:00
" { \n "
2011-10-27 16:16:29 +00:00
" tf = ftetransform(); gl_Position = tf; \n "
2011-09-03 03:49:43 +00:00
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" uniform vec3 l_lightposition; \n "
" uniform mat4 m_invviewprojection; \n "
" uniform vec3 l_lightcolour; \n "
" uniform float l_lightradius; \n "
" vec3 calcLightWorldPos(vec2 screenPos, float depth) \n "
" { \n "
" vec4 pos; \n "
" pos.x = screenPos.x; \n "
" pos.y = screenPos.y; \n "
" pos.z = depth; \n "
" pos.w = 1.0; \n "
" pos = m_invviewprojection * pos; \n "
" return pos.xyz / pos.w; \n "
" } \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-09-03 03:49:43 +00:00
" { \n "
" vec3 lightColour = l_lightcolour.rgb; \n "
" float lightIntensity = 1.0; \n "
" float lightAttenuation = l_lightradius; \n " // fixme: just use the light radius for now, use better near/far att math separately once working
" float radiusFar = l_lightradius; \n "
" float radiusNear = l_lightradius*0.5; \n "
" vec2 fc; \n "
" fc = tf.xy / tf.w; \n "
" vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0); \n "
" float depth = data.a; \n "
" vec3 norm = data.xyz; \n "
/* calc where the wall that generated this sample came from */
" vec3 worldPos = calcLightWorldPos(fc, depth); \n "
/*calc diffuse lighting term*/
" vec3 lightDir = l_lightposition - worldPos; \n "
2011-09-05 01:48:23 +00:00
" float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0); \n "
2011-09-03 03:49:43 +00:00
" float atten = (radiusFar * zdiff) / (radiusFar - radiusNear); \n "
" atten = pow(atten, 2.0); \n "
" lightDir = normalize(lightDir); \n "
" float nDotL = dot(norm, lightDir) * atten; \n "
" float lightDiffuse = max(0.0, nDotL); \n "
/*calc specular term*/
// todo: specular term in its own buffer for full coloured specular
" gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0); \n "
// gl_FragColor = vec4(normalize(lightDir), 0.0);
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " lpp_wall " ,
" varying vec2 tc, lm; \n "
" varying vec4 tf; \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" attribute vec2 v_lmcoord; \n "
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-09-03 03:49:43 +00:00
" { \n "
" tc = v_texcoord; \n "
" lm = v_lmcoord; \n "
" gl_Position = tf = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n " /*lpp lighting*/
" uniform sampler2D s_t1; \n " /*tex_diffuse*/
" uniform sampler2D s_t2; \n " /*tex_lightmap*/
//"uniform sampler2D s_t3;\n" /*tex_normalmap*/
//"uniform sampler2D s_t4;\n" /*tex_deluxmap*/
//"uniform sampler2D s_t5;\n" /*tex_fullbright*/
2012-01-17 07:57:46 +00:00
" uniform vec4 e_lmscale; \n "
2011-09-03 03:49:43 +00:00
2011-10-27 16:16:29 +00:00
" void main () \n "
2011-09-03 03:49:43 +00:00
" { \n "
2012-01-17 07:57:46 +00:00
//"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale;\n"
2011-09-03 03:49:43 +00:00
" vec2 nst; \n "
" nst = tf.xy / tf.w; \n "
" nst = (1.0 + nst) / 2.0; \n "
" vec4 l = texture2D(s_t0, nst)*5.0; \n "
" vec4 c = texture2D(s_t1, tc); \n "
" vec3 lmsamp = texture2D(s_t2, lm).rgb*lmscale; \n "
" vec3 diff = l.rgb; \n "
" vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11))); \n "
" vec3 spec = chrom * l.a; \n "
" gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0); \n " // + 0.6 * spec, 1.0);
" } \n "
" #endif \n "
} ,
2011-12-23 03:12:29 +00:00
{ QR_OPENGL , 110 , " colourtint " ,
" varying vec4 tf; \n "
" #ifdef VERTEX_SHADER \n "
" void main () \n "
" { \n "
" gl_Position = tf = vec4(v_position.xy,-1.0, 1.0); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform sampler2D s_t0; \n "
" uniform sampler3D s_t1; \n "
" void main() \n "
" { \n "
" vec2 fc; \n "
" fc = tf.xy / tf.w; \n "
" vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb; \n "
//scale+bias the sample to not clamp out at the edges
" #define LUTSIZE 16.0 \n "
" vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE); \n "
" vec3 bias = vec3(1.0/(2.0*LUTSIZE)); \n "
" gl_FragColor = texture3D(s_t1, raw * scale + bias); \n "
" } \n "
" #endif \n "
} ,
2011-12-05 15:23:40 +00:00
{ QR_OPENGL , 110 , " crepuscular_rays " ,
/*yoinked from http://fabiensanglard.net/lightScattering/index.php*/
" !!cvarf crep_decay \n "
" !!cvarf crep_density \n "
" !!cvarf crep_weight \n "
" varying vec2 tc; \n "
" #ifdef VERTEX_SHADER \n "
" attribute vec2 v_texcoord; \n "
" void main () \n "
" { \n "
" tc = v_texcoord; \n "
" gl_Position = v_position; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
2011-12-23 03:12:29 +00:00
" const float crep_decay = 0.94; \n "
" const float crep_density = 0.5; \n "
" const float crep_weight = 0.2; \n "
" uniform vec3 l_lightcolour; \n "
2011-12-05 15:23:40 +00:00
" uniform vec3 l_lightscreen; \n "
" uniform sampler2D s_t0; \n "
" const int NUM_SAMPLES = 100; \n "
" void main() \n "
" { \n "
// "gl_FragColor = texture2D(s_t0, tc.st);\n"
" vec2 deltaTextCoord = vec2( tc.st - l_lightscreen.xy ); \n "
" vec2 textCoo = tc.st; \n "
2011-12-23 03:12:29 +00:00
" deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density; \n "
2011-12-05 15:23:40 +00:00
" float illuminationDecay = 1.0; \n "
" for(int i=0; i < NUM_SAMPLES ; i++) \n "
" { \n "
" textCoo -= deltaTextCoord; \n "
" vec4 sample = texture2D(s_t0, textCoo); \n "
2011-12-23 03:12:29 +00:00
" sample *= illuminationDecay * crep_weight; \n "
2011-12-05 15:23:40 +00:00
" gl_FragColor += sample; \n "
2011-12-23 03:12:29 +00:00
" illuminationDecay *= crep_decay; \n "
2011-12-05 15:23:40 +00:00
" } \n "
2011-12-23 03:12:29 +00:00
" gl_FragColor *= vec4(l_lightcolour, 1.0); \n "
2011-12-05 15:23:40 +00:00
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " crepuscular_opaque " ,
" #ifdef VERTEX_SHADER \n "
" void main () \n "
" { \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" void main() \n "
" { \n "
" gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n "
" } \n "
" #endif \n "
} ,
{ QR_OPENGL , 110 , " crepuscular_sky " ,
" #ifdef VERTEX_SHADER \n "
" varying vec3 pos; \n "
" void main () \n "
" { \n "
" pos = v_position.xyz; \n "
" gl_Position = ftetransform(); \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" uniform float e_time; \n "
" uniform vec3 e_eyepos; \n "
" varying vec3 pos; \n "
" uniform sampler2D s_t0; \n "
" uniform sampler2D s_t1; \n "
" void main () \n "
" { \n "
" vec2 tccoord; \n "
" vec3 dir = pos - e_eyepos; \n "
2011-09-03 03:49:43 +00:00
2011-12-05 15:23:40 +00:00
" dir.z *= 3.0; \n "
" dir.xy /= 0.5*length(dir); \n "
" tccoord = (dir.xy + e_time*0.03125); \n "
" vec3 solid = vec3(texture2D(s_t0, tccoord)); \n "
" tccoord = (dir.xy + e_time*0.0625); \n "
" vec4 clouds = texture2D(s_t1, tccoord); \n "
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb); \n "
" } \n "
" #endif \n "
} ,
2011-12-26 15:19:13 +00:00
{ QR_OPENGL , 110 , " rtlight " ,
/*
texture units :
s0 = diffuse , s1 = normal , s2 = specular , s3 = shadowmap
custom modifiers :
PCF ( shadowmap )
2011-12-27 08:35:19 +00:00
CUBE ( projected cubemap )
2011-12-26 15:19:13 +00:00
*/
" !!permu BUMP \n "
" !!permu SPECULAR \n "
" !!permu OFFSETMAPPING \n "
" !!permu SKELETAL \n "
" !!permu FOG \n "
" !!cvarf r_glsl_offsetmapping_scale \n "
" varying vec2 tcbase; \n "
" varying vec3 lightvector; \n "
" #if defined(SPECULAR) || defined(OFFSETMAPPING) \n "
" varying vec3 eyevector; \n "
" #endif \n "
2011-12-27 08:35:19 +00:00
" #if defined(PCF) || defined(CUBE) \n "
2011-12-26 15:19:13 +00:00
" varying vec4 vshadowcoord; \n "
2011-12-27 08:35:19 +00:00
" uniform mat4 l_projmatrix; \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" #ifdef VERTEX_SHADER \n "
" #include \" sys/skeletal.h \" \n "
" uniform vec3 l_lightposition; \n "
" attribute vec2 v_texcoord; \n "
" #if defined(SPECULAR) || defined(OFFSETMAPPING) \n "
" uniform vec3 e_eyepos; \n "
" #endif \n "
" void main () \n "
" { \n "
" vec3 n, s, t, w; \n "
" gl_Position = skeletaltransform_wnst(w,n,s,t); \n "
" tcbase = v_texcoord; //pass the texture coords straight through \n "
" vec3 lightminusvertex = l_lightposition - w.xyz; \n "
" lightvector.x = dot(lightminusvertex, s.xyz); \n "
" lightvector.y = dot(lightminusvertex, t.xyz); \n "
" lightvector.z = dot(lightminusvertex, n.xyz); \n "
" #if defined(SPECULAR)||defined(OFFSETMAPPING) \n "
" vec3 eyeminusvertex = e_eyepos - w.xyz; \n "
" eyevector.x = dot(eyeminusvertex, s.xyz); \n "
" eyevector.y = -dot(eyeminusvertex, t.xyz); \n "
" eyevector.z = dot(eyeminusvertex, n.xyz); \n "
" #endif \n "
2011-12-27 08:35:19 +00:00
" #if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE) \n "
" vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0); \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" } \n "
" #endif \n "
/*this is full 4*4 PCF, with an added attempt at prenumbra*/
/*the offset consts are 1/(imagesize*2) */
# define PCF16P(f) "\
float xPixelOffset = ( 1.0 + shadowcoord . b / l_lightradius ) / texx ; \
float yPixelOffset = ( 1.0 + shadowcoord . b / l_lightradius ) / texy ; \
float s = 0.0 ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.5 * xPixelOffset * shadowcoord . w , - 1.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.5 * xPixelOffset * shadowcoord . w , - 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.5 * xPixelOffset * shadowcoord . w , 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.5 * xPixelOffset * shadowcoord . w , 1.1 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 0.5 * xPixelOffset * shadowcoord . w , - 1.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 0.5 * xPixelOffset * shadowcoord . w , - 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 0.5 * xPixelOffset * shadowcoord . w , 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 0.5 * xPixelOffset * shadowcoord . w , 1.1 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.5 * xPixelOffset * shadowcoord . w , - 1.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.5 * xPixelOffset * shadowcoord . w , - 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.5 * xPixelOffset * shadowcoord . w , 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.5 * xPixelOffset * shadowcoord . w , 1.1 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.5 * xPixelOffset * shadowcoord . w , - 1.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.5 * xPixelOffset * shadowcoord . w , - 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.5 * xPixelOffset * shadowcoord . w , 0.5 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.5 * xPixelOffset * shadowcoord . w , 1.1 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
colorscale * = s / 5.0 ; \ n \
"
/*this is pcf 3*3*/
/*the offset consts are 1/(imagesize*2) */
# define PCF9(f) "\
const float xPixelOffset = 1.0 / texx ; \
const float yPixelOffset = 1.0 / texy ; \
float s = 0.0 ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.0 * xPixelOffset * shadowcoord . w , - 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.0 * xPixelOffset * shadowcoord . w , 0.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.0 * xPixelOffset * shadowcoord . w , 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.0 * xPixelOffset * shadowcoord . w , - 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.0 * xPixelOffset * shadowcoord . w , 0.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.0 * xPixelOffset * shadowcoord . w , 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
\
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.0 * xPixelOffset * shadowcoord . w , - 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.0 * xPixelOffset * shadowcoord . w , 0.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.0 * xPixelOffset * shadowcoord . w , 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
colorscale * = s / 9.0 ; \ n \
"
/*this is a lazy form of pcf. take 5 samples in an x*/
/*the offset consts are 1/(imagesize*2) */
# define PCF5(f) "\
float xPixelOffset = 1.0 / texx ; \
float yPixelOffset = 1.0 / texy ; \
float s = 0.0 ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.0 * xPixelOffset * shadowcoord . w , - 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( - 1.0 * xPixelOffset * shadowcoord . w , 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 0.0 * xPixelOffset * shadowcoord . w , 0.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.0 * xPixelOffset * shadowcoord . w , - 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
s + = " f " Proj ( s_t7 , shadowcoord + vec4 ( 1.0 * xPixelOffset * shadowcoord . w , 1.0 * yPixelOffset * shadowcoord . w , 0.05 , 0.0 ) ) . r ; \ n \
colorscale * = s / 5.0 ; \ n \
"
/*this is unfiltered*/
# define PCF1(f) "\
colorscale * = " f " Proj ( shadowmap , shadowcoord ) . r ; \ n "
" #ifdef FRAGMENT_SHADER \n "
" #include \" sys/fog.h \" \n "
" uniform sampler2D s_t0; \n " /*base texture*/
" #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) \n "
" uniform sampler2D s_t1; \n " /*normalmap/height texture*/
" #endif \n "
" #ifdef SPECULAR \n "
" uniform sampler2D s_t2; \n " /*specularmap texture*/
" #endif \n "
2011-12-27 08:35:19 +00:00
" #ifdef CUBE \n "
" uniform samplerCube s_t3; \n " /*projected texture*/
2011-12-26 15:19:13 +00:00
" #endif \n "
" #ifdef PCF \n "
" #ifdef CUBE \n "
" uniform samplerCubeShadow s_t7; \n "
" #else \n "
" uniform sampler2DShadow s_t7; \n "
" #endif \n "
" #endif \n "
" uniform float l_lightradius; \n "
" uniform vec3 l_lightcolour; \n "
2012-01-01 11:22:24 +00:00
" uniform vec3 l_lightcolourscale; \n "
2011-12-26 15:19:13 +00:00
" #ifdef OFFSETMAPPING \n "
2012-01-17 07:57:46 +00:00
" #include \" sys/offsetmapping.h \" \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" void main () \n "
" { \n "
" #ifdef OFFSETMAPPING \n "
2012-01-17 07:57:46 +00:00
" vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector); \n "
" #define tcbase tcoffsetmap \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" vec3 bases = vec3(texture2D(s_t0, tcbase)); \n "
2012-01-01 02:26:42 +00:00
2011-12-26 15:19:13 +00:00
" #if defined(BUMP) || defined(SPECULAR) \n "
2012-01-01 11:22:24 +00:00
" vec3 bumps = vec3(texture2D(s_t1, tcbase)) - 0.5; \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" #ifdef SPECULAR \n "
2012-01-01 11:22:24 +00:00
" vec4 specs = texture2D(s_t2, tcbase); \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" vec3 nl = normalize(lightvector); \n "
" float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0); \n "
" vec3 diff; \n "
2012-01-01 02:26:42 +00:00
" #ifdef BUMP \n "
2012-01-01 11:22:24 +00:00
" diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(2.0*bumps, nl), 0.0)); \n "
2012-01-01 02:26:42 +00:00
" #else \n "
2012-01-01 11:22:24 +00:00
" diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0)); \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
" #ifdef SPECULAR \n "
2012-01-17 07:57:46 +00:00
" vec3 halfdir = normalize(lightvector - normalize(eyevector)); \n "
2012-01-01 11:22:24 +00:00
" float spec = pow(max(dot(halfdir, bumps), 0.0), 1.0 + 32.0 * specs.a); \n "
" diff += spec * specs.rgb * l_lightcolourscale.z; \n "
2011-12-26 15:19:13 +00:00
" #endif \n "
2011-12-27 08:35:19 +00:00
" #ifdef CUBE \n "
" diff *= textureCube(s_t3, vshadowcoord.xyz).rgb; \n "
" #endif \n "
2011-12-26 15:19:13 +00:00
" #ifdef PCF \n "
" #if defined(SPOT) \n "
" const float texx = 512.0; \n "
" const float texy = 512.0; \n "
" vec4 shadowcoord = vshadowcoord; \n "
" #else \n "
" const float texx = 512.0; \n "
" const float texy = 512.0; \n "
" vec4 shadowcoord; \n "
" shadowcoord.zw = vshadowcoord.zw; \n "
" shadowcoord.xy = vshadowcoord.xy; \n "
" #endif \n "
" #ifdef CUBE \n "
PCF9 ( " shadowCube " ) /*valid are 1,5,9*/
" #else \n "
PCF9 ( " shadow2D " ) /*valid are 1,5,9*/
" #endif \n "
" #endif \n "
" #if defined(SPOT) \n "
/*Actually, this isn't correct*/
" if (shadowcoord.w < 0.0) discard; \n "
" vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot)); \n "
" #endif \n "
" #if defined(PROJECTION) \n "
" l_lightcolour *= texture2d(s_t3, shadowcoord); \n "
" #endif \n "
" gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour); \n "
" } \n "
" #endif \n "
} ,
2011-09-03 03:49:43 +00:00
2011-03-31 02:32:32 +00:00
# endif
2011-09-03 03:49:43 +00:00
# ifdef D3DQUAKE
2012-01-01 02:26:42 +00:00
{ QR_DIRECT3D , 9 , " rtlight " ,
/*
texture units :
s0 = diffuse , s1 = normal , s2 = specular , s3 = shadowmap
custom modifiers :
PCF ( shadowmap )
CUBE ( projected cubemap )
*/
" !!permu BUMP \n "
" !!permu SPECULAR \n "
" !!permu OFFSETMAPPING \n "
" !!permu SKELETAL \n "
" !!permu FOG \n "
" struct a2v { \n "
" float4 pos: POSITION; \n "
" float3 tc: TEXCOORD0; \n "
" float3 n: NORMAL0; \n "
" float3 s: TANGENT0; \n "
" float3 t: BINORMAL0; \n "
" }; \n "
" struct v2f { \n "
" #ifndef FRAGMENT_SHADER \n "
" float4 pos: POSITION; \n "
" #endif \n "
" float3 tc: TEXCOORD0; \n "
" float3 lpos: TEXCOORD1; \n "
" }; \n "
" #ifdef VERTEX_SHADER \n "
" float4x4 m_modelviewprojection; \n "
" float3 l_lightposition; \n "
" v2f main (a2v inp) \n "
" { \n "
" v2f outp; \n "
" outp.pos = mul(m_modelviewprojection, inp.pos); \n "
" outp.tc = inp.tc; \n "
" float3 lightminusvertex = l_lightposition - inp.pos.xyz; \n "
" outp.lpos.x = dot(lightminusvertex, inp.s.xyz); \n "
" outp.lpos.y = dot(lightminusvertex, inp.t.xyz); \n "
" outp.lpos.z = dot(lightminusvertex, inp.n.xyz); \n "
" return outp; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" sampler s_t0; \n "
" sampler s_t1; \n "
" float l_lightradius; \n "
" float3 l_lightcolour; \n "
" float4 main (v2f inp) : COLOR0 \n "
" { \n "
" float3 col = l_lightcolour; \n "
" col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0); \n "
" float3 diff = tex2D(s_t0, inp.tc); \n "
" return float4(diff * col, 1); "
" } \n "
" #endif \n "
} ,
2011-09-03 03:49:43 +00:00
{ QR_DIRECT3D , 9 , " defaultsky " ,
2011-03-31 02:32:32 +00:00
" struct a2v { \n "
" float4 pos: POSITION; \n "
" }; \n "
" struct v2f { \n "
2011-09-03 03:49:43 +00:00
" #ifndef FRAGMENT_SHADER \n "
2011-03-31 02:32:32 +00:00
" float4 pos: POSITION; \n "
2011-09-03 03:49:43 +00:00
" #endif \n "
" float3 vpos: TEXCOORD0; \n "
2011-03-31 02:32:32 +00:00
" }; \n "
" #ifdef VERTEX_SHADER \n "
2011-09-03 03:49:43 +00:00
" float4x4 m_modelviewprojection; \n "
2011-03-31 02:32:32 +00:00
" v2f main (a2v inp) \n "
" { \n "
" v2f outp; \n "
2011-09-03 03:49:43 +00:00
" outp.pos = mul(m_modelviewprojection, inp.pos); \n "
2011-03-31 02:32:32 +00:00
" outp.vpos = inp.pos; \n "
" return outp; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" float e_time; \n "
" float3 e_eyepos; \n "
2012-01-01 02:26:42 +00:00
" float l_lightradius; \n "
" float3 l_lightcolour; \n "
" float3 l_lightposition; \n "
" sampler s_t0; \n " /*diffuse*/
" sampler s_t1; \n " /*normal*/
" sampler s_t2; \n " /*specular*/
2011-03-31 02:32:32 +00:00
" float4 main (v2f inp) : COLOR0 \n "
" { \n "
" float2 tccoord; \n "
" float3 dir = inp.vpos - e_eyepos; \n "
" dir.z *= 3.0; \n "
" dir.xy /= 0.5*length(dir); \n "
" tccoord = (dir.xy + e_time*0.03125); \n "
" float4 solid = tex2D(s_t0, tccoord); \n "
" tccoord = (dir.xy + e_time*0.0625); \n "
" float4 clouds = tex2D(s_t1, tccoord); \n "
" return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1); \n "
2011-09-03 03:49:43 +00:00
" } \n "
" #endif \n "
} ,
{ QR_DIRECT3D , 9 , " defaultwarp " ,
" !!cvarf r_wateralpha \n "
" struct a2v { \n "
" float4 pos: POSITION; \n "
" float2 tc: TEXCOORD0; \n "
" }; \n "
" struct v2f { \n "
" #ifndef FRAGMENT_SHADER \n "
" float4 pos: POSITION; \n "
" #endif \n "
" float2 tc: TEXCOORD0; \n "
" }; \n "
" #ifdef VERTEX_SHADER \n "
" float4x4 m_modelviewprojection; \n "
" v2f main (a2v inp) \n "
" { \n "
" v2f outp; \n "
" outp.pos = mul(m_modelviewprojection, inp.pos); \n "
" outp.tc = inp.tc; \n "
" return outp; \n "
" } \n "
" #endif \n "
" #ifdef FRAGMENT_SHADER \n "
" float cvar_r_wateralpha; \n "
" float e_time; \n "
" sampler s_t0; \n "
" float4 main (v2f inp) : COLOR0 \n "
" { \n "
" float2 ntc; \n "
" ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125; \n "
" ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125; \n "
" float3 ts = tex2D(s_t0, ntc).xyz; \n "
" return float4(ts, cvar_r_wateralpha); \n "
2011-03-31 02:32:32 +00:00
" } \n "
" #endif \n "
} ,
2011-01-23 03:51:27 +00:00
# endif
2012-01-17 07:57:46 +00:00
# include "r_bishaders.h"
2011-01-23 03:44:49 +00:00
{ QR_NONE }
} ;
2012-01-01 02:26:42 +00:00
void Shader_UnloadProg ( program_t * prog )
2011-06-05 23:53:33 +00:00
{
if ( prog - > refs = = 1 )
{
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
{
2011-12-23 03:12:29 +00:00
int p ;
2011-06-05 23:53:33 +00:00
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
if ( prog - > handle [ p ] . glsl )
qglDeleteProgramObject_ ( prog - > handle [ p ] . glsl ) ;
}
}
2011-12-23 03:12:29 +00:00
# endif
# ifdef D3DQUAKE
if ( qrenderer = = QR_DIRECT3D )
{
int p ;
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
// if (prog->handle[p].hlsl.vert || prog->handle[p].hlsl.frag)
// D3DShader_DeleteProgram(&prog->handle[p].hlsl);
}
}
2011-06-05 23:53:33 +00:00
# endif
free ( prog ) ;
}
else
prog - > refs - - ;
}
2011-01-23 03:44:49 +00:00
static void Shader_FlushGenerics ( void )
{
sgeneric_t * g ;
while ( sgenerics )
{
g = sgenerics ;
sgenerics = g - > next ;
2011-06-04 16:11:35 +00:00
if ( g - > prog . refs = = 1 )
2012-01-01 02:26:42 +00:00
{
g - > prog . refs - - ;
2011-06-04 16:11:35 +00:00
free ( g ) ;
2012-01-01 02:26:42 +00:00
}
2011-06-04 16:11:35 +00:00
else
Con_Printf ( " generic shader still used \n " ) ;
2011-01-23 03:44:49 +00:00
}
}
2011-02-25 04:22:14 +00:00
static program_t * Shader_LoadGeneric ( char * name , int qrtype )
2011-01-23 03:44:49 +00:00
{
unsigned int i ;
void * file ;
2011-02-06 20:56:39 +00:00
2011-01-23 03:44:49 +00:00
sgeneric_t * g ;
2012-01-16 06:22:06 +00:00
2011-01-23 03:44:49 +00:00
for ( g = sgenerics ; g ; g = g - > next )
{
if ( ! strcmp ( name , g - > name ) )
{
2011-02-25 04:22:14 +00:00
if ( g - > failed )
return NULL ;
g - > prog . refs + + ;
return & g - > prog ;
2011-01-23 03:44:49 +00:00
}
}
2012-01-01 02:26:42 +00:00
g = malloc ( sizeof ( * g ) + strlen ( name ) + 1 ) ;
2011-02-25 04:22:14 +00:00
memset ( g , 0 , sizeof ( * g ) ) ;
2012-01-01 02:26:42 +00:00
g - > name = ( char * ) ( g + 1 ) ;
2011-01-23 03:44:49 +00:00
strcpy ( g - > name , name ) ;
g - > next = sgenerics ;
sgenerics = g ;
2011-02-25 04:22:14 +00:00
g - > prog . refs = 1 ;
2011-09-03 03:49:43 +00:00
if ( strchr ( name , ' / ' ) | | strchr ( name , ' . ' ) )
FS_LoadFile ( name , & file ) ;
else if ( qrenderer = = QR_DIRECT3D )
FS_LoadFile ( va ( " hlsl/%s.hlsl " , name ) , & file ) ;
else if ( qrenderer = = QR_OPENGL )
{
# ifdef GLQUAKE
if ( gl_config . gles )
FS_LoadFile ( va ( " gles/%s.glsl " , name ) , & file ) ;
else
# endif
FS_LoadFile ( va ( " glsl/%s.glsl " , name ) , & file ) ;
}
else
file = NULL ;
2011-01-23 03:44:49 +00:00
if ( file )
{
2011-09-03 03:49:43 +00:00
Con_DPrintf ( " Loaded %s from disk \n " , name ) ;
2012-01-16 06:22:06 +00:00
g - > failed = ! Shader_LoadPermutations ( name , & g - > prog , file , qrtype , 0 ) ;
2011-01-23 03:44:49 +00:00
FS_FreeFile ( file ) ;
2011-02-25 04:22:14 +00:00
g - > prog . refs + + ;
return & g - > prog ;
2011-01-23 03:44:49 +00:00
}
else
{
2011-12-26 15:19:13 +00:00
int matchlen ;
char * h = strchr ( name , ' # ' ) ;
if ( h )
matchlen = h - name ;
else
matchlen = strlen ( name ) + 1 ;
2011-01-23 03:44:49 +00:00
for ( i = 0 ; * sbuiltins [ i ] . name ; i + + )
{
2011-12-26 15:19:13 +00:00
if ( sbuiltins [ i ] . qrtype = = qrenderer & & ! strncmp ( sbuiltins [ i ] . name , name , matchlen ) )
2011-01-23 03:44:49 +00:00
{
# ifdef GLQUAKE
2011-12-26 15:19:13 +00:00
if ( qrenderer = = QR_OPENGL )
2011-01-23 03:44:49 +00:00
{
2011-12-26 15:19:13 +00:00
if ( gl_config . gles )
{
if ( sbuiltins [ i ] . apiver ! = 100 )
continue ;
}
else
{
if ( sbuiltins [ i ] . apiver = = 100 )
continue ;
}
2011-01-23 03:44:49 +00:00
}
# endif
2012-01-16 06:22:06 +00:00
g - > failed = ! Shader_LoadPermutations ( name , & g - > prog , sbuiltins [ i ] . body , sbuiltins [ i ] . qrtype , sbuiltins [ i ] . apiver ) ;
2011-02-25 04:22:14 +00:00
g - > prog . refs + + ;
return & g - > prog ;
2011-01-23 03:44:49 +00:00
}
}
}
2011-02-25 04:22:14 +00:00
g - > failed = true ;
return NULL ;
2011-01-23 03:44:49 +00:00
}
2011-09-03 03:49:43 +00:00
void Shader_WriteOutGenerics_f ( void )
{
int i ;
char * name ;
for ( i = 0 ; * sbuiltins [ i ] . name ; i + + )
{
name = NULL ;
if ( sbuiltins [ i ] . qrtype = = QR_OPENGL )
{
if ( sbuiltins [ i ] . apiver = = 100 )
name = va ( " gles/%s.glsl " , sbuiltins [ i ] . name ) ;
else
name = va ( " glsl/%s.glsl " , sbuiltins [ i ] . name ) ;
}
else if ( sbuiltins [ i ] . qrtype = = QR_DIRECT3D )
name = va ( " hlsl/%s.hlsl " , sbuiltins [ i ] . name ) ;
if ( name )
{
vfsfile_t * f = FS_OpenVFS ( name , " rb " , FS_GAMEONLY ) ;
if ( f )
{
int len = VFS_GETLEN ( f ) ;
char * buf = Hunk_TempAlloc ( len ) ;
VFS_READ ( f , buf , len ) ;
if ( len ! = strlen ( sbuiltins [ i ] . body ) | | memcmp ( buf , sbuiltins [ i ] . body , len ) )
Con_Printf ( " Not writing %s - modified version in the way \n " , name ) ;
else
Con_Printf ( " %s is unmodified \n " , name ) ;
VFS_CLOSE ( f ) ;
}
else
{
Con_Printf ( " Writing %s \n " , name ) ;
FS_WriteFile ( name , sbuiltins [ i ] . body , strlen ( sbuiltins [ i ] . body ) , FS_GAMEONLY ) ;
}
}
}
}
struct shader_field_names_s shader_field_names [ ] =
{
/*vertex attributes*/
{ " v_position " , SP_ATTR_VERTEX } ,
{ " v_colour " , SP_ATTR_COLOUR } ,
{ " v_texcoord " , SP_ATTR_TEXCOORD } ,
{ " v_lmcoord " , SP_ATTR_LMCOORD } ,
{ " v_normal " , SP_ATTR_NORMALS } ,
{ " v_svector " , SP_ATTR_SNORMALS } ,
{ " v_tvector " , SP_ATTR_TNORMALS } ,
{ " v_bone " , SP_ATTR_BONENUMS } ,
{ " v_weight " , SP_ATTR_BONEWEIGHTS } ,
/*matricies*/
{ " m_model " , SP_M_MODEL } ,
{ " m_view " , SP_M_VIEW } ,
{ " m_modelview " , SP_M_MODELVIEW } ,
{ " m_projection " , SP_M_PROJECTION } ,
{ " m_modelviewprojection " , SP_M_MODELVIEWPROJECTION } ,
{ " m_bones " , SP_M_ENTBONES } ,
{ " m_invviewprojection " , SP_M_INVVIEWPROJECTION } ,
{ " m_invmodelviewprojection " , SP_M_INVMODELVIEWPROJECTION } ,
/*viewer properties*/
{ " v_eyepos " , SP_V_EYEPOS } ,
2011-12-23 03:12:29 +00:00
{ " w_fog " , SP_W_FOG } ,
2011-09-03 03:49:43 +00:00
/*ent properties*/
2011-12-26 15:19:13 +00:00
{ " e_lmscale " , SP_E_LMSCALE } , /*overbright shifting*/
2011-09-03 03:49:43 +00:00
{ " e_origin " , SP_E_ORIGIN } ,
{ " e_time " , SP_E_TIME } ,
{ " e_eyepos " , SP_E_EYEPOS } ,
{ " e_colour " , SP_E_COLOURS } ,
{ " e_colourident " , SP_E_COLOURSIDENT } ,
{ " e_glowmod " , SP_E_GLOWMOD } ,
{ " e_topcolour " , SP_E_TOPCOLOURS } ,
{ " e_bottomcolour " , SP_E_BOTTOMCOLOURS } ,
{ " e_light_dir " , SP_E_L_DIR } ,
{ " e_light_mul " , SP_E_L_MUL } ,
{ " e_light_ambient " , SP_E_L_AMBIENT } ,
/*rtlight properties, use with caution*/
2011-12-05 15:23:40 +00:00
{ " l_lightscreen " , SP_LIGHTSCREEN } ,
2011-09-03 03:49:43 +00:00
{ " l_lightradius " , SP_LIGHTRADIUS } ,
{ " l_lightcolour " , SP_LIGHTCOLOUR } ,
{ " l_lightposition " , SP_LIGHTPOSITION } ,
2012-01-01 11:22:24 +00:00
{ " l_lightcolourscale " , SP_LIGHTCOLOURSCALE } ,
2011-12-27 08:35:19 +00:00
{ " l_projmatrix " , SP_LIGHTPROJMATRIX } ,
2011-10-27 16:16:29 +00:00
{ " e_rendertexturescale " , SP_RENDERTEXTURESCALE } ,
2011-09-03 03:49:43 +00:00
{ NULL }
} ;
2011-12-23 03:12:29 +00:00
static void Shader_ProgAutoFields ( program_t * prog , char * * cvarnames , int * cvartypes )
2011-01-23 03:44:49 +00:00
{
unsigned int i , p ;
qboolean found ;
int uniformloc ;
2011-04-30 17:21:10 +00:00
char tmpname [ 128 ] ;
cvar_t * cvar ;
2011-09-03 03:49:43 +00:00
2011-02-25 04:22:14 +00:00
prog - > numparams = 0 ;
2011-01-23 03:44:49 +00:00
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
{
if ( gl_config . nofixedfunc )
2011-02-25 04:22:14 +00:00
prog - > nofixedcompat = true ;
2011-01-23 03:44:49 +00:00
2011-09-03 03:49:43 +00:00
for ( i = 0 ; shader_field_names [ i ] . name ; i + + )
2011-01-23 03:44:49 +00:00
{
found = false ;
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
2011-02-25 04:22:14 +00:00
if ( ! prog - > handle [ p ] . glsl )
2011-01-23 03:44:49 +00:00
continue ;
2011-02-25 04:22:14 +00:00
GLSlang_UseProgram ( prog - > handle [ p ] . glsl ) ;
2011-09-03 03:49:43 +00:00
if ( shader_field_names [ i ] . ptype > = SP_FIRSTUNIFORM )
uniformloc = qglGetUniformLocationARB ( prog - > handle [ p ] . glsl , shader_field_names [ i ] . name ) ;
2011-01-23 03:44:49 +00:00
else
2011-09-03 03:49:43 +00:00
uniformloc = qglGetAttribLocationARB ( prog - > handle [ p ] . glsl , shader_field_names [ i ] . name ) ;
2011-01-23 03:44:49 +00:00
if ( uniformloc ! = - 1 )
found = true ;
2012-01-01 02:26:42 +00:00
if ( prog - > numparams = = SHADER_PROGPARMS_MAX )
{
if ( found )
break ;
}
else
prog - > parm [ prog - > numparams ] . handle [ p ] = uniformloc ;
2011-01-23 03:44:49 +00:00
}
if ( found )
{
2012-01-01 02:26:42 +00:00
if ( prog - > numparams = = SHADER_PROGPARMS_MAX )
Con_Printf ( " Too many paramters for program (ignoring %s) \n " , shader_field_names [ i ] . name ) ;
else
{
prog - > parm [ prog - > numparams ] . type = shader_field_names [ i ] . ptype ;
prog - > numparams + + ;
2011-01-23 03:44:49 +00:00
2012-01-01 02:26:42 +00:00
if ( shader_field_names [ i ] . ptype < SP_FIRSTUNIFORM )
prog - > nofixedcompat = true ;
}
2011-01-23 03:44:49 +00:00
}
}
2012-01-21 07:53:49 +00:00
/*set cvar unirforms*/
for ( i = 0 ; cvarnames [ i ] ; i + + )
{
if ( prog - > numparams = = SHADER_PROGPARMS_MAX )
{
Con_Printf ( " Too many cvar paramters for program \n " ) ;
break ;
}
for ( p = 0 ; cvarnames [ i ] [ p ] & & ( unsigned char ) cvarnames [ i ] [ p ] > 32 & & p < sizeof ( tmpname ) - 1 ; p + + )
tmpname [ p ] = cvarnames [ i ] [ p ] ;
tmpname [ p ] = 0 ;
cvar = Cvar_Get ( tmpname , " 0 " , CVAR_SHADERSYSTEM , " glsl cvars " ) ;
if ( ! cvar )
continue ;
cvar - > flags | = CVAR_SHADERSYSTEM ;
prog - > parm [ prog - > numparams ] . type = cvartypes [ i ] ;
prog - > parm [ prog - > numparams ] . pval = cvar ;
found = false ;
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
if ( ! prog - > handle [ p ] . glsl )
continue ;
GL_SelectProgram ( prog - > handle [ p ] . glsl ) ;
uniformloc = qglGetUniformLocationARB ( prog - > handle [ p ] . glsl , va ( " cvar_%s " , tmpname ) ) ;
if ( uniformloc ! = - 1 )
{
qglUniform1fARB ( uniformloc , cvar - > value ) ;
found = true ;
}
prog - > parm [ prog - > numparams ] . handle [ p ] = uniformloc ;
}
if ( found )
prog - > numparams + + ;
}
2011-04-30 17:21:10 +00:00
/*set texture uniforms*/
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
if ( ! prog - > handle [ p ] . glsl )
continue ;
GLSlang_UseProgram ( prog - > handle [ p ] . glsl ) ;
for ( i = 0 ; i < 8 ; i + + )
{
uniformloc = qglGetUniformLocationARB ( prog - > handle [ p ] . glsl , va ( " s_t%i " , i ) ) ;
if ( uniformloc ! = - 1 )
qglUniform1iARB ( uniformloc , i ) ;
}
}
2011-09-03 03:49:43 +00:00
return ;
}
# endif
# ifdef D3DQUAKE
if ( qrenderer = = QR_DIRECT3D )
{
prog - > nofixedcompat = true ;
/*set cvar uniforms*/
2011-12-23 03:12:29 +00:00
for ( i = 0 ; cvarnames [ i ] ; i + + )
2011-09-03 03:49:43 +00:00
{
2011-12-23 03:12:29 +00:00
for ( p = 0 ; cvarnames [ i ] [ p ] & & ( unsigned char ) cvarnames [ i ] [ p ] > 32 & & p < sizeof ( tmpname ) - 1 ; p + + )
tmpname [ p ] = cvarnames [ i ] [ p ] ;
2011-09-03 03:49:43 +00:00
tmpname [ p ] = 0 ;
cvar = Cvar_FindVar ( tmpname ) ;
if ( ! cvar )
continue ;
cvar - > flags | = CVAR_SHADERSYSTEM ;
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
if ( ! prog - > handle [ p ] . glsl )
continue ;
uniformloc = D3DShader_FindUniform ( & prog - > handle [ p ] , 1 , va ( " cvar_%s " , tmpname ) ) ;
if ( uniformloc ! = - 1 )
{
vec4_t v = { cvar - > value , 0 , 0 , 0 } ;
IDirect3DDevice9_SetVertexShader ( pD3DDev9 , prog - > handle [ 0 ] . hlsl . vert ) ;
IDirect3DDevice9_SetVertexShaderConstantF ( pD3DDev9 , 0 , v , 1 ) ;
}
uniformloc = D3DShader_FindUniform ( & prog - > handle [ p ] , 2 , va ( " cvar_%s " , tmpname ) ) ;
if ( uniformloc ! = - 1 )
{
vec4_t v = { cvar - > value , 0 , 0 , 0 } ;
IDirect3DDevice9_SetPixelShader ( pD3DDev9 , prog - > handle [ 0 ] . hlsl . vert ) ;
IDirect3DDevice9_SetPixelShaderConstantF ( pD3DDev9 , 0 , v , 1 ) ;
}
}
}
for ( i = 0 ; shader_field_names [ i ] . name ; i + + )
{
found = false ;
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
if ( shader_field_names [ i ] . ptype > = SP_FIRSTUNIFORM )
{
uniformloc = D3DShader_FindUniform ( & prog - > handle [ p ] , 0 , shader_field_names [ i ] . name ) ;
}
else
uniformloc = - 1 ;
if ( uniformloc ! = - 1 )
found = true ;
prog - > parm [ prog - > numparams ] . handle [ p ] = uniformloc ;
}
if ( found )
{
prog - > parm [ prog - > numparams ] . type = shader_field_names [ i ] . ptype ;
prog - > numparams + + ;
if ( shader_field_names [ i ] . ptype < SP_FIRSTUNIFORM )
prog - > nofixedcompat = true ;
}
}
/*set texture uniforms*/
for ( p = 0 ; p < PERMUTATIONS ; p + + )
{
for ( i = 0 ; i < 8 ; i + + )
{
uniformloc = D3DShader_FindUniform ( & prog - > handle [ p ] , 2 , va ( " s_t%i " , i ) ) ;
if ( uniformloc ! = - 1 )
{
int v [ 4 ] = { i } ;
IDirect3DDevice9_SetPixelShader ( pD3DDev9 , prog - > handle [ 0 ] . hlsl . vert ) ;
IDirect3DDevice9_SetPixelShaderConstantI ( pD3DDev9 , 0 , v , 1 ) ;
}
}
}
IDirect3DDevice9_SetVertexShader ( pD3DDev9 , NULL ) ;
IDirect3DDevice9_SetPixelShader ( pD3DDev9 , NULL ) ;
2011-01-23 03:44:49 +00:00
}
# endif
}
2010-08-28 17:14:38 +00:00
2009-11-04 21:16:50 +00:00
static void Shader_SLProgramName ( shader_t * shader , shaderpass_t * pass , char * * ptr , int qrtype )
2006-03-11 03:12:10 +00:00
{
2010-07-11 02:22:39 +00:00
/*accepts:
program
{
BLAH
}
where BLAH is both vertex + frag with # ifdefs
or
2011-01-23 03:44:49 +00:00
program fname
2010-07-11 02:22:39 +00:00
on one line .
*/
2011-01-23 03:44:49 +00:00
char * programbody ;
char * start , * end ;
2009-07-05 18:45:53 +00:00
2011-01-23 03:44:49 +00:00
end = * ptr ;
while ( * end = = ' ' | | * end = = ' \t ' | | * end = = ' \r ' )
end + + ;
if ( * end = = ' \n ' )
2009-07-05 18:45:53 +00:00
{
int count ;
2011-01-23 03:44:49 +00:00
end + + ;
while ( * end = = ' ' | | * end = = ' \t ' )
end + + ;
if ( * end ! = ' { ' )
2009-07-05 18:45:53 +00:00
{
Con_Printf ( " shader \" %s \" missing program string \n " , shader - > name ) ;
}
else
{
2011-01-23 03:44:49 +00:00
end + + ;
start = end ;
for ( count = 1 ; * end ; end + + )
2009-07-05 18:45:53 +00:00
{
2011-01-23 03:44:49 +00:00
if ( * end = = ' } ' )
2009-07-05 18:45:53 +00:00
{
count - - ;
if ( ! count )
break ;
}
2011-01-23 03:44:49 +00:00
else if ( * end = = ' { ' )
2009-07-05 18:45:53 +00:00
count + + ;
}
2011-01-23 03:44:49 +00:00
programbody = BZ_Malloc ( end - start + 1 ) ;
memcpy ( programbody , start , end - start ) ;
programbody [ end - start ] = 0 ;
* ptr = end + 1 ; /*skip over it all*/
2010-08-28 17:14:38 +00:00
2011-02-25 04:22:14 +00:00
shader - > prog = malloc ( sizeof ( * shader - > prog ) ) ;
2011-03-05 12:39:35 +00:00
memset ( shader - > prog , 0 , sizeof ( * shader - > prog ) ) ;
2011-02-25 04:22:14 +00:00
shader - > prog - > refs = 1 ;
2012-01-16 06:22:06 +00:00
if ( ! Shader_LoadPermutations ( shader - > name , shader - > prog , programbody , qrtype , 0 ) )
{
free ( shader - > prog ) ;
shader - > prog = NULL ;
}
2009-07-05 18:45:53 +00:00
2011-01-23 03:44:49 +00:00
BZ_Free ( programbody ) ;
2009-07-05 18:45:53 +00:00
}
2010-08-28 17:14:38 +00:00
return ;
2009-11-04 21:16:50 +00:00
}
2010-08-28 17:14:38 +00:00
2011-02-25 04:22:14 +00:00
shader - > prog = Shader_LoadGeneric ( Shader_ParseString ( ptr ) , qrtype ) ;
2006-03-11 03:12:10 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shader_GLSLProgramName ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
Shader_SLProgramName ( shader , pass , ptr , QR_OPENGL ) ;
}
2011-03-31 02:32:32 +00:00
static void Shader_ProgramName ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
Shader_SLProgramName ( shader , pass , ptr , qrenderer ) ;
}
2009-11-04 21:16:50 +00:00
static void Shader_HLSLProgramName ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
Shader_SLProgramName ( shader , pass , ptr , QR_DIRECT3D ) ;
}
2006-03-11 03:12:10 +00:00
static void Shader_ProgramParam ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
2010-08-28 17:14:38 +00:00
cvar_t * cv = NULL ;
2006-03-11 03:12:10 +00:00
int specialint = 0 ;
float specialfloat = 0 ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
vec3_t specialvec = { 0 } ;
2006-03-11 03:12:10 +00:00
enum shaderprogparmtype_e parmtype = SP_BAD ;
char * token ;
2009-11-04 21:16:50 +00:00
qboolean silent = false ;
2011-01-23 03:44:49 +00:00
char * forcename = NULL ;
2006-03-11 03:12:10 +00:00
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " opt " ) )
{
silent = true ;
token = Shader_ParseString ( ptr ) ;
}
2006-03-11 03:12:10 +00:00
if ( ! Q_stricmp ( token , " texture " ) )
{
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2006-03-11 03:12:10 +00:00
specialint = atoi ( token ) ;
parmtype = SP_TEXTURE ;
}
2010-11-10 03:32:47 +00:00
else if ( ! Q_stricmp ( token , " consti " ) )
{
token = Shader_ParseSensString ( ptr ) ;
specialint = atoi ( token ) ;
parmtype = SP_CONSTI ;
}
else if ( ! Q_stricmp ( token , " constf " ) )
{
token = Shader_ParseSensString ( ptr ) ;
specialfloat = atof ( token ) ;
parmtype = SP_CONSTF ;
}
2006-03-11 03:12:10 +00:00
else if ( ! Q_stricmp ( token , " cvari " ) )
{
2010-07-11 02:22:39 +00:00
token = Shader_ParseSensString ( ptr ) ;
2006-03-11 03:12:10 +00:00
cv = Cvar_Get ( token , " " , 0 , " GLSL Shader parameters " ) ;
2010-08-28 17:14:38 +00:00
if ( ! cv )
return ;
2006-03-11 03:12:10 +00:00
parmtype = SP_CVARI ;
}
else if ( ! Q_stricmp ( token , " cvarf " ) )
{
2010-07-11 02:22:39 +00:00
token = Shader_ParseSensString ( ptr ) ;
2006-03-11 03:12:10 +00:00
cv = Cvar_Get ( token , " " , 0 , " GLSL Shader parameters " ) ;
2010-08-28 17:14:38 +00:00
if ( ! cv )
return ;
2006-03-11 03:12:10 +00:00
parmtype = SP_CVARF ;
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
else if ( ! Q_stricmp ( token , " cvar3f " ) )
{
token = Shader_ParseSensString ( ptr ) ;
cv = Cvar_Get ( token , " " , 0 , " GLSL Shader parameters " ) ;
2010-08-28 17:14:38 +00:00
if ( ! cv )
return ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
parmtype = SP_CVAR3F ;
}
2006-03-11 03:12:10 +00:00
else if ( ! Q_stricmp ( token , " time " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_E_TIME ;
2008-12-23 02:55:20 +00:00
else if ( ! Q_stricmp ( token , " eyepos " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_E_EYEPOS ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " entmatrix " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_M_MODEL ;
2008-12-23 02:55:20 +00:00
else if ( ! Q_stricmp ( token , " colours " ) | | ! Q_stricmp ( token , " colors " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_E_COLOURS ;
2008-12-23 02:55:20 +00:00
else if ( ! Q_stricmp ( token , " upper " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_E_TOPCOLOURS ;
2008-12-23 02:55:20 +00:00
else if ( ! Q_stricmp ( token , " lower " ) )
2011-09-03 03:49:43 +00:00
parmtype = SP_E_BOTTOMCOLOURS ;
2009-07-18 20:46:42 +00:00
else if ( ! Q_stricmp ( token , " lightradius " ) )
parmtype = SP_LIGHTRADIUS ;
else if ( ! Q_stricmp ( token , " lightcolour " ) )
parmtype = SP_LIGHTCOLOUR ;
else if ( ! Q_stricmp ( token , " lightpos " ) )
parmtype = SP_LIGHTPOSITION ;
2010-07-25 15:12:12 +00:00
else if ( ! Q_stricmp ( token , " rendertexturescale " ) )
parmtype = SP_RENDERTEXTURESCALE ;
2009-07-18 20:46:42 +00:00
else
Con_Printf ( " shader %s: parameter type \" %s \" not known \n " , shader - > name , token ) ;
2006-03-11 03:12:10 +00:00
2011-01-23 03:44:49 +00:00
if ( forcename )
token = forcename ;
else
token = Shader_ParseSensString ( ptr ) ;
2006-03-11 03:12:10 +00:00
2009-11-04 21:16:50 +00:00
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
{
2010-11-02 23:17:25 +00:00
int p ;
qboolean foundone ;
2009-11-04 21:16:50 +00:00
unsigned int uniformloc ;
2011-02-25 04:22:14 +00:00
program_t * prog = shader - > prog ;
if ( ! prog )
2006-03-11 03:12:10 +00:00
{
2009-11-04 21:16:50 +00:00
Con_Printf ( " shader %s: param without program set \n " , shader - > name ) ;
2006-03-11 03:12:10 +00:00
}
2011-02-25 04:22:14 +00:00
else if ( prog - > numparams = = SHADER_PROGPARMS_MAX )
2010-08-28 17:14:38 +00:00
Con_Printf ( " shader %s: too many parms \n " , shader - > name ) ;
2006-03-11 03:12:10 +00:00
else
{
2011-02-25 04:22:14 +00:00
if ( prog - > refs ! = 1 )
Con_Printf ( " shader %s: parms on shared shader \n " , shader - > name ) ;
2010-08-28 17:14:38 +00:00
foundone = false ;
2011-02-25 04:22:14 +00:00
prog - > parm [ prog - > numparams ] . type = parmtype ;
2010-08-28 17:14:38 +00:00
for ( p = 0 ; p < PERMUTATIONS ; p + + )
2009-11-04 21:16:50 +00:00
{
2011-02-25 04:22:14 +00:00
if ( ! prog - > handle [ p ] . glsl )
2010-08-28 17:14:38 +00:00
continue ;
2011-02-25 04:22:14 +00:00
GLSlang_UseProgram ( prog - > handle [ p ] . glsl ) ;
2011-01-23 03:44:49 +00:00
if ( parmtype > = SP_FIRSTUNIFORM )
2011-02-25 04:22:14 +00:00
uniformloc = qglGetUniformLocationARB ( prog - > handle [ p ] . glsl , token ) ;
2011-01-23 03:44:49 +00:00
else
2011-02-25 04:22:14 +00:00
uniformloc = qglGetAttribLocationARB ( prog - > handle [ p ] . glsl , token ) ;
prog - > parm [ prog - > numparams ] . handle [ p ] = uniformloc ;
2010-08-28 17:14:38 +00:00
if ( uniformloc ! = - 1 )
2009-11-04 21:16:50 +00:00
{
2010-08-28 17:14:38 +00:00
foundone = true ;
switch ( parmtype )
{
case SP_BAD :
foundone = false ;
break ;
case SP_TEXTURE :
2010-11-10 03:32:47 +00:00
case SP_CONSTI :
2011-02-25 04:22:14 +00:00
prog - > parm [ prog - > numparams ] . ival = specialint ;
2010-08-28 17:14:38 +00:00
break ;
2010-11-10 03:32:47 +00:00
case SP_CONSTF :
2011-02-25 04:22:14 +00:00
prog - > parm [ prog - > numparams ] . fval = specialfloat ;
2010-11-10 03:32:47 +00:00
break ;
2010-08-28 17:14:38 +00:00
case SP_CVARF :
case SP_CVARI :
2011-02-25 04:22:14 +00:00
prog - > parm [ prog - > numparams ] . pval = cv ;
2010-08-28 17:14:38 +00:00
break ;
case SP_CVAR3F :
2011-02-25 04:22:14 +00:00
prog - > parm [ prog - > numparams ] . pval = cv ;
2010-08-28 17:14:38 +00:00
qglUniform3fvARB ( uniformloc , 1 , specialvec ) ;
break ;
default :
break ;
}
2009-11-04 21:16:50 +00:00
}
2006-03-11 03:12:10 +00:00
}
2011-10-27 16:16:29 +00:00
if ( ! foundone )
{
if ( ! silent )
Con_Printf ( " shader %s: param \" %s \" not found \n " , shader - > name , token ) ;
}
2010-08-28 17:14:38 +00:00
else
2011-02-25 04:22:14 +00:00
prog - > numparams + + ;
2010-08-28 17:14:38 +00:00
2009-11-04 21:16:50 +00:00
GLSlang_UseProgram ( 0 ) ;
2006-03-11 03:12:10 +00:00
}
}
2009-11-04 21:16:50 +00:00
# endif
2006-03-11 03:12:10 +00:00
}
2011-02-25 04:22:14 +00:00
static void Shader_DiffuseMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
token = Shader_ParseString ( ptr ) ;
shader - > defaulttextures . base = R_LoadHiResTexture ( token , NULL , 0 ) ;
}
static void Shader_Translucent ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = SHADER_BLEND ;
}
2004-10-19 15:56:22 +00:00
static shaderkey_t shaderkeys [ ] =
{
2011-03-12 13:51:40 +00:00
{ " cull " , Shader_Cull } ,
{ " skyparms " , Shader_SkyParms } ,
2009-11-04 21:16:50 +00:00
{ " fogparms " , Shader_FogParms } ,
{ " surfaceparm " , Shader_SurfaceParm } ,
2011-03-12 13:51:40 +00:00
{ " nomipmaps " , Shader_NoMipMaps } ,
2009-11-04 21:16:50 +00:00
{ " nopicmip " , Shader_NoPicMip } ,
{ " polygonoffset " , Shader_PolygonOffset } ,
{ " sort " , Shader_Sort } ,
2011-03-12 13:51:40 +00:00
{ " deformvertexes " , Shader_DeformVertexes } ,
2009-11-04 21:16:50 +00:00
{ " portal " , Shader_Portal } ,
2011-09-03 03:49:43 +00:00
{ " lpp_light " , Shader_Prelight } ,
2009-11-04 21:16:50 +00:00
{ " entitymergable " , Shader_EntityMergable } ,
{ " glslprogram " , Shader_GLSLProgramName } ,
2011-03-31 02:32:32 +00:00
{ " program " , Shader_ProgramName } , //legacy
2009-11-04 21:16:50 +00:00
{ " hlslprogram " , Shader_HLSLProgramName } , //for d3d
{ " param " , Shader_ProgramParam } ,
2006-03-11 03:12:10 +00:00
2011-02-25 04:22:14 +00:00
/*doom3 compat*/
{ " diffusemap " , Shader_DiffuseMap } ,
{ " bumpmap " , NULL } ,
{ " specularmap " , NULL } ,
{ " nonsolid " , NULL } ,
{ " noimpact " , NULL } ,
{ " translucent " , Shader_Translucent } ,
{ " noshadows " , NULL } ,
{ " nooverlays " , NULL } ,
{ " nofragment " , NULL } ,
2011-03-12 13:51:40 +00:00
{ NULL , NULL }
2004-10-19 15:56:22 +00:00
} ;
// ===============================================================
2010-11-22 02:03:28 +00:00
static qboolean ShaderPass_MapGen ( shader_t * shader , shaderpass_t * pass , char * tname )
2004-10-19 15:56:22 +00:00
{
2010-11-22 02:03:28 +00:00
if ( ! Q_stricmp ( tname , " $lightmap " ) )
2005-01-07 03:10:11 +00:00
{
2004-10-19 15:56:22 +00:00
pass - > tcgen = TC_GEN_LIGHTMAP ;
2010-11-02 23:17:25 +00:00
pass - > flags | = SHADER_PASS_LIGHTMAP | SHADER_PASS_NOMIPMAP ;
2009-11-04 21:16:50 +00:00
pass - > texgen = T_GEN_LIGHTMAP ;
shader - > flags | = SHADER_HASLIGHTMAP ;
2005-01-07 03:10:11 +00:00
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $deluxmap " ) )
2005-01-07 03:10:11 +00:00
{
pass - > tcgen = TC_GEN_LIGHTMAP ;
2010-11-02 23:17:25 +00:00
pass - > flags | = SHADER_PASS_DELUXMAP | SHADER_PASS_NOMIPMAP ;
2009-11-04 21:16:50 +00:00
pass - > texgen = T_GEN_DELUXMAP ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $diffuse " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_DIFFUSE ;
pass - > tcgen = TC_GEN_BASE ;
2011-05-20 04:10:46 +00:00
shader - > flags | = SHADER_NOIMAGE ;
2009-11-04 21:16:50 +00:00
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $normalmap " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_NORMALMAP ;
pass - > tcgen = TC_GEN_BASE ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $specular " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_SPECULAR ;
pass - > tcgen = TC_GEN_BASE ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $fullbright " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_FULLBRIGHT ;
pass - > tcgen = TC_GEN_BASE ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $upperoverlay " ) )
2009-11-04 21:16:50 +00:00
{
2010-07-18 12:52:24 +00:00
shader - > flags | = SHADER_HASTOPBOTTOM ;
2009-11-04 21:16:50 +00:00
pass - > texgen = T_GEN_UPPEROVERLAY ;
pass - > tcgen = TC_GEN_BASE ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $loweroverlay " ) )
2009-11-04 21:16:50 +00:00
{
2010-07-18 12:52:24 +00:00
shader - > flags | = SHADER_HASTOPBOTTOM ;
2009-11-04 21:16:50 +00:00
pass - > texgen = T_GEN_LOWEROVERLAY ;
pass - > tcgen = TC_GEN_BASE ;
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $shadowmap " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_SHADOWMAP ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
}
2011-12-27 08:35:19 +00:00
else if ( ! Q_stricmp ( tname , " $lightcubemap " ) )
{
pass - > texgen = T_GEN_LIGHTCUBEMAP ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
}
2010-11-22 02:03:28 +00:00
else if ( ! Q_stricmp ( tname , " $currentrender " ) )
2009-11-04 21:16:50 +00:00
{
pass - > texgen = T_GEN_CURRENTRENDER ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
2005-01-07 03:10:11 +00:00
}
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( tname , " $sourcecolour " ) )
{
pass - > texgen = T_GEN_SOURCECOLOUR ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
}
2011-10-27 16:16:29 +00:00
else if ( ! Q_stricmp ( tname , " $sourcecube " ) )
{
pass - > texgen = T_GEN_SOURCECUBE ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
}
2011-09-03 03:49:43 +00:00
else if ( ! Q_stricmp ( tname , " $sourcedepth " ) )
{
pass - > texgen = T_GEN_SOURCEDEPTH ;
pass - > tcgen = TC_GEN_BASE ; //FIXME: moo!
}
2005-01-07 03:10:11 +00:00
else
2010-11-22 02:03:28 +00:00
return false ;
return true ;
}
static void Shaderpass_Map ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
int flags ;
char * token ;
pass - > anim_frames [ 0 ] = r_nulltex ;
token = Shader_ParseString ( ptr ) ;
if ( ! ShaderPass_MapGen ( shader , pass , token ) )
2005-01-07 03:10:11 +00:00
{
2011-12-23 03:12:29 +00:00
flags = Shader_SetImageFlags ( shader , & token ) ;
if ( flags & IF_3DMAP )
pass - > texgen = T_GEN_3DMAP ;
else
pass - > texgen = T_GEN_SINGLEMAP ;
2004-10-19 15:56:22 +00:00
pass - > tcgen = TC_GEN_BASE ;
2009-11-04 21:16:50 +00:00
pass - > anim_frames [ 0 ] = Shader_FindImage ( token , flags ) ;
2011-03-12 13:51:40 +00:00
}
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_AnimMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
2011-03-12 13:51:40 +00:00
int flags ;
2004-10-19 15:56:22 +00:00
char * token ;
2009-11-04 21:16:50 +00:00
texid_t image ;
2004-10-19 15:56:22 +00:00
2011-12-23 03:12:29 +00:00
flags = Shader_SetImageFlags ( shader , NULL ) ;
2004-10-19 15:56:22 +00:00
pass - > tcgen = TC_GEN_BASE ;
2011-03-12 13:51:40 +00:00
pass - > flags | = SHADER_PASS_ANIMMAP ;
2009-11-04 21:16:50 +00:00
pass - > texgen = T_GEN_ANIMMAP ;
2011-03-12 13:51:40 +00:00
pass - > anim_fps = ( int ) Shader_ParseFloat ( ptr ) ;
2004-10-19 15:56:22 +00:00
pass - > anim_numframes = 0 ;
2011-03-12 13:51:40 +00:00
for ( ; ; )
2009-11-04 21:16:50 +00:00
{
token = Shader_ParseString ( ptr ) ;
if ( ! token [ 0 ] )
{
2004-10-19 15:56:22 +00:00
break ;
}
2009-11-04 21:16:50 +00:00
if ( pass - > anim_numframes < SHADER_ANIM_FRAMES_MAX )
{
image = Shader_FindImage ( token , flags ) ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
if ( ! TEXVALID ( image ) )
{
2006-03-06 01:41:09 +00:00
pass - > anim_frames [ pass - > anim_numframes + + ] = missing_texture ;
2007-09-23 15:28:06 +00:00
Con_DPrintf ( CON_WARNING " Shader %s has an animmap with no image: %s. \n " , shader - > name , token ) ;
2009-11-04 21:16:50 +00:00
}
else
{
2004-10-19 15:56:22 +00:00
pass - > anim_frames [ pass - > anim_numframes + + ] = image ;
}
}
}
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_ClampMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
int flags ;
char * token ;
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2004-10-19 15:56:22 +00:00
2010-11-22 02:03:28 +00:00
if ( ! ShaderPass_MapGen ( shader , pass , token ) )
2009-11-04 21:16:50 +00:00
{
2011-12-23 03:12:29 +00:00
flags = Shader_SetImageFlags ( shader , & token ) ;
2010-11-22 02:03:28 +00:00
pass - > tcgen = TC_GEN_BASE ;
pass - > anim_frames [ 0 ] = Shader_FindImage ( token , flags | IF_CLAMP ) ;
2011-12-23 03:12:29 +00:00
if ( flags & IF_3DMAP )
pass - > texgen = T_GEN_3DMAP ;
else
pass - > texgen = T_GEN_SINGLEMAP ;
2010-11-22 02:03:28 +00:00
if ( ! TEXVALID ( pass - > anim_frames [ 0 ] ) )
{
2011-12-23 03:12:29 +00:00
if ( flags & ( IF_3DMAP | IF_CUBEMAP ) )
pass - > anim_frames [ 0 ] = r_nulltex ;
else
pass - > anim_frames [ 0 ] = missing_texture ;
2010-11-22 02:03:28 +00:00
Con_DPrintf ( CON_WARNING " Shader %s has a stage with no image: %s. \n " , shader - > name , token ) ;
}
}
pass - > flags | = SHADER_PASS_CLAMP ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_VideoMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
2006-03-06 01:41:09 +00:00
char * token ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
# ifdef NOMEDIA
# else
if ( pass - > cin )
Z_Free ( pass - > cin ) ;
2004-10-19 15:56:22 +00:00
2006-03-06 01:41:09 +00:00
pass - > cin = Media_StartCin ( token ) ;
if ( ! pass - > cin )
pass - > cin = Media_StartCin ( va ( " video/%s.roq " , token ) ) ;
else
2009-11-04 21:16:50 +00:00
Con_DPrintf ( CON_WARNING " (shader %s) Couldn't load video %s \n " , shader - > name , token ) ;
2006-03-06 01:41:09 +00:00
2010-05-01 22:47:47 +00:00
if ( pass - > cin )
{
pass - > flags | = SHADER_PASS_VIDEOMAP ;
shader - > flags | = SHADER_VIDEOMAP ;
pass - > texgen = T_GEN_VIDEOMAP ;
}
else
{
pass - > texgen = T_GEN_DIFFUSE ;
pass - > rgbgen = RGB_GEN_CONST ;
pass - > rgbgen_func . type = SHADER_FUNC_CONSTANT ;
pass - > rgbgen_func . args [ 0 ] = pass - > rgbgen_func . args [ 1 ] = pass - > rgbgen_func . args [ 2 ] = 0 ;
}
2009-11-04 21:16:50 +00:00
# endif
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_RGBGen ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
char * token ;
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " identitylighting " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_IDENTITY_LIGHTING ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " identity " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_IDENTITY ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " wave " ) )
2005-02-06 02:47:36 +00:00
{
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_WAVE ;
2009-11-04 21:16:50 +00:00
Shader_ParseFunc ( ptr , & pass - > rgbgen_func ) ;
2005-02-06 02:47:36 +00:00
}
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " entity " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_ENTITY ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " oneMinusEntity " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_ONE_MINUS_ENTITY ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " vertex " ) )
2011-10-27 16:16:29 +00:00
pass - > rgbgen = RGB_GEN_VERTEX_LIGHTING ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " oneMinusVertex " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_ONE_MINUS_VERTEX ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " lightingDiffuse " ) )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_LIGHTING_DIFFUSE ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " exactvertex " ) )
2011-10-27 16:16:29 +00:00
pass - > rgbgen = RGB_GEN_VERTEX_EXACT ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " const " ) | | ! Q_stricmp ( token , " constant " ) )
2005-02-06 02:47:36 +00:00
{
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_CONST ;
pass - > rgbgen_func . type = SHADER_FUNC_CONSTANT ;
2009-11-04 21:16:50 +00:00
Shader_ParseVector ( ptr , pass - > rgbgen_func . args ) ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " topcolor " ) )
2005-02-06 02:47:36 +00:00
pass - > rgbgen = RGB_GEN_TOPCOLOR ;
2009-11-04 21:16:50 +00:00
else if ( ! Q_stricmp ( token , " bottomcolor " ) )
2005-02-06 02:47:36 +00:00
pass - > rgbgen = RGB_GEN_BOTTOMCOLOR ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_AlphaGen ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
char * token ;
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " portal " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_PORTAL ;
2010-07-11 02:22:39 +00:00
shader - > portaldist = Shader_ParseFloat ( ptr ) ;
if ( ! shader - > portaldist )
shader - > portaldist = 256 ;
2004-10-19 15:56:22 +00:00
shader - > flags | = SHADER_AGEN_PORTAL ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " vertex " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_VERTEX ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " entity " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_ENTITY ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " wave " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_WAVE ;
2009-11-04 21:16:50 +00:00
Shader_ParseFunc ( ptr , & pass - > alphagen_func ) ;
}
else if ( ! Q_stricmp ( token , " lightingspecular " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_SPECULAR ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " const " ) | | ! Q_stricmp ( token , " constant " ) )
{
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_CONST ;
pass - > alphagen_func . type = SHADER_FUNC_CONSTANT ;
2009-11-04 21:16:50 +00:00
pass - > alphagen_func . args [ 0 ] = fabs ( Shader_ParseFloat ( ptr ) ) ;
2004-10-19 15:56:22 +00:00
}
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_AlphaShift ( shader_t * shader , shaderpass_t * pass , char * * ptr ) //for alienarena
2006-02-27 00:42:25 +00:00
{
float speed ;
float min , max ;
pass - > alphagen = ALPHA_GEN_WAVE ;
pass - > alphagen_func . type = SHADER_FUNC_SIN ;
//arg0 = add
//arg1 = scale
//arg2 = timeshift
//arg3 = timescale
2009-11-04 21:16:50 +00:00
speed = Shader_ParseFloat ( ptr ) ;
min = Shader_ParseFloat ( ptr ) ;
max = Shader_ParseFloat ( ptr ) ;
2006-02-27 00:42:25 +00:00
pass - > alphagen_func . args [ 0 ] = min + ( max - min ) / 2 ;
pass - > alphagen_func . args [ 1 ] = ( max - min ) / 2 ;
pass - > alphagen_func . args [ 2 ] = 0 ;
pass - > alphagen_func . args [ 3 ] = 1 / speed ;
}
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
static int Shader_BlendFactor ( char * name , qboolean dstnotsrc )
{
int factor ;
if ( ! strnicmp ( name , " gl_ " , 3 ) )
name + = 3 ;
if ( ! Q_stricmp ( name , " zero " ) )
factor = SBITS_SRCBLEND_ZERO ;
else if ( ! Q_stricmp ( name , " one " ) )
factor = SBITS_SRCBLEND_ONE ;
else if ( ! Q_stricmp ( name , " dst_color " ) )
factor = SBITS_SRCBLEND_DST_COLOR ;
else if ( ! Q_stricmp ( name , " one_minus_src_alpha " ) )
factor = SBITS_SRCBLEND_ONE_MINUS_SRC_ALPHA ;
else if ( ! Q_stricmp ( name , " src_alpha " ) )
factor = SBITS_SRCBLEND_SRC_ALPHA ;
else if ( ! Q_stricmp ( name , " src_color " ) )
factor = SBITS_SRCBLEND_SRC_COLOR_INVALID ;
else if ( ! Q_stricmp ( name , " one_minus_dst_color " ) )
factor = SBITS_SRCBLEND_ONE_MINUS_DST_COLOR ;
else if ( ! Q_stricmp ( name , " one_minus_src_color " ) )
factor = SBITS_SRCBLEND_ONE_MINUS_SRC_COLOR_INVALID ;
else if ( ! Q_stricmp ( name , " dst_alpha " ) )
factor = SBITS_SRCBLEND_DST_ALPHA ;
else if ( ! Q_stricmp ( name , " one_minus_dst_alpha " ) )
factor = SBITS_SRCBLEND_ONE_MINUS_DST_ALPHA ;
else
factor = SBITS_SRCBLEND_NONE ;
if ( dstnotsrc )
{
//dest factors are shifted
factor < < = 4 ;
/*gl doesn't accept dst_color for destinations*/
if ( factor = = SBITS_DSTBLEND_NONE | |
factor = = SBITS_DSTBLEND_DST_COLOR_INVALID | |
factor = = SBITS_DSTBLEND_ONE_MINUS_DST_COLOR_INVALID | |
factor = = SBITS_DSTBLEND_ALPHA_SATURATE_INVALID )
{
Con_DPrintf ( " Invalid shader dst blend \" %s \" \n " , name ) ;
factor = SBITS_DSTBLEND_ONE ;
}
}
else
{
/*gl doesn't accept src_color for sources*/
if ( factor = = SBITS_SRCBLEND_NONE | |
factor = = SBITS_SRCBLEND_SRC_COLOR_INVALID | |
factor = = SBITS_SRCBLEND_ONE_MINUS_SRC_COLOR_INVALID )
{
Con_DPrintf ( " Unrecognised shader src blend \" %s \" \n " , name ) ;
factor = SBITS_SRCBLEND_ONE ;
}
}
return factor ;
}
static void Shaderpass_BlendFunc ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
char * token ;
2009-11-04 21:16:50 +00:00
pass - > shaderbits & = ~ ( SBITS_BLEND_BITS ) ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2011-02-25 04:22:14 +00:00
if ( ! Q_stricmp ( token , " diffusemap " ) )
{
//if the shader is translucent then this pass must be meant to be blended
if ( shader - > flags & SHADER_BLEND )
pass - > shaderbits | = SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA ;
else
pass - > shaderbits | = SBITS_SRCBLEND_NONE | SBITS_DSTBLEND_NONE ;
}
else if ( ! Q_stricmp ( token , " blend " ) )
2009-11-04 21:16:50 +00:00
{
pass - > shaderbits | = SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA ;
}
else if ( ! Q_stricmp ( token , " filter " ) )
{
pass - > shaderbits | = SBITS_SRCBLEND_DST_COLOR | SBITS_DSTBLEND_ZERO ;
}
else if ( ! Q_stricmp ( token , " add " ) )
{
2010-11-07 02:53:46 +00:00
pass - > shaderbits | = SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " replace " ) )
{
pass - > shaderbits | = SBITS_SRCBLEND_NONE | SBITS_DSTBLEND_NONE ;
}
else
{
pass - > shaderbits | = Shader_BlendFactor ( token , false ) ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2011-02-25 04:22:14 +00:00
if ( * token = = ' , ' )
token = Shader_ParseString ( ptr ) ;
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = Shader_BlendFactor ( token , true ) ;
2011-03-12 13:51:40 +00:00
}
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_AlphaFunc ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
char * token ;
2009-11-04 21:16:50 +00:00
pass - > shaderbits & = ~ SBITS_ATEST_BITS ;
2004-10-19 15:56:22 +00:00
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2011-03-12 13:51:40 +00:00
if ( ! Q_stricmp ( token , " gt0 " ) )
2009-11-04 21:16:50 +00:00
{
pass - > shaderbits = SBITS_ATEST_GT0 ;
}
else if ( ! Q_stricmp ( token , " lt128 " ) )
{
pass - > shaderbits = SBITS_ATEST_LT128 ;
}
else if ( ! Q_stricmp ( token , " ge128 " ) )
{
pass - > shaderbits = SBITS_ATEST_GE128 ;
2011-03-12 13:51:40 +00:00
}
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_DepthFunc ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
char * token ;
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
2011-03-12 13:51:40 +00:00
if ( ! Q_stricmp ( token , " equal " ) )
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = SBITS_MISC_DEPTHEQUALONLY ;
2011-03-12 13:51:40 +00:00
else if ( ! Q_stricmp ( token , " lequal " ) )
2009-11-04 21:16:50 +00:00
pass - > shaderbits & = ~ SBITS_MISC_DEPTHEQUALONLY ;
else
Con_DPrintf ( " Invalid depth func %s \n " , token ) ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_DepthWrite ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
2011-03-12 13:51:40 +00:00
shader - > flags | = SHADER_DEPTHWRITE ;
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2004-10-19 15:56:22 +00:00
}
2011-10-27 16:16:29 +00:00
static void Shaderpass_NoDepthTest ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = SHADER_DEPTHWRITE ;
pass - > shaderbits | = SBITS_MISC_NODEPTHTEST ;
}
static void Shaderpass_NoDepth ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
shader - > flags | = SHADER_DEPTHWRITE ;
}
2009-11-04 21:16:50 +00:00
static void Shaderpass_TcMod ( shader_t * shader , shaderpass_t * pass , char * * ptr )
2004-10-19 15:56:22 +00:00
{
int i ;
tcmod_t * tcmod ;
char * token ;
2011-09-03 03:49:43 +00:00
if ( pass - > numtcmods > = SHADER_MAX_TC_MODS )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
return ;
}
tcmod = & pass - > tcmods [ pass - > numtcmods ] ;
2009-11-04 21:16:50 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " rotate " ) )
{
tcmod - > args [ 0 ] = - Shader_ParseFloat ( ptr ) / 360.0f ;
if ( ! tcmod - > args [ 0 ] )
{
2004-10-19 15:56:22 +00:00
return ;
}
tcmod - > type = SHADER_TCMOD_ROTATE ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " scale " ) )
{
tcmod - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
tcmod - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
2004-10-19 15:56:22 +00:00
tcmod - > type = SHADER_TCMOD_SCALE ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " scroll " ) )
{
tcmod - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
tcmod - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
2004-10-19 15:56:22 +00:00
tcmod - > type = SHADER_TCMOD_SCROLL ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " stretch " ) )
{
2004-10-19 15:56:22 +00:00
shaderfunc_t func ;
2009-11-04 21:16:50 +00:00
Shader_ParseFunc ( ptr , & func ) ;
2004-10-19 15:56:22 +00:00
tcmod - > args [ 0 ] = func . type ;
for ( i = 1 ; i < 5 ; + + i )
tcmod - > args [ i ] = func . args [ i - 1 ] ;
tcmod - > type = SHADER_TCMOD_STRETCH ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " transform " ) )
{
2004-10-19 15:56:22 +00:00
for ( i = 0 ; i < 6 ; + + i )
2009-11-04 21:16:50 +00:00
tcmod - > args [ i ] = Shader_ParseFloat ( ptr ) ;
2004-10-19 15:56:22 +00:00
tcmod - > type = SHADER_TCMOD_TRANSFORM ;
2009-11-04 21:16:50 +00:00
}
else if ( ! Q_stricmp ( token , " turb " ) )
{
2004-10-19 15:56:22 +00:00
for ( i = 0 ; i < 4 ; i + + )
2009-11-04 21:16:50 +00:00
tcmod - > args [ i ] = Shader_ParseFloat ( ptr ) ;
2004-10-19 15:56:22 +00:00
tcmod - > type = SHADER_TCMOD_TURB ;
2009-11-04 21:16:50 +00:00
}
else
{
2004-10-19 15:56:22 +00:00
return ;
}
pass - > numtcmods + + ;
}
2006-02-27 00:42:25 +00:00
static void Shaderpass_Scale ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
//seperate x and y
char * token ;
tcmod_t * tcmod ;
tcmod = & pass - > tcmods [ pass - > numtcmods ] ;
2011-02-25 04:22:14 +00:00
tcmod - > type = SHADER_TCMOD_SCALE ;
2006-02-27 00:42:25 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! strcmp ( token , " static " ) )
{
tcmod - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
}
else
{
2011-02-25 04:22:14 +00:00
tcmod - > args [ 0 ] = atof ( token ) ;
2006-02-27 00:42:25 +00:00
}
2011-05-15 13:23:13 +00:00
2011-02-25 04:22:14 +00:00
while ( * * ptr = = ' ' | | * * ptr = = ' \t ' )
* ptr + = 1 ;
if ( * * ptr = = ' , ' )
* ptr + = 1 ;
2006-02-27 00:42:25 +00:00
token = Shader_ParseString ( ptr ) ;
if ( ! strcmp ( token , " static " ) )
{
tcmod - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
}
else
{
2011-02-25 04:22:14 +00:00
tcmod - > args [ 1 ] = atof ( token ) ;
2006-02-27 00:42:25 +00:00
}
pass - > numtcmods + + ;
}
static void Shaderpass_Scroll ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
//seperate x and y
char * token ;
tcmod_t * tcmod ;
tcmod = & pass - > tcmods [ pass - > numtcmods ] ;
token = Shader_ParseString ( ptr ) ;
if ( ! strcmp ( token , " static " ) )
{
tcmod - > type = SHADER_TCMOD_SCROLL ;
tcmod - > args [ 0 ] = Shader_ParseFloat ( ptr ) ;
}
else
{
Con_Printf ( " Bad shader scale \n " ) ;
return ;
}
token = Shader_ParseString ( ptr ) ;
if ( ! strcmp ( token , " static " ) )
{
tcmod - > type = SHADER_TCMOD_SCROLL ;
tcmod - > args [ 1 ] = Shader_ParseFloat ( ptr ) ;
}
else
{
Con_Printf ( " Bad shader scale \n " ) ;
return ;
}
pass - > numtcmods + + ;
}
2004-10-19 15:56:22 +00:00
static void Shaderpass_TcGen ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token ;
token = Shader_ParseString ( ptr ) ;
if ( ! Q_stricmp ( token , " base " ) ) {
pass - > tcgen = TC_GEN_BASE ;
} else if ( ! Q_stricmp ( token , " lightmap " ) ) {
pass - > tcgen = TC_GEN_LIGHTMAP ;
} else if ( ! Q_stricmp ( token , " environment " ) ) {
pass - > tcgen = TC_GEN_ENVIRONMENT ;
} else if ( ! Q_stricmp ( token , " vector " ) ) {
pass - > tcgen = TC_GEN_BASE ;
2009-07-05 18:45:53 +00:00
} else if ( ! Q_stricmp ( token , " normal " ) ) {
pass - > tcgen = TC_GEN_NORMAL ;
} else if ( ! Q_stricmp ( token , " svector " ) ) {
pass - > tcgen = TC_GEN_SVECTOR ;
} else if ( ! Q_stricmp ( token , " tvector " ) ) {
pass - > tcgen = TC_GEN_TVECTOR ;
2004-10-19 15:56:22 +00:00
}
}
2006-02-27 00:42:25 +00:00
static void Shaderpass_EnvMap ( shader_t * shader , shaderpass_t * pass , char * * ptr ) //for alienarena
{
pass - > tcgen = TC_GEN_ENVIRONMENT ;
}
2004-10-19 15:56:22 +00:00
static void Shaderpass_Detail ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > flags | = SHADER_PASS_DETAIL ;
}
2006-02-27 00:42:25 +00:00
static void Shaderpass_AlphaMask ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
2009-11-04 21:16:50 +00:00
pass - > shaderbits & = ~ SBITS_ATEST_BITS ;
pass - > shaderbits | = SBITS_ATEST_GE128 ;
2006-02-27 00:42:25 +00:00
}
static void Shaderpass_NoLightMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > rgbgen = RGB_GEN_IDENTITY ;
}
2011-12-05 15:23:40 +00:00
static void Shaderpass_Red ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > rgbgen = RGB_GEN_CONST ;
pass - > rgbgen_func . args [ 0 ] = Shader_ParseFloat ( ptr ) ;
}
static void Shaderpass_Green ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > rgbgen = RGB_GEN_CONST ;
pass - > rgbgen_func . args [ 1 ] = Shader_ParseFloat ( ptr ) ;
}
static void Shaderpass_Blue ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > rgbgen = RGB_GEN_CONST ;
pass - > rgbgen_func . args [ 2 ] = Shader_ParseFloat ( ptr ) ;
}
static void Shaderpass_Alpha ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > alphagen = ALPHA_GEN_CONST ;
pass - > alphagen_func . args [ 0 ] = Shader_ParseFloat ( ptr ) ;
}
2011-02-25 04:22:14 +00:00
static void Shaderpass_MaskColor ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > shaderbits | = SBITS_MASK_RED | SBITS_MASK_GREEN | SBITS_MASK_BLUE ;
}
static void Shaderpass_MaskRed ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > shaderbits | = SBITS_MASK_RED ;
}
static void Shaderpass_MaskGreen ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > shaderbits | = SBITS_MASK_GREEN ;
}
static void Shaderpass_MaskBlue ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > shaderbits | = SBITS_MASK_BLUE ;
}
static void Shaderpass_MaskAlpha ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
pass - > shaderbits | = SBITS_MASK_ALPHA ;
}
static void Shaderpass_AlphaTest ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
if ( Shader_ParseFloat ( ptr ) = = 0.5 )
pass - > shaderbits | = SBITS_ATEST_GE128 ;
else
Con_Printf ( " unsupported alphatest value \n " ) ;
}
static void Shaderpass_TexGen ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
char * token = Shader_ParseString ( ptr ) ;
if ( ! strcmp ( token , " normal " ) )
pass - > tcgen = TC_GEN_NORMAL ;
else if ( ! strcmp ( token , " skybox " ) )
pass - > tcgen = TC_GEN_SKYBOX ;
else if ( ! strcmp ( token , " wobblesky " ) )
{
pass - > tcgen = TC_GEN_WOBBLESKY ;
token = Shader_ParseString ( ptr ) ;
token = Shader_ParseString ( ptr ) ;
token = Shader_ParseString ( ptr ) ;
}
else if ( ! strcmp ( token , " reflect " ) )
pass - > tcgen = TC_GEN_REFLECT ;
else
{
Con_Printf ( " texgen token not understood \n " ) ;
}
}
static void Shaderpass_CubeMap ( shader_t * shader , shaderpass_t * pass , char * * ptr )
{
2011-12-23 03:12:29 +00:00
char * token = Shader_ParseString ( ptr ) ;
2011-02-25 04:22:14 +00:00
if ( pass - > tcgen = = TC_GEN_BASE )
pass - > tcgen = TC_GEN_SKYBOX ;
2011-12-23 03:12:29 +00:00
pass - > texgen = T_GEN_CUBEMAP ;
pass - > anim_frames [ 0 ] = Shader_FindImage ( token , IF_CUBEMAP ) ;
2011-02-25 04:22:14 +00:00
if ( ! TEXVALID ( pass - > anim_frames [ 0 ] ) )
{
pass - > texgen = T_GEN_SINGLEMAP ;
pass - > anim_frames [ 0 ] = missing_texture ;
}
}
2004-10-19 15:56:22 +00:00
static shaderkey_t shaderpasskeys [ ] =
{
2011-03-12 13:51:40 +00:00
{ " rgbgen " , Shaderpass_RGBGen } ,
{ " blendfunc " , Shaderpass_BlendFunc } ,
{ " depthfunc " , Shaderpass_DepthFunc } ,
{ " depthwrite " , Shaderpass_DepthWrite } ,
2011-10-27 16:16:29 +00:00
{ " nodepthtest " , Shaderpass_NoDepthTest } ,
{ " nodepth " , Shaderpass_NoDepth } ,
2011-03-12 13:51:40 +00:00
{ " alphafunc " , Shaderpass_AlphaFunc } ,
{ " tcmod " , Shaderpass_TcMod } ,
{ " map " , Shaderpass_Map } ,
{ " animmap " , Shaderpass_AnimMap } ,
{ " clampmap " , Shaderpass_ClampMap } ,
{ " videomap " , Shaderpass_VideoMap } ,
{ " tcgen " , Shaderpass_TcGen } ,
{ " envmap " , Shaderpass_EnvMap } , //for alienarena
{ " nolightmap " , Shaderpass_NoLightMap } , //for alienarena
{ " scale " , Shaderpass_Scale } , //for alienarena
{ " scroll " , Shaderpass_Scroll } , //for alienarena
{ " alphagen " , Shaderpass_AlphaGen } ,
{ " alphashift " , Shaderpass_AlphaShift } , //for alienarena
{ " alphamask " , Shaderpass_AlphaMask } , //for alienarena
{ " detail " , Shaderpass_Detail } ,
2011-02-25 04:22:14 +00:00
/*doom3 compat*/
{ " blend " , Shaderpass_BlendFunc } ,
{ " maskcolor " , Shaderpass_MaskColor } ,
{ " maskred " , Shaderpass_MaskRed } ,
{ " maskgreen " , Shaderpass_MaskGreen } ,
{ " maskblue " , Shaderpass_MaskBlue } ,
{ " maskalpha " , Shaderpass_MaskAlpha } ,
{ " alphatest " , Shaderpass_AlphaTest } ,
{ " texgen " , Shaderpass_TexGen } ,
{ " cameracubemap " , Shaderpass_CubeMap } ,
2011-12-05 15:23:40 +00:00
{ " red " , Shaderpass_Red } ,
{ " green " , Shaderpass_Green } ,
{ " blue " , Shaderpass_Blue } ,
{ " alpha " , Shaderpass_Alpha } ,
2011-03-12 13:51:40 +00:00
{ NULL , NULL }
2004-10-19 15:56:22 +00:00
} ;
// ===============================================================
2011-06-04 16:11:35 +00:00
void Shader_FreePass ( shaderpass_t * pass )
{
# ifndef NOMEDIA
if ( pass - > flags & SHADER_PASS_VIDEOMAP )
{
Media_ShutdownCin ( pass - > cin ) ;
pass - > cin = NULL ;
}
# endif
}
void Shader_Free ( shader_t * shader )
{
int i ;
shaderpass_t * pass ;
if ( shader - > bucket . data = = shader )
Hash_RemoveData ( & shader_active_hash , shader - > name , shader ) ;
shader - > bucket . data = NULL ;
2011-06-05 23:53:33 +00:00
if ( shader - > prog )
2012-01-01 02:26:42 +00:00
Shader_UnloadProg ( shader - > prog ) ;
2011-06-05 23:53:33 +00:00
shader - > prog = NULL ;
2011-06-04 16:11:35 +00:00
if ( shader - > skydome )
{
Z_Free ( shader - > skydome ) ;
}
pass = shader - > passes ;
for ( i = 0 ; i < shader - > numpasses ; i + + , pass + + )
{
Shader_FreePass ( pass ) ;
}
shader - > numpasses = 0 ;
2011-12-05 15:23:40 +00:00
if ( shader - > genargs )
{
free ( shader - > genargs ) ;
shader - > genargs = NULL ;
}
shader - > uses = 0 ;
2011-06-04 16:11:35 +00:00
}
2009-04-01 22:03:56 +00:00
int Shader_InitCallback ( const char * name , int size , void * param )
2004-10-19 15:56:22 +00:00
{
2005-03-28 00:11:59 +00:00
strcpy ( shaderbuf + shaderbuflen , name ) ;
Shader_MakeCache ( shaderbuf + shaderbuflen ) ;
shaderbuflen + = strlen ( name ) + 1 ;
2004-10-19 15:56:22 +00:00
return true ;
}
qboolean Shader_Init ( void )
{
2011-10-27 16:16:29 +00:00
int wibuf [ 16 ] ;
2005-03-28 00:11:59 +00:00
shaderbuflen = 0 ;
2011-06-05 23:53:33 +00:00
if ( ! r_shaders )
{
r_shaders = calloc ( MAX_SHADERS , sizeof ( shader_t ) ) ;
2010-05-01 22:47:47 +00:00
2011-06-05 23:53:33 +00:00
shader_hash = calloc ( HASH_SIZE , sizeof ( * shader_hash ) ) ;
2010-05-01 22:47:47 +00:00
2011-06-05 23:53:33 +00:00
shader_active_hash_mem = malloc ( Hash_BytesForBuckets ( 1024 ) ) ;
memset ( shader_active_hash_mem , 0 , Hash_BytesForBuckets ( 1024 ) ) ;
Hash_InitTable ( & shader_active_hash , 1024 , shader_active_hash_mem ) ;
2004-10-19 15:56:22 +00:00
2011-06-05 23:53:33 +00:00
Shader_FlushGenerics ( ) ;
2011-06-04 16:11:35 +00:00
}
2011-12-05 15:23:40 +00:00
Shader_NeedReload ( true ) ;
2010-03-14 14:35:56 +00:00
Shader_DoReload ( ) ;
2011-10-27 16:16:29 +00:00
memset ( wibuf , 0xff , sizeof ( wibuf ) ) ;
if ( ! qrenderer )
r_whiteimage = r_nulltex ;
else
r_whiteimage = R_LoadTexture ( " $whiteimage " , 4 , 4 , TF_RGBA32 , wibuf , IF_NOMIPMAP | IF_NOPICMIP | IF_NEAREST | IF_NOGAMMA ) ;
2004-10-19 15:56:22 +00:00
return true ;
}
static void Shader_MakeCache ( char * path )
{
unsigned int key , i ;
char filename [ MAX_QPATH ] ;
char * buf , * ptr , * token , * t ;
shadercache_t * cache ;
int size ;
2005-04-26 16:04:12 +00:00
Com_sprintf ( filename , sizeof ( filename ) , " %s " , path ) ;
2005-01-18 21:06:46 +00:00
Con_DPrintf ( " ...loading '%s' \n " , filename ) ;
2004-10-19 15:56:22 +00:00
size = FS_LoadFile ( filename , ( void * * ) & buf ) ;
2009-11-04 21:16:50 +00:00
if ( ! buf | | size < = 0 )
{
2004-10-19 15:56:22 +00:00
return ;
}
ptr = buf ;
do
{
if ( ptr - buf > = size )
break ;
token = COM_ParseExt ( & ptr , true ) ;
if ( ! token [ 0 ] | | ptr - buf > = size )
break ;
2005-08-26 22:56:51 +00:00
COM_CleanUpPath ( token ) ;
2004-10-19 15:56:22 +00:00
t = NULL ;
Shader_GetPathAndOffset ( token , & t , & i ) ;
2010-07-11 02:22:39 +00:00
if ( t )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
ptr = Shader_Skip ( ptr ) ;
continue ;
}
key = Hash_Key ( token , HASH_SIZE ) ;
cache = ( shadercache_t * ) Z_Malloc ( sizeof ( shadercache_t ) ) ;
cache - > hash_next = shader_hash [ key ] ;
cache - > path = path ;
cache - > offset = ptr - buf ;
2011-05-15 13:23:13 +00:00
Com_sprintf ( cache - > name , MAX_QPATH , " %s " , token ) ; // warning: format not a string literal and no format arguments
2004-10-19 15:56:22 +00:00
shader_hash [ key ] = cache ;
ptr = Shader_Skip ( ptr ) ;
} while ( ptr ) ;
FS_FreeFile ( buf ) ;
}
char * Shader_Skip ( char * ptr )
2010-11-26 06:58:48 +00:00
{
2004-10-19 15:56:22 +00:00
char * tok ;
2011-03-12 13:51:40 +00:00
int brace_count ;
2004-10-19 15:56:22 +00:00
// Opening brace
2011-03-12 13:51:40 +00:00
tok = COM_ParseExt ( & ptr , true ) ;
2004-10-19 15:56:22 +00:00
if ( ! ptr )
return NULL ;
2010-11-26 06:58:48 +00:00
2009-11-04 21:16:50 +00:00
if ( tok [ 0 ] ! = ' { ' )
{
2004-10-19 15:56:22 +00:00
tok = COM_ParseExt ( & ptr , true ) ;
}
2011-03-12 13:51:40 +00:00
for ( brace_count = 1 ; brace_count > 0 ; ptr + + )
{
2004-10-19 15:56:22 +00:00
tok = COM_ParseExt ( & ptr , true ) ;
if ( ! tok [ 0 ] )
return NULL ;
2009-11-04 21:16:50 +00:00
if ( tok [ 0 ] = = ' { ' )
{
2004-10-19 15:56:22 +00:00
brace_count + + ;
2009-11-04 21:16:50 +00:00
} else if ( tok [ 0 ] = = ' } ' )
{
2004-10-19 15:56:22 +00:00
brace_count - - ;
}
2011-03-12 13:51:40 +00:00
}
2004-10-19 15:56:22 +00:00
return ptr ;
}
2011-06-05 23:53:33 +00:00
static void Shader_GetPathAndOffset ( char * name , char * * path , unsigned int * offset )
2004-10-19 15:56:22 +00:00
{
unsigned int key ;
shadercache_t * cache ;
key = Hash_Key ( name , HASH_SIZE ) ;
cache = shader_hash [ key ] ;
2009-11-04 21:16:50 +00:00
for ( ; cache ; cache = cache - > hash_next )
{
if ( ! Q_stricmp ( cache - > name , name ) )
{
2004-10-19 15:56:22 +00:00
* path = cache - > path ;
* offset = cache - > offset ;
return ;
}
}
path = NULL ;
}
2011-05-20 04:10:46 +00:00
void Shader_Reset ( shader_t * s )
{
char name [ MAX_QPATH ] ;
int uses = s - > uses ;
shader_gen_t * defaultgen = s - > generator ;
2011-12-05 15:23:40 +00:00
char * genargs = s - > genargs ;
2011-05-20 04:10:46 +00:00
texnums_t dt = s - > defaulttextures ;
Q_strncpyz ( name , s - > name , sizeof ( name ) ) ;
2011-12-05 15:23:40 +00:00
s - > genargs = NULL ;
2011-05-20 04:10:46 +00:00
Shader_Free ( s ) ;
memset ( s , 0 , sizeof ( * s ) ) ;
s - > defaulttextures = dt ;
s - > generator = defaultgen ;
s - > genargs = genargs ;
s - > uses = uses ;
Q_strncpyz ( s - > name , name , sizeof ( s - > name ) ) ;
Hash_Add ( & shader_active_hash , s - > name , s , & s - > bucket ) ;
}
2004-10-19 15:56:22 +00:00
void Shader_Shutdown ( void )
{
int i ;
shader_t * shader ;
shadercache_t * cache , * cache_next ;
shader = r_shaders ;
2010-07-25 15:12:12 +00:00
if ( ! r_shaders )
return ; /*nothing needs freeing yet*/
2004-10-19 15:56:22 +00:00
for ( i = 0 ; i < MAX_SHADERS ; i + + , shader + + )
{
2011-06-05 23:53:33 +00:00
if ( ! shader - > uses )
2004-10-19 15:56:22 +00:00
continue ;
2009-11-04 21:16:50 +00:00
2011-06-05 23:53:33 +00:00
Shader_Free ( shader ) ;
2004-10-19 15:56:22 +00:00
}
2011-06-05 23:53:33 +00:00
for ( i = 0 ; i < HASH_SIZE ; i + + )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
cache = shader_hash [ i ] ;
2011-06-05 23:53:33 +00:00
for ( ; cache ; cache = cache_next )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
cache_next = cache - > hash_next ;
cache - > hash_next = NULL ;
2011-06-05 23:53:33 +00:00
Z_Free ( cache ) ;
2004-10-19 15:56:22 +00:00
}
}
2010-07-11 02:22:39 +00:00
free ( r_shaders ) ;
2010-05-01 22:47:47 +00:00
r_shaders = NULL ;
2010-07-11 02:22:39 +00:00
free ( shader_hash ) ;
2010-05-01 22:47:47 +00:00
shader_hash = NULL ;
2010-07-11 02:22:39 +00:00
free ( shader_active_hash_mem ) ;
shader_active_hash_mem = NULL ;
2009-11-04 21:16:50 +00:00
shader_reload_needed = false ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_SetBlendmode ( shaderpass_t * pass )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
if ( pass - > texgen = = T_GEN_DELUXMAP )
{
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_DOTPRODUCT ;
2009-11-04 21:16:50 +00:00
return ;
}
if ( pass - > texgen < T_GEN_DIFFUSE & & ! TEXVALID ( pass - > anim_frames [ 0 ] ) & & ! ( pass - > flags & SHADER_PASS_LIGHTMAP ) )
{
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_MODULATE ;
2004-10-19 15:56:22 +00:00
return ;
}
2010-05-01 22:47:47 +00:00
if ( ! ( pass - > shaderbits & SBITS_BLEND_BITS ) )
2009-11-04 21:16:50 +00:00
{
if ( ( pass - > rgbgen = = RGB_GEN_IDENTITY ) & & ( pass - > alphagen = = ALPHA_GEN_IDENTITY ) )
{
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_REPLACE ;
2011-10-27 16:16:29 +00:00
return ;
}
else if ( ( pass - > rgbgen = = RGB_GEN_IDENTITY_LIGHTING ) & & ( pass - > alphagen = = ALPHA_GEN_IDENTITY ) )
{
pass - > shaderbits & = ~ SBITS_BLEND_BITS ;
pass - > shaderbits | = SBITS_SRCBLEND_ONE ;
pass - > shaderbits | = SBITS_DSTBLEND_ZERO ;
pass - > blendmode = PBM_REPLACELIGHT ;
2009-11-04 21:16:50 +00:00
}
else
{
pass - > shaderbits & = ~ SBITS_BLEND_BITS ;
pass - > shaderbits | = SBITS_SRCBLEND_ONE ;
pass - > shaderbits | = SBITS_DSTBLEND_ZERO ;
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_MODULATE ;
2004-10-19 15:56:22 +00:00
}
return ;
}
2009-11-04 21:16:50 +00:00
if ( ( ( pass - > shaderbits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_ZERO | SBITS_DSTBLEND_SRC_COLOR ) ) | |
( ( pass - > shaderbits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_DST_COLOR | SBITS_DSTBLEND_ZERO ) ) )
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_MODULATE ;
2009-11-04 21:16:50 +00:00
else if ( ( pass - > shaderbits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE ) )
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_ADD ;
2009-11-04 21:16:50 +00:00
else if ( ( pass - > shaderbits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_DECAL ;
2004-10-19 15:56:22 +00:00
else
2011-03-02 03:43:38 +00:00
pass - > blendmode = PBM_MODULATE ;
2004-10-19 15:56:22 +00:00
}
void Shader_Readpass ( shader_t * shader , char * * ptr )
{
2011-03-12 13:51:40 +00:00
char * token ;
2004-10-19 15:56:22 +00:00
shaderpass_t * pass ;
qboolean ignore ;
static shader_t dummy ;
2009-11-04 21:16:50 +00:00
if ( shader - > numpasses > = SHADER_PASS_MAX )
{
2004-10-19 15:56:22 +00:00
ignore = true ;
shader = & dummy ;
shader - > numpasses = 1 ;
pass = shader - > passes ;
2009-11-04 21:16:50 +00:00
}
else
{
2004-10-19 15:56:22 +00:00
ignore = false ;
pass = & shader - > passes [ shader - > numpasses + + ] ;
}
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
// Set defaults
2011-03-12 13:51:40 +00:00
pass - > flags = 0 ;
pass - > anim_frames [ 0 ] = r_nulltex ;
2004-10-19 15:56:22 +00:00
pass - > anim_numframes = 0 ;
2011-03-12 13:51:40 +00:00
pass - > rgbgen = RGB_GEN_UNKNOWN ;
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_IDENTITY ;
pass - > tcgen = TC_GEN_BASE ;
pass - > numtcmods = 0 ;
pass - > numMergedPasses = 1 ;
2010-11-02 23:17:25 +00:00
if ( shader - > flags & SHADER_NOMIPMAPS )
pass - > flags | = SHADER_PASS_NOMIPMAP ;
2010-07-11 02:22:39 +00:00
while ( * ptr )
2004-10-19 15:56:22 +00:00
{
token = COM_ParseExt ( ptr , true ) ;
2009-11-04 21:16:50 +00:00
if ( ! token [ 0 ] )
{
2004-10-19 15:56:22 +00:00
continue ;
2009-11-04 21:16:50 +00:00
}
else if ( token [ 0 ] = = ' } ' )
{
2004-10-19 15:56:22 +00:00
break ;
2009-11-04 21:16:50 +00:00
}
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
else if ( ! Q_stricmp ( token , " if " ) )
{
2011-03-12 13:51:40 +00:00
int nest = 0 ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
qboolean conditionistrue = Shader_EvaluateCondition ( ptr ) ;
while ( * ptr )
{
token = COM_ParseExt ( ptr , true ) ;
if ( ! token [ 0 ] )
continue ;
else if ( token [ 0 ] = = ' ] ' )
2011-03-12 13:51:40 +00:00
{
if ( - - nest < = 0 )
{
nest + + ;
if ( ! strcmp ( token , " ][ " ) )
conditionistrue = ! conditionistrue ;
else
break ;
}
}
else if ( token [ 0 ] = = ' [ ' )
nest + + ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
else if ( conditionistrue )
{
Shader_Parsetok ( shader , pass , shaderpasskeys , token , ptr ) ;
}
}
}
2009-11-04 21:16:50 +00:00
else if ( Shader_Parsetok ( shader , pass , shaderpasskeys , token , ptr ) )
{
2004-10-19 15:56:22 +00:00
break ;
}
}
2010-11-26 06:58:48 +00:00
// check some things
2009-11-04 21:16:50 +00:00
if ( ignore )
{
2011-10-27 16:16:29 +00:00
Shader_FreePass ( pass ) ;
shader - > numpasses - - ;
2004-10-19 15:56:22 +00:00
return ;
}
2009-11-04 21:16:50 +00:00
if ( ( pass - > shaderbits & SBITS_BLEND_BITS ) = = ( SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ZERO ) )
{
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2004-10-19 15:56:22 +00:00
shader - > flags | = SHADER_DEPTHWRITE ;
}
switch ( pass - > rgbgen )
{
case RGB_GEN_IDENTITY_LIGHTING :
case RGB_GEN_IDENTITY :
case RGB_GEN_CONST :
case RGB_GEN_WAVE :
case RGB_GEN_ENTITY :
case RGB_GEN_ONE_MINUS_ENTITY :
case RGB_GEN_UNKNOWN : // assume RGB_GEN_IDENTITY or RGB_GEN_IDENTITY_LIGHTING
switch ( pass - > alphagen )
{
case ALPHA_GEN_IDENTITY :
case ALPHA_GEN_CONST :
case ALPHA_GEN_WAVE :
case ALPHA_GEN_ENTITY :
pass - > flags | = SHADER_PASS_NOCOLORARRAY ;
break ;
default :
break ;
}
break ;
default :
break ;
}
2012-02-14 15:50:34 +00:00
/*if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE))
2009-11-04 21:16:50 +00:00
{
2011-10-27 16:16:29 +00:00
# ifdef warningmsg
# pragma warningmsg("is this valid?")
2011-05-29 04:26:29 +00:00
# endif
2009-11-04 21:16:50 +00:00
pass - > shaderbits & = ~ SBITS_MISC_DEPTHWRITE ;
}
2012-02-14 15:50:34 +00:00
*/
2009-11-04 21:16:50 +00:00
}
2004-10-19 15:56:22 +00:00
static qboolean Shader_Parsetok ( shader_t * shader , shaderpass_t * pass , shaderkey_t * keys , char * token , char * * ptr )
{
2011-03-12 13:51:40 +00:00
shaderkey_t * key ;
2004-10-19 15:56:22 +00:00
for ( key = keys ; key - > keyword ! = NULL ; key + + )
{
if ( ! Q_stricmp ( token , key - > keyword ) )
{
if ( key - > func )
key - > func ( shader , pass , ptr ) ;
return ( ptr & & * ptr & & * * ptr = = ' } ' ) ;
}
}
// Next Line
while ( ptr )
{
token = COM_ParseExt ( ptr , false ) ;
if ( ! token [ 0 ] ) {
break ;
}
}
return false ;
}
2009-11-04 21:16:50 +00:00
void Shader_SetPassFlush ( shaderpass_t * pass , shaderpass_t * pass2 )
2004-10-19 15:56:22 +00:00
{
2012-01-16 06:22:06 +00:00
qboolean config_tex_env_combine ;
qboolean config_nv_tex_env_combine4 ;
qboolean config_env_add ;
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL )
{
config_tex_env_combine = gl_config . tex_env_combine ;
config_nv_tex_env_combine4 = gl_config . nv_tex_env_combine4 ;
config_env_add = gl_config . env_add ;
}
else
# endif
{
config_tex_env_combine = 1 ;
config_nv_tex_env_combine4 = 1 ;
config_env_add = 1 ;
}
2010-11-10 03:32:47 +00:00
2009-11-04 21:16:50 +00:00
if ( ( ( pass - > flags & SHADER_PASS_DETAIL ) & & ! r_detailtextures . value ) | |
2004-10-19 15:56:22 +00:00
( ( pass2 - > flags & SHADER_PASS_DETAIL ) & & ! r_detailtextures . value ) | |
2010-08-14 00:15:07 +00:00
( pass - > flags & SHADER_PASS_VIDEOMAP ) | | ( pass2 - > flags & SHADER_PASS_VIDEOMAP ) )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
return ;
}
2011-04-30 17:21:10 +00:00
/*identity alpha is required for merging*/
if ( pass - > alphagen ! = ALPHA_GEN_IDENTITY | | pass2 - > alphagen ! = ALPHA_GEN_IDENTITY )
2004-10-19 15:56:22 +00:00
return ;
2011-04-30 17:21:10 +00:00
/*rgbgen must be identity too except if the later pass is identity_ligting, in which case all is well and we can switch the first pass to identity_lighting instead*/
if ( pass2 - > rgbgen = = RGB_GEN_IDENTITY_LIGHTING & & pass2 - > blendmode = = PBM_MODULATE & & pass - > rgbgen = = RGB_GEN_IDENTITY )
{
pass - > blendmode = PBM_REPLACELIGHT ;
pass - > rgbgen = RGB_GEN_IDENTITY_LIGHTING ;
pass2 - > rgbgen = RGB_GEN_IDENTITY ;
}
/*rgbgen must be identity (or the first is identity_lighting)*/
else if ( pass2 - > rgbgen ! = RGB_GEN_IDENTITY | | ( pass - > rgbgen ! = RGB_GEN_IDENTITY & & pass - > rgbgen ! = RGB_GEN_IDENTITY_LIGHTING ) )
2004-10-19 15:56:22 +00:00
return ;
2010-08-14 00:15:07 +00:00
/*if its alphatest, don't merge with anything other than lightmap*/
if ( ( pass - > shaderbits & SBITS_ATEST_BITS ) & & ( ! ( pass2 - > shaderbits & SBITS_MISC_DEPTHEQUALONLY ) | | pass2 - > texgen ! = T_GEN_LIGHTMAP ) )
return ;
2011-02-25 04:22:14 +00:00
if ( ( pass - > shaderbits & SBITS_MASK_BITS ) ! = ( pass2 - > shaderbits & SBITS_MASK_BITS ) )
return ;
2012-01-16 06:22:06 +00:00
/*don't merge passes if the hardware cannot support it*/
if ( pass - > numMergedPasses > = be_maxpasses )
return ;
2009-11-04 21:16:50 +00:00
// check if we can use multiple passes
2011-03-02 03:43:38 +00:00
if ( pass2 - > blendmode = = PBM_DOTPRODUCT )
2009-11-04 21:16:50 +00:00
{
pass - > numMergedPasses + + ;
}
2010-11-13 17:22:46 +00:00
else if ( pass - > numMergedPasses < be_maxpasses )
2004-10-19 15:56:22 +00:00
{
2011-04-30 17:21:10 +00:00
if ( pass - > blendmode = = PBM_REPLACE | | pass - > blendmode = = PBM_REPLACELIGHT )
2004-10-19 15:56:22 +00:00
{
2011-03-02 03:43:38 +00:00
if ( ( pass2 - > blendmode = = PBM_DECAL & & config_tex_env_combine ) | |
( pass2 - > blendmode = = PBM_ADD & & config_env_add ) | |
( pass2 - > blendmode & & pass2 - > blendmode ! = PBM_ADD ) | | config_nv_tex_env_combine4 )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
pass - > numMergedPasses + + ;
2004-10-19 15:56:22 +00:00
}
}
2011-03-02 03:43:38 +00:00
else if ( pass - > blendmode = = PBM_ADD & &
pass2 - > blendmode = = PBM_ADD & & config_env_add )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
pass - > numMergedPasses + + ;
}
2011-03-02 03:43:38 +00:00
else if ( pass - > blendmode = = PBM_MODULATE & & pass2 - > blendmode = = PBM_MODULATE )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
pass - > numMergedPasses + + ;
2004-10-19 15:56:22 +00:00
}
2011-03-02 03:43:38 +00:00
else
return ;
2004-10-19 15:56:22 +00:00
}
2011-03-02 03:43:38 +00:00
else return ;
2012-01-16 06:22:06 +00:00
if ( pass2 - > texgen = = T_GEN_LIGHTMAP & & pass2 - > blendmode = = PBM_MODULATE & & config_tex_env_combine )
2011-03-02 03:43:38 +00:00
pass2 - > blendmode = PBM_OVERBRIGHT ;
2004-10-19 15:56:22 +00:00
}
void Shader_SetFeatures ( shader_t * s )
{
int i ;
qboolean trnormals ;
shaderpass_t * pass ;
s - > features = MF_NONE ;
2010-11-26 06:58:48 +00:00
2009-11-04 21:16:50 +00:00
for ( i = 0 , trnormals = true ; i < s - > numdeforms ; i + + )
{
switch ( s - > deforms [ i ] . type )
{
2004-10-19 15:56:22 +00:00
case DEFORMV_BULGE :
case DEFORMV_WAVE :
trnormals = false ;
case DEFORMV_NORMAL :
s - > features | = MF_NORMALS ;
break ;
case DEFORMV_MOVE :
break ;
default :
trnormals = false ;
break ;
}
}
2009-11-04 21:16:50 +00:00
if ( trnormals )
{
2004-10-19 15:56:22 +00:00
s - > features | = MF_TRNORMALS ;
}
2009-11-04 21:16:50 +00:00
for ( i = 0 , pass = s - > passes ; i < s - > numpasses ; i + + , pass + + )
{
switch ( pass - > rgbgen )
{
2004-10-19 15:56:22 +00:00
case RGB_GEN_LIGHTING_DIFFUSE :
s - > features | = MF_NORMALS ;
break ;
2011-10-27 16:16:29 +00:00
case RGB_GEN_VERTEX_LIGHTING :
2004-10-19 15:56:22 +00:00
case RGB_GEN_ONE_MINUS_VERTEX :
2011-10-27 16:16:29 +00:00
case RGB_GEN_VERTEX_EXACT :
2004-10-19 15:56:22 +00:00
s - > features | = MF_COLORS ;
break ;
2004-12-09 23:42:00 +00:00
default :
break ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
switch ( pass - > alphagen )
{
2004-10-19 15:56:22 +00:00
case ALPHA_GEN_SPECULAR :
s - > features | = MF_NORMALS ;
break ;
case ALPHA_GEN_VERTEX :
s - > features | = MF_COLORS ;
break ;
2004-12-09 23:42:00 +00:00
default :
break ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
switch ( pass - > tcgen )
{
2004-10-19 15:56:22 +00:00
default :
s - > features | = MF_STCOORDS ;
break ;
case TC_GEN_LIGHTMAP :
s - > features | = MF_LMCOORDS ;
break ;
case TC_GEN_ENVIRONMENT :
2009-07-05 18:45:53 +00:00
case TC_GEN_NORMAL :
2004-10-19 15:56:22 +00:00
s - > features | = MF_NORMALS ;
break ;
2009-11-04 21:16:50 +00:00
case TC_GEN_SVECTOR :
case TC_GEN_TVECTOR :
s - > features | = MF_NORMALS ;
break ;
2004-10-19 15:56:22 +00:00
}
}
}
2009-11-04 21:16:50 +00:00
void Shader_Finish ( shader_t * s )
2004-10-19 15:56:22 +00:00
{
int i ;
shaderpass_t * pass ;
2010-12-05 02:46:07 +00:00
if ( s - > flags & SHADER_SKY )
2009-11-04 21:16:50 +00:00
{
2010-12-05 02:46:07 +00:00
/*skies go all black if fastsky is set*/
if ( r_fastsky . ival )
s - > flags = 0 ;
/*or if its purely a skybox and has missing textures*/
if ( ! s - > numpasses )
for ( i = 0 ; i < 6 ; i + + )
2011-10-27 16:16:29 +00:00
if ( missing_texture . ref = = s - > skydome - > farbox_textures [ i ] . ref )
2010-12-05 02:46:07 +00:00
s - > flags = 0 ;
if ( ! ( s - > flags & SHADER_SKY ) )
{
2011-05-20 04:10:46 +00:00
Shader_Reset ( s ) ;
2011-04-30 17:21:10 +00:00
2011-05-20 04:10:46 +00:00
Shader_DefaultScript ( s - > name , s ,
2009-11-04 21:16:50 +00:00
" { \n "
2010-12-05 02:46:07 +00:00
" sort sky \n "
" { \n "
" map $whiteimage \n "
" rgbgen const $r_fastskycolour \n "
" } \n "
" surfaceparm nodlight \n "
2009-11-04 21:16:50 +00:00
" } \n "
2010-12-05 02:46:07 +00:00
) ;
return ;
}
2004-10-19 15:56:22 +00:00
}
2011-05-20 04:10:46 +00:00
if ( TEXVALID ( s - > defaulttextures . base ) )
s - > flags & = ~ SHADER_NOIMAGE ;
2011-12-23 03:12:29 +00:00
if ( ! s - > numpasses & & s - > sort ! = SHADER_SORT_PORTAL & & ! ( s - > flags & ( SHADER_NODRAW | SHADER_SKY ) ) & & ! s - > fog_dist & & ! s - > prog )
2005-05-26 12:55:34 +00:00
{
pass = & s - > passes [ s - > numpasses + + ] ;
pass = & s - > passes [ 0 ] ;
pass - > tcgen = TC_GEN_BASE ;
2011-02-25 04:22:14 +00:00
if ( TEXVALID ( s - > defaulttextures . base ) )
pass - > texgen = T_GEN_DIFFUSE ;
else
2009-01-15 04:58:12 +00:00
{
2011-02-25 04:22:14 +00:00
pass - > texgen = T_GEN_SINGLEMAP ;
2011-10-27 16:16:29 +00:00
TEXASSIGN ( pass - > anim_frames [ 0 ] , R_LoadHiResTexture ( s - > name , NULL , IF_NOALPHA ) ) ;
2011-02-25 04:22:14 +00:00
if ( ! TEXVALID ( pass - > anim_frames [ 0 ] ) )
{
Con_Printf ( " Shader %s failed to load default texture \n " , s - > name ) ;
pass - > anim_frames [ 0 ] = missing_texture ;
}
Con_Printf ( " Shader %s with no passes and no surfaceparm nodraw, inserting pass \n " , s - > name ) ;
2009-01-15 04:58:12 +00:00
}
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2011-10-27 16:16:29 +00:00
pass - > rgbgen = RGB_GEN_VERTEX_LIGHTING ;
2005-05-26 12:55:34 +00:00
pass - > alphagen = ALPHA_GEN_IDENTITY ;
pass - > numMergedPasses = 1 ;
2009-11-04 21:16:50 +00:00
Shader_SetBlendmode ( pass ) ;
2005-05-26 12:55:34 +00:00
}
2009-11-04 21:16:50 +00:00
if ( ! Q_stricmp ( s - > name , " flareShader " ) )
{
s - > flags | = SHADER_FLARE ;
2010-11-22 02:03:28 +00:00
s - > flags | = SHADER_NODRAW ;
2009-11-04 21:16:50 +00:00
}
if ( ! s - > numpasses & & ! s - > sort )
{
2004-10-19 15:56:22 +00:00
s - > sort = SHADER_SORT_ADDITIVE ;
return ;
}
2009-11-04 21:16:50 +00:00
if ( ! s - > sort & & s - > passes - > texgen = = T_GEN_CURRENTRENDER )
s - > sort = SHADER_SORT_NEAREST ;
if ( ( s - > polyoffset . unit < 0 ) & & ! s - > sort )
{
s - > sort = SHADER_SORT_DECAL ;
2004-10-19 15:56:22 +00:00
}
2011-02-25 04:22:14 +00:00
if ( r_vertexlight . value & & ! s - > prog )
2004-10-19 15:56:22 +00:00
{
// do we have a lightmap pass?
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
if ( pass - > flags & SHADER_PASS_LIGHTMAP )
2004-10-19 15:56:22 +00:00
break ;
}
2009-11-04 21:16:50 +00:00
if ( i = = s - > numpasses )
2004-10-19 15:56:22 +00:00
{
goto done ;
}
// try to find pass with rgbgen set to RGB_GEN_VERTEX
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
2004-10-19 15:56:22 +00:00
{
2011-10-27 16:16:29 +00:00
if ( pass - > rgbgen = = RGB_GEN_VERTEX_LIGHTING )
2004-10-19 15:56:22 +00:00
break ;
}
2009-11-04 21:16:50 +00:00
if ( i < s - > numpasses )
2004-10-19 15:56:22 +00:00
{ // we found it
pass - > flags | = SHADER_CULL_FRONT ;
2009-11-04 21:16:50 +00:00
pass - > flags & = ~ SHADER_PASS_ANIMMAP ;
pass - > shaderbits & = ~ SBITS_BLEND_BITS ;
2004-10-19 15:56:22 +00:00
pass - > blendmode = 0 ;
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2004-10-19 15:56:22 +00:00
pass - > alphagen = ALPHA_GEN_IDENTITY ;
pass - > numMergedPasses = 1 ;
s - > flags | = SHADER_DEPTHWRITE ;
s - > sort = SHADER_SORT_OPAQUE ;
s - > numpasses = 1 ;
2009-11-04 21:16:50 +00:00
memcpy ( & s - > passes [ 0 ] , pass , sizeof ( shaderpass_t ) ) ;
2004-10-19 15:56:22 +00:00
}
else
{ // we didn't find it - simply remove all lightmap passes
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
if ( pass - > flags & SHADER_PASS_LIGHTMAP )
2004-10-19 15:56:22 +00:00
break ;
}
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
if ( i = = s - > numpasses - 1 )
{
s - > numpasses - - ;
}
else if ( i < s - > numpasses - 1 )
{
for ( ; i < s - > numpasses - 1 ; i + + , pass + + )
{
memcpy ( pass , & s - > passes [ i + 1 ] , sizeof ( shaderpass_t ) ) ;
}
s - > numpasses - - ;
}
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
if ( s - > passes [ 0 ] . numtcmods )
{
pass = s - > passes ;
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
{
if ( ! pass - > numtcmods )
break ;
}
2010-11-26 06:58:48 +00:00
2004-10-19 15:56:22 +00:00
memcpy ( & s - > passes [ 0 ] , pass , sizeof ( shaderpass_t ) ) ;
}
2010-11-26 06:58:48 +00:00
2011-10-27 16:16:29 +00:00
s - > passes [ 0 ] . rgbgen = RGB_GEN_VERTEX_LIGHTING ;
2004-10-19 15:56:22 +00:00
s - > passes [ 0 ] . alphagen = ALPHA_GEN_IDENTITY ;
s - > passes [ 0 ] . blendmode = 0 ;
2009-11-04 21:16:50 +00:00
s - > passes [ 0 ] . flags & = ~ ( SHADER_PASS_ANIMMAP | SHADER_PASS_NOCOLORARRAY ) ;
pass - > shaderbits & = ~ SBITS_BLEND_BITS ;
s - > passes [ 0 ] . shaderbits | = SBITS_MISC_DEPTHWRITE ;
2004-10-19 15:56:22 +00:00
s - > passes [ 0 ] . numMergedPasses = 1 ;
s - > numpasses = 1 ;
s - > flags | = SHADER_DEPTHWRITE ;
}
}
done : ;
2012-01-17 07:57:46 +00:00
for ( pass = s - > passes , i = 0 ; i < s - > numpasses ; i + + , pass + + )
{
if ( ( pass - > texgen = = T_GEN_ANIMMAP | | pass - > texgen = = T_GEN_SINGLEMAP ) & & ! TEXVALID ( s - > defaulttextures . base ) )
s - > defaulttextures . base = pass - > anim_frames [ 0 ] ;
2012-01-18 04:15:16 +00:00
# ifndef NOMEDIA
2012-01-17 07:57:46 +00:00
if ( pass - > texgen = = T_GEN_VIDEOMAP & & pass - > cin & & ! TEXVALID ( s - > defaulttextures . base ) )
s - > defaulttextures . base = Media_UpdateForShader ( pass - > cin ) ;
2012-01-18 04:15:16 +00:00
# endif
2012-01-17 07:57:46 +00:00
}
2004-10-19 15:56:22 +00:00
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
{
2011-02-25 04:22:14 +00:00
if ( ! ( pass - > shaderbits & ( SBITS_BLEND_BITS | SBITS_MASK_BITS ) ) )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
break ;
}
}
// all passes have blendfuncs
2009-11-04 21:16:50 +00:00
if ( i = = s - > numpasses )
{
2004-10-19 15:56:22 +00:00
int opaque ;
opaque = - 1 ;
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; i + + , pass + + )
{
2010-07-11 02:22:39 +00:00
if ( pass - > shaderbits & SBITS_ATEST_BITS )
2009-11-04 21:16:50 +00:00
{
2004-10-19 15:56:22 +00:00
opaque = i ;
}
2009-11-04 21:16:50 +00:00
if ( pass - > rgbgen = = RGB_GEN_UNKNOWN )
2010-11-26 06:58:48 +00:00
{
2011-10-27 16:16:29 +00:00
if ( ( pass - > shaderbits & SBITS_SRCBLEND_BITS ) = = 0
| | ( pass - > shaderbits & SBITS_SRCBLEND_BITS ) = = SBITS_SRCBLEND_ONE
| | ( pass - > shaderbits & SBITS_SRCBLEND_BITS ) = = SBITS_SRCBLEND_SRC_ALPHA )
2004-10-19 15:56:22 +00:00
pass - > rgbgen = RGB_GEN_IDENTITY_LIGHTING ;
else
pass - > rgbgen = RGB_GEN_IDENTITY ;
}
2009-11-04 21:16:50 +00:00
Shader_SetBlendmode ( pass ) ;
2012-01-01 11:22:24 +00:00
if ( pass - > blendmode = = PBM_ADD )
s - > defaulttextures . fullbright = pass - > anim_frames [ 0 ] ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
if ( ! ( s - > flags & SHADER_SKY ) & & ! s - > sort )
{
if ( opaque = = - 1 )
2010-07-11 02:22:39 +00:00
s - > sort = SHADER_SORT_BLEND ;
2004-10-19 15:56:22 +00:00
else
2010-07-11 02:22:39 +00:00
s - > sort = SHADER_SORT_SEETHROUGH ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
}
else
{
2004-10-19 15:56:22 +00:00
int j ;
shaderpass_t * sp ;
sp = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( j = 0 ; j < s - > numpasses ; j + + , sp + + )
{
if ( sp - > rgbgen = = RGB_GEN_UNKNOWN )
2010-11-26 06:58:48 +00:00
{
2011-04-30 17:21:10 +00:00
if ( sp - > flags & SHADER_PASS_LIGHTMAP )
sp - > rgbgen = RGB_GEN_IDENTITY_LIGHTING ;
else
sp - > rgbgen = RGB_GEN_IDENTITY ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
Shader_SetBlendmode ( sp ) ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
if ( ! s - > sort )
{
if ( pass - > shaderbits & SBITS_ATEST_BITS )
2010-07-11 02:22:39 +00:00
s - > sort = SHADER_SORT_SEETHROUGH ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
if ( ! ( s - > flags & SHADER_DEPTHWRITE ) & &
! ( s - > flags & SHADER_SKY ) )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2004-10-19 15:56:22 +00:00
s - > flags | = SHADER_DEPTHWRITE ;
}
}
2009-11-04 21:16:50 +00:00
if ( s - > numpasses > = 2 )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
int j ;
2004-10-19 15:56:22 +00:00
pass = s - > passes ;
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < s - > numpasses ; )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
if ( i = = s - > numpasses - 1 )
2004-10-19 15:56:22 +00:00
break ;
pass = s - > passes + i ;
2009-11-04 21:16:50 +00:00
for ( j = 1 ; j < s - > numpasses - i & & j = = i + pass - > numMergedPasses & & j < be_maxpasses ; j + + )
Shader_SetPassFlush ( pass , pass + j ) ;
2004-10-19 15:56:22 +00:00
i + = pass - > numMergedPasses ;
}
}
2009-11-04 21:16:50 +00:00
if ( ! s - > sort )
{
2004-10-19 15:56:22 +00:00
s - > sort = SHADER_SORT_OPAQUE ;
}
2009-11-04 21:16:50 +00:00
if ( ( s - > flags & SHADER_SKY ) & & ( s - > flags & SHADER_DEPTHWRITE ) )
{
2004-10-19 15:56:22 +00:00
s - > flags & = ~ SHADER_DEPTHWRITE ;
}
2011-02-25 04:22:14 +00:00
if ( s - > prog )
2006-03-11 03:12:10 +00:00
{
if ( ! s - > numpasses )
s - > numpasses = 1 ;
s - > passes - > numMergedPasses = s - > numpasses ;
}
2009-11-04 21:16:50 +00:00
Shader_SetFeatures ( s ) ;
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
# ifdef FORCEGLSL
BE_GenerateProgram ( s ) ;
# endif
2004-10-19 15:56:22 +00:00
}
/*
void Shader_UpdateRegistration ( void )
{
int i , j , l ;
shader_t * shader ;
shaderpass_t * pass ;
shader = r_shaders ;
for ( i = 0 ; i < MAX_SHADERS ; i + + , shader + + )
{
2009-11-04 21:16:50 +00:00
if ( ! shader - > registration_sequence )
2004-10-19 15:56:22 +00:00
continue ;
2009-11-04 21:16:50 +00:00
if ( shader - > registration_sequence ! = registration_sequence )
{
2004-10-19 15:56:22 +00:00
Shader_Free ( shader ) ;
shader - > registration_sequence = 0 ;
continue ;
}
pass = shader - > passes ;
for ( j = 0 ; j < shader - > numpasses ; j + + , pass + + )
{
2009-11-04 21:16:50 +00:00
if ( pass - > flags & SHADER_PASS_ANIMMAP )
{
2010-11-26 06:58:48 +00:00
for ( l = 0 ; l < pass - > anim_numframes ; l + + )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
if ( pass - > anim_frames [ l ] )
2004-10-19 15:56:22 +00:00
pass - > anim_frames [ l ] - > registration_sequence = registration_sequence ;
}
2009-11-04 21:16:50 +00:00
}
else if ( pass - > flags & SHADER_PASS_VIDEOMAP )
{
2004-10-19 15:56:22 +00:00
// Shader_RunCinematic will do the job
// pass->cin->frame = -1;
2009-11-04 21:16:50 +00:00
}
else if ( ! ( pass - > flags & SHADER_PASS_LIGHTMAP ) )
{
2004-10-19 15:56:22 +00:00
if ( pass - > anim_frames [ 0 ] )
pass - > anim_frames [ 0 ] - > registration_sequence = registration_sequence ;
2010-11-26 06:58:48 +00:00
}
2004-10-19 15:56:22 +00:00
}
}
}
*/
2009-11-04 21:16:50 +00:00
void R_BuildDefaultTexnums ( texnums_t * tn , shader_t * shader )
2004-10-19 15:56:22 +00:00
{
2012-02-12 05:18:31 +00:00
if ( ! tn )
tn = & shader - > defaulttextures ;
2012-01-17 07:57:46 +00:00
if ( ! TEXVALID ( shader - > defaulttextures . base ) )
2011-05-20 04:10:46 +00:00
{
2012-01-17 07:57:46 +00:00
/*dlights/realtime lighting needs some stuff*/
if ( ! TEXVALID ( tn - > base ) )
{
tn - > base = R_LoadHiResTexture ( shader - > name , NULL , IF_NOALPHA ) ;
}
if ( TEXVALID ( tn - > base ) )
shader - > flags & = ~ SHADER_NOIMAGE ;
TEXASSIGN ( shader - > defaulttextures . base , tn - > base ) ;
2011-05-20 04:10:46 +00:00
}
2004-10-19 15:56:22 +00:00
2012-01-17 07:57:46 +00:00
if ( ! TEXVALID ( shader - > defaulttextures . bump ) )
2010-07-18 12:52:24 +00:00
{
2012-01-17 07:57:46 +00:00
if ( r_loadbumpmapping )
{
if ( ! TEXVALID ( tn - > bump ) )
tn - > bump = R_LoadHiResTexture ( va ( " %s_norm " , shader - > name ) , NULL , IF_NOALPHA ) ;
if ( ! TEXVALID ( tn - > bump ) )
tn - > bump = R_LoadHiResTexture ( va ( " %s_bump " , shader - > name ) , NULL , IF_NOALPHA ) ;
if ( ! TEXVALID ( tn - > bump ) )
tn - > bump = R_LoadHiResTexture ( va ( " normalmaps/%s " , shader - > name ) , NULL , IF_NOALPHA ) ;
}
TEXASSIGN ( shader - > defaulttextures . bump , tn - > bump ) ;
2010-07-18 12:52:24 +00:00
}
2012-01-17 07:57:46 +00:00
if ( ! TEXVALID ( shader - > defaulttextures . loweroverlay ) )
2010-07-18 12:52:24 +00:00
{
2012-01-17 07:57:46 +00:00
if ( shader - > flags & SHADER_HASTOPBOTTOM )
{
if ( ! TEXVALID ( tn - > loweroverlay ) )
tn - > loweroverlay = R_LoadHiResTexture ( va ( " %s_pants " , shader - > name ) , NULL , 0 ) ; /*how rude*/
}
TEXASSIGN ( shader - > defaulttextures . loweroverlay , tn - > loweroverlay ) ;
}
if ( ! TEXVALID ( shader - > defaulttextures . upperoverlay ) )
{
if ( shader - > flags & SHADER_HASTOPBOTTOM )
{
if ( ! TEXVALID ( tn - > upperoverlay ) )
tn - > upperoverlay = R_LoadHiResTexture ( va ( " %s_shirt " , shader - > name ) , NULL , 0 ) ;
}
TEXASSIGN ( shader - > defaulttextures . upperoverlay , tn - > upperoverlay ) ;
2010-07-18 12:52:24 +00:00
}
2004-10-19 15:56:22 +00:00
2012-01-17 07:57:46 +00:00
if ( ! TEXVALID ( shader - > defaulttextures . specular ) )
TEXASSIGN ( shader - > defaulttextures . specular , tn - > specular ) ;
if ( ! TEXVALID ( shader - > defaulttextures . fullbright ) )
TEXASSIGN ( shader - > defaulttextures . fullbright , tn - > fullbright ) ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_DefaultScript ( char * shortname , shader_t * s , const void * args )
2005-03-20 02:57:11 +00:00
{
2009-11-04 21:16:50 +00:00
const char * f = args ;
if ( ! args )
return ;
while ( * f = = ' ' | | * f = = ' \t ' | | * f = = ' \n ' | | * f = = ' \r ' )
f + + ;
if ( * f = = ' { ' )
2009-07-18 20:46:42 +00:00
{
2009-11-04 21:16:50 +00:00
f + + ;
2011-12-05 15:23:40 +00:00
Shader_ReadShader ( s , ( void * ) f , SPM_DEFAULT ) ;
2009-07-18 20:46:42 +00:00
}
2009-11-04 21:16:50 +00:00
} ;
2009-07-18 20:46:42 +00:00
2010-07-11 02:22:39 +00:00
void Shader_DefaultBSPLM ( char * shortname , shader_t * s , const void * args )
2009-11-04 21:16:50 +00:00
{
char * builtin = NULL ;
2010-07-11 02:22:39 +00:00
if ( ! builtin & & r_drawflat . value )
builtin = (
" { \n "
2011-12-23 03:12:29 +00:00
" program drawflat_wall \n "
2010-07-11 02:22:39 +00:00
" { \n "
" map $lightmap \n "
" tcgen lightmap \n "
" rgbgen const $r_floorcolour \n "
" } \n "
" } \n "
) ;
2011-01-23 03:44:49 +00:00
# ifdef GLQUAKE
2011-12-23 03:12:29 +00:00
if ( qrenderer = = QR_OPENGL )
2010-08-28 17:14:38 +00:00
{
2011-12-23 03:12:29 +00:00
if ( ! builtin & & r_lightprepass . ival )
{
builtin = (
2010-08-28 17:14:38 +00:00
" { \n "
2011-12-23 03:12:29 +00:00
" program lpp_wall \n "
" { \n "
" map $sourcecolour \n "
" } \n "
" { \n "
" map $diffuse \n "
" } \n "
" { \n "
" map $lightmap \n "
" } \n "
" { \n "
" map $normalmap \n "
" } \n "
" { \n "
" map $deluxmap \n "
" } \n "
" { \n "
" map $fullbright \n "
" } \n "
2010-08-28 17:14:38 +00:00
" } \n "
2011-12-23 03:12:29 +00:00
) ;
}
if ( ! builtin & & gl_config . arb_shader_objects )
{
builtin = (
2010-08-28 17:14:38 +00:00
" { \n "
2011-12-23 03:12:29 +00:00
" program defaultwall \n "
/*"param texture 0 tex_diffuse\n"
" param texture 1 tex_lightmap \n "
" param texture 2 tex_normalmap \n "
" param texture 3 tex_deluxmap \n "
" param texture 4 tex_fullbright \n " */
" { \n "
" map $diffuse \n "
" } \n "
" { \n "
" map $lightmap \n "
" } \n "
" { \n "
" map $normalmap \n "
" } \n "
" { \n "
" map $deluxmap \n "
" } \n "
" { \n "
" map $fullbright \n "
" } \n "
2010-08-28 17:14:38 +00:00
" } \n "
2011-12-23 03:12:29 +00:00
) ;
}
2010-08-28 17:14:38 +00:00
}
2011-01-23 03:44:49 +00:00
# endif
2010-07-11 02:22:39 +00:00
if ( ! builtin )
builtin = (
" { \n "
2011-04-30 17:21:10 +00:00
" if $deluxmap \n "
2010-07-11 02:22:39 +00:00
" [ \n "
" { \n "
" map $normalmap \n "
" tcgen base \n "
2010-07-18 08:42:59 +00:00
" depthwrite \n "
2010-07-11 02:22:39 +00:00
" } \n "
" { \n "
" map $deluxmap \n "
" tcgen lightmap \n "
" } \n "
" ] \n "
" { \n "
" map $diffuse \n "
" tcgen base \n "
2011-10-27 16:16:29 +00:00
" if $deluxmap \n "
2010-07-18 08:42:59 +00:00
" [ \n "
" blendfunc gl_one gl_zero \n "
" ] \n "
2010-07-11 02:22:39 +00:00
" } \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" if !r_fullbright \n "
2010-07-11 02:22:39 +00:00
" [ \n "
" { \n "
" map $lightmap \n "
" blendfunc gl_dst_color gl_zero \n "
" } \n "
" ] \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" if gl_fb_bmodels \n "
2010-07-18 08:42:59 +00:00
" [ \n "
" { \n "
" map $fullbright \n "
" blendfunc add \n "
" depthfunc equal \n "
" } \n "
" ] \n "
2010-07-11 02:22:39 +00:00
" } \n "
) ;
Shader_DefaultScript ( shortname , s , builtin ) ;
}
void Shader_DefaultCinematic ( char * shortname , shader_t * s , const void * args )
{
Shader_DefaultScript ( shortname , s ,
va (
" { \n "
" { \n "
" videomap %s \n "
" } \n "
" } \n "
2011-01-29 19:53:38 +00:00
, ( const char * ) args )
2010-07-11 02:22:39 +00:00
) ;
}
/*shortname should begin with 'skybox_'*/
void Shader_DefaultSkybox ( char * shortname , shader_t * s , const void * args )
{
Shader_DefaultScript ( shortname , s ,
va (
" { \n "
" skyparms %s - - \n "
" } \n "
, shortname + 7 )
) ;
}
void Shader_DefaultBSPQ2 ( char * shortname , shader_t * s , const void * args )
{
if ( ! strncmp ( shortname , " sky/ " , 4 ) )
2009-07-18 20:46:42 +00:00
{
2010-07-11 02:22:39 +00:00
Shader_DefaultScript ( shortname , s ,
" { \n "
2011-04-20 03:31:41 +00:00
" surfaceparm nodlight \n "
2010-07-11 02:22:39 +00:00
" skyparms - - - \n "
" } \n "
) ;
2009-07-18 20:46:42 +00:00
}
2011-04-20 03:31:41 +00:00
else if ( ! strncmp ( shortname , " warp/ " , 5 ) )
2010-07-11 02:22:39 +00:00
{
Shader_DefaultScript ( shortname , s ,
" { \n "
2011-04-20 03:31:41 +00:00
" program defaultwarp \n "
2010-07-11 02:22:39 +00:00
" { \n "
" map $diffuse \n "
2011-04-20 23:34:13 +00:00
" tcmod turb 0 0.01 0.5 0 \n "
2010-07-11 02:22:39 +00:00
" } \n "
" } \n "
) ;
}
else if ( ! strncmp ( shortname , " warp33/ " , 7 ) )
{
Shader_DefaultScript ( shortname , s ,
" { \n "
" { \n "
" map $diffuse \n "
" tcmod turb 0 0.01 0.5 0 \n "
" alphagen const 0.333 \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
}
else if ( ! strncmp ( shortname , " warp66/ " , 7 ) )
{
Shader_DefaultScript ( shortname , s ,
" { \n "
" { \n "
" map $diffuse \n "
" tcmod turb 0 0.01 0.5 0 \n "
" alphagen const 0.666 \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
}
else if ( ! strncmp ( shortname , " trans/ " , 7 ) )
Shader_DefaultScript ( shortname , s ,
" { \n "
" { \n "
" map $diffuse \n "
" alphagen const 1 \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
else if ( ! strncmp ( shortname , " trans33/ " , 7 ) )
Shader_DefaultScript ( shortname , s ,
" { \n "
" { \n "
" map $diffuse \n "
" alphagen const 0.333 \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
else if ( ! strncmp ( shortname , " trans66/ " , 7 ) )
Shader_DefaultScript ( shortname , s ,
" { \n "
" { \n "
" map $diffuse \n "
" alphagen const 0.666 \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
else
Shader_DefaultBSPLM ( shortname , s , args ) ;
}
2009-07-18 20:46:42 +00:00
2010-07-11 02:22:39 +00:00
void Shader_DefaultBSPQ1 ( char * shortname , shader_t * s , const void * args )
{
char * builtin = NULL ;
if ( r_mirroralpha . value < 1 & & ! strcmp ( shortname , " window02_1 " ) )
2005-03-20 02:57:11 +00:00
{
2010-07-11 02:22:39 +00:00
if ( r_mirroralpha . value < 0 )
2009-06-21 17:45:33 +00:00
{
2010-07-11 02:22:39 +00:00
builtin = " { \n "
" portal \n "
" { \n "
" map $diffuse \n "
" blendfunc blend \n "
" alphagen portal 512 \n "
" depthwrite \n "
" } \n "
" } \n " ;
2009-06-21 17:45:33 +00:00
}
2006-03-06 01:41:09 +00:00
else
2010-07-11 02:22:39 +00:00
{
builtin = " { \n "
" portal \n "
" { \n "
" map $diffuse \n "
" blendfunc blend \n "
" alphagen const $r_mirroralpha \n "
" depthwrite \n "
" } \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" surfaceparm nodlight \n "
2010-07-11 02:22:39 +00:00
" } \n " ;
}
2006-03-06 01:41:09 +00:00
2005-03-20 02:57:11 +00:00
}
2006-03-06 01:41:09 +00:00
2009-11-04 21:16:50 +00:00
if ( ! builtin & & ( * shortname = = ' * ' ) )
2009-07-18 20:46:42 +00:00
{
2009-11-04 21:16:50 +00:00
//q1 water
2010-11-22 02:03:28 +00:00
if ( r_wateralpha . value = = 0 )
{
builtin = (
" { \n "
2010-11-28 19:10:34 +00:00
" sort blend \n "
2010-11-22 02:03:28 +00:00
" surfaceparm nodraw \n "
" surfaceparm nodlight \n "
" } \n "
) ;
}
else if ( r_fastturb . ival )
2009-07-18 20:46:42 +00:00
{
2010-07-11 02:22:39 +00:00
builtin = (
" { \n "
2010-11-28 19:10:34 +00:00
" sort blend \n "
2009-11-04 21:16:50 +00:00
" { \n "
2010-07-11 02:22:39 +00:00
" map $whiteimage \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" rgbgen const $r_fastturbcolour \n "
2009-11-04 21:16:50 +00:00
" } \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" surfaceparm nodlight \n "
2010-07-11 02:22:39 +00:00
" } \n "
) ;
2009-11-04 21:16:50 +00:00
}
2011-03-12 13:51:40 +00:00
else
2010-07-11 02:22:39 +00:00
{
2009-11-04 21:16:50 +00:00
builtin = (
" { \n "
2011-01-23 03:44:49 +00:00
" sort blend \n " /*make sure it always has the same sort order, so switching on/off wateralpha doesn't break stuff*/
" program defaultwarp \n "
2011-02-25 04:22:14 +00:00
" { \n "
" map $diffuse \n "
2011-04-20 23:34:13 +00:00
" tcmod turb 0.02 0.1 0.5 0.1 \n "
2011-02-25 04:22:14 +00:00
" if r_wateralpha != 1 \n "
" [ \n "
2011-03-12 13:51:40 +00:00
" alphagen const $r_wateralpha \n "
2010-11-10 03:32:47 +00:00
" blendfunc gl_src_alpha gl_one_minus_src_alpha \n "
2011-02-25 04:22:14 +00:00
" ] \n "
" } \n "
2009-11-04 21:16:50 +00:00
" surfaceparm nodlight \n "
" } \n "
) ;
2006-03-06 01:41:09 +00:00
}
2009-11-04 21:16:50 +00:00
}
if ( ! builtin & & ! strncmp ( shortname , " sky " , 3 ) )
2005-03-20 02:57:11 +00:00
{
2009-11-04 21:16:50 +00:00
//q1 sky
if ( r_fastsky . ival )
2010-12-05 02:46:07 +00:00
{
2009-11-04 21:16:50 +00:00
builtin = (
" { \n "
2010-11-28 19:10:34 +00:00
" sort sky \n "
2009-11-04 21:16:50 +00:00
" { \n "
" map $whiteimage \n "
2010-07-11 02:22:39 +00:00
" rgbgen const $r_fastskycolour \n "
2009-11-04 21:16:50 +00:00
" } \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" surfaceparm nodlight \n "
2009-11-04 21:16:50 +00:00
" } \n "
) ;
2010-12-05 02:46:07 +00:00
}
2009-11-04 21:16:50 +00:00
else if ( * r_skyboxname . string )
2010-12-05 02:46:07 +00:00
{
2009-11-04 21:16:50 +00:00
builtin = (
" { \n "
2010-11-28 19:10:34 +00:00
" sort sky \n "
2009-11-04 21:16:50 +00:00
" skyparms $r_skybox - - \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" surfaceparm nodlight \n "
2009-11-04 21:16:50 +00:00
" } \n "
) ;
2010-12-05 02:46:07 +00:00
Shader_DefaultScript ( shortname , s , builtin ) ;
if ( s - > flags & SHADER_SKY )
return ;
builtin = NULL ;
/*if the r_skybox failed to load or whatever, reset and fall through and just use the regular sky*/
2011-05-20 04:10:46 +00:00
Shader_Reset ( s ) ;
2010-12-05 02:46:07 +00:00
}
if ( ! builtin )
2010-07-11 02:22:39 +00:00
builtin = (
" { \n "
2010-11-28 19:10:34 +00:00
" sort sky \n "
2011-03-31 02:32:32 +00:00
" program defaultsky \n "
2010-07-11 02:22:39 +00:00
" skyparms - 512 - \n "
/*WARNING: these values are not authentic quake, only close aproximations*/
" { \n "
" map $diffuse \n "
" tcmod scale 10 10 \n "
" tcmod scroll 0.04 0.04 \n "
2012-02-14 15:50:34 +00:00
" depthwrite \n "
2010-07-11 02:22:39 +00:00
" } \n "
" { \n "
" map $fullbright \n "
" blendfunc blend \n "
" tcmod scale 10 10 \n "
" tcmod scroll 0.02 0.02 \n "
" } \n "
" } \n "
) ;
2009-11-04 21:16:50 +00:00
}
if ( ! builtin & & * shortname = = ' { ' )
2006-03-06 01:41:09 +00:00
{
2009-11-04 21:16:50 +00:00
/*alpha test*/
builtin = (
" { \n "
/* "if $deluxmap\n"
" [ \n "
" { \n "
" map $normalmap \n "
" tcgen base \n "
" } \n "
" { \n "
" map $deluxmap \n "
" tcgen lightmap \n "
" } \n "
" ] \n " */
" { \n "
" map $diffuse \n "
" tcgen base \n "
" alphamask \n "
" } \n "
" if $lightmap \n "
" [ \n "
" { \n "
" map $lightmap \n "
" blendfunc gl_dst_color gl_zero \n "
" depthfunc equal \n "
" } \n "
" ] \n "
" { \n "
" map $fullbright \n "
" blendfunc add \n "
" depthfunc equal \n "
" } \n "
" } \n "
) ;
}
/*Hack: note that halflife would normally expect you to use rendermode/renderampt*/
2010-07-11 02:22:39 +00:00
if ( ! builtin & & ( ! strncmp ( shortname , " glass " , 5 ) /* || !strncmp(shortname, "window", 6)*/ ) )
2005-05-26 12:55:34 +00:00
{
2009-11-04 21:16:50 +00:00
/*alpha bended*/
builtin = (
" { \n "
" { \n "
" map $diffuse \n "
" tcgen base \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
}
2010-07-11 02:22:39 +00:00
if ( builtin )
Shader_DefaultScript ( shortname , s , builtin ) ;
else
Shader_DefaultBSPLM ( shortname , s , args ) ;
2009-11-04 21:16:50 +00:00
}
void Shader_DefaultBSPVertex ( char * shortname , shader_t * s , const void * args )
2005-03-20 02:57:11 +00:00
{
shaderpass_t * pass ;
2011-12-05 15:23:40 +00:00
s - > defaulttextures . base = R_LoadHiResTexture ( va ( " %s_d.tga " , shortname ) , NULL , 0 ) ;
2005-03-20 02:57:11 +00:00
pass = & s - > passes [ 0 ] ;
pass - > tcgen = TC_GEN_BASE ;
2009-11-04 21:16:50 +00:00
pass - > shaderbits | = SBITS_MISC_DEPTHWRITE ;
2011-10-27 16:16:29 +00:00
pass - > rgbgen = RGB_GEN_VERTEX_LIGHTING ;
2005-03-20 02:57:11 +00:00
pass - > alphagen = ALPHA_GEN_IDENTITY ;
pass - > numMergedPasses = 1 ;
2009-11-04 21:16:50 +00:00
Shader_SetBlendmode ( pass ) ;
2005-03-20 02:57:11 +00:00
2011-12-05 15:23:40 +00:00
if ( TEXVALID ( s - > defaulttextures . base ) )
2009-11-04 21:16:50 +00:00
{
2011-12-05 15:23:40 +00:00
pass - > texgen = T_GEN_DIFFUSE ;
}
else
{
pass - > anim_frames [ 0 ] = R_LoadHiResTexture ( shortname , NULL , 0 ) ;
if ( ! TEXVALID ( pass - > anim_frames [ 0 ] ) )
{
Con_DPrintf ( CON_WARNING " Shader %s has a stage with no image: %s. \n " , s - > name , shortname ) ;
pass - > anim_frames [ 0 ] = missing_texture ;
}
2005-03-20 02:57:11 +00:00
}
s - > numpasses = 1 ;
s - > numdeforms = 0 ;
s - > flags = SHADER_DEPTHWRITE | SHADER_CULL_FRONT ;
2009-11-04 21:16:50 +00:00
s - > features = MF_STCOORDS | MF_COLORS ;
2005-03-20 02:57:11 +00:00
s - > sort = SHADER_SORT_OPAQUE ;
2010-07-11 02:22:39 +00:00
s - > uses = 1 ;
2005-03-20 02:57:11 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_DefaultBSPFlare ( char * shortname , shader_t * s , const void * args )
2005-03-20 02:57:11 +00:00
{
shaderpass_t * pass ;
pass = & s - > passes [ 0 ] ;
2009-11-04 21:16:50 +00:00
pass - > flags = SHADER_PASS_NOCOLORARRAY ;
pass - > shaderbits | = SBITS_SRCBLEND_ONE | SBITS_DSTBLEND_ONE ;
pass - > anim_frames [ 0 ] = R_LoadHiResTexture ( shortname , NULL , 0 ) ;
2011-10-27 16:16:29 +00:00
pass - > rgbgen = RGB_GEN_VERTEX_LIGHTING ;
2005-03-20 02:57:11 +00:00
pass - > alphagen = ALPHA_GEN_IDENTITY ;
pass - > numtcmods = 0 ;
pass - > tcgen = TC_GEN_BASE ;
pass - > numMergedPasses = 1 ;
2009-11-04 21:16:50 +00:00
Shader_SetBlendmode ( pass ) ;
2005-03-20 02:57:11 +00:00
2009-11-04 21:16:50 +00:00
if ( ! TEXVALID ( pass - > anim_frames [ 0 ] ) )
{
2007-09-23 15:28:06 +00:00
Con_DPrintf ( CON_WARNING " Shader %s has a stage with no image: %s. \n " , s - > name , shortname ) ;
2006-03-06 01:41:09 +00:00
pass - > anim_frames [ 0 ] = missing_texture ;
2005-03-20 02:57:11 +00:00
}
s - > numpasses = 1 ;
s - > numdeforms = 0 ;
s - > flags = SHADER_FLARE ;
s - > features = MF_STCOORDS | MF_COLORS ;
s - > sort = SHADER_SORT_ADDITIVE ;
2010-07-11 02:22:39 +00:00
s - > uses = 1 ;
2010-11-22 02:03:28 +00:00
s - > flags | = SHADER_NODRAW ;
2005-03-20 02:57:11 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_DefaultSkin ( char * shortname , shader_t * s , const void * args )
{
2010-11-26 06:58:48 +00:00
Shader_DefaultScript ( shortname , s ,
2009-11-04 21:16:50 +00:00
" { \n "
2011-09-03 03:49:43 +00:00
" if $lpp \n "
" [ \n "
" program lpp_skin \n "
2011-12-23 03:12:29 +00:00
" ][ \n "
" program defaultskin \n "
2011-09-03 03:49:43 +00:00
" ] \n "
2009-11-04 21:16:50 +00:00
" { \n "
" map $diffuse \n "
" rgbgen lightingDiffuse \n "
" } \n "
" { \n "
" map $loweroverlay \n "
" rgbgen bottomcolor \n "
2010-07-11 02:22:39 +00:00
" blendfunc gl_src_alpha gl_one \n "
2009-11-04 21:16:50 +00:00
" } \n "
" { \n "
" map $upperoverlay \n "
2010-07-11 02:22:39 +00:00
" rgbgen topcolor \n "
" blendfunc gl_src_alpha gl_one \n "
2009-11-04 21:16:50 +00:00
" } \n "
" { \n "
" map $fullbright \n "
" blendfunc add \n "
" } \n "
" } \n "
) ;
}
void Shader_DefaultSkinShell ( char * shortname , shader_t * s , const void * args )
2005-03-20 02:57:11 +00:00
{
2011-04-23 20:37:20 +00:00
Shader_DefaultScript ( shortname , s ,
" { \n "
" sort blend \n "
" deformvertexes normal 1 1 \n "
" { \n "
" map $diffuse \n "
" rgbgen entity \n "
" alphagen entity \n "
" blendfunc blend \n "
" } \n "
" } \n "
) ;
2005-03-20 02:57:11 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_Default2D ( char * shortname , shader_t * s , const void * genargs )
2005-03-20 02:57:11 +00:00
{
2010-11-26 06:58:48 +00:00
Shader_DefaultScript ( shortname , s ,
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" { \n "
2011-05-20 04:10:46 +00:00
" if $nofixed \n "
" [ \n "
" program default2d \n "
" ] \n "
2010-11-02 23:17:25 +00:00
" nomipmaps \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" { \n "
2010-11-22 02:03:28 +00:00
" clampmap $diffuse \n "
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
" rgbgen vertex \n "
" alphagen vertex \n "
" blendfunc gl_src_alpha gl_one_minus_src_alpha \n "
" } \n "
" sort additive \n "
" } \n "
) ;
2011-10-27 16:16:29 +00:00
TEXASSIGN ( s - > defaulttextures . base , R_LoadHiResTexture ( shortname , NULL , IF_NOPICMIP | IF_NOMIPMAP | IF_CLAMP ) ) ;
2010-11-02 23:17:25 +00:00
if ( ! TEXVALID ( s - > defaulttextures . base ) )
{
unsigned char data [ 4 * 4 ] = { 0 } ;
2011-10-27 16:16:29 +00:00
TEXASSIGN ( s - > defaulttextures . base , R_LoadTexture8 ( " black " , 4 , 4 , data , 0 , 0 ) ) ;
2011-05-20 04:10:46 +00:00
s - > flags | = SHADER_NOIMAGE ;
}
else
{
s - > flags & = ~ SHADER_NOIMAGE ;
s - > width = image_width ;
s - > height = image_height ;
2010-11-02 23:17:25 +00:00
}
2005-03-20 02:57:11 +00:00
}
2009-11-04 21:16:50 +00:00
//loads a shader string into an existing shader object, and finalises it and stuff
2011-12-05 15:23:40 +00:00
static void Shader_ReadShader ( shader_t * s , char * shadersource , int parsemode )
2009-11-04 21:16:50 +00:00
{
char * token ;
2011-12-05 15:23:40 +00:00
shaderparsemode = parsemode ;
2009-11-04 21:16:50 +00:00
// set defaults
s - > flags = SHADER_CULL_FRONT ;
2010-07-11 02:22:39 +00:00
s - > uses = 1 ;
2009-11-04 21:16:50 +00:00
while ( shadersource )
{
token = COM_ParseExt ( & shadersource , true ) ;
if ( ! token [ 0 ] )
continue ;
else if ( token [ 0 ] = = ' } ' )
break ;
else if ( ! Q_stricmp ( token , " if " ) )
{
2011-03-12 13:51:40 +00:00
int nest = 0 ;
2009-11-04 21:16:50 +00:00
qboolean conditionistrue = Shader_EvaluateCondition ( & shadersource ) ;
while ( shadersource )
{
token = COM_ParseExt ( & shadersource , true ) ;
if ( ! token [ 0 ] )
continue ;
2011-03-12 13:51:40 +00:00
else if ( token [ 0 ] = = ' ] ' )
{
if ( - - nest < = 0 )
{
nest + + ;
if ( ! strcmp ( token , " ][ " ) )
conditionistrue = ! conditionistrue ;
else
break ;
}
}
else if ( token [ 0 ] = = ' [ ' )
nest + + ;
2009-11-04 21:16:50 +00:00
else if ( conditionistrue )
{
if ( token [ 0 ] = = ' { ' )
Shader_Readpass ( s , & shadersource ) ;
else
Shader_Parsetok ( s , NULL , shaderkeys , token , & shadersource ) ;
}
}
}
else if ( token [ 0 ] = = ' { ' )
Shader_Readpass ( s , & shadersource ) ;
else if ( Shader_Parsetok ( s , NULL , shaderkeys , token , & shadersource ) )
break ;
}
Shader_Finish ( s ) ;
}
2010-07-11 02:22:39 +00:00
static qboolean Shader_ParseShader ( char * shortname , char * usename , shader_t * s )
2006-03-11 03:12:10 +00:00
{
unsigned int offset = 0 , length ;
char path [ MAX_QPATH ] ;
char * buf = NULL , * ts = NULL ;
2011-12-05 15:23:40 +00:00
int parsemode = SPM_DEFAULT ;
2006-03-11 03:12:10 +00:00
Shader_GetPathAndOffset ( shortname , & ts , & offset ) ;
if ( ts )
{
2011-12-05 15:23:40 +00:00
if ( ! strcmp ( COM_FileExtension ( ts ) , " mtr " ) )
parsemode = SPM_DOOM3 ;
2006-03-11 03:12:10 +00:00
Com_sprintf ( path , sizeof ( path ) , " %s " , ts ) ;
length = FS_LoadFile ( path , ( void * * ) & buf ) ;
}
else
length = 0 ;
// the shader is in the shader scripts
if ( ts & & buf & & ( offset < length ) )
{
char * file , * token ;
file = buf + offset ;
token = COM_ParseExt ( & file , true ) ;
if ( ! file | | token [ 0 ] ! = ' { ' )
{
FS_FreeFile ( buf ) ;
return false ;
}
2011-05-20 04:10:46 +00:00
Shader_Reset ( s ) ;
2006-03-11 03:12:10 +00:00
2011-12-05 15:23:40 +00:00
Shader_ReadShader ( s , file , parsemode ) ;
2006-03-11 03:12:10 +00:00
FS_FreeFile ( buf ) ;
return true ;
}
if ( buf )
FS_FreeFile ( buf ) ;
return false ;
}
2010-07-11 02:22:39 +00:00
void R_UnloadShader ( shader_t * shader )
{
if ( shader - > uses - - = = 1 )
Shader_Free ( shader ) ;
}
static int R_LoadShader ( char * name , shader_gen_t * defaultgen , const char * genargs )
2004-10-19 15:56:22 +00:00
{
int i , f = - 1 ;
2006-03-11 03:12:10 +00:00
char shortname [ MAX_QPATH ] ;
2004-10-19 15:56:22 +00:00
shader_t * s ;
2011-05-20 04:10:46 +00:00
if ( ! * name )
name = " gfx/white " ;
* ( int * ) shortname = 0 ;
2006-03-11 03:12:10 +00:00
COM_StripExtension ( name , shortname , sizeof ( shortname ) ) ;
2004-10-19 15:56:22 +00:00
2005-08-26 22:56:51 +00:00
COM_CleanUpPath ( shortname ) ;
2010-07-11 02:22:39 +00:00
// check the hash first
s = Hash_Get ( & shader_active_hash , shortname ) ;
if ( s )
{
i = s - r_shaders ;
r_shaders [ i ] . uses + + ;
return i ;
}
// not loaded, find a free slot
2004-10-19 15:56:22 +00:00
for ( i = 0 ; i < MAX_SHADERS ; i + + )
{
2010-07-11 02:22:39 +00:00
if ( ! r_shaders [ i ] . uses )
2004-10-19 15:56:22 +00:00
{
if ( f = = - 1 ) // free shader
2010-07-11 02:22:39 +00:00
{
2004-10-19 15:56:22 +00:00
f = i ;
2010-07-11 02:22:39 +00:00
break ;
}
2004-10-19 15:56:22 +00:00
}
}
if ( f = = - 1 )
{
Sys_Error ( " R_LoadShader: Shader limit exceeded. " ) ;
return f ;
}
s = & r_shaders [ f ] ;
2011-05-20 04:10:46 +00:00
Q_strncpyz ( s - > name , shortname , sizeof ( s - > name ) ) ;
s - > generator = defaultgen ;
2011-12-05 15:23:40 +00:00
if ( genargs )
s - > genargs = strdup ( genargs ) ;
else
s - > genargs = NULL ;
2011-05-20 04:10:46 +00:00
2009-11-04 21:16:50 +00:00
if ( ruleset_allow_shaders . ival )
2004-10-19 15:56:22 +00:00
{
2009-11-04 21:16:50 +00:00
# ifdef GLQUAKE
2011-01-23 03:44:49 +00:00
if ( qrenderer = = QR_OPENGL )
{
if ( gl_config . gles & & gl_config . glversion > = 2 )
{
if ( Shader_ParseShader ( va ( " %s_gles2 " , shortname ) , shortname , s ) )
{
return f ;
}
}
if ( gl_config . glversion > = 3 )
{
if ( Shader_ParseShader ( va ( " %s_glsl3 " , shortname ) , shortname , s ) )
{
return f ;
}
}
if ( gl_config . arb_shader_objects )
{
if ( Shader_ParseShader ( va ( " %s_glsl " , shortname ) , shortname , s ) )
{
return f ;
}
}
}
# endif
# ifdef D3DQUAKE
if ( qrenderer = = QR_DIRECT3D )
2009-11-04 21:16:50 +00:00
{
{
2011-01-23 03:44:49 +00:00
if ( Shader_ParseShader ( va ( " %s_hlsl " , shortname ) , shortname , s ) )
{
return f ;
}
2009-11-04 21:16:50 +00:00
}
}
# endif
if ( Shader_ParseShader ( shortname , shortname , s ) )
{
2006-03-11 03:12:10 +00:00
return f ;
2009-11-04 21:16:50 +00:00
}
2006-03-11 03:12:10 +00:00
}
2004-10-19 15:56:22 +00:00
2006-03-11 03:12:10 +00:00
// make a default shader
2004-10-19 15:56:22 +00:00
2011-05-20 04:10:46 +00:00
if ( s - > generator )
2004-10-19 15:56:22 +00:00
{
2011-05-20 04:10:46 +00:00
Shader_Reset ( s ) ;
2011-02-25 04:22:14 +00:00
if ( ! strcmp ( shortname , " textures/common/clip " ) )
2011-05-15 13:23:13 +00:00
Shader_DefaultScript ( shortname , s ,
2011-02-25 04:22:14 +00:00
" { \n "
" surfaceparm nodraw \n "
" surfaceparm nodlight \n "
" } \n " ) ;
else
2011-05-20 04:10:46 +00:00
s - > generator ( shortname , s , s - > genargs ) ;
2006-03-11 03:12:10 +00:00
return f ;
}
2011-05-20 04:10:46 +00:00
else
{
2011-12-05 15:23:40 +00:00
Shader_Free ( s ) ;
2011-05-20 04:10:46 +00:00
}
2006-03-11 03:12:10 +00:00
return - 1 ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
void Shader_DoReload ( void )
{
shader_t * s ;
unsigned int i ;
char shortname [ MAX_QPATH ] ;
2010-07-11 02:22:39 +00:00
if ( shader_rescan_needed & & ruleset_allow_shaders . ival )
{
2011-02-25 04:22:14 +00:00
COM_EnumerateFiles ( " materials/*.mtr " , Shader_InitCallback , NULL ) ;
2010-07-11 02:22:39 +00:00
COM_EnumerateFiles ( " shaders/*.shader " , Shader_InitCallback , NULL ) ;
COM_EnumerateFiles ( " scripts/*.shader " , Shader_InitCallback , NULL ) ;
2011-03-02 03:43:38 +00:00
COM_EnumerateFiles ( " scripts/*.rscript " , Shader_InitCallback , NULL ) ;
2010-07-11 02:22:39 +00:00
shader_reload_needed = true ;
shader_rescan_needed = false ;
}
2009-11-04 21:16:50 +00:00
if ( ! shader_reload_needed )
return ;
shader_reload_needed = false ;
2010-03-14 14:35:56 +00:00
Font_InvalidateColour ( ) ;
2009-11-04 21:16:50 +00:00
for ( s = r_shaders , i = 0 ; i < MAX_SHADERS ; i + + , s + + )
{
2010-07-11 02:22:39 +00:00
if ( ! s - > uses )
2009-11-04 21:16:50 +00:00
continue ;
strcpy ( shortname , s - > name ) ;
if ( ruleset_allow_shaders . ival )
{
# ifdef GLQUAKE
if ( qrenderer = = QR_OPENGL & & gl_config . arb_shader_objects )
{
if ( Shader_ParseShader ( va ( " %s_glsl " , shortname ) , shortname , s ) )
{
continue ;
}
}
# endif
if ( Shader_ParseShader ( shortname , shortname , s ) )
{
continue ;
}
}
if ( s - > generator )
{
2011-05-20 04:10:46 +00:00
Shader_Reset ( s ) ;
2010-12-05 02:46:07 +00:00
2011-05-20 04:10:46 +00:00
s - > generator ( shortname , s , s - > genargs ) ;
2009-11-04 21:16:50 +00:00
}
}
}
2011-12-05 15:23:40 +00:00
void Shader_NeedReload ( qboolean rescanfs )
2009-11-04 21:16:50 +00:00
{
2011-12-05 15:23:40 +00:00
if ( rescanfs )
shader_rescan_needed = true ;
2009-11-04 21:16:50 +00:00
shader_reload_needed = true ;
}
2010-07-11 02:22:39 +00:00
cin_t * R_ShaderGetCinematic ( shader_t * s )
{
# ifndef NOMEDIA
int j ;
if ( ! s )
return NULL ;
for ( j = 0 ; j < s - > numpasses ; j + + )
if ( s - > passes [ j ] . cin )
return s - > passes [ j ] . cin ;
# endif
/*no cinematic in this shader!*/
return NULL ;
}
cin_t * R_ShaderFindCinematic ( char * name )
2008-11-09 22:29:28 +00:00
{
2009-11-04 21:16:50 +00:00
# ifdef NOMEDIA
return NULL ;
# else
2010-07-11 02:22:39 +00:00
int i ;
char shortname [ MAX_QPATH ] ;
2008-11-09 22:29:28 +00:00
COM_StripExtension ( name , shortname , sizeof ( shortname ) ) ;
COM_CleanUpPath ( shortname ) ;
//try and find it
for ( i = 0 ; i < MAX_SHADERS ; i + + )
{
2010-07-11 02:22:39 +00:00
if ( ! r_shaders [ i ] . uses )
2008-11-09 22:29:28 +00:00
continue ;
if ( ! Q_stricmp ( shortname , r_shaders [ i ] . name ) )
break ;
}
if ( i = = MAX_SHADERS )
return NULL ;
2010-07-11 02:22:39 +00:00
//found the named shader.
return R_ShaderGetCinematic ( & r_shaders [ i ] ) ;
2009-11-04 21:16:50 +00:00
# endif
2008-11-09 22:29:28 +00:00
}
2010-11-26 06:58:48 +00:00
shader_t * R_RegisterPic ( char * name )
2004-10-19 15:56:22 +00:00
{
2011-12-26 15:19:13 +00:00
shader_t * shader ;
/*don't get confused by other shaders*/
image_width = 64 ;
image_height = 64 ;
shader = & r_shaders [ R_LoadShader ( name , Shader_Default2D , NULL ) ] ;
/*worth a try*/
if ( shader - > width < = 0 )
shader - > width = image_width ;
if ( shader - > height < = 0 )
shader - > height = image_height ;
/*last ditch attempt*/
if ( shader - > width < = 0 )
shader - > width = 64 ;
if ( shader - > height < = 0 )
shader - > height = 64 ;
return shader ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
shader_t * R_RegisterShader ( char * name , const char * shaderscript )
{
return & r_shaders [ R_LoadShader ( name , Shader_DefaultScript , shaderscript ) ] ;
}
shader_t * R_RegisterShader_Lightmap ( char * name )
2004-10-19 15:56:22 +00:00
{
2010-07-11 02:22:39 +00:00
return & r_shaders [ R_LoadShader ( name , Shader_DefaultBSPLM , NULL ) ] ;
2004-10-19 15:56:22 +00:00
}
shader_t * R_RegisterShader_Vertex ( char * name )
{
2009-06-21 17:45:33 +00:00
return & r_shaders [ R_LoadShader ( name , Shader_DefaultBSPVertex , NULL ) ] ;
2004-10-19 15:56:22 +00:00
}
shader_t * R_RegisterShader_Flare ( char * name )
{
2009-06-21 17:45:33 +00:00
return & r_shaders [ R_LoadShader ( name , Shader_DefaultBSPFlare , NULL ) ] ;
2004-10-19 15:56:22 +00:00
}
2011-07-30 14:14:56 +00:00
shader_t * R_RegisterSkin ( char * shadername , char * modname )
2004-10-19 15:56:22 +00:00
{
2011-07-30 14:14:56 +00:00
shader_t * shader ;
if ( modname & & ! strchr ( shadername , ' / ' ) )
{
char newsname [ MAX_QPATH ] ;
char * b = COM_SkipPath ( modname ) ;
if ( b ! = modname & & b - modname + strlen ( shadername ) + 1 < sizeof ( newsname ) )
{
memcpy ( newsname , modname , b - modname ) ;
memcpy ( newsname + ( b - modname ) , shadername , strlen ( shadername ) + 1 ) ;
/*if the specified shader does not contain a path, try and load one relative to the name of the model*/
shader = & r_shaders [ R_LoadShader ( newsname , Shader_DefaultSkin , NULL ) ] ;
R_BuildDefaultTexnums ( & shader - > defaulttextures , shader ) ;
/*if its a valid shader with valid textures, use it*/
if ( ! ( shader - > flags & SHADER_NOIMAGE ) )
return shader ;
}
}
shader = & r_shaders [ R_LoadShader ( shadername , Shader_DefaultSkin , NULL ) ] ;
return shader ;
2005-03-20 02:57:11 +00:00
}
2009-11-04 21:16:50 +00:00
shader_t * R_RegisterCustom ( char * name , shader_gen_t * defaultgen , const void * args )
2005-03-20 02:57:11 +00:00
{
2005-08-03 23:14:59 +00:00
int i ;
2009-06-21 17:45:33 +00:00
i = R_LoadShader ( name , defaultgen , args ) ;
2005-08-03 23:14:59 +00:00
if ( i < 0 )
return NULL ;
return & r_shaders [ i ] ;
2004-10-19 15:56:22 +00:00
}
2009-11-04 21:16:50 +00:00
# endif //SERVERONLY