r_wireframe. requires cheats.

omni shadowmaps should work, but do still have issues.
added colour tints to terrain, and clipped decals.
fixed issue where fixed-function shaders were getting drawn with the glsl rendering functions.
tweeked mvd recording code a little. don't use until next mvd-related commit.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4100 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-08-04 01:35:52 +00:00
parent 7135c3ee19
commit 197f716f75
34 changed files with 1360 additions and 714 deletions

View file

@ -116,12 +116,10 @@ static void CL_ClearDlight(dlight_t *dl, int key)
{ {
void *sm; void *sm;
texid_t st; texid_t st;
TEXASSIGNF(st, dl->stexture);
sm = dl->worldshadowmesh; sm = dl->worldshadowmesh;
memset (dl, 0, sizeof(*dl)); memset (dl, 0, sizeof(*dl));
dl->rebuildcache = true; dl->rebuildcache = true;
dl->worldshadowmesh = sm; dl->worldshadowmesh = sm;
TEXASSIGNF(dl->stexture, st);
dl->axis[0][0] = 1; dl->axis[0][0] = 1;
dl->axis[1][1] = 1; dl->axis[1][1] = 1;
dl->axis[2][2] = 1; dl->axis[2][2] = 1;
@ -873,10 +871,10 @@ void CL_ParsePacketEntities (qboolean delta)
if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD) if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD)
{ {
extern float nextdemotime; extern float olddemotime; //time from the most recent demo packet
cl.oldgametime = cl.gametime; cl.oldgametime = cl.gametime;
cl.oldgametimemark = cl.gametimemark; cl.oldgametimemark = cl.gametimemark;
cl.gametime = nextdemotime; cl.gametime = olddemotime;
cl.gametimemark = realtime; cl.gametimemark = realtime;
} }
else if (!(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS) && cls.protocol == CP_QUAKEWORLD) else if (!(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS) && cls.protocol == CP_QUAKEWORLD)
@ -2872,6 +2870,8 @@ void CL_LinkPacketEntities (void)
// angles[1] += sin(realtime)*8; // angles[1] += sin(realtime)*8;
// angles[0] += cos(realtime*1.13)*5; // angles[0] += cos(realtime*1.13)*5;
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorMA(dl->origin, 16, dl->axis[0], dl->origin);
} }
// add automatic particle trails // add automatic particle trails
@ -4146,7 +4146,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
if (playertime > realtime) if (playertime > realtime)
playertime = realtime; playertime = realtime;
if (cl_nopred.value || /*cls.demoplayback ||*/ cl.paused) if (cl_nopred.value || /*cls.demoplayback ||*/ cl.paused || cl.worldmodel->needload)
return; return;
frame = &cl.frames[cl.parsecount&UPDATE_MASK]; frame = &cl.frames[cl.parsecount&UPDATE_MASK];

View file

@ -665,7 +665,10 @@ void CL_CalcClientTime(void)
max = cl.gametime; max = cl.gametime;
min = cl.oldgametime; min = cl.oldgametime;
cl.servertime += host_frametime; if (max)
cl.servertime += host_frametime;
else
cl.servertime = 0;
if (cl.servertime > max) if (cl.servertime > max)
{ {

View file

@ -2282,10 +2282,8 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
// //
// draw any areas not covered by the refresh // draw any areas not covered by the refresh
// //
#ifdef GLQUAKE if (r_netgraph.value)
if (r_netgraph.value && qrenderer == QR_OPENGL)
GLR_NetGraph (); GLR_NetGraph ();
#endif
if (scr_drawloading || loading_stage) if (scr_drawloading || loading_stage)
{ {

View file

@ -274,7 +274,6 @@ typedef struct dlight_s
//the following are used for rendering (client code should clear on create) //the following are used for rendering (client code should clear on create)
qboolean rebuildcache; qboolean rebuildcache;
struct shadowmesh_s *worldshadowmesh; struct shadowmesh_s *worldshadowmesh;
texid_t stexture;
texid_t cubetexture; texid_t cubetexture;
struct { struct {
float updatetime; float updatetime;

View file

@ -887,6 +887,8 @@ void CLQ3_SendCmd(usercmd_t *cmd)
ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime); ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime);
cl.servertime = ccs.serverTime / 1000.0f; cl.servertime = ccs.serverTime / 1000.0f;
cl.gametime = cl.oldgametime = cl.servertime;
//reuse the q1 array //reuse the q1 array
cmd->servertime = ccs.serverTime; cmd->servertime = ccs.serverTime;
cmd->weapon = ccs.selected_weapon; cmd->weapon = ccs.selected_weapon;

View file

@ -3119,6 +3119,422 @@ void TTS_Say_f(void)
{ {
TTS_SayAsciiString(Cmd_Args()); TTS_SayAsciiString(Cmd_Args());
} }
#define ISpRecognizer void
#define SPPHRASE void
#define SPSERIALIZEDPHRASE void
#define SPSTATEHANDLE void*
#define SPGRAMMARWORDTYPE int
#define SPPROPERTYINFO void
#define SPLOADOPTIONS void*
#define SPBINARYGRAMMAR void*
#define SPRULESTATE int
#define SPTEXTSELECTIONINFO void
#define SPWORDPRONOUNCEABLE void
#define SPGRAMMARSTATE int
typedef struct ISpRecoResult ISpRecoResult;
typedef struct ISpRecoContext ISpRecoContext;
typedef struct ISpRecoGrammar ISpRecoGrammar;
typedef struct ISpRecoContextVtbl
{
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISpRecoContext * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISpRecoContext * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISpRecoContext * This);
HRESULT ( STDMETHODCALLTYPE *SetNotifySink )(
ISpRecoContext * This,
/* [in] */ ISpNotifySink *pNotifySink);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetNotifyWindowMessage )(
ISpRecoContext * This,
/* [in] */ HWND hWnd,
/* [in] */ UINT Msg,
/* [in] */ WPARAM wParam,
/* [in] */ LPARAM lParam);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetNotifyCallbackFunction )(
ISpRecoContext * This,
/* [in] */ SPNOTIFYCALLBACK *pfnCallback,
/* [in] */ WPARAM wParam,
/* [in] */ LPARAM lParam);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetNotifyCallbackInterface )(
ISpRecoContext * This,
/* [in] */ ISpNotifyCallback *pSpCallback,
/* [in] */ WPARAM wParam,
/* [in] */ LPARAM lParam);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetNotifyWin32Event )(
ISpRecoContext * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *WaitForNotifyEvent )(
ISpRecoContext * This,
/* [in] */ DWORD dwMilliseconds);
/* [local] */ HANDLE ( STDMETHODCALLTYPE *GetNotifyEventHandle )(
ISpRecoContext * This);
HRESULT ( STDMETHODCALLTYPE *SetInterest )(
ISpRecoContext * This,
/* [in] */ ULONGLONG ullEventInterest,
/* [in] */ ULONGLONG ullQueuedInterest);
HRESULT ( STDMETHODCALLTYPE *GetEvents )(
ISpRecoContext * This,
/* [in] */ ULONG ulCount,
/* [size_is][out] */ SPEVENT *pEventArray,
/* [out] */ ULONG *pulFetched);
HRESULT ( STDMETHODCALLTYPE *GetInfo )(
ISpRecoContext * This,
/* [out] */ SPEVENTSOURCEINFO *pInfo);
HRESULT ( STDMETHODCALLTYPE *GetRecognizer )(
ISpRecoContext * This,
/* [out] */ ISpRecognizer **ppRecognizer);
HRESULT ( STDMETHODCALLTYPE *CreateGrammar )(
ISpRecoContext * This,
/* [in] */ ULONGLONG ullGrammarId,
/* [out] */ ISpRecoGrammar **ppGrammar);
} ISpRecoContextVtbl;
struct ISpRecoContext
{
struct ISpRecoContextVtbl *lpVtbl;
};
typedef struct ISpRecoResultVtbl
{
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISpRecoResult * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISpRecoResult * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISpRecoResult * This);
HRESULT ( STDMETHODCALLTYPE *GetPhrase )(
ISpRecoResult * This,
/* [out] */ SPPHRASE **ppCoMemPhrase);
HRESULT ( STDMETHODCALLTYPE *GetSerializedPhrase )(
ISpRecoResult * This,
/* [out] */ SPSERIALIZEDPHRASE **ppCoMemPhrase);
HRESULT ( STDMETHODCALLTYPE *GetText )(
ISpRecoResult * This,
/* [in] */ ULONG ulStart,
/* [in] */ ULONG ulCount,
/* [in] */ BOOL fUseTextReplacements,
/* [out] */ WCHAR **ppszCoMemText,
/* [out] */ BYTE *pbDisplayAttributes);
HRESULT ( STDMETHODCALLTYPE *Discard )(
ISpRecoResult * This,
/* [in] */ DWORD dwValueTypes);
#if 0
HRESULT ( STDMETHODCALLTYPE *GetResultTimes )(
ISpRecoResult * This,
/* [out] */ SPRECORESULTTIMES *pTimes);
HRESULT ( STDMETHODCALLTYPE *GetAlternates )(
ISpRecoResult * This,
/* [in] */ ULONG ulStartElement,
/* [in] */ ULONG cElements,
/* [in] */ ULONG ulRequestCount,
/* [out] */ ISpPhraseAlt **ppPhrases,
/* [out] */ ULONG *pcPhrasesReturned);
HRESULT ( STDMETHODCALLTYPE *GetAudio )(
ISpRecoResult * This,
/* [in] */ ULONG ulStartElement,
/* [in] */ ULONG cElements,
/* [out] */ ISpStreamFormat **ppStream);
HRESULT ( STDMETHODCALLTYPE *SpeakAudio )(
ISpRecoResult * This,
/* [in] */ ULONG ulStartElement,
/* [in] */ ULONG cElements,
/* [in] */ DWORD dwFlags,
/* [out] */ ULONG *pulStreamNumber);
HRESULT ( STDMETHODCALLTYPE *Serialize )(
ISpRecoResult * This,
/* [out] */ SPSERIALIZEDRESULT **ppCoMemSerializedResult);
HRESULT ( STDMETHODCALLTYPE *ScaleAudio )(
ISpRecoResult * This,
/* [in] */ const GUID *pAudioFormatId,
/* [in] */ const WAVEFORMATEX *pWaveFormatEx);
HRESULT ( STDMETHODCALLTYPE *GetRecoContext )(
ISpRecoResult * This,
/* [out] */ ISpRecoContext **ppRecoContext);
#endif
} ISpRecoResultVtbl;
struct ISpRecoResult
{
struct ISpRecoResultVtbl *lpVtbl;
};
typedef struct ISpRecoGrammarVtbl
{
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISpRecoGrammar * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISpRecoGrammar * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISpRecoGrammar * This);
HRESULT ( STDMETHODCALLTYPE *ResetGrammar )(
ISpRecoGrammar * This,
/* [in] */ WORD NewLanguage);
HRESULT ( STDMETHODCALLTYPE *GetRule )(
ISpRecoGrammar * This,
/* [in] */ const WCHAR *pszRuleName,
/* [in] */ DWORD dwRuleId,
/* [in] */ DWORD dwAttributes,
/* [in] */ BOOL fCreateIfNotExist,
/* [out] */ SPSTATEHANDLE *phInitialState);
HRESULT ( STDMETHODCALLTYPE *ClearRule )(
ISpRecoGrammar * This,
SPSTATEHANDLE hState);
HRESULT ( STDMETHODCALLTYPE *CreateNewState )(
ISpRecoGrammar * This,
SPSTATEHANDLE hState,
SPSTATEHANDLE *phState);
HRESULT ( STDMETHODCALLTYPE *AddWordTransition )(
ISpRecoGrammar * This,
SPSTATEHANDLE hFromState,
SPSTATEHANDLE hToState,
const WCHAR *psz,
const WCHAR *pszSeparators,
SPGRAMMARWORDTYPE eWordType,
float Weight,
const SPPROPERTYINFO *pPropInfo);
HRESULT ( STDMETHODCALLTYPE *AddRuleTransition )(
ISpRecoGrammar * This,
SPSTATEHANDLE hFromState,
SPSTATEHANDLE hToState,
SPSTATEHANDLE hRule,
float Weight,
const SPPROPERTYINFO *pPropInfo);
HRESULT ( STDMETHODCALLTYPE *AddResource )(
ISpRecoGrammar * This,
/* [in] */ SPSTATEHANDLE hRuleState,
/* [in] */ const WCHAR *pszResourceName,
/* [in] */ const WCHAR *pszResourceValue);
HRESULT ( STDMETHODCALLTYPE *Commit )(
ISpRecoGrammar * This,
DWORD dwReserved);
HRESULT ( STDMETHODCALLTYPE *GetGrammarId )(
ISpRecoGrammar * This,
/* [out] */ ULONGLONG *pullGrammarId);
HRESULT ( STDMETHODCALLTYPE *GetRecoContext )(
ISpRecoGrammar * This,
/* [out] */ ISpRecoContext **ppRecoCtxt);
HRESULT ( STDMETHODCALLTYPE *LoadCmdFromFile )(
ISpRecoGrammar * This,
/* [string][in] */ const WCHAR *pszFileName,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *LoadCmdFromObject )(
ISpRecoGrammar * This,
/* [in] */ REFCLSID rcid,
/* [string][in] */ const WCHAR *pszGrammarName,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *LoadCmdFromResource )(
ISpRecoGrammar * This,
/* [in] */ HMODULE hModule,
/* [string][in] */ const WCHAR *pszResourceName,
/* [string][in] */ const WCHAR *pszResourceType,
/* [in] */ WORD wLanguage,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *LoadCmdFromMemory )(
ISpRecoGrammar * This,
/* [in] */ const SPBINARYGRAMMAR *pGrammar,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *LoadCmdFromProprietaryGrammar )(
ISpRecoGrammar * This,
/* [in] */ REFGUID rguidParam,
/* [string][in] */ const WCHAR *pszStringParam,
/* [in] */ const void *pvDataPrarm,
/* [in] */ ULONG cbDataSize,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *SetRuleState )(
ISpRecoGrammar * This,
/* [string][in] */ const WCHAR *pszName,
void *pReserved,
/* [in] */ SPRULESTATE NewState);
HRESULT ( STDMETHODCALLTYPE *SetRuleIdState )(
ISpRecoGrammar * This,
/* [in] */ ULONG ulRuleId,
/* [in] */ SPRULESTATE NewState);
HRESULT ( STDMETHODCALLTYPE *LoadDictation )(
ISpRecoGrammar * This,
/* [string][in] */ const WCHAR *pszTopicName,
/* [in] */ SPLOADOPTIONS Options);
HRESULT ( STDMETHODCALLTYPE *UnloadDictation )(
ISpRecoGrammar * This);
HRESULT ( STDMETHODCALLTYPE *SetDictationState )(
ISpRecoGrammar * This,
/* [in] */ SPRULESTATE NewState);
HRESULT ( STDMETHODCALLTYPE *SetWordSequenceData )(
ISpRecoGrammar * This,
/* [in] */ const WCHAR *pText,
/* [in] */ ULONG cchText,
/* [in] */ const SPTEXTSELECTIONINFO *pInfo);
HRESULT ( STDMETHODCALLTYPE *SetTextSelection )(
ISpRecoGrammar * This,
/* [in] */ const SPTEXTSELECTIONINFO *pInfo);
HRESULT ( STDMETHODCALLTYPE *IsPronounceable )(
ISpRecoGrammar * This,
/* [string][in] */ const WCHAR *pszWord,
/* [out] */ SPWORDPRONOUNCEABLE *pWordPronounceable);
HRESULT ( STDMETHODCALLTYPE *SetGrammarState )(
ISpRecoGrammar * This,
/* [in] */ SPGRAMMARSTATE eGrammarState);
HRESULT ( STDMETHODCALLTYPE *SaveCmd )(
ISpRecoGrammar * This,
/* [in] */ IStream *pStream,
/* [optional][out] */ WCHAR **ppszCoMemErrorText);
HRESULT ( STDMETHODCALLTYPE *GetGrammarState )(
ISpRecoGrammar * This,
/* [out] */ SPGRAMMARSTATE *peGrammarState);
} ISpRecoGrammarVtbl;
struct ISpRecoGrammar
{
struct ISpRecoGrammarVtbl *lpVtbl;
};
static ISpRecoContext *stt_recctx = NULL;
static ISpRecoGrammar *stt_gram = NULL;
void STT_Event(void)
{
WCHAR *wstring, *i;
struct SPEVENT ev;
ISpRecoResult *rr;
HRESULT hr;
char asc[2048], *o;
int l;
unsigned short c;
char *nib = "0123456789abcdef";
if (!stt_gram)
return;
while (SUCCEEDED(hr = stt_recctx->lpVtbl->GetEvents(stt_recctx, 1, &ev, NULL)) && hr != S_FALSE)
{
rr = (ISpRecoResult*)ev.lParam;
rr->lpVtbl->GetText(rr, -1, -1, TRUE, &wstring, NULL);
for (l = sizeof(asc)-1, o = asc, i = wstring; l > 0 && *i; )
{
c = *i++;
if (c == '\n' || c == ';')
{
}
else if (c < 128)
{
*o++ = c;
l--;
}
else if (l > 6)
{
*o++ = '^';
*o++ = 'U';
*o++ = nib[(c>>12)&0xf];
*o++ = nib[(c>>8)&0xf];
*o++ = nib[(c>>4)&0xf];
*o++ = nib[(c>>0)&0xf];
}
else
break;
}
*o = 0;
CoTaskMemFree(wstring);
Cbuf_AddText("say tts ", RESTRICT_LOCAL);
Cbuf_AddText(asc, RESTRICT_LOCAL);
Cbuf_AddText("\n", RESTRICT_LOCAL);
rr->lpVtbl->Release(rr);
}
}
void STT_Init_f(void)
{
static CLSID CLSID_SpSharedRecoContext = {0x47206204, 0x5ECA, 0x11D2, 0x96, 0x0F, 0x00, 0xC0, 0x4F, 0x8E, 0xE6, 0x28};
static CLSID IID_SpRecoContext = {0xF740A62F, 0x7C15, 0x489E, 0x82, 0x34, 0x94, 0x0A, 0x33, 0xD9, 0x27, 0x2D};
if (stt_gram)
{
stt_gram->lpVtbl->Release(stt_gram);
stt_recctx->lpVtbl->Release(stt_recctx);
stt_gram = NULL;
stt_recctx = NULL;
Con_Printf("Speech-to-text disabled\n");
return;
}
if (SUCCEEDED(CoCreateInstance(&CLSID_SpSharedRecoContext, NULL, CLSCTX_SERVER, &IID_SpRecoContext, &stt_recctx)))
{
ULONGLONG ev = (((ULONGLONG)1) << 38) | (((ULONGLONG)1) << 30) | (((ULONGLONG)1) << 33);
if (SUCCEEDED(stt_recctx->lpVtbl->SetNotifyWindowMessage(stt_recctx, mainwindow, WM_USER, 0, 0)))
if (SUCCEEDED(stt_recctx->lpVtbl->SetInterest(stt_recctx, ev, ev)))
if (SUCCEEDED(stt_recctx->lpVtbl->CreateGrammar(stt_recctx, 0, &stt_gram)))
{
if (SUCCEEDED(stt_gram->lpVtbl->LoadDictation(stt_gram, NULL, 0)))
if (SUCCEEDED(stt_gram->lpVtbl->SetDictationState(stt_gram, 1)))
{
//success!
Con_Printf("Speech-to-text active\n");
return;
}
stt_gram->lpVtbl->Release(stt_gram);
}
stt_recctx->lpVtbl->Release(stt_recctx);
}
stt_gram = NULL;
stt_recctx = NULL;
Con_Printf("Speech-to-text unavailable\n");
}
#endif #endif
qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed); qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed);
@ -3127,6 +3543,7 @@ void Media_Init(void)
{ {
#ifdef _WIN32 #ifdef _WIN32
Cmd_AddCommand("tts", TTS_Say_f); Cmd_AddCommand("tts", TTS_Say_f);
Cmd_AddCommand("stt", STT_Init_f);
Cvar_Register(&tts_mode, "Gimmicks"); Cvar_Register(&tts_mode, "Gimmicks");
#endif #endif

View file

@ -212,16 +212,17 @@ typedef enum uploadfmt
//not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented) //not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented)
typedef enum backendmode_e typedef enum backendmode_e
{ {
BEM_STANDARD, //regular mode to draw surfaces akin to q3 (aka: legacy mode). lightmaps+delux+ambient BEM_STANDARD, //regular mode to draw surfaces akin to q3 (aka: legacy mode). lightmaps+delux+ambient
BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps). BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps).
BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer. BEM_WIREFRAME, //for debugging or something
BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal. BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer.
BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal.
BEM_CREPUSCULAR, //sky is special, everything else completely black BEM_CREPUSCULAR, //sky is special, everything else completely black
BEM_DEPTHNORM, //all opaque stuff drawn using 'depthnorm' shader BEM_DEPTHNORM, //all opaque stuff drawn using 'depthnorm' shader
BEM_LIGHT, //we have a valid light BEM_LIGHT, //we have a valid light
BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap
BEM_SMAPLIGHT, //we have a light using a shadowmap BEM_SMAPLIGHT, //we have a light using a shadowmap
BEM_FOG //drawing a fog volume BEM_FOG //drawing a fog volume
} backendmode_t; } backendmode_t;
typedef struct rendererinfo_s { typedef struct rendererinfo_s {

View file

@ -73,6 +73,8 @@ cvar_t r_bouncysparks = CVARFD ("r_bouncysparks", "0",
cvar_t r_drawentities = CVAR ("r_drawentities", "1"); cvar_t r_drawentities = CVAR ("r_drawentities", "1");
cvar_t r_drawflat = CVARF ("r_drawflat", "0", cvar_t r_drawflat = CVARF ("r_drawflat", "0",
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM); CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
cvar_t r_wireframe = CVARF ("r_wireframe", "0",
CVAR_CHEAT);
cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0"); cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0");
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE); cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0"); cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
@ -595,6 +597,7 @@ void Renderer_Init(void)
Cvar_Register (&r_sun_dir, GRAPHICALNICETIES); Cvar_Register (&r_sun_dir, GRAPHICALNICETIES);
Cvar_Register (&r_sun_colour, GRAPHICALNICETIES); Cvar_Register (&r_sun_colour, GRAPHICALNICETIES);
Cvar_Register (&r_waterstyle, GRAPHICALNICETIES); Cvar_Register (&r_waterstyle, GRAPHICALNICETIES);
Cvar_Register (&r_wireframe, GRAPHICALNICETIES);
Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_viewsize, SCREENOPTIONS);
Cvar_Register(&scr_fov, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS);

View file

@ -132,9 +132,9 @@ void RQ_Init(void)
if (initialque) if (initialque)
return; return;
initialque = (renderque_t *) Hunk_AllocName (rquesize * sizeof(renderque_t), "renderque"); initialque = (renderque_t *) Z_Malloc (rquesize * sizeof(renderque_t));
freerque = &initialque[0]; freerque = &initialque[0];
activerque = NULL; activerque = NULL;

View file

@ -638,7 +638,6 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel, char *data, char *mapname) //a
} }
else if (!strcmp("fog", key)) else if (!strcmp("fog", key))
{ {
char *s;
void CL_Fog_f(void); void CL_Fog_f(void);
key[0] = 'f'; key[0] = 'f';
key[1] = ' '; key[1] = ' ';

View file

@ -398,7 +398,7 @@ typedef struct q2miptex_s
#define MAX_Q2MAP_EDGES 128000 #define MAX_Q2MAP_EDGES 128000
#define MAX_Q2MAP_SURFEDGES 256000 #define MAX_Q2MAP_SURFEDGES 256000
#define MAX_Q2MAP_LIGHTING 0x200000 #define MAX_Q2MAP_LIGHTING 0x200000
#define MAX_Q2MAP_VISIBILITY MAX_MAP_VISIBILITY //#define MAX_Q2MAP_VISIBILITY MAX_MAP_VISIBILITY
// key / value pair sizes // key / value pair sizes

View file

@ -2593,6 +2593,17 @@ void FS_StartupWithGame(int gamenum)
COM_Gamedir(com_argv[i+1]); COM_Gamedir(com_argv[i+1]);
} }
#if 1//def ANDROID
{
vfsfile_t *f;
//write a .nomedia file to avoid people from getting random explosion sounds etc intersperced with their music
f = FS_OpenVFS(".nomedia", "rb", FS_ROOT);
if (f)
VFS_CLOSE(f);
else
FS_WriteFile(".nomedia", NULL, 0, FS_ROOT);
}
#endif
if (gamemode_info[gamenum].customexec) if (gamemode_info[gamenum].customexec)
Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL); Cbuf_AddText(gamemode_info[gamenum].customexec, RESTRICT_LOCAL);

View file

@ -1093,7 +1093,8 @@ void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node)
#define MAXFRAGMENTTRIS 256 #define MAXFRAGMENTTRIS 256
vec3_t decalfragmentverts[MAXFRAGMENTTRIS*3]; vec3_t decalfragmentverts[MAXFRAGMENTTRIS*3];
typedef struct { struct fragmentdecal_s
{
vec3_t center; vec3_t center;
vec3_t normal; vec3_t normal;
@ -1106,8 +1107,8 @@ typedef struct {
vec_t radius; vec_t radius;
int numtris; int numtris;
};
} fragmentdecal_t; typedef struct fragmentdecal_s fragmentdecal_t;
//#define SHOWCLIPS //#define SHOWCLIPS
//#define FRAGMENTASTRIANGLES //works, but produces more fragments. //#define FRAGMENTASTRIANGLES //works, but produces more fragments.
@ -1115,7 +1116,7 @@ typedef struct {
#ifdef FRAGMENTASTRIANGLES #ifdef FRAGMENTASTRIANGLES
//if the triangle is clipped away, go recursive if there are tris left. //if the triangle is clipped away, go recursive if there are tris left.
void Fragment_ClipTriToPlane(int trinum, float *plane, float planedist, fragmentdecal_t *dec) static void Fragment_ClipTriToPlane(int trinum, float *plane, float planedist, fragmentdecal_t *dec)
{ {
float *point[3]; float *point[3];
float dotv[3]; float dotv[3];
@ -1249,7 +1250,7 @@ void Fragment_ClipTriToPlane(int trinum, float *plane, float planedist, fragment
} }
} }
void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c) static void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c)
{ {
//emit the triangle, and clip it's fragments. //emit the triangle, and clip it's fragments.
int start, i; int start, i;
@ -1279,7 +1280,7 @@ void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c)
#else #else
#define MAXFRAGMENTVERTS 360 #define MAXFRAGMENTVERTS 360
int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float *plane, float planedist) static int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float *plane, float planedist)
{ {
#define C 4 #define C 4
float dotv[MAXFRAGMENTVERTS+1]; float dotv[MAXFRAGMENTVERTS+1];
@ -1400,7 +1401,7 @@ void Fragment_ClipPoly(fragmentdecal_t *dec, int numverts, float *inverts)
#endif #endif
//this could be inlined, but I'm lazy. //this could be inlined, but I'm lazy.
void Fragment_Mesh (fragmentdecal_t *dec, mesh_t *mesh) static void Fragment_Mesh (fragmentdecal_t *dec, mesh_t *mesh)
{ {
int i; int i;
@ -1428,7 +1429,7 @@ void Fragment_Mesh (fragmentdecal_t *dec, mesh_t *mesh)
} }
} }
void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) static void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node)
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;
@ -1479,7 +1480,7 @@ extern int sh_shadowframe;
static int sh_shadowframe; static int sh_shadowframe;
#endif #endif
#ifdef Q3BSPS #ifdef Q3BSPS
void Q3BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) static void Q3BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node)
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;
@ -1547,8 +1548,9 @@ int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangen
sh_shadowframe++; sh_shadowframe++;
if (!cl.worldmodel) if (!cl.worldmodel || cl.worldmodel->type != mod_brush)
return 0; {
}
else if (cl.worldmodel->fromgame == fg_quake) else if (cl.worldmodel->fromgame == fg_quake)
Q1BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes); Q1BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes);
#ifdef Q3BSPS #ifdef Q3BSPS
@ -1556,96 +1558,15 @@ int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangen
Q3BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes); Q3BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes);
#endif #endif
#ifdef TERRAIN
if (cl.worldmodel->terrain)
Terrain_ClipDecal(&dec, center, dec.radius, cl.worldmodel);
#endif
*out = (float *)decalfragmentverts; *out = (float *)decalfragmentverts;
return dec.numtris; return dec.numtris;
} }
//This is spike's testing function, and is only usable by gl. :)
/*
#include "glquake.h"
void Q1BSP_TestClipDecal(void)
{
int i;
int numtris;
vec3_t fwd;
vec3_t start;
vec3_t center, normal, tangent, tangent2;
float *verts;
if (cls.state != ca_active)
return;
VectorCopy(r_origin, start);
// start[2]+=22;
VectorMA(start, 10000, vpn, fwd);
if (!TraceLineN(start, fwd, center, normal))
{
VectorCopy(start, center);
normal[0] = 0;
normal[1] = 0;
normal[2] = 1;
}
CrossProduct(fwd, normal, tangent);
VectorNormalize(tangent);
CrossProduct(normal, tangent, tangent2);
numtris = Q1BSP_ClipDecal(center, normal, tangent, tangent2, 128, &verts);
PPL_RevertToKnownState();
qglDisable(GL_TEXTURE_2D);
qglDisable(GL_BLEND);
qglDisable(GL_ALPHA_TEST);
qglDisable(GL_DEPTH_TEST);
qglColor3f(1, 0, 0);
qglShadeModel(GL_SMOOTH);
qglBegin(GL_TRIANGLES);
for (i = 0; i < numtris; i++)
{
qglVertex3fv(verts+i*9+0);
qglVertex3fv(verts+i*9+3);
qglVertex3fv(verts+i*9+6);
}
qglEnd();
qglColor3f(1, 1, 1);
qglBegin(GL_LINES);
for (i = 0; i < numtris; i++)
{
qglVertex3fv(verts+i*9+0);
qglVertex3fv(verts+i*9+3);
qglVertex3fv(verts+i*9+3);
qglVertex3fv(verts+i*9+6);
qglVertex3fv(verts+i*9+6);
qglVertex3fv(verts+i*9+0);
}
qglVertex3fv(center);
VectorMA(center, 10, normal, fwd);
qglVertex3fv(fwd);
qglColor3f(0, 1, 0);
qglVertex3fv(center);
VectorMA(center, 10, tangent, fwd);
qglVertex3fv(fwd);
qglColor3f(0, 0, 1);
qglVertex3fv(center);
CrossProduct(tangent, normal, fwd);
VectorMA(center, 10, fwd, fwd);
qglVertex3fv(fwd);
qglColor3f(1, 1, 1);
qglEnd();
qglEnable(GL_TEXTURE_2D);
qglEnable(GL_DEPTH_TEST);
PPL_RevertToKnownState();
}
*/
#endif #endif
/* /*
Rendering functions (Client only) Rendering functions (Client only)

View file

@ -1230,7 +1230,7 @@ void Hunk_Check (void)
for (h = (hunk_t *)hunk_base ; (qbyte *)h != hunk_base + hunk_low_used ; ) for (h = (hunk_t *)hunk_base ; (qbyte *)h != hunk_base + hunk_low_used ; )
{ {
if (h->sentinal != HUNK_SENTINAL) if (h->sentinal != HUNK_SENTINAL)
Sys_Error ("Hunk_Check: trahsed sentinal"); Sys_Error ("Hunk_Check: trashed sentinal");
if (h->size < 16+HUNKDEBUG*2 || h->size + (qbyte *)h - hunk_base > hunk_size) if (h->size < 16+HUNKDEBUG*2 || h->size + (qbyte *)h - hunk_base > hunk_size)
Sys_Error ("Hunk_Check: bad size"); Sys_Error ("Hunk_Check: bad size");
#if HUNKDEBUG > 0 #if HUNKDEBUG > 0
@ -1243,9 +1243,9 @@ void Hunk_Check (void)
for (i = 0; i < HUNKDEBUG; i++) for (i = 0; i < HUNKDEBUG; i++)
{ {
if (present[i] != sentinalkey) if (present[i] != sentinalkey)
*(int*)0 = -3; Sys_Error ("Hunk_Check: trashed pre-sentinal on \"%s\"", h->name);
if (postsent[i] != sentinalkey) if (postsent[i] != sentinalkey)
*(int*)0 = -3; Sys_Error ("Hunk_Check: trashed post-sentinal on \"%s\"", h->name);
} }
} }
#endif #endif

View file

@ -1,7 +1,6 @@
#include "quakedef.h" #include "quakedef.h"
//#define FORCESTATE //#define FORCESTATE
//#define WIREFRAME
#ifdef GLQUAKE #ifdef GLQUAKE
@ -26,7 +25,9 @@
extern cvar_t gl_overbright; extern cvar_t gl_overbright;
extern cvar_t gl_ati_truform; extern cvar_t gl_ati_truform;
extern cvar_t r_wireframe;
//simple dlight
static const char LIGHTPASS_SHADER[] = "\ static const char LIGHTPASS_SHADER[] = "\
{\n\ {\n\
program rtlight%s\n\ program rtlight%s\n\
@ -41,7 +42,8 @@ static const char LIGHTPASS_SHADER[] = "\
map $specular\n\ map $specular\n\
}\n\ }\n\
}"; }";
static const char RTLIGHTCUBE_SHADER[] = "\ //dlight with cubemap projection
static const char RTLIGHTCUBEPROJ_SHADER[] = "\
{\n\ {\n\
program rtlight%s\n\ program rtlight%s\n\
{\n\ {\n\
@ -79,6 +81,9 @@ static const char PCFPASS_SHADER[] = "\
{\n\ {\n\
map $specular\n\ map $specular\n\
}\n\ }\n\
{\n\
map $lightcubemap\n\
}\n\
{\n\ {\n\
map $shadowmap\n\ map $shadowmap\n\
}\n\ }\n\
@ -102,8 +107,8 @@ struct {
qboolean inited_shader_rtlight; qboolean inited_shader_rtlight;
const shader_t *shader_rtlight; const shader_t *shader_rtlight;
qboolean inited_shader_cube; qboolean inited_shader_cubeproj;
const shader_t *shader_cube; const shader_t *shader_cubeproj;
qboolean inited_shader_smap; qboolean inited_shader_smap;
const shader_t *shader_smap; const shader_t *shader_smap;
qboolean inited_shader_spot; qboolean inited_shader_spot;
@ -213,44 +218,36 @@ struct {
static void BE_PolyOffset(qboolean pushdepth) static void BE_PolyOffset(qboolean pushdepth)
{ {
polyoffset_t po;
po.factor = shaderstate.curshader->polyoffset.factor;
po.unit = shaderstate.curshader->polyoffset.unit;
if (pushdepth) if (pushdepth)
{ {
/*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc
we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/
extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor;
polyoffset_t po; po.factor += r_polygonoffset_submodel_factor.value;
po.factor = shaderstate.curshader->polyoffset.factor + r_polygonoffset_submodel_factor.value; po.unit += r_polygonoffset_submodel_offset.value;
po.unit = shaderstate.curshader->polyoffset.unit + r_polygonoffset_submodel_offset.value; }
if (shaderstate.mode == BEM_DEPTHONLY)
{
po.factor += 5;
po.unit += 25;
}
#ifndef FORCESTATE #ifndef FORCESTATE
if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1])
#endif #endif
{
shaderstate.curpolyoffset = po;
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
}
}
else
{ {
#ifndef FORCESTATE shaderstate.curpolyoffset = po;
if (*(int*)&shaderstate.curpolyoffset.factor != *(int*)&shaderstate.curshader->polyoffset.factor || *(int*)&shaderstate.curpolyoffset.unit != *(int*)&shaderstate.curshader->polyoffset.unit) if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
#endif
{ {
shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; qglEnable(GL_POLYGON_OFFSET_FILL);
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
} }
else
qglDisable(GL_POLYGON_OFFSET_FILL);
} }
} }
@ -343,12 +340,6 @@ void GL_SetShaderState2D(qboolean is2d)
{ {
shaderstate.updatetime = realtime; shaderstate.updatetime = realtime;
shaderstate.force2d = is2d; shaderstate.force2d = is2d;
#ifdef WIREFRAME
if (!is2d)
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
if (is2d) if (is2d)
memcpy(shaderstate.modelviewmatrix, r_refdef.m_view, sizeof(shaderstate.modelviewmatrix)); memcpy(shaderstate.modelviewmatrix, r_refdef.m_view, sizeof(shaderstate.modelviewmatrix));
BE_SelectMode(BEM_STANDARD); BE_SelectMode(BEM_STANDARD);
@ -910,17 +901,19 @@ void R_IBrokeTheArrays(void)
#ifdef RTLIGHTS #ifdef RTLIGHTS
//called from gl_shadow //called from gl_shadow
void BE_SetupForShadowMap(void) void BE_SetupForShadowMap(texid_t shadowmaptex)
{ {
shaderstate.curshadowmap = shadowmaptex;
while(shaderstate.lastpasstmus>0) while(shaderstate.lastpasstmus>0)
{ {
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex); GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex);
} }
shaderstate.shaderbits &= ~SBITS_MISC_DEPTHWRITE;
qglShadeModel(GL_FLAT); qglShadeModel(GL_FLAT);
BE_SetPassBlendMode(0, PBM_REPLACE); BE_SetPassBlendMode(0, PBM_REPLACE);
qglDepthMask(GL_TRUE); GL_ForceDepthWritable();
shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE;
// qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
BE_SelectMode(BEM_DEPTHONLY); BE_SelectMode(BEM_DEPTHONLY);
@ -930,6 +923,9 @@ void BE_SetupForShadowMap(void)
static void T_Gen_CurrentRender(int tmu) static void T_Gen_CurrentRender(int tmu)
{ {
int vwidth, vheight; int vwidth, vheight;
if (r_refdef.recurse)
return;
if (gl_config.arb_texture_non_power_of_two) if (gl_config.arb_texture_non_power_of_two)
{ {
vwidth = vid.pixelwidth; vwidth = vid.pixelwidth;
@ -1140,10 +1136,10 @@ void Shader_LightPass_Std(char *shortname, shader_t *s, const void *args)
sprintf(shadertext, LIGHTPASS_SHADER, ""); sprintf(shadertext, LIGHTPASS_SHADER, "");
Shader_DefaultScript(shortname, s, shadertext); Shader_DefaultScript(shortname, s, shadertext);
} }
void Shader_LightPass_Cube(char *shortname, shader_t *s, const void *args) void Shader_LightPass_CubeProj(char *shortname, shader_t *s, const void *args)
{ {
char shadertext[8192*2]; char shadertext[8192*2];
sprintf(shadertext, RTLIGHTCUBE_SHADER, "#CUBE"); sprintf(shadertext, RTLIGHTCUBEPROJ_SHADER, "#CUBEPROJ");
Shader_DefaultScript(shortname, s, shadertext); Shader_DefaultScript(shortname, s, shadertext);
} }
void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args) void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args)
@ -1246,10 +1242,10 @@ void GLBE_Init(void)
shaderstate.inited_shader_rtlight = true; shaderstate.inited_shader_rtlight = true;
shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL); shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL);
} }
if (r_shadow_realtime_dlight.ival && !shaderstate.inited_shader_cube && gl_config.arb_shader_objects) if (r_shadow_realtime_dlight.ival && !shaderstate.inited_shader_cubeproj && gl_config.arb_shader_objects)
{ {
shaderstate.inited_shader_cube = true; shaderstate.inited_shader_cubeproj = true;
shaderstate.shader_cube = R_RegisterCustom("rtlight_sube", Shader_LightPass_Cube, NULL); shaderstate.shader_cubeproj = R_RegisterCustom("rtlight_cubeproj", Shader_LightPass_CubeProj, NULL);
} }
gl_overbright.modified = true; /*in case the d3d renderer does the same*/ gl_overbright.modified = true; /*in case the d3d renderer does the same*/
@ -2842,10 +2838,17 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
qglUniform3fvARB(p->handle[perm], 1, shaderstate.lightcolourscale); qglUniform3fvARB(p->handle[perm], 1, shaderstate.lightcolourscale);
break; break;
case SP_LIGHTPROJMATRIX: case SP_LIGHTPROJMATRIX:
{
float t[16];
Matrix4x4_CM_Projection_Far(t, 90, 90, 4, 3000);
qglUniformMatrix4fvARB(p->handle[perm], 1, false, t);
}
break;
case SP_LIGHTCUBEMATRIX:
/*light's texture projection matrix*/ /*light's texture projection matrix*/
{ {
float t[16]; float t[16];
Matrix4_Multiply(shaderstate.lightprojmatrix, shaderstate.modelmatrix, t); Matrix4_Multiply(shaderstate.modelmatrix, shaderstate.lightprojmatrix, t);
qglUniformMatrix4fvARB(p->handle[perm], 1, false, t); qglUniformMatrix4fvARB(p->handle[perm], 1, false, t);
} }
break; break;
@ -3105,10 +3108,10 @@ void GLBE_SelectMode(backendmode_t mode)
shaderstate.inited_shader_rtlight = true; shaderstate.inited_shader_rtlight = true;
shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL); shaderstate.shader_rtlight = R_RegisterCustom("rtlight", Shader_LightPass_Std, NULL);
} }
if (!shaderstate.inited_shader_cube && gl_config.arb_shader_objects) if (!shaderstate.inited_shader_cubeproj && gl_config.arb_shader_objects)
{ {
shaderstate.inited_shader_cube = true; shaderstate.inited_shader_cubeproj = true;
shaderstate.shader_cube = R_RegisterCustom("rtlight_sube", Shader_LightPass_Cube, NULL); shaderstate.shader_cubeproj = R_RegisterCustom("rtlight_sube", Shader_LightPass_CubeProj, NULL);
} }
break; break;
@ -3197,34 +3200,27 @@ void BE_SelectFog(vec3_t colour, float alpha, float density)
void GLBE_SelectDLight(dlight_t *dl, vec3_t colour) void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
{ {
static float shadowprojectionbias[16] = float view[16], proj[16];
{
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.4993f, 1.0f
};
float view[16], proj[16], t[16];
/*generate light projection information*/ /*generate light projection information*/
float nearplane = 4; float nearplane = 4;
if (dl->fov) if (dl->fov)
{
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, nearplane, dl->radius); Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, nearplane, dl->radius);
Matrix4x4_CM_ModelViewMatrixFromAxis(view, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
}
else else
{
Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, dl->radius); Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, dl->radius);
Matrix4x4_CM_ModelViewMatrixFromAxis(view, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(shaderstate.lightprojmatrix, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
Matrix4_Multiply(shadowprojectionbias, proj, t); }
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
/*simple info*/ /*simple info*/
shaderstate.lightradius = dl->radius; shaderstate.lightradius = dl->radius;
VectorCopy(dl->origin, shaderstate.lightorg); VectorCopy(dl->origin, shaderstate.lightorg);
VectorCopy(dl->lightcolourscales, shaderstate.lightcolourscale); VectorCopy(dl->lightcolourscales, shaderstate.lightcolourscale);
VectorCopy(colour, shaderstate.lightcolours); VectorCopy(colour, shaderstate.lightcolours);
#ifdef RTLIGHTS
shaderstate.curshadowmap = dl->stexture;
#endif
#ifdef RTLIGHTS #ifdef RTLIGHTS
shaderstate.lightcubemap = dl->cubetexture; shaderstate.lightcubemap = dl->cubetexture;
#endif #endif
@ -3436,10 +3432,12 @@ static void DrawMeshes(void)
break; break;
#ifdef RTLIGHTS #ifdef RTLIGHTS
case BEM_SMAPLIGHTSPOT: case BEM_SMAPLIGHTSPOT:
BE_RenderMeshProgram(shaderstate.shader_spot, shaderstate.shader_spot->passes); if (shaderstate.shader_smap->prog)
BE_RenderMeshProgram(shaderstate.shader_spot, shaderstate.shader_spot->passes);
break; break;
case BEM_SMAPLIGHT: case BEM_SMAPLIGHT:
BE_RenderMeshProgram(shaderstate.shader_smap, shaderstate.shader_smap->passes); if (shaderstate.shader_smap->prog)
BE_RenderMeshProgram(shaderstate.shader_smap, shaderstate.shader_smap->passes);
break; break;
case BEM_LIGHT: case BEM_LIGHT:
if (!shaderstate.inited_shader_rtlight) if (!shaderstate.inited_shader_rtlight)
@ -3447,9 +3445,9 @@ static void DrawMeshes(void)
BE_LegacyLighting(); BE_LegacyLighting();
break; break;
} }
if (TEXVALID(shaderstate.lightcubemap)) if (TEXVALID(shaderstate.lightcubemap) && shaderstate.shader_cubeproj->prog)
BE_RenderMeshProgram(shaderstate.shader_cube, shaderstate.shader_cube->passes); BE_RenderMeshProgram(shaderstate.shader_cubeproj, shaderstate.shader_cubeproj->passes);
else else if (shaderstate.shader_rtlight->prog)
BE_RenderMeshProgram(shaderstate.shader_rtlight, shaderstate.shader_rtlight->passes); BE_RenderMeshProgram(shaderstate.shader_rtlight, shaderstate.shader_rtlight->passes);
break; break;
case BEM_DEPTHNORM: case BEM_DEPTHNORM:
@ -3481,6 +3479,23 @@ static void DrawMeshes(void)
BE_SubmitMeshChain(); BE_SubmitMeshChain();
break; break;
case BEM_WIREFRAME:
//FIXME: do this with a shader instead? its not urgent as we can draw the shader normally anyway, just faster.
GL_DeselectVAO();
GL_DeSelectProgram();
shaderstate.pendingcolourvbo = 0;
shaderstate.pendingcolourpointer = NULL;
Vector4Set(shaderstate.pendingcolourflat, 1, 1, 1, 1);
while(shaderstate.lastpasstmus>0)
{
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex);
}
BE_SetPassBlendMode(0, PBM_REPLACE);
BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits | SBITS_MISC_NODEPTHTEST);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR));
BE_SubmitMeshChain();
break;
case BEM_DEPTHDARK: case BEM_DEPTHDARK:
if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright) && !gl_config.nofixedfunc) if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright) && !gl_config.nofixedfunc)
{ {
@ -3756,15 +3771,17 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
continue; continue;
} }
} }
else if (shaderstate.mode != BEM_FOG && shaderstate.mode != BEM_CREPUSCULAR) else if (shaderstate.mode != BEM_FOG && shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
continue; continue;
} }
if (batch->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) if ((batch->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) && shaderstate.mode != BEM_WIREFRAME)
{ {
//these flags require rendering some view as an fbo //these flags require rendering some view as an fbo
if (r_refdef.recurse) if (r_refdef.recurse)
continue; continue;
if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK)
continue;
if (batch->shader->flags & SHADER_HASREFLECT) if (batch->shader->flags & SHADER_HASREFLECT)
{ {
@ -4227,7 +4244,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
} }
#ifdef RTLIGHTS #ifdef RTLIGHTS
if (vis) if (drawworld)
{ {
RSpeedRemark(); RSpeedRemark();
TRACE(("GLBE_DrawWorld: drawing lights\n")); TRACE(("GLBE_DrawWorld: drawing lights\n"));
@ -4249,10 +4266,28 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST);
} }
*/ */
if (r_wireframe.ival)
{
BE_SelectMode(BEM_WIREFRAME);
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLBE_SubmitMeshes(true, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST);
BE_SelectMode(BEM_STANDARD);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
} }
else else
{ {
GLBE_SubmitMeshes(false, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); GLBE_SubmitMeshes(false, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST);
if (r_wireframe.ival)
{
BE_SelectMode(BEM_WIREFRAME);
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLBE_SubmitMeshes(false, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST);
BE_SelectMode(BEM_STANDARD);
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
} }
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);

View file

@ -298,6 +298,7 @@ void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue)
{ {
int i; int i;
gltexture_t *glt; gltexture_t *glt;
int targ;
if (qrenderer != QR_OPENGL) if (qrenderer != QR_OPENGL)
return; return;
@ -323,12 +324,17 @@ void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue)
{ {
if (!(glt->flags & IF_NOMIPMAP)) if (!(glt->flags & IF_NOMIPMAP))
{ {
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); if (glt->flags & IF_CUBEMAP)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); targ = GL_TEXTURE_CUBE_MAP_ARB;
if (glt->flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); targ = GL_TEXTURE_2D;
GL_MTBind(0, targ, glt->texnum);
qglTexParameteri(targ, GL_TEXTURE_MIN_FILTER, gl_filter_min);
if (glt->flags & IF_NEAREST)
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(targ, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
} }
} }
@ -1127,7 +1133,7 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
unsigned *scaled = (unsigned *)uploadmemorybuffer; unsigned *scaled = (unsigned *)uploadmemorybuffer;
int scaled_width, scaled_height; int scaled_width, scaled_height;
int type; int type;
int targ; int targ, targface;
TRACE(("dbg: GL_Upload32: %s %i %i\n", name, width, height)); TRACE(("dbg: GL_Upload32: %s %i %i\n", name, width, height));
@ -1152,13 +1158,14 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
switch((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT) switch((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT)
{ {
case 0: case 0:
targ = GL_TEXTURE_2D; targface = targ = GL_TEXTURE_2D;
break; break;
case 1: case 1:
targ = GL_TEXTURE_3D; targface = targ = GL_TEXTURE_3D;
break; break;
default: default:
targ = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + (((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT) - 2); targface = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + (((flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT) - 2);
targ = GL_TEXTURE_CUBE_MAP_ARB;
break; break;
} }
@ -1265,11 +1272,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
{ {
TRACE(("dbg: GL_Upload32: non-mipmapped/unscaled\n")); TRACE(("dbg: GL_Upload32: non-mipmapped/unscaled\n"));
if (type == GL_UNSIGNED_SHORT_5_6_5) if (type == GL_UNSIGNED_SHORT_5_6_5)
GL_8888to565(targ, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height); GL_8888to565(targface, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
else if (type == GL_UNSIGNED_SHORT_4_4_4_4) else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
GL_8888to4444(targ, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height); GL_8888to4444(targface, (unsigned char *)data, (unsigned short*)scaled, 0, scaled_width, scaled_height);
else else
qglTexImage2D (targ, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data); qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data);
goto done; goto done;
} }
memcpy (scaled, data, width*height*4); memcpy (scaled, data, width*height*4);
@ -1279,11 +1286,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
TRACE(("dbg: GL_Upload32: recaled\n")); TRACE(("dbg: GL_Upload32: recaled\n"));
if (type == GL_UNSIGNED_SHORT_5_6_5) if (type == GL_UNSIGNED_SHORT_5_6_5)
GL_8888to565(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height); GL_8888to565(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
else if (type == GL_UNSIGNED_SHORT_4_4_4_4) else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
GL_8888to4444(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height); GL_8888to4444(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, 0, scaled_width, scaled_height);
else else
qglTexImage2D (targ, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled); qglTexImage2D (targface, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
if (!(flags&IF_NOMIPMAP) && !gl_config.sgis_generate_mipmap) if (!(flags&IF_NOMIPMAP) && !gl_config.sgis_generate_mipmap)
{ {
miplevel = 0; miplevel = 0;
@ -1299,11 +1306,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
scaled_height = 1; scaled_height = 1;
miplevel++; miplevel++;
if (type == GL_UNSIGNED_SHORT_5_6_5) if (type == GL_UNSIGNED_SHORT_5_6_5)
GL_8888to565(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height); GL_8888to565(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
else if (type == GL_UNSIGNED_SHORT_4_4_4_4) else if (type == GL_UNSIGNED_SHORT_4_4_4_4)
GL_8888to4444(targ, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height); GL_8888to4444(targface, (unsigned char *)scaled, (unsigned short*)uploadmemorybufferintermediate, miplevel, scaled_width, scaled_height);
else else
qglTexImage2D (targ, miplevel, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled); qglTexImage2D (targface, miplevel, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled);
} }
} }

View file

@ -851,9 +851,8 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
{ {
hlmodelcache_t *modelc = Mod_Extradata(rent->model); hlmodelcache_t *modelc = Mod_Extradata(rent->model);
hlmodel_t model; hlmodel_t model;
int body, m, v; int body, m;
short *skins; short *skins;
int bgroup, cbone, lastbone;
int batchid = 0; int batchid = 0;
static mesh_t bmesh, *mptr = &bmesh; static mesh_t bmesh, *mptr = &bmesh;

View file

@ -60,6 +60,10 @@ typedef struct mesh_s
unsigned int vbofirstvert; unsigned int vbofirstvert;
unsigned int vbofirstelement; unsigned int vbofirstelement;
/*
FIXME: move most of this stuff out into a vbo struct
*/
float xyz_blendw[2]; float xyz_blendw[2];
/*arrays used for rendering*/ /*arrays used for rendering*/
@ -87,8 +91,6 @@ typedef struct mesh_s
} mesh_t; } mesh_t;
extern mesh_t nullmesh; extern mesh_t nullmesh;
extern int gl_canbumpmap;
/* /*
batches are generated for each shader/ent as required. batches are generated for each shader/ent as required.
once a batch is known to the backend for that frame, its shader, vbo, ent, lightmap, textures may not be changed until the frame has finished rendering. This is to potentially permit caching. once a batch is known to the backend for that frame, its shader, vbo, ent, lightmap, textures may not be changed until the frame has finished rendering. This is to potentially permit caching.
@ -1019,6 +1021,8 @@ void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean light
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname); //call this after loading a bsp void *Mod_LoadTerrainInfo(model_t *mod, char *loadname); //call this after loading a bsp
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, struct trace_s *trace); qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, struct trace_s *trace);
unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org); unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org);
struct fragmentdecal_s;
void Terrain_ClipDecal(struct fragmentdecal_s *dec, float *center, float radius, model_t *model);
#endif #endif

View file

@ -421,7 +421,7 @@ void R_SetupGL (void)
stencilshadows |= r_shadow_realtime_world.ival && r_shadow_realtime_world_shadows.ival; stencilshadows |= r_shadow_realtime_world.ival && r_shadow_realtime_world_shadows.ival;
#endif #endif
if ((!stencilshadows || !gl_stencilbits) && gl_maxdist.value>=100)//gl_nv_range_clamp) if (1)//(!stencilshadows || !gl_stencilbits) && gl_maxdist.value>=100)//gl_nv_range_clamp)
{ {
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
// yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;

View file

@ -1506,6 +1506,8 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype)
FS_FreeFile(file); FS_FreeFile(file);
g->prog.refs++; g->prog.refs++;
if (g->failed)
return NULL;
return &g->prog; return &g->prog;
} }
else else
@ -1644,6 +1646,7 @@ struct shader_field_names_s shader_unif_names[] =
{"l_lightposition", SP_LIGHTPOSITION}, {"l_lightposition", SP_LIGHTPOSITION},
{"l_lightcolourscale", SP_LIGHTCOLOURSCALE}, {"l_lightcolourscale", SP_LIGHTCOLOURSCALE},
{"l_projmatrix", SP_LIGHTPROJMATRIX}, {"l_projmatrix", SP_LIGHTPROJMATRIX},
{"l_cubematrix", SP_LIGHTCUBEMATRIX},
{"e_rendertexturescale", SP_RENDERTEXTURESCALE}, {"e_rendertexturescale", SP_RENDERTEXTURESCALE},
{NULL} {NULL}
@ -3958,7 +3961,7 @@ void Shader_DefaultScript(char *shortname, shader_t *s, const void *args)
void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
{ {
char *builtin = NULL; char *builtin = NULL;
if (!builtin && r_drawflat.value) if (!builtin && r_drawflat.ival)
builtin = ( builtin = (
"{\n" "{\n"
"program drawflat_wall\n" "program drawflat_wall\n"
@ -4158,6 +4161,7 @@ char *Shader_DefaultBSPWater(char *shortname)
case 2: //refraction of the underwater surface, with a fresnel case 2: //refraction of the underwater surface, with a fresnel
return ( return (
"{\n" "{\n"
"surfaceparm nodlight\n"
"{\n" "{\n"
"map $refraction\n" "map $refraction\n"
"}\n" "}\n"
@ -4170,9 +4174,26 @@ char *Shader_DefaultBSPWater(char *shortname)
"program altwater#FRESNEL=4\n" "program altwater#FRESNEL=4\n"
"}\n" "}\n"
); );
case 3: //ripples case 3: //reflections
return ( return (
"{\n" "{\n"
"surfaceparm nodlight\n"
"{\n"
"map $refraction\n"
"}\n"
"{\n"
"map $normalmap\n"
"}\n"
"{\n"
"map $reflection\n"
"}\n"
"program altwater#REFLECT#FRESNEL=4\n"
"}\n"
);
case 4: //ripples
return (
"{\n"
"surfaceparm nodlight\n"
"{\n" "{\n"
"map $refraction\n" "map $refraction\n"
"}\n" "}\n"
@ -4188,9 +4209,10 @@ char *Shader_DefaultBSPWater(char *shortname)
"program altwater#RIPPLEMAP#FRESNEL=4\n" "program altwater#RIPPLEMAP#FRESNEL=4\n"
"}\n" "}\n"
); );
case 4: //reflections case 5: //ripples+reflections
return ( return (
"{\n" "{\n"
"surfaceparm nodlight\n"
"{\n" "{\n"
"map $refraction\n" "map $refraction\n"
"}\n" "}\n"

View file

@ -6,6 +6,9 @@ There is no screen-space culling of lit surfaces.
model meshes are interpolated multiple times per frame model meshes are interpolated multiple times per frame
*/ */
//#define DBG_COLOURNOTDEPTH
#if defined(GLQUAKE) || defined(D3DQUAKE) #if defined(GLQUAKE) || defined(D3DQUAKE)
#ifdef RTLIGHTS #ifdef RTLIGHTS
@ -25,11 +28,14 @@ void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbu
#endif #endif
void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies); void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies);
static void SHM_Shutdown(void);
#define SHADOWMAP_SIZE 512 #define SHADOWMAP_SIZE 512
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
#define nearplane (16) #define nearplane (4)
static texid_t shadowmap[2];
static int shadow_fbo_id; static int shadow_fbo_id;
static int crepuscular_fbo_id; static int crepuscular_fbo_id;
@ -58,6 +64,16 @@ void Sh_Shutdown(void)
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id); qglDeleteRenderbuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0; shadow_fbo_id = 0;
} }
if (shadowmap[0].num)
{
R_DestroyTexture(shadowmap[0]);
shadowmap[0] = r_nulltex;
}
if (shadowmap[1].num)
{
R_DestroyTexture(shadowmap[1]);
shadowmap[1] = r_nulltex;
}
if (crepuscular_texture_id.num) if (crepuscular_texture_id.num)
{ {
R_DestroyTexture(crepuscular_texture_id); R_DestroyTexture(crepuscular_texture_id);
@ -69,6 +85,8 @@ void Sh_Shutdown(void)
crepuscular_fbo_id = 0; crepuscular_fbo_id = 0;
} }
#endif #endif
SHM_Shutdown();
} }
@ -968,6 +986,14 @@ static struct {
int *edgeuses; /*negative for back sides, so 0 means unused or used equally on both sides*/ int *edgeuses; /*negative for back sides, so 0 means unused or used equally on both sides*/
} cv; } cv;
static void SHM_Shutdown(void)
{
free(cv.tris);
free(cv.edges);
free(cv.points);
memset(&cv, 0, sizeof(cv));
}
#define VERT_POS_EPSILON (1.0f/32) #define VERT_POS_EPSILON (1.0f/32)
static int SHM_ComposeVolume_FindVert(float *vert) static int SHM_ComposeVolume_FindVert(float *vert)
{ {
@ -1233,6 +1259,7 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
firstedge=0; firstedge=0;
if (cl.worldmodel->type == mod_brush)
switch(cl.worldmodel->fromgame) switch(cl.worldmodel->fromgame)
{ {
case fg_quake: case fg_quake:
@ -1778,6 +1805,34 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, vrect_t *r)
#endif #endif
#ifdef GLQUAKE #ifdef GLQUAKE
#ifdef DBG_COLOURNOTDEPTH
void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
{
if (gl_config.ext_framebuffer_objects)
{
if (!shadow_fbo_id)
{
int drb;
qglGenFramebuffersEXT(1, &shadow_fbo_id);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id);
//create an unnamed depth buffer
// qglGenRenderbuffersEXT(1, &drb);
// qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, drb);
// qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, SHADOWMAP_SIZE*3, SHADOWMAP_SIZE*2);
// qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
qglReadBuffer(GL_NONE);
}
else
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id);
if (TEXVALID(depthtexture))
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, depthtexture.num, 0);
}
}
#else
void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
{ {
if (gl_config.ext_framebuffer_objects) if (gl_config.ext_framebuffer_objects)
@ -1796,6 +1851,7 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthtexture.num, 0); qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthtexture.num, 0);
} }
} }
#endif
void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize)
{ {
if (gl_config.ext_framebuffer_objects) if (gl_config.ext_framebuffer_objects)
@ -1812,74 +1868,86 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize)
static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float proj[16]) static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float proj[16])
{ {
qboolean oxv; qboolean oxv;
float mvm[16], sav[16]; vec3_t t1,t2, t3;
vec3_t t1,t2; texture_t *tex;
int tno;
int smsize = SHADOWMAP_SIZE; int smsize = SHADOWMAP_SIZE;
// qglDepthRange(0, 1);
if (l->fov) if (l->fov)
qglViewport (0, 0, smsize, smsize); qglViewport (0, 0, smsize, smsize);
else else
qglViewport (((face/2)*smsize)/3, ((face&1)*smsize)/2, smsize/3, smsize/2); {
qglViewport ((face%3 * smsize), ((face>=3)*smsize), smsize, smsize);
}
switch(face) switch(face)
{ {
case 0: case 0:
//forward //+x - forward
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[0], l->axis[1], l->axis[2], l->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[0], l->axis[1], l->axis[2], l->origin);
r_refdef.flipcull = false;
break; break;
case 1: case 1:
//back //+y - right
VectorNegate(l->axis[0], t1); VectorNegate(l->axis[0], t1);
VectorNegate(l->axis[1], t2); VectorNegate(l->axis[1], t2);
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, t2, l->axis[2], l->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t2, t1, l->axis[2], l->origin);
r_refdef.flipcull = true;
break; break;
case 2: case 2:
//left //+z - down
VectorNegate(l->axis[1], t1); VectorNegate(l->axis[0], t1);
VectorNegate(l->axis[0], t2); VectorNegate(l->axis[2], t2);
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[1], t2, l->axis[2], l->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t2, l->axis[1], t1, l->origin);
r_refdef.flipcull = true;
break; break;
case 3: case 3:
//right //-x - back
VectorNegate(l->axis[1], t1); VectorNegate(l->axis[0], t1);
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, l->axis[0], l->axis[2], l->origin); VectorNegate(l->axis[1], t2);
VectorNegate(l->axis[2], t3);
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t1, l->axis[1], l->axis[2], l->origin);
r_refdef.flipcull = true;
break; break;
case 4: case 4:
//up //-y - left
VectorNegate(l->axis[1], t1);
VectorNegate(l->axis[0], t2); VectorNegate(l->axis[0], t2);
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, l->axis[2], l->axis[1], t2, l->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[1], t2, l->axis[2], l->origin);
r_refdef.flipcull = false;
break; break;
case 5: case 5:
//down //-z - up
VectorNegate(l->axis[2], t1); VectorNegate(l->axis[0], t2);
Matrix4x4_CM_ModelViewMatrixFromAxis(mvm, t1, l->axis[1], l->axis[0], l->origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[2], l->axis[1], t2, l->origin);
r_refdef.flipcull = false;
break; break;
} }
GL_CullFace(0);
R_SetFrustum(proj, r_refdef.m_view);
qglMatrixMode(GL_MODELVIEW); #ifdef DBG_COLOURNOTDEPTH
memcpy(sav, r_refdef.m_view, sizeof(r_refdef.m_view)); BE_SelectMode(BEM_STANDARD);
memcpy(r_refdef.m_view, mvm, sizeof(r_refdef.m_view)); #else
qglLoadMatrixf(mvm);
R_SetFrustum(proj, mvm);
/* if (smesh)
for (tno = 0; tno < smesh->numsurftextures; tno++)
{
m = NULL;
if (!smesh->litsurfs[tno].count)
continue;
tex = cl.worldmodel->textures[tno];
BE_DrawMesh_List(tex->shader, smesh->litsurfs[tno].count, smesh->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures, 0);
}
*/
BE_SelectMode(BEM_DEPTHONLY); BE_SelectMode(BEM_DEPTHONLY);
#endif
/*shadow meshes are always drawn as an external view*/ /*shadow meshes are always drawn as an external view*/
oxv = r_refdef.externalview; oxv = r_refdef.externalview;
r_refdef.externalview = true; r_refdef.externalview = true;
BE_SelectEntity(&r_worldentity);
for (tno = 0; tno < smesh->numbatches; tno++)
{
if (!smesh->batches[tno].count)
continue;
tex = cl.worldmodel->shadowbatches[tno].tex;
if (tex->shader->flags & SHADER_NODLIGHT)
continue;
BE_DrawMesh_List(tex->shader, smesh->batches[tno].count, smesh->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0);
}
switch(qrenderer) switch(qrenderer)
{ {
#ifdef GLQUAKE #ifdef GLQUAKE
@ -1893,9 +1961,10 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p
break; break;
#endif #endif
} }
r_refdef.externalview = oxv; r_refdef.externalview = oxv;
if (0) /*
{ {
int i; int i;
static float depth[SHADOWMAP_SIZE*SHADOWMAP_SIZE]; static float depth[SHADOWMAP_SIZE*SHADOWMAP_SIZE];
@ -1908,6 +1977,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p
else else
*((unsigned int*)depth+i) = 0xff000000|((((unsigned char)(int)(depth[i]*128)))*0x10101); *((unsigned int*)depth+i) = 0xff000000|((((unsigned char)(int)(depth[i]*128)))*0x10101);
} }
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
smsize, smsize, 0, smsize, smsize, 0,
GL_RGBA, GL_UNSIGNED_BYTE, depth); GL_RGBA, GL_UNSIGNED_BYTE, depth);
@ -1917,65 +1987,99 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
} }
*/
memcpy(r_refdef.m_view, sav, sizeof(r_refdef.m_view));
} }
void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
{ {
int f; int f;
int smsize = SHADOWMAP_SIZE; int smsize = SHADOWMAP_SIZE;
float proj[16]; float oproj[16], oview[16];
shadowmesh_t *smesh; shadowmesh_t *smesh;
int isspot = (l->fov != 0);
if (!TEXVALID(l->stexture)) if (!TEXVALID(shadowmap[isspot]))
{ {
l->stexture = GL_AllocNewTexture("***shadowmap***", smsize, smsize); if (isspot)
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize, smsize);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
else
{
shadowmap[isspot] = GL_AllocNewTexture("***shadowmap***", smsize*3, smsize*2);
GL_MTBind(0, GL_TEXTURE_2D, shadowmap[isspot]);
#ifdef DBG_COLOURNOTDEPTH
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize*3, smsize*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#else
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize*3, smsize*2, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#endif
}
GL_MTBind(0, GL_TEXTURE_2D, l->stexture);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
// qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); #if 1//def DBG_COLOURNOTDEPTH
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
//in case we're using shadow samplers
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
} }
smesh = SHM_BuildShadowMesh(l, lvis, NULL, true); smesh = SHM_BuildShadowMesh(l, lvis, NULL, true);
/*polygon offsets. urgh.*/
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(5, 25);
BE_SetupForShadowMap();
/*set framebuffer*/ /*set framebuffer*/
GL_BeginRenderBuffer_DepthOnly(l->stexture); GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]);
qglClear (GL_DEPTH_BUFFER_BIT); BE_SetupForShadowMap(shadowmap[isspot]);
qglViewport(0, 0, smsize*3, smsize*2);
qglClear (GL_DEPTH_BUFFER_BIT);
#ifdef DBG_COLOURNOTDEPTH
qglClearColor(0,1,0,1);
qglClear (GL_COLOR_BUFFER_BIT);
#endif
memcpy(oproj, r_refdef.m_projection, sizeof(oproj));
memcpy(oview, r_refdef.m_view, sizeof(oview));
if (l->fov) if (l->fov)
{ {
Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); Matrix4x4_CM_Projection_Far(r_refdef.m_projection, l->fov, l->fov, nearplane, l->radius);
qglMatrixMode(GL_PROJECTION); qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(proj); qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
/*single face*/ /*single face*/
Sh_GenShadowFace(l, smesh, 0, proj); Sh_GenShadowFace(l, smesh, 0, r_refdef.m_projection);
} }
else else
{ {
Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, l->radius); Matrix4x4_CM_Projection_Far(r_refdef.m_projection, 90, 90, nearplane, l->radius);
qglMatrixMode(GL_PROJECTION); qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(proj); qglLoadMatrixf(r_refdef.m_projection);
qglMatrixMode(GL_MODELVIEW);
/*generate faces*/ /*generate faces*/
for (f = 0; f < 6; f++) for (f = 0; f < 6; f++)
{ {
Sh_GenShadowFace(l, smesh, f, proj); Sh_GenShadowFace(l, smesh, f, r_refdef.m_projection);
} }
} }
/*end framebuffer*/ /*end framebuffer*/
GL_EndRenderBuffer_DepthOnly(l->stexture, smsize); GL_EndRenderBuffer_DepthOnly(shadowmap[isspot], smsize);
memcpy(r_refdef.m_view, oview, sizeof(r_refdef.m_view));
memcpy(r_refdef.m_projection, oproj, sizeof(r_refdef.m_projection));
qglDisable(GL_POLYGON_OFFSET_FILL); qglDisable(GL_POLYGON_OFFSET_FILL);
@ -1990,20 +2094,8 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
R_SetFrustum(r_refdef.m_projection, r_refdef.m_view); R_SetFrustum(r_refdef.m_projection, r_refdef.m_view);
} }
static float shadowprojectionbias[16] =
{
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.4993f, 1.0f
};
static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
{ {
float t[16];
float bp[16];
float proj[16], view[16];
vec3_t biasorg;
int ve; int ve;
vec3_t mins, maxs; vec3_t mins, maxs;
qbyte *lvis; qbyte *lvis;
@ -2030,86 +2122,49 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
return; return;
} }
if (l->worldshadowmesh) if (vvis)
{
lvis = l->worldshadowmesh->litleaves;
//fixme: check head node first?
if (!Sh_LeafInView(l->worldshadowmesh->litleaves, vvis))
{
bench.numpvsculled++;
return;
}
}
else
{ {
int leaf; if (l->worldshadowmesh)
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, l->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb));
if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
{ {
bench.numpvsculled++; lvis = l->worldshadowmesh->litleaves;
return; //fixme: check head node first?
if (!Sh_LeafInView(l->worldshadowmesh->litleaves, vvis))
{
bench.numpvsculled++;
return;
}
}
else
{
int leaf;
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, l->origin);
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb));
if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
{
bench.numpvsculled++;
return;
}
} }
} }
qglDisable(GL_SCISSOR_TEST);
Sh_GenShadowMap(l, lvis); Sh_GenShadowMap(l, lvis);
if (l->fov)
Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius);
else
Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, l->radius);
VectorMA(l->origin, 0, l->axis[0], biasorg);
Matrix4x4_CM_ModelViewMatrixFromAxis(view, l->axis[0], l->axis[1], l->axis[2], l->origin);
//bp = shadowprojectionbias*proj*view;
Matrix4_Multiply(shadowprojectionbias, proj, t);
Matrix4_Multiply(t, view, bp);
t[0] = bp[0];
t[1] = bp[4];
t[2] = bp[8];
t[3] = bp[12];
t[4] = bp[1];
t[5] = bp[5];
t[6] = bp[9];
t[7] = bp[13];
t[8] = bp[2];
t[9] = bp[6];
t[10] = bp[10];
t[11] = bp[14];
t[12] = bp[3];
t[13] = bp[7];
t[14] = bp[11];
t[15] = bp[15];
bench.numlights++; bench.numlights++;
//may as well use scissors
Sh_Scissor(rect); Sh_Scissor(rect);
qglEnable(GL_STENCIL_TEST); qglEnable(GL_SCISSOR_TEST);
qglMatrixMode(GL_TEXTURE);
GL_MTBind(7, GL_TEXTURE_2D, l->stexture);
// qglEnable(GL_TEXTURE_2D);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
qglLoadMatrixf(bp);
qglMatrixMode(GL_MODELVIEW);
GL_SelectTexture(0);
ve = 0; ve = 0;
BE_SelectEntity(&r_worldentity);
GLBE_SelectDLight(l, colour); GLBE_SelectDLight(l, colour);
BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT); BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT);
Sh_DrawEntLighting(l, colour); Sh_DrawEntLighting(l, colour);
GL_SelectTexture(7);
qglDisable(GL_TEXTURE_2D);
qglMatrixMode(GL_TEXTURE);
qglLoadIdentity();
qglMatrixMode(GL_MODELVIEW);
} }
#endif #endif
@ -2871,6 +2926,7 @@ void Sh_DrawLights(qbyte *vis)
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_dlight; extern cvar_t r_shadow_realtime_world, r_shadow_realtime_dlight;
extern cvar_t r_shadow_realtime_world_shadows, r_shadow_realtime_dlight_shadows; extern cvar_t r_shadow_realtime_world_shadows, r_shadow_realtime_dlight_shadows;
extern cvar_t r_sun_dir, r_sun_colour; extern cvar_t r_sun_dir, r_sun_colour;
extern cvar_t r_shadow_shadowmapping;
if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival) if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival)
{ {
@ -2942,7 +2998,7 @@ void Sh_DrawLights(qbyte *vis)
{ {
Sh_DrawShadowlessLight(dl, colour, vis); Sh_DrawShadowlessLight(dl, colour, vis);
} }
else if (dl->flags & LFLAG_SHADOWMAP) else if ((dl->flags & LFLAG_SHADOWMAP) || dl->fov || r_shadow_shadowmapping.ival)
{ {
#ifdef GLQUAKE #ifdef GLQUAKE
Sh_DrawShadowMapLight(dl, colour, vis); Sh_DrawShadowMapLight(dl, colour, vis);

View file

@ -666,9 +666,40 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB"); qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB");
} }
if (0 && !gl_config.nofixedfunc) if (Cvar_Get("gl_blacklist_debug_glsl", "0", CVAR_RENDERERLATCH, "gl blacklists")->ival && !gl_config.nofixedfunc)
{ {
Con_Printf(CON_NOTICE "GLSL disabled\n"); Con_Printf(CON_NOTICE "GLSL disabled\n");
gl_config.arb_shader_objects = false;
qglCreateProgramObjectARB = NULL;
qglDeleteProgramObject_ = NULL;
qglDeleteShaderObject_ = NULL;
qglUseProgramObjectARB = NULL;
qglCreateShaderObjectARB = NULL;
qglGetProgramParameteriv_ = NULL;
qglGetShaderParameteriv_ = NULL;
qglAttachObjectARB = NULL;
qglGetProgramInfoLog_ = NULL;
qglGetShaderInfoLog_ = NULL;
qglShaderSourceARB = NULL;
qglCompileShaderARB = NULL;
qglLinkProgramARB = NULL;
qglBindAttribLocationARB = NULL;
qglGetAttribLocationARB = NULL;
qglVertexAttribPointer = NULL;
qglGetVertexAttribiv = NULL;
qglEnableVertexAttribArray = NULL;
qglDisableVertexAttribArray = NULL;
qglGetUniformLocationARB = NULL;
qglUniformMatrix4fvARB = NULL;
qglUniformMatrix3x4fv = NULL;
qglUniformMatrix4x3fv = NULL;
qglUniform4fARB = NULL;
qglUniform4fvARB = NULL;
qglUniform3fARB = NULL;
qglUniform3fvARB = NULL;
qglUniform2fvARB = NULL;
qglUniform1iARB = NULL;
qglUniform1fARB = NULL;
} }
// glslang // glslang
//the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects.

View file

@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "shader.h" #include "shader.h"
#include <commctrl.h> #include <commctrl.h>
void STT_Event(void);
#ifndef SetWindowLongPtr //yes its a define, for unicode support #ifndef SetWindowLongPtr //yes its a define, for unicode support
#define SetWindowLongPtr SetWindowLong #define SetWindowLongPtr SetWindowLong
#endif #endif
@ -1206,7 +1208,9 @@ qboolean VID_AttachGL (rendererstate_t *info)
else else
attribs[i+1] |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; attribs[i+1] |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
attribs[i] = WGL_CONTEXT_PROFILE_MASK_ARB; attribs[i] = WGL_CONTEXT_PROFILE_MASK_ARB;
i+=2; //WGL_CONTEXT_PROFILE_MASK_ARB is ignored if < 3.2 - however, nvidia do not agree and return errors
if (atof(ver) >= 3.2 || vid_gl_context_es2.ival)
i+=2;
attribs[i] = 0; attribs[i] = 0;
@ -1924,6 +1928,10 @@ LONG WINAPI GLMainWndProc (
IN_RawInput_Read((HANDLE)lParam); IN_RawInput_Read((HANDLE)lParam);
break; break;
case WM_USER:
STT_Event();
break;
case WM_GETMINMAXINFO: case WM_GETMINMAXINFO:
{ {
RECT windowrect; RECT windowrect;

View file

@ -90,8 +90,8 @@ void ClearBounds (vec3_t mins, vec3_t maxs);
#define GL_QUADS (Con_Printf("GL_QUADS was used"),0) #define GL_QUADS (Con_Printf("GL_QUADS was used"),0)
#define GL_PROJECTION (Con_Printf("GL_QUADS was used"),0) #define GL_PROJECTION (Con_Printf("GL_PROJECTION was used"),0)
#define GL_MODELVIEW (Con_Printf("GL_QUADS was used"),0) #define GL_MODELVIEW (Con_Printf("GL_MODELVIEW was used"),0)
#define GL_CLIP_PLANE0 (Con_Printf("GL_CLIP_PLANE0 was used"),0) #define GL_CLIP_PLANE0 (Con_Printf("GL_CLIP_PLANE0 was used"),0)
#define GL_MODULATE (Con_Printf("GL_MODULATE was used"),0) #define GL_MODULATE (Con_Printf("GL_MODULATE was used"),0)
#define GL_FLAT (Con_Printf("GL_FLAT was used"),0) #define GL_FLAT (Con_Printf("GL_FLAT was used"),0)

View file

@ -902,7 +902,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//s0=diffuse, s1=normal, s2=specular, s3=shadowmap //s0=diffuse, s1=normal, s2=specular, s3=shadowmap
//custom modifiers: //custom modifiers:
//PCF(shadowmap) //PCF(shadowmap)
//CUBE(projected cubemap) //CUBEPROJ(projected cubemap)
//SPOT(projected circle
//CUBESHADOW
"#if 0 && defined(GL_ARB_texture_gather) && defined(PCF) \n"
"#extension GL_ARB_texture_gather : enable\n"
"#endif\n"
"varying vec2 tcbase;\n" "varying vec2 tcbase;\n"
@ -910,10 +916,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" "#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n" "varying vec3 eyevector;\n"
"#endif\n" "#endif\n"
"#if defined(PCF) || defined(CUBE)\n" "#if defined(PCF) || defined(CUBEPROJ)\n"
"varying vec4 vshadowcoord;\n" "varying vec4 vtexprojcoord;\n"
"uniform mat4 l_cubematrix;\n"
"#ifndef SPOT\n"
"uniform mat4 l_projmatrix;\n" "uniform mat4 l_projmatrix;\n"
"#endif\n" "#endif\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n" "#include \"sys/skeletal.h\"\n"
"uniform vec3 l_lightposition;\n" "uniform vec3 l_lightposition;\n"
@ -936,33 +945,142 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"eyevector.y = dot(eyeminusvertex, t.xyz);\n" "eyevector.y = dot(eyeminusvertex, t.xyz);\n"
"eyevector.z = dot(eyeminusvertex, n.xyz);\n" "eyevector.z = dot(eyeminusvertex, n.xyz);\n"
"#endif\n" "#endif\n"
"#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE)\n" "#if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n"
"vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0);\n" //for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
"#endif\n" "#endif\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
"#include \"sys/fog.h\"\n" "#include \"sys/fog.h\"\n"
"uniform sampler2D s_t0;\n" "uniform sampler2D s_t0;\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n" "#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"uniform sampler2D s_t1;\n" "uniform sampler2D s_t1;\n"
"#endif\n" "#endif\n"
"#ifdef SPECULAR\n" "#ifdef SPECULAR\n"
"uniform sampler2D s_t2;\n" "uniform sampler2D s_t2;\n"
"#endif\n" "#endif\n"
"#ifdef CUBE\n" "#ifdef CUBEPROJ\n"
"uniform samplerCube s_t3;\n" "uniform samplerCube s_t3;\n"
"#endif\n" "#endif\n"
"#ifdef PCF\n" "#ifdef PCF\n"
"#ifdef CUBE\n" "#ifdef CUBESHADOW\n"
"uniform samplerCubeShadow s_t7;\n" "uniform samplerCubeShadow s_t4;\n"
"#else\n" "#else\n"
"uniform sampler2DShadow s_t7;\n" "#if 0//def GL_ARB_texture_gather\n"
"uniform sampler2D s_t4;\n"
"#else\n"
"uniform sampler2DShadow s_t4;\n"
"#endif\n" "#endif\n"
"#endif\n" "#endif\n"
"#endif\n"
"uniform float l_lightradius;\n" "uniform float l_lightradius;\n"
"uniform vec3 l_lightcolour;\n" "uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightcolourscale;\n" "uniform vec3 l_lightcolourscale;\n"
"#ifdef PCF\n"
//#define shadow2DProj(t,c) (vec2(1.0,1.0))
//#define shadow2DProj(t,c) texture2DProj(t,c).rg
"float ShadowmapFilter(void)\n"
"{\n"
"#ifdef SPOT\n"
"const vec3 texscale = vec3(1.0/512.0, 1.0/512.0, 1.0);\n"
"#else\n"
"const vec3 texscale = vec3(1.0/(512.0*3.0), 1.0/(512.0*2.0), 1.0);\n"
"#endif\n"
//dehomogonize input
"vec3 shadowcoord = (vtexprojcoord.xyz / vtexprojcoord.w);\n"
"#ifdef CUBESHADOW\n"
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
"#else\n"
"#ifdef SPOT\n"
//bias it. don't bother figuring out which side or anything, its not needed
//l_projmatrix contains the light's projection matrix so no other magic needed
"shadowcoord.xyz = (shadowcoord.xyz + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
"#else\n"
//figure out which axis to use
//texture is arranged thusly:
//forward left up
//back right down
"vec3 dir = abs(shadowcoord);\n"
//assume z is the major axis (ie: forward from the light)
"vec3 t = shadowcoord;\n"
"float ma = dir.z;\n"
"vec4 axis = vec4(1.0, 1.0, 1.0, 0.0);\n"
"if (dir.x > ma)\n"
"{\n"
"ma = dir.x;\n"
"t = shadowcoord.zyx;\n"
"axis.x = 3.0;\n"
"}\n"
"if (dir.y > ma)\n"
"{\n"
"ma = dir.y;\n"
"t = shadowcoord.xzy;\n"
"axis.x = 5.0;\n"
"}\n"
"if (t.z > 0.0)\n"
"{\n"
"axis.y = 3.0;\n"
"t.z = -t.z;\n"
"}\n"
//we also need to pass the result through the light's projection matrix too
"vec4 nsc =l_projmatrix*vec4(t, 1.0);\n"
"shadowcoord = (nsc.xyz / nsc.w);\n"
//now bias and relocate it
"shadowcoord = (shadowcoord + axis.xyz) * vec3(0.5/3.0, 0.5/2.0, 0.5);\n"
"#endif\n"
"#if 0//def GL_ARB_texture_gather\n"
"vec2 ipart, fpart;\n"
"#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n"
"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n"
"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n"
"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n"
"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n"
//we now have 4*4 results, woo
//we can just average them for 1/16th precision, but that's still limited graduations
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
"vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength\n"
"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows\n"
"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.\n"
"#else\n"
"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*texscale.xyz)).r\n"
"float s = 0.0;\n"
"s += dosamp(-1.0, -1.0);\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(-1.0, 1.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, -1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"s += dosamp(1.0, 1.0);\n"
"return s/9.0;\n"
"#endif\n"
"#endif\n"
"}\n"
"#endif\n"
"#ifdef OFFSETMAPPING\n" "#ifdef OFFSETMAPPING\n"
"#include \"sys/offsetmapping.h\"\n" "#include \"sys/offsetmapping.h\"\n"
"#endif\n" "#endif\n"
@ -987,6 +1105,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef BUMP\n" "#ifdef BUMP\n"
"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));\n" "diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));\n"
"#else\n" "#else\n"
//we still do bumpmapping even without bumps to ensure colours are always sane. light.exe does it too.
"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n" "diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
"#endif\n" "#endif\n"
@ -999,54 +1118,30 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef CUBE\n" "#ifdef CUBEPROJ\n"
"diff *= textureCube(s_t3, vshadowcoord.xyz).rgb;\n" /*filter the colour by the cubemap projection*/
"diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;\n"
"#endif\n" "#endif\n"
"#if defined(SPOT)\n"
/*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/
"if (vtexprojcoord.w < 0.0) discard;\n"
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));\n"
"#endif\n"
"#ifdef PCF\n" "#ifdef PCF\n"
"#if defined(SPOT)\n" /*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
"const float texx = 512.0;\n" //diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
"const float texy = 512.0;\n" "colorscale *= ShadowmapFilter();\n"
"vec4 shadowcoord = vshadowcoord;\n" // gl_FragColor.rgb = vec3(ShadowmapFilter());
"#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"
"const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadowCubeProj(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"
"#else\n"
"const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n"
"s += shadow2DProj(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"
"#endif\n"
"#endif\n"
"#if defined(SPOT)\n"
"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" "#endif\n"
"#if defined(PROJECTION)\n" "#if defined(PROJECTION)\n"
"l_lightcolour *= texture2d(s_t3, shadowcoord);\n" /*2d projection, not used*/
// diff *= texture2d(s_t3, shadowcoord);
"#endif\n" "#endif\n"
"gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" "gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
@ -1107,14 +1202,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#include \"sys/fog.h\"\n" "#include \"sys/fog.h\"\n"
"varying vec2 tc;\n" "varying vec2 tc;\n"
"varying vec2 lm;\n" "varying vec2 lm;\n"
"varying vec4 vc;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n" "attribute vec2 v_lmcoord;\n"
"attribute vec4 v_colour;\n"
"void main (void)\n" "void main (void)\n"
"{\n" "{\n"
"tc = v_texcoord.st;\n" "tc = v_texcoord.st;\n"
"lm = v_lmcoord.st;\n" "lm = v_lmcoord.st;\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n" "gl_Position = ftetransform();\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
@ -1137,7 +1235,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"{\n" "{\n"
"vec4 m = texture2D(s_t4, lm);\n" "vec4 m = texture2D(s_t4, lm);\n"
"gl_FragColor = fog4(vec4(m.aaa,1.0)*(\n" "gl_FragColor = fog4(vc*vec4(m.aaa,1.0)*(\n"
"texture2D(s_t0, tc)*m.r\n" "texture2D(s_t0, tc)*m.r\n"
"+ texture2D(s_t1, tc)*m.g\n" "+ texture2D(s_t1, tc)*m.g\n"
"+ texture2D(s_t2, tc)*m.b\n" "+ texture2D(s_t2, tc)*m.b\n"

View file

@ -336,6 +336,7 @@ typedef struct {
SP_LIGHTPOSITION, SP_LIGHTPOSITION,
SP_LIGHTSCREEN, SP_LIGHTSCREEN,
SP_LIGHTPROJMATRIX, SP_LIGHTPROJMATRIX,
SP_LIGHTCUBEMATRIX,
//things that are set immediatly //things that are set immediatly
SP_FIRSTIMMEDIATE, //never set SP_FIRSTIMMEDIATE, //never set
@ -556,7 +557,7 @@ void BE_GenerateProgram(shader_t *shader);
#ifdef RTLIGHTS #ifdef RTLIGHTS
void BE_PushOffsetShadow(qboolean foobar); void BE_PushOffsetShadow(qboolean foobar);
//sets up gl for depth-only FIXME //sets up gl for depth-only FIXME
void BE_SetupForShadowMap(void); void BE_SetupForShadowMap(texid_t shadowmaptex);
//Called from shadowmapping code into backend //Called from shadowmapping code into backend
void GLBE_BaseEntTextures(void); void GLBE_BaseEntTextures(void);
void D3DBE_BaseEntTextures(void); void D3DBE_BaseEntTextures(void);

View file

@ -3324,9 +3324,9 @@ static void QCBUILTIN PF_stuffcmd (progfuncs_t *prinst, struct globalvars_s *pr_
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_single, entnum - 1, 2 + slen); sizebuf_t *msg = MVDWrite_Begin (dem_single, entnum - 1, 2 + slen);
MSG_WriteByte (&demo.dbuf->sb, svc_stufftext); MSG_WriteByte (msg, svc_stufftext);
MSG_WriteString (&demo.dbuf->sb, str); MSG_WriteString (msg, str);
} }
} }

View file

@ -646,8 +646,8 @@ typedef struct {
typedef struct typedef struct
{ {
demobuf_t *dbuf; // demobuf_t *dbuf;
dbuffer_t dbuffer; // dbuffer_t dbuffer;
sizebuf_t datagram; sizebuf_t datagram;
qbyte datagram_data[MSG_BUF_SIZE]; qbyte datagram_data[MSG_BUF_SIZE];
int lastto; int lastto;
@ -1270,8 +1270,7 @@ typedef struct mvddest_s {
} mvddest_t; } mvddest_t;
void SV_MVDPings (void); void SV_MVDPings (void);
void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player); void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player);
void SV_MVDWriteToDisk(int type, int to, float time); sizebuf_t *MVDWrite_Begin(qbyte type, int to, int size);
qboolean MVDWrite_Begin(qbyte type, int to, int size);
void MVDSetMsgBuf(demobuf_t *prev,demobuf_t *cur); void MVDSetMsgBuf(demobuf_t *prev,demobuf_t *cur);
void SV_MVDStop (int reason, qboolean mvdonly); void SV_MVDStop (int reason, qboolean mvdonly);
void SV_MVDStop_f (void); void SV_MVDStop_f (void);

View file

@ -1590,13 +1590,14 @@ void SV_ConSay_f(void)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_all, 0, strlen(text)+4); sizebuf_t *msg;
MSG_WriteByte (&demo.dbuf->sb, svc_print); msg = MVDWrite_Begin (dem_all, 0, strlen(text)+4);
MSG_WriteByte (&demo.dbuf->sb, PRINT_CHAT); MSG_WriteByte (msg, svc_print);
MSG_WriteByte (msg, PRINT_CHAT);
for (j = 0; text[j]; j++) for (j = 0; text[j]; j++)
MSG_WriteChar(&demo.dbuf->sb, text[j]); MSG_WriteChar(msg, text[j]);
MSG_WriteChar(&demo.dbuf->sb, '\n'); MSG_WriteChar(msg, '\n');
MSG_WriteChar(&demo.dbuf->sb, 0); MSG_WriteChar(msg, 0);
} }
} }

View file

@ -31,10 +31,10 @@ void SV_MVDStop_f (void);
#define demo_size_padding 0x1000 #define demo_size_padding 0x1000
#define MIN_MVD_MEMORY 0x100000 //#define MIN_MVD_MEMORY 0x100000
#define MAXSIZE (demobuffer->end < demobuffer->last ? \ //#define MAXSIZE (demobuffer->end < demobuffer->last ? \
demobuffer->start - demobuffer->end : \ // demobuffer->start - demobuffer->end : \
demobuffer->maxsize - demobuffer->end) // demobuffer->maxsize - demobuffer->end)
static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue); static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue);
@ -59,10 +59,16 @@ cvar_t sv_demoSuffix = CVAR("sv_demoSuffix", "");
cvar_t sv_demotxt = CVAR("sv_demotxt", "1"); cvar_t sv_demotxt = CVAR("sv_demotxt", "1");
void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time); void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time);
void SV_WriteRecordMVDMessage (sizebuf_t *msg);
demo_t demo; demo_t demo;
static dbuffer_t *demobuffer; static float demo_prevtime;
static int header = (char *)&((header_t*)0)->data - (char *)NULL; //static dbuffer_t *demobuffer;
//static int header = (char *)&((header_t*)0)->data - (char *)NULL;
static sizebuf_t demomsg;
int demomsgtype;
int demomsgto;
static char demomsgbuf[MAX_OVERALLMSGLEN];
entity_state_t demo_entities[UPDATE_MASK+1][MAX_MVDPACKET_ENTITIES]; entity_state_t demo_entities[UPDATE_MASK+1][MAX_MVDPACKET_ENTITIES];
client_frame_t demo_frames[UPDATE_MASK+1]; client_frame_t demo_frames[UPDATE_MASK+1];
@ -753,6 +759,7 @@ static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue)
void SV_MVDPings (void) void SV_MVDPings (void)
{ {
sizebuf_t *msg;
client_t *client; client_t *client;
int j; int j;
@ -761,50 +768,45 @@ void SV_MVDPings (void)
if (client->state != cs_spawned) if (client->state != cs_spawned)
continue; continue;
MVDWrite_Begin (dem_all, 0, 7); msg = MVDWrite_Begin (dem_all, 0, 7);
MSG_WriteByte(&demo.dbuf->sb, svc_updateping); MSG_WriteByte(msg, svc_updateping);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(msg, j);
MSG_WriteShort(&demo.dbuf->sb, SV_CalcPing(client, false)); MSG_WriteShort(msg, SV_CalcPing(client, false));
MSG_WriteByte(&demo.dbuf->sb, svc_updatepl); MSG_WriteByte(msg, svc_updatepl);
MSG_WriteByte (&demo.dbuf->sb, j); MSG_WriteByte (msg, j);
MSG_WriteByte (&demo.dbuf->sb, client->lossage); MSG_WriteByte (msg, client->lossage);
} }
} }
void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player) void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
{ {
char info[MAX_INFO_STRING]; char info[MAX_INFO_STRING];
qboolean dosizes; qboolean dosizes;
if (!sv.mvdrecording) if (!sv.mvdrecording)
return; return;
if (msg) dosizes = !msg;
dosizes = false;
else
{
dosizes = true;
msg = &demo.dbuf->sb;
}
if (dosizes) if (dosizes)
MVDWrite_Begin (dem_all, 0, 4); msg = MVDWrite_Begin (dem_all, 0, 4);
MSG_WriteByte (msg, svc_updatefrags); MSG_WriteByte (msg, svc_updatefrags);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteShort (msg, player->old_frags); MSG_WriteShort (msg, player->old_frags);
if (dosizes) if (dosizes)
MVDWrite_Begin (dem_all, 0, 4); msg = MVDWrite_Begin (dem_all, 0, 4);
MSG_WriteByte (msg, svc_updateping); MSG_WriteByte (msg, svc_updateping);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteShort (msg, SV_CalcPing(player, false)); MSG_WriteShort (msg, SV_CalcPing(player, false));
if (dosizes) if (dosizes)
MVDWrite_Begin (dem_all, 0, 3); msg = MVDWrite_Begin (dem_all, 0, 3);
MSG_WriteByte (msg, svc_updatepl); MSG_WriteByte (msg, svc_updatepl);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteByte (msg, player->lossage); MSG_WriteByte (msg, player->lossage);
if (dosizes) if (dosizes)
MVDWrite_Begin (dem_all, 0, 6); msg = MVDWrite_Begin (dem_all, 0, 6);
MSG_WriteByte (msg, svc_updateentertime); MSG_WriteByte (msg, svc_updateentertime);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteFloat (msg, realtime - player->connection_started); MSG_WriteFloat (msg, realtime - player->connection_started);
@ -815,47 +817,14 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
Info_RemoveKey(info, "*ip"); Info_RemoveKey(info, "*ip");
if (dosizes) if (dosizes)
MVDWrite_Begin (dem_all, 0, 7 + strlen(info)); msg = MVDWrite_Begin (dem_all, 0, 7 + strlen(info));
MSG_WriteByte (msg, svc_updateuserinfo); MSG_WriteByte (msg, svc_updateuserinfo);
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteLong (msg, player->userid); MSG_WriteLong (msg, player->userid);
MSG_WriteString (msg, info); MSG_WriteString (msg, info);
} }
void MVDBuffer_Init(dbuffer_t *dbuffer, qbyte *buf, size_t size) #if 0
{
demobuffer = dbuffer;
demobuffer->data = buf;
demobuffer->maxsize = size;
demobuffer->start = 0;
demobuffer->end = 0;
demobuffer->last = 0;
}
/*
==============
MVD_SetMsgBuf
Sets the frame message buffer
==============
*/
void MVDSetMsgBuf(demobuf_t *prev,demobuf_t *cur)
{
// fix the maxsize of previous msg buffer,
// we won't be able to write there anymore
if (prev != NULL)
prev->sb.maxsize = prev->bufsize;
demo.dbuf = cur;
memset(demo.dbuf, 0, sizeof(*demo.dbuf));
demo.dbuf->sb.data = demobuffer->data + demobuffer->end;
demo.dbuf->sb.maxsize = MAXSIZE;
demo.dbuf->sb.prim = demo.recorder.netchan.netprim;
}
/* /*
============== ==============
DemoWriteToDisk DemoWriteToDisk
@ -866,7 +835,7 @@ Message is cleared from demobuf after that
============== ==============
*/ */
void SV_MVDWriteToDisk(int type, int to, float time) static void SV_MVDWriteToDisk(int type, int to, float time)
{ {
int pos = 0, oldm, oldd; int pos = 0, oldm, oldd;
header_t *p; header_t *p;
@ -921,63 +890,21 @@ void SV_MVDWriteToDisk(int type, int to, float time)
demobuffer->start = 0; demobuffer->start = 0;
} }
} }
#endif
/* sizebuf_t *MVDWrite_Begin(qbyte type, int to, int size)
==============
MVDSetBuf
Sets position in the buf for writing to specific client
==============
*/
static void MVDSetBuf(qbyte type, int to)
{ {
header_t *p; if (demomsg.cursize)
int pos = 0; SV_WriteMVDMessage(&demomsg, demomsgtype, demomsgto, demo_prevtime);
p = (header_t *)demo.dbuf->sb.data; demomsgtype = type;
demomsgto = to;
while (pos < demo.dbuf->bufsize) demomsg.maxsize = size;
{ demomsg.cursize = 0;
pos += header + p->size; demomsg.data = demomsgbuf;
return &demomsg;
if (type == p->type && to == p->to && !p->full) #if 0
{
demo.dbuf->sb.cursize = pos;
demo.dbuf->h = p;
return;
}
p = (header_t *)(p->data + p->size);
}
// type&&to not exist in the buf, so add it
p->type = type;
p->to = to;
p->size = 0;
p->full = 0;
demo.dbuf->bufsize += header;
demo.dbuf->sb.cursize = demo.dbuf->bufsize;
demobuffer->end += header;
demo.dbuf->h = p;
}
void MVDMoveBuf(void)
{
// set the last message mark to the previous frame (i/e begining of this one)
demobuffer->last = demobuffer->end - demo.dbuf->bufsize;
// move buffer to the begining of demo buffer
memmove(demobuffer->data, demo.dbuf->sb.data, demo.dbuf->bufsize);
demo.dbuf->sb.data = demobuffer->data;
demobuffer->end = demo.dbuf->bufsize;
demo.dbuf->h = NULL; // it will be setup again
demo.dbuf->sb.maxsize = MAXSIZE + demo.dbuf->bufsize;
}
qboolean MVDWrite_Begin(qbyte type, int to, int size)
{
qbyte *p; qbyte *p;
qboolean move = false; qboolean move = false;
@ -1017,28 +944,37 @@ qboolean MVDWrite_Begin(qbyte type, int to, int size)
demobuffer->last = demobuffer->end; demobuffer->last = demobuffer->end;
return true; return true;
#endif
} }
/* /*
==================== ====================
SV_WriteMVDMessage SV_WriteMVDMessage
Dumps the current net message, prefixed by the length and view angles Dumps the current net message, along with framing
==================== ====================
*/ */
void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time) void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time)
{ {
int len, i, msec; int len, i, msec;
qbyte c; qbyte c;
static double prevtime;
if (!sv.mvdrecording) if (!sv.mvdrecording)
return; return;
msec = (time - prevtime)*1000; msec = (time - demo_prevtime)*1000;
prevtime += msec*0.001; if (abs(msec) > 1000)
if (msec > 255) msec = 255; {
if (msec < 2) msec = 0; //catastoptic slip. debugging? reset any sync
msec = 0;
demo_prevtime = time;
}
else
{
if (msec > 255) msec = 255;
if (msec < 2) msec = 0;
demo_prevtime += msec*0.001;
}
c = msec; c = msec;
DemoWrite(&c, sizeof(c)); DemoWrite(&c, sizeof(c));
@ -1155,8 +1091,6 @@ qboolean SV_MVDWritePackets (int num)
nextframe = frame; nextframe = frame;
msg.cursize = 0; msg.cursize = 0;
demo.dbuf = &frame->buf;
// find two frames // find two frames
// one before the exact time (time - msec) and one after, // one before the exact time (time - msec) and one after,
// then we can interpolte exact position for current frame // then we can interpolte exact position for current frame
@ -1264,8 +1198,8 @@ qboolean SV_MVDWritePackets (int num)
demoinfo->model = cl->info.model; demoinfo->model = cl->info.model;
} }
SV_MVDWriteToDisk(demo.lasttype,demo.lastto, (float)time); // this goes first to reduce demo size a bit //flush any intermediate data
SV_MVDWriteToDisk(0,0, (float)time); // now goes the rest MVDWrite_Begin(255, -1, 0);
if (msg.cursize) if (msg.cursize)
SV_WriteMVDMessage(&msg, dem_all, 0, (float)time); SV_WriteMVDMessage(&msg, dem_all, 0, (float)time);
@ -1277,9 +1211,6 @@ qboolean SV_MVDWritePackets (int num)
if (demo.lastwritten > demo.parsecount) if (demo.lastwritten > demo.parsecount)
demo.lastwritten = demo.parsecount; demo.lastwritten = demo.parsecount;
demo.dbuf = &demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf;
demo.dbuf->sb.maxsize = MAXSIZE + demo.dbuf->bufsize;
return true; return true;
} }
@ -1497,6 +1428,7 @@ stop recording a demo
*/ */
void SV_MVDStop (int reason, qboolean mvdonly) void SV_MVDStop (int reason, qboolean mvdonly)
{ {
sizebuf_t *msg;
int numclosed; int numclosed;
if (!sv.mvdrecording) if (!sv.mvdrecording)
{ {
@ -1521,15 +1453,11 @@ void SV_MVDStop (int reason, qboolean mvdonly)
return; return;
} }
// write a disconnect message to the demo file
// clearup to be sure message will fit // write a disconnect message to the demo file
demo.dbuf->sb.cursize = 0; msg = MVDWrite_Begin(dem_all, 0, 2+strlen("EndOfDemo"));
demo.dbuf->h = NULL; MSG_WriteByte (msg, svc_disconnect);
demo.dbuf->bufsize = 0; MSG_WriteString (msg, "EndOfDemo");
MVDWrite_Begin(dem_all, 0, 2+strlen("EndOfDemo"));
MSG_WriteByte (&demo.dbuf->sb, svc_disconnect);
MSG_WriteString (&demo.dbuf->sb, "EndOfDemo");
SV_MVDWritePackets(demo.parsecount - demo.lastwritten + 1); SV_MVDWritePackets(demo.parsecount - demo.lastwritten + 1);
// finish up // finish up
@ -1579,7 +1507,7 @@ Dumps the current net message, prefixed by the length and view angles
==================== ====================
*/ */
void SV_WriteRecordMVDMessage (sizebuf_t *msg, int seq) void SV_WriteRecordMVDMessage (sizebuf_t *msg)
{ {
int len; int len;
qbyte c; qbyte c;
@ -1660,14 +1588,17 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
demo.recorder.frameunion.frames[i].entities.entities = demo_entities[i]; demo.recorder.frameunion.frames[i].entities.entities = demo_entities[i];
} }
MVDBuffer_Init(&demo.dbuffer, demo.buffer, sizeof(demo.buffer));
MVDSetMsgBuf(NULL, &demo.frames[0].buf);
demo.datagram.maxsize = sizeof(demo.datagram_data); demo.datagram.maxsize = sizeof(demo.datagram_data);
demo.datagram.data = demo.datagram_data; demo.datagram.data = demo.datagram_data;
demo.datagram.prim = demo.recorder.netchan.netprim; demo.datagram.prim = demo.recorder.netchan.netprim;
if (sv_demoExtensions.ival) if (sv_demoExtensions.ival == 2)
{ /*more limited subset supported by ezquake*/
demo.recorder.fteprotocolextensions = PEXT_CHUNKEDDOWNLOADS|PEXT_256PACKETENTITIES|PEXT_FLOATCOORDS|PEXT_ACCURATETIMINGS|PEXT_TRANS|PEXT_HLBSP|PEXT_MODELDBL|PEXT_ENTITYDBL|PEXT_ENTITYDBL2|PEXT_SPAWNSTATIC2;
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT;
demo.recorder.zquake_extensions = Z_EXT_PM_TYPE | Z_EXT_PM_TYPE_NEW | Z_EXT_VIEWHEIGHT | Z_EXT_SERVERTIME | Z_EXT_PITCHLIMITS | Z_EXT_JOIN_OBSERVE | Z_EXT_VWEP;
}
else
{ {
demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS | PEXT_VIEW2; demo.recorder.fteprotocolextensions = PEXT_CSQC | PEXT_COLOURMOD | PEXT_DPFLAGS | PEXT_CUSTOMTEMPEFFECTS | PEXT_ENTITYDBL | PEXT_ENTITYDBL2 | PEXT_FATNESS | PEXT_HEXEN2 | PEXT_HULLSIZE | PEXT_LIGHTSTYLECOL | PEXT_MODELDBL | PEXT_SCALE | PEXT_SETATTACHMENT | PEXT_SETVIEW | PEXT_SOUNDDBL | PEXT_SPAWNSTATIC2 | PEXT_TRANS | PEXT_VIEW2;
demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR; demo.recorder.fteprotocolextensions2 = PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_PRYDONCURSOR;
@ -1677,6 +1608,9 @@ static qboolean SV_MVD_Record (mvddest_t *dest)
demo.recorder.zquake_extensions = Z_EXT_PM_TYPE | Z_EXT_PM_TYPE_NEW | Z_EXT_VIEWHEIGHT | Z_EXT_SERVERTIME | Z_EXT_PITCHLIMITS | Z_EXT_JOIN_OBSERVE | Z_EXT_VWEP; demo.recorder.zquake_extensions = Z_EXT_PM_TYPE | Z_EXT_PM_TYPE_NEW | Z_EXT_VIEWHEIGHT | Z_EXT_SERVERTIME | Z_EXT_PITCHLIMITS | Z_EXT_JOIN_OBSERVE | Z_EXT_VWEP;
} }
//pointless extensions that are redundant with mvds
demo.recorder.fteprotocolextensions &= ~PEXT_ACCURATETIMINGS | PEXT_HLBSP|PEXT_Q2BSP|PEXT_Q3BSP;
demo.recorder.max_net_ents = 512; demo.recorder.max_net_ents = 512;
if (demo.recorder.fteprotocolextensions & PEXT_ENTITYDBL) if (demo.recorder.fteprotocolextensions & PEXT_ENTITYDBL)
demo.recorder.max_net_ents += 512; demo.recorder.max_net_ents += 512;
@ -1706,7 +1640,6 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
client_t *player; client_t *player;
char *gamedir; char *gamedir;
int seq = 1;
if (!demo.dest) if (!demo.dest)
return; return;
@ -1789,7 +1722,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", svs.info) ); MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", svs.info) );
// flush packet // flush packet
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
// soundlist // soundlist
@ -1805,7 +1738,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n); MSG_WriteByte (&buf, n);
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_soundlist); MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, n + 1); MSG_WriteByte (&buf, n + 1);
@ -1818,7 +1751,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1835,7 +1768,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n); MSG_WriteByte (&buf, n);
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_modellist); MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, n + 1); MSG_WriteByte (&buf, n + 1);
@ -1847,7 +1780,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1915,7 +1848,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
} }
if (buf.cursize > MAX_QWMSGLEN/2) if (buf.cursize > MAX_QWMSGLEN/2)
{ {
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
} }
@ -1927,7 +1860,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
{ {
if (buf.cursize+sv.signon_buffer_size[n] > MAX_QWMSGLEN/2) if (buf.cursize+sv.signon_buffer_size[n] > MAX_QWMSGLEN/2)
{ {
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
SZ_Write (&buf, SZ_Write (&buf,
@ -1937,7 +1870,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (buf.cursize > MAX_QWMSGLEN/2) if (buf.cursize > MAX_QWMSGLEN/2)
{ {
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1946,7 +1879,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (buf.cursize) if (buf.cursize)
{ {
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
@ -1960,7 +1893,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
if (buf.cursize > MAX_QWMSGLEN/2) if (buf.cursize > MAX_QWMSGLEN/2)
{ {
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
} }
@ -1993,7 +1926,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest)
MSG_WriteByte (&buf, svc_stufftext); MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, "skins\n"); MSG_WriteString (&buf, "skins\n");
SV_WriteRecordMVDMessage (&buf, seq++); SV_WriteRecordMVDMessage (&buf);
SV_WriteSetMVDMessage(); SV_WriteSetMVDMessage();

View file

@ -314,10 +314,10 @@ void VARGS SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_single, cl - svs.clients, strlen(string)+3); sizebuf_t *msg = MVDWrite_Begin (dem_single, cl - svs.clients, strlen(string)+3);
MSG_WriteByte (&demo.dbuf->sb, svc_print); MSG_WriteByte (msg, svc_print);
MSG_WriteByte (&demo.dbuf->sb, level); MSG_WriteByte (msg, level);
MSG_WriteString (&demo.dbuf->sb, string); MSG_WriteString (msg, string);
} }
if (cl->controller) if (cl->controller)
@ -344,10 +344,10 @@ void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t stringnum, .
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_single, cl - svs.clients, strlen(string)+3); sizebuf_t *msg = MVDWrite_Begin (dem_single, cl - svs.clients, strlen(string)+3);
MSG_WriteByte (&demo.dbuf->sb, svc_print); MSG_WriteByte (msg, svc_print);
MSG_WriteByte (&demo.dbuf->sb, level); MSG_WriteByte (msg, level);
MSG_WriteString (&demo.dbuf->sb, string); MSG_WriteString (msg, string);
} }
SV_PrintToClient(cl, level, string); SV_PrintToClient(cl, level, string);
@ -393,10 +393,10 @@ void VARGS SV_BroadcastPrintf (int level, char *fmt, ...)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_all, 0, strlen(string)+3); sizebuf_t *msg = MVDWrite_Begin (dem_all, 0, strlen(string)+3);
MSG_WriteByte (&demo.dbuf->sb, svc_print); MSG_WriteByte (msg, svc_print);
MSG_WriteByte (&demo.dbuf->sb, level); MSG_WriteByte (msg, level);
MSG_WriteString (&demo.dbuf->sb, string); MSG_WriteString (msg, string);
} }
} }
@ -794,24 +794,24 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
} }
} }
if (sv.mvdrecording && !with) //mvds don't get the pext stuff if (sv.mvdrecording && ((demo.recorder.fteprotocolextensions & with) == with) && !(demo.recorder.fteprotocolextensions & without))
{ {
sizebuf_t *msg;
if (!mask) if (!mask)
{ {
/*no distinction between reliable or not*/ /*no distinction between reliable or not*/
MVDWrite_Begin(dem_single, pnum, sv.multicast.cursize); msg = MVDWrite_Begin(dem_single, pnum, sv.multicast.cursize);
SZ_Write(&demo.dbuf->sb, sv.multicast.data, sv.multicast.cursize);
} }
else else
{ {
if (reliable) if (reliable)
{ {
MVDWrite_Begin(dem_all, 0, sv.multicast.cursize); msg = MVDWrite_Begin(dem_all, 0, sv.multicast.cursize);
SZ_Write(&demo.dbuf->sb, sv.multicast.data, sv.multicast.cursize);
} }
else else
SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize); msg = &demo.datagram;
} }
SZ_Write(&demo.datagram, sv.multicast.data, sv.multicast.cursize);
} }
#ifdef NQPROT #ifdef NQPROT
@ -1141,9 +1141,9 @@ void SV_WriteCenterPrint(client_t *cl, char *s)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_single, cl - svs.clients, 2 + strlen(s)); sizebuf_t *msg = MVDWrite_Begin (dem_single, cl - svs.clients, 2 + strlen(s));
MSG_WriteByte (&demo.dbuf->sb, svc_centerprint); MSG_WriteByte (msg, svc_centerprint);
MSG_WriteString (&demo.dbuf->sb, s); MSG_WriteString (msg, s);
} }
} }
@ -2025,10 +2025,10 @@ void SV_UpdateToReliableMessages (void)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin(dem_all, 0, 4); sizebuf_t *msg = MVDWrite_Begin(dem_all, 0, 4);
MSG_WriteByte(&demo.dbuf->sb, svc_updatefrags); MSG_WriteByte(msg, svc_updatefrags);
MSG_WriteByte(&demo.dbuf->sb, i); MSG_WriteByte(msg, i);
MSG_WriteShort(&demo.dbuf->sb, host_client->edict->v->frags); MSG_WriteShort(msg, host_client->edict->v->frags);
} }
host_client->old_frags = host_client->edict->v->frags; host_client->old_frags = host_client->edict->v->frags;
@ -2086,10 +2086,10 @@ void SV_UpdateToReliableMessages (void)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin(dem_all, 0, 4); sizebuf_t *msg = MVDWrite_Begin(dem_all, 0, 4);
MSG_WriteByte(&demo.dbuf->sb, svc_updatefrags); MSG_WriteByte(msg, svc_updatefrags);
MSG_WriteByte(&demo.dbuf->sb, i); MSG_WriteByte(msg, i);
MSG_WriteShort(&demo.dbuf->sb, curfrags); MSG_WriteShort(msg, curfrags);
} }
host_client->old_frags = curfrags; host_client->old_frags = curfrags;
@ -2391,6 +2391,7 @@ void SV_SendMVDMessage(void)
extern cvar_t sv_demofps; extern cvar_t sv_demofps;
extern cvar_t sv_demoPings; extern cvar_t sv_demoPings;
// extern cvar_t sv_demoMaxSize; // extern cvar_t sv_demoMaxSize;
sizebuf_t *dmsg;
SV_MVD_RunPendingConnections(); SV_MVD_RunPendingConnections();
@ -2461,11 +2462,11 @@ void SV_SendMVDMessage(void)
if (statss[j] || demo.statss[i][j]) if (statss[j] || demo.statss[i][j])
if (strcmp(statss[j]?statss[j]:"", demo.statss[i][j]?demo.statss[i][j]:"")) if (strcmp(statss[j]?statss[j]:"", demo.statss[i][j]?demo.statss[i][j]:""))
{ {
MVDWrite_Begin(dem_stats, i, 3+strlen(statss[j])); sizebuf_t *msg = MVDWrite_Begin(dem_stats, i, 3+strlen(statss[j]));
demo.statss[i][j] = statss[j]; demo.statss[i][j] = statss[j];
MSG_WriteByte(&demo.dbuf->sb, svcfte_updatestatstring); MSG_WriteByte(msg, svcfte_updatestatstring);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(msg, j);
MSG_WriteString(&demo.dbuf->sb, statss[j]); MSG_WriteString(msg, statss[j]);
} }
} }
@ -2477,17 +2478,17 @@ void SV_SendMVDMessage(void)
{ {
if (statsf[j] - (float)(int)statsf[j] == 0 && statsf[j] >= 0 && statsf[j] <= 255) if (statsf[j] - (float)(int)statsf[j] == 0 && statsf[j] >= 0 && statsf[j] <= 255)
{ {
MVDWrite_Begin(dem_stats, i, 3); dmsg = MVDWrite_Begin(dem_stats, i, 3);
MSG_WriteByte(&demo.dbuf->sb, svc_updatestat); MSG_WriteByte(dmsg, svc_updatestat);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(dmsg, j);
MSG_WriteByte(&demo.dbuf->sb, statsf[j]); MSG_WriteByte(dmsg, statsf[j]);
} }
else else
{ {
MVDWrite_Begin(dem_stats, i, 6); dmsg = MVDWrite_Begin(dem_stats, i, 6);
MSG_WriteByte(&demo.dbuf->sb, svcfte_updatestatfloat); MSG_WriteByte(dmsg, svcfte_updatestatfloat);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(dmsg, j);
MSG_WriteFloat(&demo.dbuf->sb, statsf[j]); MSG_WriteFloat(dmsg, statsf[j]);
} }
demo.statsf[i][j] = statsf[j]; demo.statsf[i][j] = statsf[j];
/*make sure statsf is correct*/ /*make sure statsf is correct*/
@ -2505,17 +2506,17 @@ void SV_SendMVDMessage(void)
demo.statsf[i][j] = statsi[j]; demo.statsf[i][j] = statsi[j];
if (statsi[j] >=0 && statsi[j] <= 255) if (statsi[j] >=0 && statsi[j] <= 255)
{ {
MVDWrite_Begin(dem_stats, i, 3); dmsg = MVDWrite_Begin(dem_stats, i, 3);
MSG_WriteByte(&demo.dbuf->sb, svc_updatestat); MSG_WriteByte(dmsg, svc_updatestat);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(dmsg, j);
MSG_WriteByte(&demo.dbuf->sb, statsi[j]); MSG_WriteByte(dmsg, statsi[j]);
} }
else else
{ {
MVDWrite_Begin(dem_stats, i, 6); dmsg = MVDWrite_Begin(dem_stats, i, 6);
MSG_WriteByte(&demo.dbuf->sb, svc_updatestatlong); MSG_WriteByte(dmsg, svc_updatestatlong);
MSG_WriteByte(&demo.dbuf->sb, j); MSG_WriteByte(dmsg, j);
MSG_WriteLong(&demo.dbuf->sb, statsi[j]); MSG_WriteLong(dmsg, statsi[j]);
} }
} }
} }
@ -2531,15 +2532,14 @@ void SV_SendMVDMessage(void)
SV_WriteEntitiesToClient (&demo.recorder, &msg, true); SV_WriteEntitiesToClient (&demo.recorder, &msg, true);
if (!MVDWrite_Begin(dem_all, 0, msg.cursize)) dmsg = MVDWrite_Begin(dem_all, 0, msg.cursize);
return; SZ_Write (dmsg, msg.data, msg.cursize);
SZ_Write (&demo.dbuf->sb, msg.data, msg.cursize);
// copy the accumulated multicast datagram // copy the accumulated multicast datagram
// for this client out to the message // for this client out to the message
if (demo.datagram.cursize) { if (demo.datagram.cursize)
MVDWrite_Begin(dem_all, 0, demo.datagram.cursize); {
SZ_Write (&demo.dbuf->sb, demo.datagram.data, demo.datagram.cursize); dmsg = MVDWrite_Begin(dem_all, 0, demo.datagram.cursize);
SZ_Write (dmsg, demo.datagram.data, demo.datagram.cursize);
SZ_Clear (&demo.datagram); SZ_Clear (&demo.datagram);
} }
@ -2553,7 +2553,7 @@ void SV_SendMVDMessage(void)
} }
demo.parsecount++; demo.parsecount++;
MVDSetMsgBuf(demo.dbuf,&demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf); // MVDSetMsgBuf(demo.dbuf,&demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf);
} }

View file

@ -2351,10 +2351,11 @@ void SV_VoiceReadPacket(void)
if (sv.mvdrecording && sv_voip_record.ival && !(sv_voip_record.ival == 2 && !host_client->spectator)) if (sv.mvdrecording && sv_voip_record.ival && !(sv_voip_record.ival == 2 && !host_client->spectator))
{ {
sizebuf_t *msg;
// non-team messages should be seen always, even if not tracking any player // non-team messages should be seen always, even if not tracking any player
if (vt == VT_ALL && (!host_client->spectator || sv_spectalk.ival)) if (vt == VT_ALL && (!host_client->spectator || sv_spectalk.ival))
{ {
MVDWrite_Begin (dem_all, 0, ring->datalen+6); msg = MVDWrite_Begin (dem_all, 0, ring->datalen+6);
} }
else else
{ {
@ -2363,15 +2364,15 @@ void SV_VoiceReadPacket(void)
(ring->receiver[1]<<8) | (ring->receiver[1]<<8) |
(ring->receiver[2]<<16) | (ring->receiver[2]<<16) |
(ring->receiver[3]<<24); (ring->receiver[3]<<24);
MVDWrite_Begin (dem_multiple, cls, ring->datalen+6); msg = MVDWrite_Begin (dem_multiple, cls, ring->datalen+6);
} }
MSG_WriteByte( &demo.dbuf->sb, svcfte_voicechat); MSG_WriteByte(msg, svcfte_voicechat);
MSG_WriteByte( &demo.dbuf->sb, ring->sender); MSG_WriteByte(msg, ring->sender);
MSG_WriteByte( &demo.dbuf->sb, ring->gen); MSG_WriteByte(msg, ring->gen);
MSG_WriteByte( &demo.dbuf->sb, ring->seq); MSG_WriteByte(msg, ring->seq);
MSG_WriteShort(&demo.dbuf->sb, ring->datalen); MSG_WriteShort(msg, ring->datalen);
SZ_Write( &demo.dbuf->sb, ring->data, ring->datalen); SZ_Write(msg, ring->data, ring->datalen);
} }
} }
void SV_VoiceInitClient(client_t *client) void SV_VoiceInitClient(client_t *client)
@ -3088,6 +3089,7 @@ void SV_Say (qboolean team)
char t1[32], *t2; char t1[32], *t2;
int cls = 0; int cls = 0;
float floodtime; float floodtime;
sizebuf_t *msg;
qboolean sent[MAX_CLIENTS]; //so we don't send to the same splitscreen connection twice. (it's ugly) qboolean sent[MAX_CLIENTS]; //so we don't send to the same splitscreen connection twice. (it's ugly)
int cln; int cln;
@ -3222,15 +3224,13 @@ void SV_Say (qboolean team)
// non-team messages should be seen always, even if not tracking any player // non-team messages should be seen always, even if not tracking any player
if (!team && ((host_client->spectator && sv_spectalk.value) || !host_client->spectator)) if (!team && ((host_client->spectator && sv_spectalk.value) || !host_client->spectator))
{ msg = MVDWrite_Begin (dem_all, 0, strlen(text)+3);
MVDWrite_Begin (dem_all, 0, strlen(text)+3);
}
else else
MVDWrite_Begin (dem_multiple, cls, strlen(text)+3); msg = MVDWrite_Begin (dem_multiple, cls, strlen(text)+3);
MSG_WriteByte (&demo.dbuf->sb, svc_print); MSG_WriteByte (msg, svc_print);
MSG_WriteByte (&demo.dbuf->sb, PRINT_CHAT); MSG_WriteByte (msg, PRINT_CHAT);
MSG_WriteString (&demo.dbuf->sb, text); MSG_WriteString (msg, text);
} }
@ -3664,11 +3664,11 @@ void SV_SetInfo_f (void)
if (sv.mvdrecording) if (sv.mvdrecording)
{ {
MVDWrite_Begin (dem_all, 0, strlen(key)+strlen(val)+4); sizebuf_t *msg = MVDWrite_Begin (dem_all, 0, strlen(key)+strlen(val)+4);
MSG_WriteByte (&demo.dbuf->sb, svc_setinfo); MSG_WriteByte (msg, svc_setinfo);
MSG_WriteByte (&demo.dbuf->sb, i); MSG_WriteByte (msg, i);
MSG_WriteString (&demo.dbuf->sb, key); MSG_WriteString (msg, key);
MSG_WriteString (&demo.dbuf->sb, val); MSG_WriteString (msg, val);
} }
} }

View file

@ -11,7 +11,13 @@
//s0=diffuse, s1=normal, s2=specular, s3=shadowmap //s0=diffuse, s1=normal, s2=specular, s3=shadowmap
//custom modifiers: //custom modifiers:
//PCF(shadowmap) //PCF(shadowmap)
//CUBE(projected cubemap) //CUBEPROJ(projected cubemap)
//SPOT(projected circle
//CUBESHADOW
#if 0 && defined(GL_ARB_texture_gather) && defined(PCF)
#extension GL_ARB_texture_gather : enable
#endif
varying vec2 tcbase; varying vec2 tcbase;
@ -19,10 +25,13 @@ varying vec3 lightvector;
#if defined(SPECULAR) || defined(OFFSETMAPPING) #if defined(SPECULAR) || defined(OFFSETMAPPING)
varying vec3 eyevector; varying vec3 eyevector;
#endif #endif
#if defined(PCF) || defined(CUBE) #if defined(PCF) || defined(CUBEPROJ)
varying vec4 vshadowcoord; varying vec4 vtexprojcoord;
uniform mat4 l_cubematrix;
#ifndef SPOT
uniform mat4 l_projmatrix; uniform mat4 l_projmatrix;
#endif #endif
#endif
#ifdef VERTEX_SHADER #ifdef VERTEX_SHADER
#include "sys/skeletal.h" #include "sys/skeletal.h"
uniform vec3 l_lightposition; uniform vec3 l_lightposition;
@ -45,33 +54,142 @@ void main ()
eyevector.y = dot(eyeminusvertex, t.xyz); eyevector.y = dot(eyeminusvertex, t.xyz);
eyevector.z = dot(eyeminusvertex, n.xyz); eyevector.z = dot(eyeminusvertex, n.xyz);
#endif #endif
#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE) #if defined(PCF) || defined(SPOT) || defined(PROJECTION)
vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0); //for texture projections/shadowmapping on dlights
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
#endif #endif
} }
#endif #endif
#ifdef FRAGMENT_SHADER #ifdef FRAGMENT_SHADER
#include "sys/fog.h" #include "sys/fog.h"
uniform sampler2D s_t0; uniform sampler2D s_t0;
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)
uniform sampler2D s_t1; uniform sampler2D s_t1;
#endif #endif
#ifdef SPECULAR #ifdef SPECULAR
uniform sampler2D s_t2; uniform sampler2D s_t2;
#endif #endif
#ifdef CUBE #ifdef CUBEPROJ
uniform samplerCube s_t3; uniform samplerCube s_t3;
#endif #endif
#ifdef PCF #ifdef PCF
#ifdef CUBE #ifdef CUBESHADOW
uniform samplerCubeShadow s_t7; uniform samplerCubeShadow s_t4;
#else #else
uniform sampler2DShadow s_t7; #if 0//def GL_ARB_texture_gather
uniform sampler2D s_t4;
#else
uniform sampler2DShadow s_t4;
#endif #endif
#endif #endif
#endif
uniform float l_lightradius; uniform float l_lightradius;
uniform vec3 l_lightcolour; uniform vec3 l_lightcolour;
uniform vec3 l_lightcolourscale; uniform vec3 l_lightcolourscale;
#ifdef PCF
//#define shadow2DProj(t,c) (vec2(1.0,1.0))
//#define shadow2DProj(t,c) texture2DProj(t,c).rg
float ShadowmapFilter(void)
{
#ifdef SPOT
const vec3 texscale = vec3(1.0/512.0, 1.0/512.0, 1.0);
#else
const vec3 texscale = vec3(1.0/(512.0*3.0), 1.0/(512.0*2.0), 1.0);
#endif
//dehomogonize input
vec3 shadowcoord = (vtexprojcoord.xyz / vtexprojcoord.w);
#ifdef CUBESHADOW
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
#else
#ifdef SPOT
//bias it. don't bother figuring out which side or anything, its not needed
//l_projmatrix contains the light's projection matrix so no other magic needed
shadowcoord.xyz = (shadowcoord.xyz + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);
#else
//figure out which axis to use
//texture is arranged thusly:
//forward left up
//back right down
vec3 dir = abs(shadowcoord);
//assume z is the major axis (ie: forward from the light)
vec3 t = shadowcoord;
float ma = dir.z;
vec4 axis = vec4(1.0, 1.0, 1.0, 0.0);
if (dir.x > ma)
{
ma = dir.x;
t = shadowcoord.zyx;
axis.x = 3.0;
}
if (dir.y > ma)
{
ma = dir.y;
t = shadowcoord.xzy;
axis.x = 5.0;
}
if (t.z > 0.0)
{
axis.y = 3.0;
t.z = -t.z;
}
//we also need to pass the result through the light's projection matrix too
vec4 nsc =l_projmatrix*vec4(t, 1.0);
shadowcoord = (nsc.xyz / nsc.w);
//now bias and relocate it
shadowcoord = (shadowcoord + axis.xyz) * vec3(0.5/3.0, 0.5/2.0, 0.5);
#endif
#if 0//def GL_ARB_texture_gather
vec2 ipart, fpart;
#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))
vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));
vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));
vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));
vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));
//we now have 4*4 results, woo
//we can just average them for 1/16th precision, but that's still limited graduations
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + //middle two rows are full strength
mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y); //top+bottom rows
return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0)); //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.
#else
#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*texscale.xyz)).r
float s = 0.0;
s += dosamp(-1.0, -1.0);
s += dosamp(-1.0, 0.0);
s += dosamp(-1.0, 1.0);
s += dosamp(0.0, -1.0);
s += dosamp(0.0, 0.0);
s += dosamp(0.0, 1.0);
s += dosamp(1.0, -1.0);
s += dosamp(1.0, 0.0);
s += dosamp(1.0, 1.0);
return s/9.0;
#endif
#endif
}
#endif
#ifdef OFFSETMAPPING #ifdef OFFSETMAPPING
#include "sys/offsetmapping.h" #include "sys/offsetmapping.h"
#endif #endif
@ -96,6 +214,7 @@ void main ()
#ifdef BUMP #ifdef BUMP
diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0)); diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
#else #else
//we still do bumpmapping even without bumps to ensure colours are always sane. light.exe does it too.
diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0)); diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));
#endif #endif
@ -108,54 +227,30 @@ void main ()
#ifdef CUBE #ifdef CUBEPROJ
diff *= textureCube(s_t3, vshadowcoord.xyz).rgb; /*filter the colour by the cubemap projection*/
#endif diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;
#ifdef PCF
#if defined(SPOT)
const float texx = 512.0;
const float texy = 512.0;
vec4 shadowcoord = vshadowcoord;
#else
const float texx = 512.0;
const float texy = 512.0;
vec4 shadowcoord;
shadowcoord.zw = vshadowcoord.zw;
shadowcoord.xy = vshadowcoord.xy;
#endif
#ifdef CUBE
const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;
s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
colorscale *= s/9.0;
#else
const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;
s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;
colorscale *= s/9.0;
#endif
#endif #endif
#if defined(SPOT) #if defined(SPOT)
if (shadowcoord.w < 0.0) discard; /*filter the colour by the spotlight. discard anything behind the light so we don't get a mirror image*/
vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot)); if (vtexprojcoord.w < 0.0) discard;
vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);colorscale*=1.0-(dot(spot,spot));
#endif #endif
#ifdef PCF
/*filter the light by the shadowmap. logically a boolean, but we allow fractions for softer shadows*/
//diff.rgb = (vtexprojcoord.xyz/vtexprojcoord.w) * 0.5 + 0.5;
colorscale *= ShadowmapFilter();
// gl_FragColor.rgb = vec3(ShadowmapFilter());
#endif
#if defined(PROJECTION) #if defined(PROJECTION)
l_lightcolour *= texture2d(s_t3, shadowcoord); /*2d projection, not used*/
// diff *= texture2d(s_t3, shadowcoord);
#endif #endif
gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour); gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);
} }
#endif #endif

View file

@ -2,14 +2,17 @@
#include "sys/fog.h" #include "sys/fog.h"
varying vec2 tc; varying vec2 tc;
varying vec2 lm; varying vec2 lm;
varying vec4 vc;
#ifdef VERTEX_SHADER #ifdef VERTEX_SHADER
attribute vec2 v_texcoord; attribute vec2 v_texcoord;
attribute vec2 v_lmcoord; attribute vec2 v_lmcoord;
attribute vec4 v_colour;
void main (void) void main (void)
{ {
tc = v_texcoord.st; tc = v_texcoord.st;
lm = v_lmcoord.st; lm = v_lmcoord.st;
vc = v_colour;
gl_Position = ftetransform(); gl_Position = ftetransform();
} }
#endif #endif
@ -32,7 +35,7 @@ void main (void)
{ {
vec4 m = texture2D(s_t4, lm); vec4 m = texture2D(s_t4, lm);
gl_FragColor = fog4(vec4(m.aaa,1.0)*( gl_FragColor = fog4(vc*vec4(m.aaa,1.0)*(
texture2D(s_t0, tc)*m.r texture2D(s_t0, tc)*m.r
+ texture2D(s_t1, tc)*m.g + texture2D(s_t1, tc)*m.g
+ texture2D(s_t2, tc)*m.b + texture2D(s_t2, tc)*m.b