preliminary attempt to get rtlights in d3d builds. shadows are only cast by world, and the hlsl code is somewhat lacking. also only works in d3d-only builds.

no longer using the vfw header or lib, so avi playback/recording should work when compiled with gcc.
added d_mipcap cvar.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3944 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-01-01 02:26:42 +00:00
parent ebc29fe683
commit d877bd4e39
20 changed files with 1491 additions and 906 deletions

View File

@ -118,7 +118,7 @@ static void CL_ClearDlight(dlight_t *dl, int key)
dl->color[0] = 1;
dl->color[1] = 1;
dl->color[2] = 1;
dl->corona = r_flashblend.value;
dl->corona = r_flashblend.value * 0.25;
dl->coronascale = r_flashblendscale.value;
// if (r_shadow_realtime_dlight_shadowmap.value)
// dl->flags |= LFLAG_SHADOWMAP;
@ -2057,7 +2057,7 @@ void CL_LinkPacketEntities (void)
if (state->effects & EF_RED)
{
radius = max(radius,200);
colour[0] += 5.0;
colour[0] += 3.0;
colour[1] += 0.5;
colour[2] += 0.5;
}
@ -2081,8 +2081,20 @@ void CL_LinkPacketEntities (void)
colour[1] = state->light[1]/1024.0f;
colour[2] = state->light[2]/1024.0f;
}
CL_NewDlight(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
/*FIXME: .skin is meant to be "cubemaps/%i" */
dl = CL_NewDlight(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
dl->corona = (state->lightpflags & PFLAGS_CORONA)?1:0;
dl->coronascale = 0.25;
dl->flags &= ~LFLAG_FLASHBLEND;
dl->flags |= (state->lightpflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0;
if (state->skinnum)
{
VectorCopy(angles, ent->angles);
angles[0]*=-1; //pflags matches alias models.
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
VectorInverse(dl->axis[1]);
snprintf(dl->cubemapname, sizeof(dl->cubemapname), "cubemaps/%i", state->skinnum);
dl->cubetexture = R_LoadReplacementTexture(dl->cubemapname, "", IF_CUBEMAP);
}
}
// if set to invisible, skip
@ -2149,31 +2161,6 @@ void CL_LinkPacketEntities (void)
ent->drawflags = state->hexen2flags;
CL_LerpNetFrameState(FS_REG, &ent->framestate, le);
/*
// set frame
if (le->framechange == le->oldframechange)
ent->framestate.g[FS_REG].lerpfrac = 0;
else
{
ent->framestate.g[FS_REG].lerpfrac = 1-(servertime - le->framechange) / (le->framechange - le->oldframechange);
if (ent->framestate.g[FS_REG].lerpfrac > 1)
ent->framestate.g[FS_REG].lerpfrac = 1;
else if (ent->framestate.g[FS_REG].lerpfrac < 0)
{
ent->framestate.g[FS_REG].lerpfrac = 0;
//le->oldframechange = le->framechange;
}
}
ent->framestate.g[FS_REG].frame[0] = state->frame;
ent->framestate.g[FS_REG].frame[1] = le->frame;
ent->framestate.g[FS_REG].frametime[0] = cl.servertime - le->framechange;
ent->framestate.g[FS_REG].frametime[1] = cl.servertime - le->oldframechange;
*/
// f = (sin(realtime)+1)/2;
#ifdef PEXT_SCALE
//set scale
@ -2269,9 +2256,9 @@ void CL_LinkPacketEntities (void)
float rad = 0;
vec3_t dclr;
dclr[0] = 0.20;
dclr[1] = 0.10;
dclr[2] = 0;
dclr[0] = 2.0;
dclr[1] = 1.0;
dclr[2] = 0.25;
if (model->flags & MF_ROCKET)
{
@ -2281,7 +2268,6 @@ void CL_LinkPacketEntities (void)
if (strncmp(model->name, "models/sflesh", 13))
{ //hmm. hexen spider gibs...
rad = 200;
dclr[2] = 0.05;
rad += r_lightflicker.value?((flicker + state->number)&31):0;
}
}

View File

@ -1077,9 +1077,9 @@ void CL_ParseTEnt (void)
dl->die = cl.time + 1;
dl->decay = 300;
dl->color[0] = 1.0;
dl->color[1] = 0.775;
dl->color[2] = 0.25;
dl->color[0] = 4.0;
dl->color[1] = 2.0;
dl->color[2] = 0.5;
dl->channelfade[0] = 0.196;
dl->channelfade[1] = 0.23;
dl->channelfade[2] = 0.12;
@ -1117,12 +1117,12 @@ void CL_ParseTEnt (void)
dl->die = cl.time + 1;
dl->decay = 300;
dl->color[0] = 1.0;
dl->color[1] = 0.775;
dl->color[2] = 0.25;
dl->channelfade[0] = 0.196;
dl->channelfade[1] = 0.23;
dl->channelfade[2] = 0.12;
dl->color[0] = 4.0;
dl->color[1] = 2.0;
dl->color[2] = 0.5;
dl->channelfade[0] = 0.784;
dl->channelfade[1] = 0.92;
dl->channelfade[2] = 0.48;
}
@ -1741,12 +1741,13 @@ void CLDP_ParseTrailParticles(void)
end[1] = MSG_ReadCoord();
end[2] = MSG_ReadCoord();
effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex));
if (entityindex && (unsigned int)entityindex < MAX_EDICTS)
ts = &cl.lerpents[entityindex].trailstate;
else
ts = NULL;
effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex));
if (P_ParticleTrail(start, end, effectindex, entityindex, ts))
P_ParticleTrail(start, end, rt_blood, entityindex, ts);
}
@ -1774,6 +1775,7 @@ void CLDP_ParsePointParticles(qboolean compact)
}
effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex));
if (P_RunParticleEffectType(org, dir, count, effectindex))
P_RunParticleEffect (org, dir, 15, 15);
}

View File

@ -741,7 +741,7 @@ char *Media_NextTrack(int musicchannelnum)
//Avi files are specific to windows. Bit of a bummer really.
#if defined(_WIN32) && !defined(__GNUC__)
#if defined(_WIN32)
#define WINAVI
#endif
@ -773,11 +773,114 @@ char *Media_NextTrack(int musicchannelnum)
#ifdef WINAVI
#undef CDECL //windows is stupid at times.
#define CDECL __cdecl
#if 0
#include <vfw.h>
#else
typedef struct
{
DWORD fccType;
DWORD fccHandler;
DWORD dwFlags;
DWORD dwCaps;
WORD wPriority;
WORD wLanguage;
DWORD dwScale;
DWORD dwRate;
DWORD dwStart;
DWORD dwLength;
DWORD dwInitialFrames;
DWORD dwSuggestedBufferSize;
DWORD dwQuality;
DWORD dwSampleSize;
RECT rcFrame;
DWORD dwEditCount;
DWORD dwFormatChangeCount;
TCHAR szName[64];
} AVISTREAMINFOA, *LPAVISTREAMINFOA;
typedef struct AVISTREAM *PAVISTREAM;
typedef struct AVIFILE *PAVIFILE;
typedef struct GETFRAME *PGETFRAME;
typedef struct
{
DWORD fccType;
DWORD fccHandler;
DWORD dwKeyFrameEvery;
DWORD dwQuality;
DWORD dwBytesPerSecond;
DWORD dwFlags;
LPVOID lpFormat;
DWORD cbFormat;
LPVOID lpParms;
DWORD cbParms;
DWORD dwInterleaveEvery;
} AVICOMPRESSOPTIONS;
#define streamtypeVIDEO mmioFOURCC('v', 'i', 'd', 's')
#define streamtypeAUDIO mmioFOURCC('a', 'u', 'd', 's')
#define AVISTREAMREAD_CONVENIENT (-1L)
#define AVIIF_KEYFRAME 0x00000010L
#endif
int aviinited;
ULONG (WINAPI *qAVIStreamRelease) (PAVISTREAM pavi);
HRESULT (WINAPI *qAVIStreamEndStreaming) (PAVISTREAM pavi);
HRESULT (WINAPI *qAVIStreamGetFrameClose) (PGETFRAME pg);
HRESULT (WINAPI *qAVIStreamRead) (PAVISTREAM pavi, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG FAR * plBytes, LONG FAR * plSamples);
LPVOID (WINAPI *qAVIStreamGetFrame) (PGETFRAME pg, LONG lPos);
HRESULT (WINAPI *qAVIStreamReadFormat) (PAVISTREAM pavi, LONG lPos,LPVOID lpFormat,LONG FAR *lpcbFormat);
LONG (WINAPI *qAVIStreamStart) (PAVISTREAM pavi);
PGETFRAME(WINAPI*qAVIStreamGetFrameOpen) (PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted);
HRESULT (WINAPI *qAVIStreamBeginStreaming) (PAVISTREAM pavi, LONG lStart, LONG lEnd, LONG lRate);
LONG (WINAPI *qAVIStreamSampleToTime) (PAVISTREAM pavi, LONG lSample);
LONG (WINAPI *qAVIStreamLength) (PAVISTREAM pavi);
HRESULT (WINAPI *qAVIStreamInfoA) (PAVISTREAM pavi, LPAVISTREAMINFOA psi, LONG lSize);
ULONG (WINAPI *qAVIFileRelease) (PAVIFILE pfile);
HRESULT (WINAPI *qAVIFileGetStream) (PAVIFILE pfile, PAVISTREAM FAR * ppavi, DWORD fccType, LONG lParam);
HRESULT (WINAPI *qAVIFileOpenA) (PAVIFILE FAR *ppfile, LPCSTR szFile, UINT uMode, LPCLSID lpHandler);
void (WINAPI *qAVIFileInit) (void);
HRESULT (WINAPI *qAVIStreamWrite) (PAVISTREAM pavi, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten);
HRESULT (WINAPI *qAVIStreamSetFormat) (PAVISTREAM pavi, LONG lPos,LPVOID lpFormat,LONG cbFormat);
HRESULT (WINAPI *qAVIMakeCompressedStream) (PAVISTREAM FAR * ppsCompressed, PAVISTREAM ppsSource, AVICOMPRESSOPTIONS FAR * lpOptions, CLSID FAR *pclsidHandler);
HRESULT (WINAPI *qAVIFileCreateStreamA) (PAVIFILE pfile, PAVISTREAM FAR *ppavi, AVISTREAMINFOA FAR * psi);
#pragma comment( lib, "vfw32.lib" )
qboolean qAVIStartup(void)
{
static int aviinited;
static dllhandle_t *avimodule;
if (!aviinited)
{
dllfunction_t funcs[] =
{
{(void*)&qAVIFileInit, "AVIFileInit"},
{(void*)&qAVIStreamRelease, "AVIStreamRelease"},
{(void*)&qAVIStreamEndStreaming, "AVIStreamEndStreaming"},
{(void*)&qAVIStreamGetFrameClose, "AVIStreamGetFrameClose"},
{(void*)&qAVIStreamRead, "AVIStreamRead"},
{(void*)&qAVIStreamGetFrame, "AVIStreamGetFrame"},
{(void*)&qAVIStreamReadFormat, "AVIStreamReadFormat"},
{(void*)&qAVIStreamStart, "AVIStreamStart"},
{(void*)&qAVIStreamGetFrameOpen, "AVIStreamGetFrameOpen"},
{(void*)&qAVIStreamBeginStreaming, "AVIStreamBeginStreaming"},
{(void*)&qAVIStreamSampleToTime, "AVIStreamSampleToTime"},
{(void*)&qAVIStreamLength, "AVIStreamLength"},
{(void*)&qAVIStreamInfoA, "AVIStreamInfoA"},
{(void*)&qAVIFileRelease, "AVIFileRelease"},
{(void*)&qAVIFileGetStream, "AVIFileGetStream"},
{(void*)&qAVIFileOpenA, "AVIFileOpenA"},
{(void*)&qAVIStreamWrite, "AVIStreamWrite"},
{(void*)&qAVIStreamSetFormat, "AVIStreamSetFormat"},
{(void*)&qAVIMakeCompressedStream, "AVIMakeCompressedStream"},
{(void*)&qAVIFileCreateStreamA, "AVIFileCreateStreamA"},
{NULL,NULL}
};
aviinited = true;
avimodule = Sys_LoadLibrary("avifil32.dll", funcs);
if (avimodule)
qAVIFileInit();
}
return avimodule?true:false;
}
#endif
#define MFT_CAPTURE 5 //fixme
@ -822,7 +925,7 @@ struct cin_s {
#ifdef WINAVI
struct {
AVISTREAMINFO psi; // Pointer To A Structure Containing Stream Info
AVISTREAMINFOA psi; // Pointer To A Structure Containing Stream Info
PAVISTREAM pavivideo;
PAVISTREAM pavisound;
PAVIFILE pavi;
@ -876,9 +979,9 @@ shader_t *videoshader;
#ifdef WINAVI
void Media_WINAVI_Shutdown(struct cin_s *cin)
{
AVIStreamGetFrameClose(cin->avi.pgf);
AVIStreamEndStreaming(cin->avi.pavivideo);
AVIStreamRelease(cin->avi.pavivideo);
qAVIStreamGetFrameClose(cin->avi.pgf);
qAVIStreamEndStreaming(cin->avi.pavivideo);
qAVIStreamRelease(cin->avi.pavivideo);
//we don't need to free the file (we freed it immediatly after getting the stream handles)
}
qboolean Media_WinAvi_DecodeFrame(cin_t *cin, qboolean nosound)
@ -892,6 +995,9 @@ qboolean Media_WinAvi_DecodeFrame(cin_t *cin, qboolean nosound)
newframe = (curtime - cin->filmstarttime)*cin->avi.filmfps;
newframei = newframe;
if (newframei>=cin->avi.num_frames)
cin->ended = true;
if (newframe == cin->currentframe)
{
cin->outunchanged = true;
@ -904,18 +1010,18 @@ qboolean Media_WinAvi_DecodeFrame(cin_t *cin, qboolean nosound)
cin->currentframe = newframei;
Con_DPrintf("%i\n", newframei);
if (cin->currentframe>=cin->avi.num_frames)
if (newframei>=cin->avi.num_frames)
{
return false;
cin->filmstarttime = curtime;
cin->currentframe = newframei = 0;
cin->avi.soundpos = 0;
}
lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(cin->avi.pgf, cin->currentframe); // Grab Data From The AVI Stream
cin->currentframe++;
lpbi = (LPBITMAPINFOHEADER)qAVIStreamGetFrame(cin->avi.pgf, cin->currentframe); // Grab Data From The AVI Stream
if (!lpbi || lpbi->biBitCount != 24)//oops
{
SCR_SetUpToDrawConsole();
R2D_ConsoleBackground(0, vid.height, true);
Draw_FunString(0, 0, "Video stream is corrupt\n");
cin->ended = true;
return false;
}
else
{
@ -931,14 +1037,13 @@ qboolean Media_WinAvi_DecodeFrame(cin_t *cin, qboolean nosound)
LPBYTE pBuffer;
LONG samples;
AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT,
NULL, 0, &lSize, &samples);
qAVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, &samples);
cin->avi.soundpos+=samples;
pBuffer = cin->framedata;
AVIStreamRead(cin->avi.pavisound, cin->avi.soundpos, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, &samples);
qAVIStreamRead(cin->avi.pavisound, cin->avi.soundpos, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, &samples);
S_RawAudio(-1, pBuffer, cin->avi.pWaveFormat->nSamplesPerSec, samples, cin->avi.pWaveFormat->nChannels, 2);
}
@ -948,13 +1053,15 @@ cin_t *Media_WinAvi_TryLoad(char *name)
{
cin_t *cin;
PAVIFILE pavi;
flocation_t loc;
if (!aviinited)
{
aviinited=true;
AVIFileInit();
}
if (!AVIFileOpen(&pavi, name, OF_READ, NULL))//!AVIStreamOpenFromFile(&pavi, name, streamtypeVIDEO, 0, OF_READ, NULL))
if (!qAVIStartup())
return NULL;
FS_FLocateFile(name, FSLFRT_DEPTH_OSONLY, &loc);
if (!loc.offset && !qAVIFileOpenA(&pavi, loc.rawname, OF_READ, NULL))//!AVIStreamOpenFromFile(&pavi, name, streamtypeVIDEO, 0, OF_READ, NULL))
{
int filmwidth;
int filmheight;
@ -963,32 +1070,41 @@ cin_t *Media_WinAvi_TryLoad(char *name)
cin->filmtype = MFT_AVI;
cin->avi.pavi = pavi;
if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavivideo, streamtypeVIDEO, 0)) //retrieve video stream
if (qAVIFileGetStream(cin->avi.pavi, &cin->avi.pavivideo, streamtypeVIDEO, 0)) //retrieve video stream
{
AVIFileRelease(pavi);
qAVIFileRelease(pavi);
Con_Printf("%s contains no video stream\n", name);
return NULL;
}
if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavisound, streamtypeAUDIO, 0)) //retrieve audio stream
if (qAVIFileGetStream(cin->avi.pavi, &cin->avi.pavisound, streamtypeAUDIO, 0)) //retrieve audio stream
{
Con_DPrintf("%s contains no audio stream\n", name);
cin->avi.pavisound=NULL;
}
AVIFileRelease(cin->avi.pavi);
qAVIFileRelease(cin->avi.pavi);
//play with video
AVIStreamInfo(cin->avi.pavivideo, &cin->avi.psi, sizeof(cin->avi.psi));
qAVIStreamInfoA(cin->avi.pavivideo, &cin->avi.psi, sizeof(cin->avi.psi));
filmwidth=cin->avi.psi.rcFrame.right-cin->avi.psi.rcFrame.left; // Width Is Right Side Of Frame Minus Left
filmheight=cin->avi.psi.rcFrame.bottom-cin->avi.psi.rcFrame.top; // Height Is Bottom Of Frame Minus Top
cin->framedata = BZ_Malloc(filmwidth*filmheight*4);
cin->avi.num_frames=AVIStreamLength(cin->avi.pavivideo); // The Last Frame Of The Stream
cin->avi.filmfps=1000.0f*(float)cin->avi.num_frames/(float)AVIStreamSampleToTime(cin->avi.pavivideo,cin->avi.num_frames); // Calculate Rough Milliseconds Per Frame
cin->avi.num_frames=qAVIStreamLength(cin->avi.pavivideo); // The Last Frame Of The Stream
cin->avi.filmfps=1000.0f*(float)cin->avi.num_frames/(float)qAVIStreamSampleToTime(cin->avi.pavivideo,cin->avi.num_frames); // Calculate Rough Milliseconds Per Frame
qAVIStreamBeginStreaming(cin->avi.pavivideo, 0, cin->avi.num_frames, 100);
AVIStreamBeginStreaming(cin->avi.pavivideo, 0, cin->avi.num_frames, 100);
cin->avi.pgf=qAVIStreamGetFrameOpen(cin->avi.pavivideo, NULL);
cin->avi.pgf=AVIStreamGetFrameOpen(cin->avi.pavivideo, NULL);
if (!cin->avi.pgf)
{
Con_Printf("AVIStreamGetFrameOpen failed. Please install codec for '%c%c%c%c'.\n",
((unsigned char*)&cin->avi.psi.fccHandler)[0],
((unsigned char*)&cin->avi.psi.fccHandler)[1],
((unsigned char*)&cin->avi.psi.fccHandler)[2],
((unsigned char*)&cin->avi.psi.fccHandler)[3]
);
}
cin->currentframe=0;
cin->filmstarttime = Sys_DoubleTime();
@ -1001,7 +1117,7 @@ cin_t *Media_WinAvi_TryLoad(char *name)
{
LONG lSize;
LPBYTE pChunk;
AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL);
qAVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL);
if (!lSize)
cin->avi.pWaveFormat = NULL;
@ -1011,7 +1127,7 @@ cin_t *Media_WinAvi_TryLoad(char *name)
pChunk = BZ_Malloc(sizeof(qbyte)*lSize);
if(AVIStreamReadFormat(cin->avi.pavisound, AVIStreamStart(cin->avi.pavisound), pChunk, &lSize))
if(qAVIStreamReadFormat(cin->avi.pavisound, qAVIStreamStart(cin->avi.pavisound), pChunk, &lSize))
{
// error
Con_Printf("Failiure reading sound info\n");
@ -1022,13 +1138,13 @@ cin_t *Media_WinAvi_TryLoad(char *name)
if (!cin->avi.pWaveFormat)
{
Con_Printf("VFW is broken\n");
AVIStreamRelease(cin->avi.pavisound);
qAVIStreamRelease(cin->avi.pavisound);
cin->avi.pavisound=NULL;
}
else if (cin->avi.pWaveFormat->wFormatTag != 1)
{
Con_Printf("Audio stream is not PCM\n"); //FIXME: so that it no longer is...
AVIStreamRelease(cin->avi.pavisound);
qAVIStreamRelease(cin->avi.pavisound);
cin->avi.pavisound=NULL;
}
@ -1994,7 +2110,7 @@ void Media_RecordFrame (void)
framebuffer[i+2] = temp;
}
//write it
hr = AVIStreamWrite(recordavi_video_stream, captureframe++, 1, framebuffer, vid.pixelwidth*vid.pixelheight * 3, ((captureframe%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL);
hr = qAVIStreamWrite(recordavi_video_stream, captureframe++, 1, framebuffer, vid.pixelwidth*vid.pixelheight * 3, ((captureframe%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL);
if (FAILED(hr)) Con_Printf("Recoring error\n");
}
#endif /* WINAVI */
@ -2082,11 +2198,11 @@ static void MSD_Submit(soundcardinfo_t *sc, int start, int end)
int partialsamplestosubmit;
//wraped, two chunks to send
partialsamplestosubmit = ((sc->sn.samples/sc->sn.numchannels)) - offset;
AVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, partialsamplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
qAVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, partialsamplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
samplestosubmit -= partialsamplestosubmit;
offset = 0;
}
AVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, samplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
qAVIStreamWrite(recordavi_uncompressed_audio_stream, recordavi_audio_frame_counter++, 1, sc->sn.buffer+offset*bytespersample, samplestosubmit*bytespersample, AVIIF_KEYFRAME, NULL, NULL);
#endif /* WINAVI */
break;
case CT_NONE:
@ -2154,10 +2270,10 @@ void Media_InitFakeSoundDevice (int channels, int samplebits)
void Media_StopRecordFilm_f (void)
{
#if defined(WINAVI)
if (recordavi_uncompressed_video_stream) AVIStreamRelease(recordavi_uncompressed_video_stream);
if (recordavi_compressed_video_stream) AVIStreamRelease(recordavi_compressed_video_stream);
if (recordavi_uncompressed_audio_stream) AVIStreamRelease(recordavi_uncompressed_audio_stream);
if (recordavi_file) AVIFileRelease(recordavi_file);
if (recordavi_uncompressed_video_stream) qAVIStreamRelease(recordavi_uncompressed_video_stream);
if (recordavi_compressed_video_stream) qAVIStreamRelease(recordavi_compressed_video_stream);
if (recordavi_uncompressed_audio_stream) qAVIStreamRelease(recordavi_uncompressed_audio_stream);
if (recordavi_file) qAVIFileRelease(recordavi_file);
recordavi_uncompressed_video_stream=NULL;
recordavi_compressed_video_stream = NULL;
@ -2263,7 +2379,7 @@ void Media_RecordFilm_f (void)
{
HRESULT hr;
BITMAPINFOHEADER bitmap_info_header;
AVISTREAMINFO stream_header;
AVISTREAMINFOA stream_header;
FILE *f;
char aviname[256];
char nativepath[256];
@ -2273,10 +2389,10 @@ void Media_RecordFilm_f (void)
else
recordavi_codec_fourcc = 0;
if (!aviinited)
if (!qAVIStartup())
{
aviinited=true;
AVIFileInit();
Con_Printf("vfw support not available.\n");
return;
}
/*convert to foo.avi*/
@ -2293,7 +2409,7 @@ void Media_RecordFilm_f (void)
unlink(nativepath);
}
hr = AVIFileOpen(&recordavi_file, nativepath, OF_WRITE | OF_CREATE, NULL);
hr = qAVIFileOpenA(&recordavi_file, nativepath, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to open %s\n", nativepath);
@ -2318,7 +2434,7 @@ void Media_RecordFilm_f (void)
stream_header.dwRate = (unsigned long)(0.5 + 100.0/recordavi_frametime);
SetRect(&stream_header.rcFrame, 0, 0, vid.pixelwidth, vid.pixelheight);
hr = AVIFileCreateStream(recordavi_file, &recordavi_uncompressed_video_stream, &stream_header);
hr = qAVIFileCreateStreamA(recordavi_file, &recordavi_uncompressed_video_stream, &stream_header);
if (FAILED(hr))
{
Con_Printf("Couldn't initialise the stream, check codec\n");
@ -2334,7 +2450,7 @@ void Media_RecordFilm_f (void)
opts.fccType = stream_header.fccType;
opts.fccHandler = recordavi_codec_fourcc;
// Make the stream according to compression
hr = AVIMakeCompressedStream(&recordavi_compressed_video_stream, recordavi_uncompressed_video_stream, &opts, NULL);
hr = qAVIMakeCompressedStream(&recordavi_compressed_video_stream, recordavi_uncompressed_video_stream, &opts, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to init compressor\n");
@ -2344,7 +2460,7 @@ void Media_RecordFilm_f (void)
}
hr = AVIStreamSetFormat(recordavi_video_stream, 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
hr = qAVIStreamSetFormat(recordavi_video_stream, 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
if (FAILED(hr))
{
Con_Printf("Failed to set format\n");
@ -2375,10 +2491,10 @@ void Media_RecordFilm_f (void)
stream_header.dwRate = stream_header.dwScale * (unsigned long)recordavi_wave_format.nSamplesPerSec;
stream_header.dwSampleSize = recordavi_wave_format.nBlockAlign;
hr = AVIFileCreateStream(recordavi_file, &recordavi_uncompressed_audio_stream, &stream_header);
hr = qAVIFileCreateStreamA(recordavi_file, &recordavi_uncompressed_audio_stream, &stream_header);
if (FAILED(hr)) return;
hr = AVIStreamSetFormat(recordavi_uncompressed_audio_stream, 0, &recordavi_wave_format, sizeof(WAVEFORMATEX));
hr = qAVIStreamSetFormat(recordavi_uncompressed_audio_stream, 0, &recordavi_wave_format, sizeof(WAVEFORMATEX));
if (FAILED(hr)) return;
Media_InitFakeSoundDevice(recordavi_wave_format.nChannels, recordavi_wave_format.wBitsPerSample);

View File

@ -720,7 +720,7 @@ void M_Menu_Textures_f (void)
};
extern cvar_t gl_load24bit, gl_specular, gl_detail, gl_compress, gl_picmip, gl_picmip2d, gl_max_size, r_drawflat, r_glsl_offsetmapping;
extern cvar_t gl_texture_anisotropic_filtering, gl_texturemode, gl_texturemode2d;
extern cvar_t gl_texture_anisotropic_filtering, gl_texturemode, gl_texturemode2d, gl_mipcap;
int y;
menubulk_t bulk[] =
{
@ -740,6 +740,7 @@ void M_Menu_Textures_f (void)
MB_CHECKBOXCVAR("Texture Compression", gl_compress, 0), // merge the save compressed tex options into here?
MB_SLIDER("3D Picmip", gl_picmip, 0, 16, 1, NULL),
MB_SLIDER("2D Picmip", gl_picmip2d, 0, 16, 1, NULL),
MB_SLIDER("World Mipcap", gl_mipcap, 0, 3, 1, NULL),
MB_COMBOCVAR("Max Texture Size", gl_max_size, texturesizeoptions, texturesizeoptions, NULL),
MB_END()
};

View File

@ -4922,7 +4922,7 @@ qboolean CSQC_Init (qboolean anycsqc, unsigned int checksum)
PR_ExecuteProgram(csqcprogs, csqcg.init_function);
}
Con_Printf("Loaded csqc\n");
Con_DPrintf("Loaded csqc\n");
csqcmapentitydataloaded = false;
}

View File

@ -275,7 +275,7 @@ enum imageflags
IF_CUBEMAPEXTRA = 1<<8,
IF_TEXTYPE = (1<<6) | (1<<7) | (1<<8), /*0=2d, 1=3d, 2-7=cubeface*/
IF_TEXTYPESHIFT = 6, /*0=2d, 1=3d, 2-7=cubeface*/
IF_MIPCAP = 1<<9,
IF_REPLACE = 1<<30,
IF_SUBDIRONLY = 1<<31
};
@ -430,7 +430,7 @@ extern cvar_t gl_poly;
extern cvar_t gl_affinemodels;
extern cvar_t gl_nohwblend;
extern cvar_t gl_reporttjunctions;
extern cvar_t r_flashblend, r_flashblendscale;
extern cvar_t r_coronas, r_flashblend, r_flashblendscale;
extern cvar_t r_lightstylesmooth;
extern cvar_t r_lightstylesmooth_limit;
extern cvar_t r_lightstylespeed;

View File

@ -3,6 +3,7 @@
#include "pr_common.h"
#include "gl_draw.h"
#include "shader.h"
#include "glquake.h"
#include <string.h>
@ -34,6 +35,7 @@ extern int gl_anisotropy_factor;
void SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue);
void SCR_Fov_Callback (struct cvar_s *var, char *oldvalue);
#if defined(GLQUAKE)
void GL_Mipcap_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue);
void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldvalue);
@ -88,6 +90,8 @@ cvar_t r_fb_models = CVARAF ("r_fb_models", "1",
"gl_fb_models", CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1",
CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_coronas = SCVARF ("r_coronas", "0",
CVAR_ARCHIVE);
cvar_t r_flashblend = SCVARF ("gl_flashblend", "0",
CVAR_ARCHIVE);
cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35",
@ -284,6 +288,9 @@ cvar_t gl_texture_anisotropic_filtering = CVARFC("gl_texture_anisotropic_filter
cvar_t gl_texturemode = CVARFC("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Texturemode_Callback);
cvar_t gl_mipcap = CVARFC("d_mipcap", "0 1000",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Mipcap_Callback);
cvar_t gl_texturemode2d = CVARFC("gl_texturemode2d", "GL_LINEAR",
CVAR_ARCHIVE | CVAR_RENDERERCALLBACK,
GL_Texturemode2d_Callback);
@ -367,11 +374,6 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_bumpmap, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_world, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_world_shadows, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_dlight, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_dlight_shadows, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_realtime_world_lightmaps, GLRENDEREROPTIONS);
Cvar_Register (&gl_reporttjunctions, GLRENDEREROPTIONS);
@ -396,6 +398,7 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_picmip, GLRENDEREROPTIONS);
Cvar_Register (&gl_picmip2d, GLRENDEREROPTIONS);
Cvar_Register (&gl_mipcap, GLRENDEREROPTIONS);
Cvar_Register (&gl_texturemode, GLRENDEREROPTIONS);
Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS);
Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS);
@ -487,6 +490,10 @@ void Renderer_Init(void)
Cmd_AddCommand("setrenderer", R_SetRenderer_f);
Cmd_AddCommand("vid_restart", R_RestartRenderer_f);
#ifdef RTLIGHTS
Cmd_AddCommand ("r_editlights_reload", R_ReloadRTLights_f);
Cmd_AddCommand ("r_editlights_save", R_SaveRTLights_f);
#endif
Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f);
#if defined(GLQUAKE) || defined(D3DQUAKE)
@ -537,9 +544,17 @@ void Renderer_Init(void)
Cvar_Register(&r_stains, GRAPHICALNICETIES);
Cvar_Register(&r_stainfadetime, GRAPHICALNICETIES);
Cvar_Register(&r_stainfadeammount, GRAPHICALNICETIES);
Cvar_Register(&r_lightprepass, GRAPHICALNICETIES);
Cvar_Register (&r_flashblend, GLRENDEREROPTIONS);
Cvar_Register (&r_flashblendscale, GLRENDEREROPTIONS);
Cvar_Register(&r_lightprepass, GLRENDEREROPTIONS);
Cvar_Register (&r_coronas, GRAPHICALNICETIES);
Cvar_Register (&r_flashblend, GRAPHICALNICETIES);
Cvar_Register (&r_flashblendscale, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_world, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_world_shadows, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_dlight_shadows, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_realtime_world_lightmaps, GRAPHICALNICETIES);
Cvar_Register(&scr_viewsize, SCREENOPTIONS);
Cvar_Register(&scr_fov, SCREENOPTIONS);
@ -1942,9 +1957,10 @@ qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs)
#if 1
float mrad = 0, v;
static vec3_t identaxis[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
if (!memcmp(e->axis, identaxis, sizeof(identaxis)))
if (e->axis[0][0]==1 && e->axis[0][1]==0 && e->axis[0][1]==0 &&
e->axis[1][0]==0 && e->axis[1][1]==1 && e->axis[1][1]==0 &&
e->axis[2][0]==0 && e->axis[2][1]==0 && e->axis[2][1]==1)
{
for (i = 0; i < 3; i++)
{

View File

@ -18,6 +18,8 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
extern float d3d_trueprojection[16];
static void BE_RotateForEntity (const entity_t *e, const model_t *mod);
/*========================================== tables for deforms =====================================*/
#define frand() (rand()*(1.0/RAND_MAX))
#define FTABLE_SIZE 1024
@ -119,7 +121,9 @@ typedef struct
unsigned int flags;
float curtime;
const entity_t *curentity;
const entity_t *curentity;
const dlight_t *curdlight;
vec3_t curdlight_colours;
shader_t *curshader;
texnums_t *curtexnums;
texid_t curlightmap;
@ -133,6 +137,7 @@ typedef struct
unsigned int lastpasscount;
vbo_t *batchvbo;
shader_t *shader_rtlight;
texid_t curtex[MAX_TMUS];
unsigned int tmuflags[MAX_TMUS];
@ -365,6 +370,15 @@ static void D3DBE_ApplyShaderBits(unsigned int bits)
break;
}
}
if (delta & (SBITS_MASK_BITS))
{
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_COLORWRITEENABLE,
((bits&SBITS_MASK_RED)?0:D3DCOLORWRITEENABLE_RED) |
((bits&SBITS_MASK_GREEN)?0:D3DCOLORWRITEENABLE_GREEN) |
((bits&SBITS_MASK_BLUE)?0:D3DCOLORWRITEENABLE_BLUE) |
((bits&SBITS_MASK_ALPHA)?0:D3DCOLORWRITEENABLE_ALPHA));
}
}
void D3DBE_Reset(qboolean before)
@ -512,6 +526,21 @@ void D3DBE_Reset(qboolean before)
}
}
static const char LIGHTPASS_SHADER[] = "\
{\n\
program rtlight\n\
{\n\
map $diffuse\n\
blendfunc add\n\
}\n\
{\n\
map $normalmap\n\
}\n\
{\n\
map $specular\n\
}\n\
}";
void D3DBE_Init(void)
{
be_maxpasses = MAX_TMUS;
@ -527,6 +556,8 @@ void D3DBE_Init(void)
D3DBE_Reset(false);
shaderstate.shader_rtlight = R_RegisterShader("rtlight", LIGHTPASS_SHADER);
R_InitFlashblends();
}
@ -1625,6 +1656,27 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], mvp, 4);
}
break;
case SP_LIGHTPOSITION:
{
/*light position in model space*/
float inv[16];
vec3_t t2;
qboolean Matrix4_Invert(const float *m, float *out);
Matrix4_Invert(shaderstate.m_model, inv);
Matrix4x4_CM_Transform3(inv, shaderstate.curdlight->origin, t2);
IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t2, 3);
break;
}
case SP_LIGHTRADIUS:
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], &shaderstate.curdlight->radius, 1);
break;
case SP_LIGHTCOLOUR:
IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], shaderstate.curdlight_colours, 3);
break;
case SP_E_COLOURS:
case SP_E_COLOURSIDENT:
case SP_E_TOPCOLOURS:
@ -1639,10 +1691,6 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
case SP_RENDERTEXTURESCALE:
case SP_LIGHTRADIUS:
case SP_LIGHTCOLOUR:
case SP_LIGHTPOSITION:
case SP_FIRSTIMMEDIATE:
case SP_CONSTI:
case SP_CONSTF:
@ -1656,18 +1704,33 @@ static void BE_ApplyUniforms(program_t *prog, int permu)
}
}
static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount)
static void BE_RenderMeshProgram(shader_t *s, unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount)
{
int vdec = D3D_VDEC_ST0;
int vdec = D3D_VDEC_ST0|D3D_VDEC_NORM;
int passno;
shader_t *s = shaderstate.curshader;
//shaderpass_t *pass = s->passes; //unused variable
int perm = 0;
D3DBE_ApplyShaderBits(shaderstate.curshader->passes->shaderbits);
program_t *p = s->prog;
BE_ApplyUniforms(s->prog, 0);
if (TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_BUMPMAP].hlsl.vert)
perm |= PERMUTATION_BUMPMAP;
if (TEXVALID(shaderstate.curtexnums->specular) && p->handle[perm|PERMUTATION_SPECULAR].hlsl.vert)
perm |= PERMUTATION_SPECULAR;
if (TEXVALID(shaderstate.curtexnums->fullbright) && p->handle[perm|PERMUTATION_FULLBRIGHT].hlsl.vert)
perm |= PERMUTATION_FULLBRIGHT;
if (TEXVALID(shaderstate.curtexnums->loweroverlay) && p->handle[perm|PERMUTATION_LOWER].hlsl.vert)
perm |= PERMUTATION_LOWER;
if (TEXVALID(shaderstate.curtexnums->upperoverlay) && p->handle[perm|PERMUTATION_UPPER].hlsl.vert)
perm |= PERMUTATION_UPPER;
if (r_refdef.gfog_rgbd[3] && p->handle[perm|PERMUTATION_FOG].hlsl.vert)
perm |= PERMUTATION_FOG;
// if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert)
// perm |= PERMUTATION_OFFSET;
BE_ApplyUniforms(p, perm);
D3DBE_ApplyShaderBits(s->passes->shaderbits);
/*activate tmus*/
for (passno = 0; passno < s->numpasses; passno++)
@ -1766,8 +1829,17 @@ static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst,
/*normals/tangents/bitangents*/
if (vdec & D3D_VDEC_NORM)
{
if (shaderstate.batchvbo)
{
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vec3_t)));
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vec3_t)));
d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vec3_t)));
}
else
{
/*FIXME*/
vdec &= ~D3D_VDEC_NORM;
}
}
/*bone weights+indexes*/
@ -1790,7 +1862,7 @@ static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst,
IDirect3DDevice9_SetPixelShader(pD3DDev9, NULL);
}
static void BE_Cull(unsigned int cullflags)
void D3DBE_Cull(unsigned int cullflags)
{
cullflags |= r_refdef.flipcull;
if (shaderstate.curcull != cullflags)
@ -1830,7 +1902,7 @@ static void BE_DrawMeshChain_Internal(void)
float pushdepth;
// float pushfactor;
BE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK));
D3DBE_Cull(shaderstate.curshader->flags & (SHADER_CULL_FRONT | SHADER_CULL_BACK));
pushdepth = (shaderstate.curshader->polyoffset.factor + ((shaderstate.flags & BEF_PUSHDEPTH)?r_polygonoffset_submodel_factor.value:0))/0xffff;
if (pushdepth != shaderstate.depthbias)
{
@ -1906,6 +1978,9 @@ static void BE_DrawMeshChain_Internal(void)
switch (shaderstate.mode)
{
case BEM_LIGHT:
BE_RenderMeshProgram(shaderstate.shader_rtlight, vertcount, idxfirst, idxcount);
break;
case BEM_DEPTHONLY:
shaderstate.lastpasscount = 0;
i = 0;
@ -1931,7 +2006,7 @@ static void BE_DrawMeshChain_Internal(void)
case BEM_STANDARD:
if (shaderstate.curshader->prog)
{
BE_RenderMeshProgram(vertcount, idxfirst, idxcount);
BE_RenderMeshProgram(shaderstate.curshader, vertcount, idxfirst, idxcount);
}
else
{
@ -1956,6 +2031,21 @@ static void BE_DrawMeshChain_Internal(void)
void D3DBE_SelectMode(backendmode_t mode)
{
shaderstate.mode = mode;
if (mode == BEM_STENCIL)
D3DBE_ApplyShaderBits(SBITS_MASK_BITS);
}
void D3DBE_SelectDLight(dlight_t *dl, vec3_t colour)
{
shaderstate.curdlight = dl;
VectorCopy(colour, shaderstate.curdlight_colours);
}
void D3DBE_SelectEntity(entity_t *ent)
{
shaderstate.curentity = ent;
BE_RotateForEntity(ent, ent->model);
}
/*Generates an optimised vbo for each of the given model's textures*/
@ -2719,12 +2809,12 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
}
}
void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist)
void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int first, int stop)
{
model_t *model = cl.worldmodel;
int i;
for (i = SHADER_SORT_PORTAL; i < SHADER_SORT_COUNT; i++)
for (i = first; i < stop; i++)
{
if (drawworld)
{
@ -2737,6 +2827,30 @@ void D3DBE_SubmitMeshes (qboolean drawworld, batch_t **blist)
}
}
#ifdef RTLIGHTS
void BE_BaseEntTextures(void)
{
batch_t *batches[SHADER_SORT_COUNT];
BE_GenModelBatches(batches);
D3DBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL);
BE_SelectEntity(&r_worldentity);
}
void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf)
{
IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, vbuf, 0, sizeof(vecV_t));
IDirect3DDevice9_SetIndices(pD3DDev9, ibuf);
if (0 != shaderstate.curvertdecl)
{
shaderstate.curvertdecl = 0;
d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl]));
}
IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, numverts, 0, numindicies/3);
}
#endif
void D3DBE_DrawWorld (qbyte *vis)
{
batch_t *batches[SHADER_SORT_COUNT];
@ -2774,13 +2888,22 @@ void D3DBE_DrawWorld (qbyte *vis)
BE_SelectMode(BEM_STANDARD);
RSpeedRemark();
D3DBE_SubmitMeshes(true, batches);
D3DBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL);
RSpeedEnd(RSPEED_WORLD);
#ifdef RTLIGHTS
RSpeedRemark();
D3DBE_SelectEntity(&r_worldentity);
Sh_DrawLights(vis, batches);
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif
D3DBE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_COUNT);
}
else
{
RSpeedRemark();
D3DBE_SubmitMeshes(false, batches);
D3DBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_COUNT);
RSpeedEnd(RSPEED_DRAWENTITIES);
}

View File

@ -472,7 +472,7 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de
d3dpp.Windowed = !info->fullscreen;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;//D3DFMT_D16;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
if (info->fullscreen)
{
@ -755,6 +755,16 @@ static void (D3D9_R_NewMap) (void)
Surf_DeInit();
Surf_WipeStains();
Surf_BuildLightmaps();
#ifdef RTLIGHTS
if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival)
{
R_LoadRTLights();
if (rtlights_first == rtlights_max)
R_ImportRTLights(cl.worldmodel->entities);
}
Sh_PreGenerateLights();
#endif
}
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
@ -1299,8 +1309,8 @@ rendererinfo_t d3drendererinfo =
D3DBE_GenBrushModelVBO,
D3DBE_ClearVBO,
D3DBE_UploadAllLightmaps,
NULL,
NULL,
D3DBE_SelectEntity,
D3DBE_SelectDLight,
D3DBE_LightCullModel,
"no more"

View File

@ -590,7 +590,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
return texnums;
}
#if defined(RTLIGHTS) && defined(GLQUAKE)
#if defined(RTLIGHTS)
static int numFacing;
static qbyte *triangleFacing;
static void R_CalcFacing(mesh_t *mesh, vec3_t lightpos)
@ -653,6 +653,7 @@ static void R_ProjectShadowVolume(mesh_t *mesh, vec3_t lightpos)
static void R_DrawShadowVolume(mesh_t *mesh)
{
#ifdef GLQUAKE
int t;
vec3_t *proj = ProjectedShadowVerts;
vecV_t *verts = mesh->xyz_array;
@ -708,6 +709,7 @@ static void R_DrawShadowVolume(mesh_t *mesh)
}
}
qglEnd();
#endif
}
#endif
@ -1136,8 +1138,8 @@ void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lig
result[2] = DotProduct (offs, axis[2]);
}
#if defined(RTLIGHTS) && defined(GLQUAKE)
void GL_LightMesh (mesh_t *mesh, vec3_t lightpos, vec3_t colours, float radius)
#if defined(RTLIGHTS)
static void GL_LightMesh (mesh_t *mesh, vec3_t lightpos, vec3_t colours, float radius)
{
vec3_t dir;
int i;
@ -1202,7 +1204,7 @@ void GL_LightMesh (mesh_t *mesh, vec3_t lightpos, vec3_t colours, float radius)
}
//courtesy of DP
void R_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
static void R_BuildBumpVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
{
float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
// 79 add/sub/negate/multiply (1 cycle), 1 compare (3 cycle?), total cycles not counting load/store/exchange roughly 82 cycles

View File

@ -4,7 +4,7 @@
//FIXME: this shouldn't be defined
#define FORCESTATE
#else
#define FORCESTATE
//#define FORCESTATE
#endif
//#define WIREFRAME
@ -18,6 +18,10 @@
#include <alloca.h>
#endif
#ifdef FORCESTATE
#pragma warningmsg("FORCESTATE is active")
#endif
extern cvar_t gl_overbright;
static const char LIGHTPASS_SHADER[] = "\
@ -482,6 +486,19 @@ void GL_SelectProgram(int program)
}
}
void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies)
{
GL_SelectVBO(vbo);
GL_SelectEBO(ibo);
qglEnableClientState(GL_VERTEX_ARRAY);
//draw cached world shadow mesh
qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), verts);
qglDrawRangeElements(GL_TRIANGLES, 0, numverts, numindicies, GL_INDEX_TYPE, indicies);
RQuantAdd(RQUANT_SHADOWFACES, numindicies);
GL_SelectVBO(0);
GL_SelectEBO(0);
}
static void GL_DeSelectProgram(void)
{
if (shaderstate.currentprogram != 0)

View File

@ -159,6 +159,8 @@ bucket_t *gltexturetablebuckets[256];
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;
int gl_filter_max_2d = GL_LINEAR;
int gl_mipcap_min = 0;
int gl_mipcap_max = 1000;
typedef struct gltexture_s
{
@ -257,6 +259,31 @@ void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldval
gl_anisotropy_factor = 0;
}
void GL_Mipcap_Callback (struct cvar_s *var, char *oldvalue)
{
gltexture_t *glt;
char *s = var->string;
s = COM_Parse(s);
gl_mipcap_min = *com_token?atoi(com_token):0;
if (gl_mipcap_min > 3) /*cap it to 3, so no 16*16 textures get bugged*/
gl_mipcap_min = 3;
s = COM_Parse(s);
gl_mipcap_max = *com_token?atoi(com_token):1000;
if (gl_mipcap_max < gl_mipcap_min)
gl_mipcap_max = gl_mipcap_min;
for (glt=gltextures ; glt ; glt=glt->next)
{
if (!(glt->flags & IF_NOMIPMAP))
if (glt->flags & IF_MIPCAP)
{
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, gl_mipcap_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, gl_mipcap_max);
}
}
}
/*
===============
Draw_TextureMode_f
@ -1336,6 +1363,13 @@ done:
if (gl_config.sgis_generate_mipmap && !(flags&IF_NOMIPMAP))
qglTexParameteri(targ, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
/*apply this flag after, so that we can safely change the base (to avoid drivers just not uploading lower mips)*/
if (flags & IF_MIPCAP)
{
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, gl_mipcap_min);
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, gl_mipcap_max);
}
}
void GL_Upload32 (char *name, unsigned *data, int width, int height, unsigned int flags)

View File

@ -1156,12 +1156,12 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
mipheight = tx->height;
}
tn.base = R_LoadReplacementTexture(mt->name, loadname, IF_NOALPHA|IF_SUBDIRONLY);
tn.base = R_LoadReplacementTexture(mt->name, loadname, ((*mt->name == '{')?0:IF_NOALPHA)|IF_SUBDIRONLY|IF_MIPCAP);
if (!TEXVALID(tn.base))
{
tn.base = R_LoadReplacementTexture(mt->name, "bmodels", (*mt->name == '{')?0:IF_NOALPHA);
tn.base = R_LoadReplacementTexture(mt->name, "bmodels", ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP);
if (!TEXVALID(tn.base))
tn.base = R_LoadTexture8 (mt->name, mipwidth, mipheight, mipbase, (*mt->name == '{')?0:IF_NOALPHA, 1);
tn.base = R_LoadTexture8 (mt->name, mipwidth, mipheight, mipbase, ((*mt->name == '{')?0:IF_NOALPHA)|IF_MIPCAP, 1);
}
if (r_fb_bmodels.value)
@ -1169,12 +1169,12 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
snprintf(altname, sizeof(altname)-1, "%s_luma", mt->name);
if (gl_load24bit.value)
{
tn.fullbright = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY);
tn.fullbright = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP);
if (!TEXVALID(tn.fullbright))
tn.fullbright = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA);
tn.fullbright = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP);
}
if ((*mt->name != '{') && !TEXVALID(tn.fullbright)) //generate one (if possible).
tn.fullbright = R_LoadTextureFB(altname, mipwidth, mipheight, mipbase, IF_NOGAMMA);
tn.fullbright = R_LoadTextureFB(altname, mipwidth, mipheight, mipbase, IF_NOGAMMA|IF_MIPCAP);
}
}
@ -1184,9 +1184,9 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
if (r_loadbumpmapping)
{
snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name);
tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY);
tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP);
if (!TEXVALID(tn.bump))
tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA);
tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP);
}
if (!TEXVALID(tn.bump))
{
@ -1215,9 +1215,9 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
if (gl_specular.value && gl_load24bit.value)
{
snprintf(altname, sizeof(altname)-1, "%s_gloss", mt->name);
tn.specular = R_LoadHiResTexture(altname, loadname, IF_NOALPHA|IF_NOGAMMA|IF_SUBDIRONLY);
tn.specular = R_LoadHiResTexture(altname, loadname, IF_NOALPHA|IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP);
if (!TEXVALID(tn.specular))
tn.specular = R_LoadHiResTexture(altname, "bmodels", IF_NOALPHA|IF_NOGAMMA);
tn.specular = R_LoadHiResTexture(altname, "bmodels", IF_NOALPHA|IF_NOGAMMA|IF_MIPCAP);
}
}
}
@ -1360,12 +1360,12 @@ void RMod_NowLoadExternal(void)
tx->alphaed = alphaed;
}
tn.base = R_LoadHiResTexture(tx->name, loadname, IF_NOALPHA);
tn.base = R_LoadHiResTexture(tx->name, loadname, IF_NOALPHA|IF_MIPCAP);
if (!TEXVALID(tn.base))
{
tn.base = R_LoadHiResTexture(tx->name, "bmodels", IF_NOALPHA);
tn.base = R_LoadHiResTexture(tx->name, "bmodels", IF_NOALPHA|IF_MIPCAP);
if (!TEXVALID(tn.base))
tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA); //a fallback. :/
tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA|IF_MIPCAP); //a fallback. :/
}
}
if (!TEXVALID(tn.bump) && *tx->name != '{' && r_loadbumpmapping)

View File

@ -274,18 +274,10 @@ void R_RenderDlights (void)
dlight_t *l;
vec3_t waste1, waste2;
unsigned int beflags = 0;
float intensity;
switch(r_flashblend.ival)
{
case 0:
return;
default:
case 1:
break;
case 2:
if (r_coronas.value)
beflags |= BEF_FORCENODEPTH;
break;
}
// r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
@ -308,13 +300,23 @@ void R_RenderDlights (void)
continue; //was a muzzleflash
}
if (r_flashblend.ival == 2)
intensity = l->corona * 0.25;
if (r_flashblend.value && (l->flags & LFLAG_FLASHBLEND))
intensity = l->corona; /*intensity is already in the corona value...*/
else
intensity = l->corona * r_coronas.value;
if (intensity <= 0)
continue;
/*coronas use depth testing to compute visibility*/
if (r_coronas.value)
{
if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2))
continue;
}
if (!R_BuildDlightMesh (l, l->corona, l->coronascale, false))
AddLightBlend (l->color[0]*5, l->color[1]*5, l->color[2]*5, l->radius * 0.0003);
if (!R_BuildDlightMesh (l, intensity, l->coronascale, false) && r_flashblend.value)
AddLightBlend (l->color[0], l->color[1], l->color[2], l->radius * 0.0003);
else
BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, beflags);
}
@ -445,6 +447,457 @@ void R_PushDlights (void)
}
/////////////////////////////////////////////////////////////
//rtlight loading
#ifdef RTLIGHTS
void R_ImportRTLights(char *entlump)
{
typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
/*I'm using the DP code so I know I'll get the DP results*/
int entnum, style, islight, skin, pflags, effects, n;
lighttype_t type;
float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
char key[256], value[8192];
int nest;
COM_Parse(entlump);
if (!strcmp(com_token, "Version"))
{
entlump = COM_Parse(entlump);
entlump = COM_Parse(entlump);
}
for (entnum = 0; ;entnum++)
{
entlump = COM_Parse(entlump);
if (com_token[0] != '{')
break;
type = LIGHTTYPE_MINUSX;
origin[0] = origin[1] = origin[2] = 0;
originhack[0] = originhack[1] = originhack[2] = 0;
angles[0] = angles[1] = angles[2] = 0;
color[0] = color[1] = color[2] = 1;
light[0] = light[1] = light[2] = 1;light[3] = 300;
overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
fadescale = 1;
lightscale = 1;
style = 0;
skin = 0;
pflags = 0;
effects = 0;
islight = false;
nest = 1;
while (1)
{
entlump = COM_Parse(entlump);
if (!entlump)
break; // error
if (com_token[0] == '{')
{
nest++;
continue;
}
if (com_token[0] == '}')
{
nest--;
if (!nest)
break; // end of entity
continue;
}
if (nest!=1)
continue;
if (com_token[0] == '_')
Q_strncpyz(key, com_token + 1, sizeof(key));
else
Q_strncpyz(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
entlump = COM_Parse(entlump);
if (!entlump)
break; // error
Q_strncpyz(value, com_token, sizeof(value));
// now that we have the key pair worked out...
if (!strcmp("light", key))
{
n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
if (n == 1)
{
// quake
light[0] = vec[0] * (1.0f / 256.0f);
light[1] = vec[0] * (1.0f / 256.0f);
light[2] = vec[0] * (1.0f / 256.0f);
light[3] = vec[0];
}
else if (n == 4)
{
// halflife
light[0] = vec[0] * (1.0f / 255.0f);
light[1] = vec[1] * (1.0f / 255.0f);
light[2] = vec[2] * (1.0f / 255.0f);
light[3] = vec[3];
}
}
else if (!strcmp("delay", key))
type = atoi(value);
else if (!strcmp("origin", key))
sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
else if (!strcmp("angle", key))
angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
else if (!strcmp("angles", key))
sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
else if (!strcmp("color", key))
sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
else if (!strcmp("wait", key))
fadescale = atof(value);
else if (!strcmp("classname", key))
{
if (!strncmp(value, "light", 5))
{
islight = true;
if (!strcmp(value, "light_fluoro"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 1;
overridecolor[2] = 1;
}
if (!strcmp(value, "light_fluorospark"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 1;
overridecolor[2] = 1;
}
if (!strcmp(value, "light_globe"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.8;
overridecolor[2] = 0.4;
}
if (!strcmp(value, "light_flame_large_yellow"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_flame_small_yellow"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_torch_small_white"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_torch_small_walltorch"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
}
}
else if (!strcmp("style", key))
style = atoi(value);
else if (!strcmp("skin", key))
skin = (int)atof(value);
else if (!strcmp("pflags", key))
pflags = (int)atof(value);
else if (!strcmp("effects", key))
effects = (int)atof(value);
else if (!strcmp("scale", key))
lightscale = atof(value);
else if (!strcmp("fade", key))
fadescale = atof(value);
else if (!strcmp("light_radius", key))
{
light[0] = 1;
light[1] = 1;
light[2] = 1;
light[3] = atof(value);
}
}
if (!islight)
continue;
if (lightscale <= 0)
lightscale = 1;
if (fadescale <= 0)
fadescale = 1;
if (color[0] == color[1] && color[0] == color[2])
{
color[0] *= overridecolor[0];
color[1] *= overridecolor[1];
color[2] *= overridecolor[2];
}
radius = light[3] * 1/*r_editlights_quakelightsizescale*/ * lightscale / fadescale;
color[0] = color[0] * light[0];
color[1] = color[1] * light[1];
color[2] = color[2] * light[2];
switch (type)
{
case LIGHTTYPE_MINUSX:
break;
case LIGHTTYPE_RECIPX:
radius *= 2;
VectorScale(color, (1.0f / 16.0f), color);
break;
case LIGHTTYPE_RECIPXX:
radius *= 2;
VectorScale(color, (1.0f / 16.0f), color);
break;
default:
case LIGHTTYPE_NONE:
break;
case LIGHTTYPE_SUN:
break;
case LIGHTTYPE_MINUSXX:
break;
}
VectorAdd(origin, originhack, origin);
if (radius >= 1)
{
dlight_t *dl = CL_AllocSlight();
if (!dl)
break;
VectorCopy(origin, dl->origin);
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
dl->radius = radius;
VectorCopy(color, dl->color);
dl->flags = 0;
dl->flags |= LFLAG_REALTIMEMODE;
dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_FLASHBLEND:0;
dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0;
dl->style = style+1;
//FIXME: cubemaps if skin >= 16
}
}
}
void R_LoadRTLights(void)
{
dlight_t *dl;
char fname[MAX_QPATH];
char cubename[MAX_QPATH];
char *file;
char *end;
int style;
vec3_t org;
float radius;
vec3_t rgb;
unsigned int flags;
float coronascale;
float corona;
float ambientscale, diffusescale, specularscale;
vec3_t angles;
//delete all old lights, even dynamic ones
rtlights_first = RTL_FIRST;
rtlights_max = RTL_FIRST;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1);
file = COM_LoadTempFile(fname);
if (file)
while(1)
{
end = strchr(file, '\n');
if (!end)
end = file + strlen(file);
if (end == file)
break;
*end = '\0';
while(*file == ' ' || *file == '\t')
file++;
if (*file == '!')
{
flags = LFLAG_NOSHADOWS;
file++;
}
else
flags = 0;
file = COM_Parse(file);
org[0] = atof(com_token);
file = COM_Parse(file);
org[1] = atof(com_token);
file = COM_Parse(file);
org[2] = atof(com_token);
file = COM_Parse(file);
radius = atof(com_token);
file = COM_Parse(file);
rgb[0] = file?atof(com_token):1;
file = COM_Parse(file);
rgb[1] = file?atof(com_token):1;
file = COM_Parse(file);
rgb[2] = file?atof(com_token):1;
file = COM_Parse(file);
style = file?atof(com_token):0;
file = COM_Parse(file);
//cubemap
Q_strncpyz(cubename, com_token, sizeof(cubename));
file = COM_Parse(file);
//corona
corona = file?atof(com_token):0;
file = COM_Parse(file);
angles[0] = file?atof(com_token):0;
file = COM_Parse(file);
angles[1] = file?atof(com_token):0;
file = COM_Parse(file);
angles[2] = file?atof(com_token):0;
file = COM_Parse(file);
//corrona scale
coronascale = file?atof(com_token):0.25;
file = COM_Parse(file);
//ambient
ambientscale = file?atof(com_token):0;
file = COM_Parse(file);
//diffuse
diffusescale = file?atof(com_token):1;
file = COM_Parse(file);
//specular
specularscale = file?atof(com_token):1;
file = COM_Parse(file);
flags |= file?atoi(com_token):LFLAG_REALTIMEMODE;
if (radius)
{
dl = CL_AllocSlight();
if (!dl)
break;
VectorCopy(org, dl->origin);
dl->radius = radius;
VectorCopy(rgb, dl->color);
dl->corona = corona;
dl->coronascale = coronascale;
dl->die = 0;
dl->flags = flags;
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
Q_strncpyz(dl->cubemapname, cubename, sizeof(dl->cubemapname));
if (*dl->cubemapname)
dl->cubetexture = R_LoadReplacementTexture(dl->cubemapname, "", IF_CUBEMAP);
else
dl->cubetexture = r_nulltex;
dl->style = style+1;
}
file = end+1;
}
}
void R_SaveRTLights_f(void)
{
dlight_t *light;
vfsfile_t *f;
unsigned int i;
char fname[MAX_QPATH];
vec3_t ang;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1);
FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
if (!f)
{
Con_Printf("couldn't open %s\n", fname);
return;
}
for (light = cl_dlights+rtlights_first, i=rtlights_first; i<rtlights_max; i++, light++)
{
if (light->die)
continue;
if (!light->radius)
continue;
VectorAngles(light->axis[0], light->axis[2], ang);
VFS_PUTS(f, va(
"%s%f %f %f "
"%f %f %f %f "
"%i "
"\"%s\" %f "
"%f %f %f "
"%f %f %f %f %i "
"\n"
,
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
light->radius, light->color[0], light->color[1], light->color[2],
light->style-1,
light->cubemapname, light->corona,
ang[0], ang[1], ang[2],
light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE|LFLAG_CREPUSCULAR)
));
}
VFS_CLOSE(f);
Con_Printf("rtlights saved to %s\n", fname);
}
void R_ReloadRTLights_f(void)
{
if (!cl.worldmodel)
{
Con_Printf("Cannot reload lights at this time\n");
return;
}
rtlights_first = RTL_FIRST;
rtlights_max = RTL_FIRST;
if (!strcmp(Cmd_Argv(1), "bsp"))
R_ImportRTLights(cl.worldmodel->entities);
else if (!strcmp(Cmd_Argv(1), "rtlights"))
R_LoadRTLights();
else if (strcmp(Cmd_Argv(1), "none"))
{
R_LoadRTLights();
if (rtlights_first == rtlights_max)
R_ImportRTLights(cl.worldmodel->entities);
}
}
#endif
/*
=============================================================================

View File

@ -24,9 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "glquake.h"
#include "gl_draw.h"
static void R_ReloadRTLights_f(void);
static void R_SaveRTLights_f(void);
/*
==================
R_InitTextures
@ -446,8 +443,6 @@ void GLV_Gamma_Callback(struct cvar_s *var, char *oldvalue);
void GLR_DeInit (void)
{
Cmd_RemoveCommand ("timerefresh");
Cmd_RemoveCommand ("r_editlights_reload");
Cmd_RemoveCommand ("r_editlights_save");
Cmd_RemoveCommand ("makewad");
@ -472,10 +467,6 @@ void GLR_DeInit (void)
void GLR_Init (void)
{
Cmd_AddRemCommand ("timerefresh", GLR_TimeRefresh_f);
#ifdef RTLIGHTS
Cmd_AddRemCommand ("r_editlights_reload", R_ReloadRTLights_f);
Cmd_AddRemCommand ("r_editlights_save", R_SaveRTLights_f);
#endif
// Cmd_AddRemCommand ("makewad", R_MakeTexWad_f);
@ -491,453 +482,6 @@ void GLR_Init (void)
GLR_ReInit();
}
#ifdef RTLIGHTS
static void R_ImportRTLights(char *entlump)
{
typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t;
/*I'm using the DP code so I know I'll get the DP results*/
int entnum, style, islight, skin, pflags, effects, n;
lighttype_t type;
float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
char key[256], value[8192];
int nest;
COM_Parse(entlump);
if (!strcmp(com_token, "Version"))
{
entlump = COM_Parse(entlump);
entlump = COM_Parse(entlump);
}
for (entnum = 0; ;entnum++)
{
entlump = COM_Parse(entlump);
if (com_token[0] != '{')
break;
type = LIGHTTYPE_MINUSX;
origin[0] = origin[1] = origin[2] = 0;
originhack[0] = originhack[1] = originhack[2] = 0;
angles[0] = angles[1] = angles[2] = 0;
color[0] = color[1] = color[2] = 1;
light[0] = light[1] = light[2] = 1;light[3] = 300;
overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
fadescale = 1;
lightscale = 1;
style = 0;
skin = 0;
pflags = 0;
effects = 0;
islight = false;
nest = 1;
while (1)
{
entlump = COM_Parse(entlump);
if (!entlump)
break; // error
if (com_token[0] == '{')
{
nest++;
continue;
}
if (com_token[0] == '}')
{
nest--;
if (!nest)
break; // end of entity
continue;
}
if (nest!=1)
continue;
if (com_token[0] == '_')
Q_strncpyz(key, com_token + 1, sizeof(key));
else
Q_strncpyz(key, com_token, sizeof(key));
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
entlump = COM_Parse(entlump);
if (!entlump)
break; // error
Q_strncpyz(value, com_token, sizeof(value));
// now that we have the key pair worked out...
if (!strcmp("light", key))
{
n = sscanf(value, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
if (n == 1)
{
// quake
light[0] = vec[0] * (1.0f / 256.0f);
light[1] = vec[0] * (1.0f / 256.0f);
light[2] = vec[0] * (1.0f / 256.0f);
light[3] = vec[0];
}
else if (n == 4)
{
// halflife
light[0] = vec[0] * (1.0f / 255.0f);
light[1] = vec[1] * (1.0f / 255.0f);
light[2] = vec[2] * (1.0f / 255.0f);
light[3] = vec[3];
}
}
else if (!strcmp("delay", key))
type = atoi(value);
else if (!strcmp("origin", key))
sscanf(value, "%f %f %f", &origin[0], &origin[1], &origin[2]);
else if (!strcmp("angle", key))
angles[0] = 0, angles[1] = atof(value), angles[2] = 0;
else if (!strcmp("angles", key))
sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]);
else if (!strcmp("color", key))
sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
else if (!strcmp("wait", key))
fadescale = atof(value);
else if (!strcmp("classname", key))
{
if (!strncmp(value, "light", 5))
{
islight = true;
if (!strcmp(value, "light_fluoro"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 1;
overridecolor[2] = 1;
}
if (!strcmp(value, "light_fluorospark"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 1;
overridecolor[2] = 1;
}
if (!strcmp(value, "light_globe"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.8;
overridecolor[2] = 0.4;
}
if (!strcmp(value, "light_flame_large_yellow"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_flame_small_yellow"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_torch_small_white"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
if (!strcmp(value, "light_torch_small_walltorch"))
{
originhack[0] = 0;
originhack[1] = 0;
originhack[2] = 0;
overridecolor[0] = 1;
overridecolor[1] = 0.5;
overridecolor[2] = 0.1;
}
}
}
else if (!strcmp("style", key))
style = atoi(value);
else if (!strcmp("skin", key))
skin = (int)atof(value);
else if (!strcmp("pflags", key))
pflags = (int)atof(value);
else if (!strcmp("effects", key))
effects = (int)atof(value);
else if (!strcmp("scale", key))
lightscale = atof(value);
else if (!strcmp("fade", key))
fadescale = atof(value);
else if (!strcmp("light_radius", key))
{
light[0] = 1;
light[1] = 1;
light[2] = 1;
light[3] = atof(value);
}
}
if (!islight)
continue;
if (lightscale <= 0)
lightscale = 1;
if (fadescale <= 0)
fadescale = 1;
if (color[0] == color[1] && color[0] == color[2])
{
color[0] *= overridecolor[0];
color[1] *= overridecolor[1];
color[2] *= overridecolor[2];
}
radius = light[3] * 1/*r_editlights_quakelightsizescale*/ * lightscale / fadescale;
color[0] = color[0] * light[0];
color[1] = color[1] * light[1];
color[2] = color[2] * light[2];
switch (type)
{
case LIGHTTYPE_MINUSX:
break;
case LIGHTTYPE_RECIPX:
radius *= 2;
VectorScale(color, (1.0f / 16.0f), color);
break;
case LIGHTTYPE_RECIPXX:
radius *= 2;
VectorScale(color, (1.0f / 16.0f), color);
break;
default:
case LIGHTTYPE_NONE:
break;
case LIGHTTYPE_SUN:
break;
case LIGHTTYPE_MINUSXX:
break;
}
VectorAdd(origin, originhack, origin);
if (radius >= 1)
{
dlight_t *dl = CL_AllocSlight();
if (!dl)
break;
VectorCopy(origin, dl->origin);
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
dl->radius = radius;
VectorCopy(color, dl->color);
dl->flags = 0;
dl->flags |= LFLAG_REALTIMEMODE;
dl->flags |= (pflags & PFLAGS_CORONA)?LFLAG_FLASHBLEND:0;
dl->flags |= (pflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0;
dl->style = style+1;
//FIXME: cubemaps if skin >= 16
}
}
}
static void R_LoadRTLights(void)
{
dlight_t *dl;
char fname[MAX_QPATH];
char cubename[MAX_QPATH];
char *file;
char *end;
int style;
vec3_t org;
float radius;
vec3_t rgb;
unsigned int flags;
float coronascale;
float corona;
float ambientscale, diffusescale, specularscale;
vec3_t angles;
//delete all old lights, even dynamic ones
rtlights_first = RTL_FIRST;
rtlights_max = RTL_FIRST;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1);
file = COM_LoadTempFile(fname);
if (file)
while(1)
{
end = strchr(file, '\n');
if (!end)
end = file + strlen(file);
if (end == file)
break;
*end = '\0';
while(*file == ' ' || *file == '\t')
file++;
if (*file == '!')
{
flags = LFLAG_NOSHADOWS;
file++;
}
else
flags = 0;
file = COM_Parse(file);
org[0] = atof(com_token);
file = COM_Parse(file);
org[1] = atof(com_token);
file = COM_Parse(file);
org[2] = atof(com_token);
file = COM_Parse(file);
radius = atof(com_token);
file = COM_Parse(file);
rgb[0] = file?atof(com_token):1;
file = COM_Parse(file);
rgb[1] = file?atof(com_token):1;
file = COM_Parse(file);
rgb[2] = file?atof(com_token):1;
file = COM_Parse(file);
style = file?atof(com_token):0;
file = COM_Parse(file);
//cubemap
Q_strncpyz(cubename, com_token, sizeof(cubename));
file = COM_Parse(file);
//corona
corona = file?atof(com_token):0;
file = COM_Parse(file);
angles[0] = file?atof(com_token):0;
file = COM_Parse(file);
angles[1] = file?atof(com_token):0;
file = COM_Parse(file);
angles[2] = file?atof(com_token):0;
file = COM_Parse(file);
//corrona scale
coronascale = file?atof(com_token):0.25;
file = COM_Parse(file);
//ambient
ambientscale = file?atof(com_token):0;
file = COM_Parse(file);
//diffuse
diffusescale = file?atof(com_token):1;
file = COM_Parse(file);
//specular
specularscale = file?atof(com_token):1;
file = COM_Parse(file);
flags |= file?atoi(com_token):LFLAG_REALTIMEMODE;
if (radius)
{
dl = CL_AllocSlight();
if (!dl)
break;
VectorCopy(org, dl->origin);
dl->radius = radius;
VectorCopy(rgb, dl->color);
dl->corona = corona;
dl->coronascale = coronascale;
dl->die = 0;
dl->flags = flags;
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
Q_strncpyz(dl->cubemapname, cubename, sizeof(dl->cubemapname));
if (*dl->cubemapname)
dl->cubetexture = R_LoadReplacementTexture(dl->cubemapname, "", IF_CUBEMAP);
else
dl->cubetexture = r_nulltex;
dl->style = style+1;
}
file = end+1;
}
}
static void R_SaveRTLights_f(void)
{
dlight_t *light;
vfsfile_t *f;
unsigned int i;
char fname[MAX_QPATH];
vec3_t ang;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1);
FS_CreatePath(fname, FS_GAMEONLY);
f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
if (!f)
{
Con_Printf("couldn't open %s\n", fname);
return;
}
for (light = cl_dlights+rtlights_first, i=rtlights_first; i<rtlights_max; i++, light++)
{
if (light->die)
continue;
if (!light->radius)
continue;
VectorAngles(light->axis[0], light->axis[2], ang);
VFS_PUTS(f, va(
"%s%f %f %f "
"%f %f %f %f "
"%i "
"\"%s\" %f "
"%f %f %f "
"%f %f %f %f %i "
"\n"
,
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
light->radius, light->color[0], light->color[1], light->color[2],
light->style-1,
light->cubemapname, light->corona,
ang[0], ang[1], ang[2],
light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE|LFLAG_CREPUSCULAR)
));
}
VFS_CLOSE(f);
Con_Printf("rtlights saved to %s\n", fname);
}
void R_ReloadRTLights_f(void)
{
if (!cl.worldmodel)
{
Con_Printf("Cannot reload lights at this time\n");
return;
}
rtlights_first = RTL_FIRST;
rtlights_max = RTL_FIRST;
if (!strcmp(Cmd_Argv(1), "bsp"))
R_ImportRTLights(cl.worldmodel->entities);
else if (!strcmp(Cmd_Argv(1), "rtlights"))
R_LoadRTLights();
else if (strcmp(Cmd_Argv(1), "none"))
{
R_LoadRTLights();
if (rtlights_first == rtlights_max)
R_ImportRTLights(cl.worldmodel->entities);
}
}
#endif
/*
===============
R_NewMap

View File

@ -949,7 +949,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
typedef struct sgeneric_s
{
struct sgeneric_s *next;
char name[MAX_QPATH];
char *name;
qboolean failed;
program_t prog;
} sgeneric_t;
@ -2047,11 +2047,8 @@ struct sbuiltin_s
"#endif\n"
"#ifdef BUMP\n"
"vec3 bases = vec3(texture2D(s_t0, tcbase));\n"
"#else\n"
"vec3 diff = vec3(texture2D(s_t0, tcbase));\n"
"#endif\n"
"#if defined(BUMP) || defined(SPECULAR)\n"
"vec3 bumps = vec3(texture2D(s_t1, tcbase)) * 2.0 - 1.0;\n"
"#endif\n"
@ -2062,9 +2059,11 @@ struct sbuiltin_s
"vec3 nl = normalize(lightvector);\n"
"float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n"
"#ifdef BUMP\n"
"vec3 diff;\n"
"#ifdef BUMP\n"
"diff = bases * max(dot(bumps, nl), 0.0);\n"
"#else\n"
"diff = bases * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0);\n"
"#endif\n"
"#ifdef SPECULAR\n"
"vec3 halfdir = (normalize(eyevector) + normalize(lightvector))/2.0;\n"
@ -2110,6 +2109,68 @@ struct sbuiltin_s
#endif
#ifdef D3DQUAKE
{QR_DIRECT3D, 9, "rtlight",
/*
texture units:
s0=diffuse, s1=normal, s2=specular, s3=shadowmap
custom modifiers:
PCF(shadowmap)
CUBE(projected cubemap)
*/
"!!permu BUMP\n"
"!!permu SPECULAR\n"
"!!permu OFFSETMAPPING\n"
"!!permu SKELETAL\n"
"!!permu FOG\n"
"struct a2v {\n"
"float4 pos: POSITION;\n"
"float3 tc: TEXCOORD0;\n"
"float3 n: NORMAL0;\n"
"float3 s: TANGENT0;\n"
"float3 t: BINORMAL0;\n"
"};\n"
"struct v2f {\n"
"#ifndef FRAGMENT_SHADER\n"
"float4 pos: POSITION;\n"
"#endif\n"
"float3 tc: TEXCOORD0;\n"
"float3 lpos: TEXCOORD1;\n"
"};\n"
"#ifdef VERTEX_SHADER\n"
"float4x4 m_modelviewprojection;\n"
"float3 l_lightposition;\n"
"v2f main (a2v inp)\n"
"{\n"
" v2f outp;\n"
" outp.pos = mul(m_modelviewprojection, inp.pos);\n"
" outp.tc = inp.tc;\n"
"float3 lightminusvertex = l_lightposition - inp.pos.xyz;\n"
"outp.lpos.x = dot(lightminusvertex, inp.s.xyz);\n"
"outp.lpos.y = dot(lightminusvertex, inp.t.xyz);\n"
"outp.lpos.z = dot(lightminusvertex, inp.n.xyz);\n"
" return outp;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"sampler s_t0;\n"
"sampler s_t1;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float4 main (v2f inp) : COLOR0\n"
"{\n"
" float3 col = l_lightcolour;\n"
" col *= max(1.0 - dot(inp.lpos, inp.lpos)/(l_lightradius*l_lightradius), 0.0);\n"
" float3 diff = tex2D(s_t0, inp.tc);\n"
" return float4(diff * col, 1);"
"}\n"
"#endif\n"
},
{QR_DIRECT3D, 9, "defaultsky",
"struct a2v {\n"
@ -2136,8 +2197,14 @@ struct sbuiltin_s
"#ifdef FRAGMENT_SHADER\n"
"float e_time;\n"
"float3 e_eyepos;\n"
"sampler s_t0;\n"
"sampler s_t1;\n"
"float l_lightradius;\n"
"float3 l_lightcolour;\n"
"float3 l_lightposition;\n"
"sampler s_t0;\n" /*diffuse*/
"sampler s_t1;\n" /*normal*/
"sampler s_t2;\n" /*specular*/
"float4 main (v2f inp) : COLOR0\n"
"{\n"
" float2 tccoord;\n"
@ -2154,7 +2221,6 @@ struct sbuiltin_s
" float4 clouds = tex2D(s_t1, tccoord);\n"
" return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n"
// " return float4(solid.rgb, 1);"///*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n"
"}\n"
"#endif\n"
},
@ -2200,8 +2266,7 @@ struct sbuiltin_s
#endif
{QR_NONE}
};
static sgeneric_t *sgenerics;
void Shader_UnloadGeneric(program_t *prog)
void Shader_UnloadProg(program_t *prog)
{
if (prog->refs == 1)
{
@ -2241,7 +2306,10 @@ static void Shader_FlushGenerics(void)
sgenerics = g->next;
if (g->prog.refs == 1)
{
g->prog.refs--;
free(g);
}
else
Con_Printf("generic shader still used\n");
}
@ -2263,10 +2331,9 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype)
}
}
if (strlen(name) >= sizeof(g->name))
return NULL; /*name overflow*/
g = malloc(sizeof(*g));
g = malloc(sizeof(*g) + strlen(name)+1);
memset(g, 0, sizeof(*g));
g->name = (char*)(g+1);
strcpy(g->name, name);
g->next = sgenerics;
sgenerics = g;
@ -2445,6 +2512,11 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
/*set cvar unirforms*/
for (i = 0; cvarnames[i]; i++)
{
if (prog->numparams == SHADER_PROGPARMS_MAX)
{
Con_Printf("Too many cvar paramters for program\n");
break;
}
for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++)
tmpname[p] = cvarnames[i][p];
tmpname[p] = 0;
@ -2485,15 +2557,26 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, shader_field_names[i].name);
if (uniformloc != -1)
found = true;
prog->parm[prog->numparams].handle[p] = uniformloc;
if (prog->numparams == SHADER_PROGPARMS_MAX)
{
if (found)
break;
}
else
prog->parm[prog->numparams].handle[p] = uniformloc;
}
if (found)
{
prog->parm[prog->numparams].type = shader_field_names[i].ptype;
prog->numparams++;
if (prog->numparams == SHADER_PROGPARMS_MAX)
Con_Printf("Too many paramters for program (ignoring %s)\n", shader_field_names[i].name);
else
{
prog->parm[prog->numparams].type = shader_field_names[i].ptype;
prog->numparams++;
if (shader_field_names[i].ptype < SP_FIRSTUNIFORM)
prog->nofixedcompat = true;
if (shader_field_names[i].ptype < SP_FIRSTUNIFORM)
prog->nofixedcompat = true;
}
}
}
/*set texture uniforms*/
@ -3663,7 +3746,7 @@ void Shader_Free (shader_t *shader)
shader->bucket.data = NULL;
if (shader->prog)
Shader_UnloadGeneric(shader->prog);
Shader_UnloadProg(shader->prog);
shader->prog = NULL;
if (shader->skydome)

View File

@ -1,11 +1,24 @@
#include "quakedef.h"
#ifdef GLQUAKE
#if defined(GLQUAKE) || defined(D3DQUAKE)
#ifdef RTLIGHTS
#include "glquake.h"
#include "shader.h"
#ifdef D3DQUAKE
#include "shader.h"
#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
#define HMONITOR_DECLARED
DECLARE_HANDLE(HMONITOR);
#endif
#include <d3d9.h>
extern LPDIRECT3DDEVICE9 pD3DDev9;
void D3DBE_Cull(unsigned int sflags);
void D3DBE_RenderShadowBuffer(unsigned int numverts, IDirect3DVertexBuffer9 *vbuf, unsigned int numindicies, IDirect3DIndexBuffer9 *ibuf);
#endif
void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsigned numindicies, int ibo, index_t *indicies);
#define SHADOWMAP_SIZE 512
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
@ -31,7 +44,21 @@ struct {
void Sh_Shutdown(void)
{
#ifdef GLQUAKE
if (shadow_fbo_id)
{
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0;
}
if (crepuscular_fbo_id)
{
qglDeleteRenderbuffersEXT(1, &crepuscular_fbo_id);
crepuscular_fbo_id = 0;
}
#endif
}
@ -58,7 +85,13 @@ typedef struct shadowmesh_s {
unsigned int leafbytes;
unsigned char *litleaves;
#ifdef GLQUAKE
GLuint vebo[2];
#endif
#ifdef D3DQUAKE
IDirect3DVertexBuffer9 *d3d_vbuffer;
IDirect3DIndexBuffer9 *d3d_ibuffer;
#endif
} shadowmesh_t;
/*state of the current shadow mesh*/
@ -95,7 +128,7 @@ static void SHM_End (void)
}
sh_vertnum = 0;
}
static void SHM_Vertex3fv (const GLfloat *v)
static void SHM_Vertex3fv (const float *v)
{
int i;
@ -213,9 +246,26 @@ static void SH_FreeShadowMesh(shadowmesh_t *sm)
Z_Free(sm->indicies);
Z_Free(sm->verts);
qglDeleteBuffersARB(2, sm->vebo);
sm->vebo[0] = 0;
sm->vebo[1] = 0;
switch (qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
qglDeleteBuffersARB(2, sm->vebo);
sm->vebo[0] = 0;
sm->vebo[1] = 0;
break;
#endif
#ifdef D3DQUAKE
case QR_DIRECT3D:
if (sm->d3d_ibuffer)
IDirect3DIndexBuffer9_Release(sm->d3d_ibuffer);
sm->d3d_ibuffer = NULL;
if (sm->d3d_vbuffer)
IDirect3DVertexBuffer9_Release(sm->d3d_vbuffer);
sm->d3d_vbuffer = NULL;
break;
#endif
}
Z_Free(sm);
}
@ -285,15 +335,42 @@ static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl)
{
if (sh_shmesh != &sh_tempshmesh)
{
qglGenBuffersARB(2, sh_shmesh->vebo);
switch (qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
qglGenBuffersARB(2, sh_shmesh->vebo);
GL_SelectVBO(sh_shmesh->vebo[0]);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->verts) * sh_shmesh->numverts, sh_shmesh->verts, GL_STATIC_DRAW_ARB);
GL_SelectEBO(sh_shmesh->vebo[1]);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->indicies) * sh_shmesh->numindicies, sh_shmesh->indicies, GL_STATIC_DRAW_ARB);
break;
#endif
#ifdef D3DQUAKE
case QR_DIRECT3D:
if (sh_shmesh->numindicies && sh_shmesh->numverts)
{
void *map;
IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, sizeof(index_t) * sh_shmesh->numindicies, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &sh_shmesh->d3d_ibuffer, NULL);
IDirect3DIndexBuffer9_Lock(sh_shmesh->d3d_ibuffer, 0, sizeof(index_t) * sh_shmesh->numindicies, &map, D3DLOCK_DISCARD);
memcpy(map, sh_shmesh->indicies, sizeof(index_t) * sh_shmesh->numindicies);
IDirect3DIndexBuffer9_Unlock(sh_shmesh->d3d_ibuffer);
IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, sizeof(vecV_t) * sh_shmesh->numverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &sh_shmesh->d3d_vbuffer, NULL);
IDirect3DVertexBuffer9_Lock(sh_shmesh->d3d_vbuffer, 0, sizeof(vecV_t) * sh_shmesh->numverts, &map, D3DLOCK_DISCARD);
memcpy(map, sh_shmesh->verts, sizeof(vecV_t) * sh_shmesh->numverts);
IDirect3DVertexBuffer9_Unlock(sh_shmesh->d3d_vbuffer);
}
break;
#endif
}
GL_SelectVBO(sh_shmesh->vebo[0]);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->verts) * sh_shmesh->numverts, sh_shmesh->verts, GL_STATIC_DRAW_ARB);
Z_Free(sh_shmesh->verts);
sh_shmesh->verts = NULL;
GL_SelectEBO(sh_shmesh->vebo[1]);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->indicies) * sh_shmesh->numindicies, sh_shmesh->indicies, GL_STATIC_DRAW_ARB);
Z_Free(sh_shmesh->indicies);
sh_shmesh->indicies = NULL;
}
@ -1279,12 +1356,31 @@ static void Sh_Scissor (srect_t r)
}
#endif
qglScissor(r.x, r.y, r.width, r.height);
if (qglDepthBoundsEXT)
switch(qrenderer)
{
qglDepthBoundsEXT(r.dmin, r.dmax);
qglEnable(GL_DEPTH_BOUNDS_TEST_EXT);
#ifdef GLQUAKE
case QR_OPENGL:
qglScissor(r.x, r.y, r.width, r.height);
if (qglDepthBoundsEXT)
{
qglDepthBoundsEXT(r.dmin, r.dmax);
qglEnable(GL_DEPTH_BOUNDS_TEST_EXT);
}
break;
#endif
#ifdef D3DQUAKE
case QR_DIRECT3D:
{
RECT rect;
rect.left = r.x;
rect.right = r.x + r.width;
rect.top = r.y;
rect.bottom = r.y + r.height;
IDirect3DDevice9_SetScissorRect(pD3DDev9, &rect);
}
break;
#endif
}
}
@ -1656,7 +1752,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, vrect_t *r)
}
#endif
#ifdef GLQUAKE
void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
{
if (gl_config.ext_framebuffer_objects)
@ -1791,20 +1887,6 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p
memcpy(r_refdef.m_view, sav, sizeof(r_refdef.m_view));
}
void Sh_Shutdown(void)
{
if (shadow_fbo_id)
{
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0;
}
if (crepuscular_fbo_id)
{
qglDeleteRenderbuffersEXT(1, &crepuscular_fbo_id);
crepuscular_fbo_id = 0;
}
}
void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
{
int f;
@ -1995,7 +2077,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
qglLoadIdentity();
qglMatrixMode(GL_MODELVIEW);
}
#endif
@ -2064,6 +2146,7 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
#endif
static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
{
#ifdef GLQUAKE
int v;
float *v1, *v2;
vec3_t v3, v4;
@ -2162,6 +2245,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
}
BE_PushOffsetShadow(false);
#endif
}
@ -2175,27 +2259,29 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
struct shadowmesh_s *sm;
entity_t *ent;
BE_PushOffsetShadow(false);
#ifdef GLQUAKE
if (qrenderer == QR_OPENGL)
BE_PushOffsetShadow(false);
#endif
sm = SHM_BuildShadowMesh(dl, lvis, vvis, false);
if (!sm)
Sh_DrawBrushModelShadow(dl, &r_worldentity);
else
{
//qglEnable(GL_POLYGON_OFFSET_FILL);
//qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
GL_SelectVBO(sm->vebo[0]);
GL_SelectEBO(sm->vebo[1]);
qglEnableClientState(GL_VERTEX_ARRAY);
//draw cached world shadow mesh
qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), sm->verts);
qglDrawRangeElements(GL_TRIANGLES, 0, sm->numverts, sm->numindicies, GL_INDEX_TYPE, sm->indicies);
RQuantAdd(RQUANT_SHADOWFACES, sm->numindicies);
GL_SelectVBO(0);
GL_SelectEBO(0);
//qglEnable(GL_POLYGON_OFFSET_FILL);
//qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
switch (qrenderer)
{
#ifdef D3DQUAKE
case QR_DIRECT3D:
D3DBE_RenderShadowBuffer(sm->numverts, sm->d3d_vbuffer, sm->numindicies, sm->d3d_ibuffer);
break;
#endif
#ifdef GLQUAKE
case QR_OPENGL:
GLBE_RenderShadowBuffer(sm->numverts, sm->vebo[0], sm->verts, sm->numindicies, sm->vebo[1], sm->indicies);
break;
#endif
}
}
if (!r_drawentities.value)
return;
@ -2246,8 +2332,6 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{
int sref;
int sfrontfail;
int sbackfail;
int leaf;
qbyte *lvis;
srect_t rect;
@ -2301,165 +2385,217 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
}
bench.numlights++;
GLBE_SelectDLight(dl, colour);
BE_SelectDLight(dl, colour);
BE_SelectMode(BEM_STENCIL);
//The backend doesn't maintain scissor state.
//The backend doesn't maintain stencil test state either - it needs to be active for more than just stencils, or disabled. its awkward.
Sh_Scissor(rect);
qglEnable(GL_SCISSOR_TEST);
qglEnable(GL_STENCIL_TEST);
//FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer?
/*we don't need all that much stencil buffer depth, and if we don't get enough or have dodgy volumes, wrap if we can*/
#ifdef I_LIVE_IN_A_FREE_COUNTRY
sref = 0;
sbackfail = GL_INCR;
sfrontfail = GL_DECR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sbackfail = GL_INCR_WRAP_EXT;
sdecrw = GL_DECR_WRAP_EXT;
}
#else
sref = (1<<gl_stencilbits)-1; /*this is halved for two-sided stencil support, just in case there's no wrap support*/
sbackfail = GL_DECR;
sfrontfail = GL_INCR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sbackfail = GL_DECR_WRAP_EXT;
sfrontfail = GL_INCR_WRAP_EXT;
}
#endif
//our stencil writes.
if (gl_config.arb_depth_clamp)
qglEnable(GL_DEPTH_CLAMP_ARB);
#if 0 //def _DEBUG
// if (r_shadows.value == 666) //testing (visible shadow volumes)
switch(qrenderer)
{
checkglerror();
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
qglColor3f(dl->color[0], dl->color[1], dl->color[2]);
qglDisable(GL_STENCIL_TEST);
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(-1, -1);
// qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglDisable(GL_POLYGON_OFFSET_FILL);
checkglerror();
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
#ifdef GLQUAKE
case QR_OPENGL:
{
int sfrontfail;
int sbackfail;
qglEnable(GL_SCISSOR_TEST);
qglEnable(GL_STENCIL_TEST);
if (qglStencilOpSeparateATI)
{
//FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer?
/*we don't need all that much stencil buffer depth, and if we don't get enough or have dodgy volumes, wrap if we can*/
#ifdef I_LIVE_IN_A_FREE_COUNTRY
sref = 0;
sbackfail = GL_INCR;
sfrontfail = GL_DECR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sbackfail = GL_INCR_WRAP_EXT;
sdecrw = GL_DECR_WRAP_EXT;
}
#else
sref = (1<<gl_stencilbits)-1; /*this is halved for two-sided stencil support, just in case there's no wrap support*/
sbackfail = GL_DECR;
sfrontfail = GL_INCR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sbackfail = GL_DECR_WRAP_EXT;
sfrontfail = GL_INCR_WRAP_EXT;
}
#endif
//our stencil writes.
if (gl_config.arb_depth_clamp)
qglEnable(GL_DEPTH_CLAMP_ARB);
#if 0 //def _DEBUG
// if (r_shadows.value == 666) //testing (visible shadow volumes)
{
checkglerror();
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
qglColor3f(dl->color[0], dl->color[1], dl->color[2]);
qglDisable(GL_STENCIL_TEST);
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(-1, -1);
// qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglDisable(GL_POLYGON_OFFSET_FILL);
checkglerror();
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
#endif
if (qglStencilOpSeparateATI)
{
sref/=2;
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglStencilFunc(GL_ALWAYS, 0, ~0);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, sbackfail, GL_KEEP);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglStencilOpSeparateATI(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilFunc(GL_EQUAL, sref, ~0);
}
else if (qglActiveStencilFaceEXT)
{
sref/=2;
/*personally I prefer the ATI way (nvidia method)*/
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, sref, ~0 );
qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
}
else //your graphics card sucks and lacks efficient stencil shadow techniques.
{ //centered around 0. Will only be increased then decreased less.
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
qglStencilFunc(GL_ALWAYS, 0, ~0);
GL_CullFace(SHADER_CULL_BACK);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, true);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, sref, ~0);
}
if (gl_config.arb_depth_clamp)
qglDisable(GL_DEPTH_CLAMP_ARB);
//end stencil writing.
/*stencil writing probably changed the vertex pointer, and our backend caches it*/
PPL_RevertToKnownState();
#if 0 //draw the stencil stuff to the red channel
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
GL_Set2D();
{
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_GREATER, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_LESS, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
qglStencilFunc(GL_EQUAL, sref, ~0);
R2D_ConsoleBackground(vid.height);
}
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
#endif
BE_SelectMode(BEM_LIGHT);
Sh_DrawEntLighting(dl, colour);
qglDisable(GL_STENCIL_TEST);
qglStencilFunc( GL_ALWAYS, 0, ~0 );
}
break;
#endif
#ifdef D3DQUAKE
case QR_DIRECT3D:
sref = (1<<8)-1;
sref/=2;
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglStencilFunc(GL_ALWAYS, 0, ~0);
/*clear the stencil buffer*/
IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 0), 1.0f, sref);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, sbackfail, GL_KEEP);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglStencilOpSeparateATI(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilFunc(GL_EQUAL, sref, ~0);
}
else if (qglActiveStencilFaceEXT)
{
sref/=2;
/*personally I prefer the ATI way (nvidia method)*/
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
/*set up 2-sided stenciling*/
D3DBE_Cull(0);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILENABLE, true);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_TWOSIDEDSTENCILMODE, true);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_INCR);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
/*draw the shadows*/
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
//disable stencil writing, switch culling back to normal
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_TWOSIDEDSTENCILMODE, false);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_CULLMODE, D3DCULL_CW);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILREF, sref);
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILMASK, ~0);
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, sref, ~0 );
/*draw the light*/
BE_SelectMode(BEM_LIGHT);
Sh_DrawEntLighting(dl, colour);
qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
GL_CullFace(SHADER_CULL_FRONT);
}
else //your graphics card sucks and lacks efficient stencil shadow techniques.
{ //centered around 0. Will only be increased then decreased less.
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
qglStencilFunc(GL_ALWAYS, 0, ~0);
GL_CullFace(SHADER_CULL_BACK);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, true);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, sref, ~0);
}
if (gl_config.arb_depth_clamp)
qglDisable(GL_DEPTH_CLAMP_ARB);
//end stencil writing.
#if 0 //draw the stencil stuff to the red channel
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
GL_Set2D();
{
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_GREATER, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_LESS, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
qglStencilFunc(GL_EQUAL, sref, ~0);
R2D_ConsoleBackground(vid.height);
}
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
/*okay, no more stencil stuff*/
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_STENCILENABLE, false);
break;
#endif
PPL_RevertToKnownState();
BE_SelectMode(BEM_LIGHT);
Sh_DrawEntLighting(dl, colour);
qglDisable(GL_STENCIL_TEST);
qglStencilFunc( GL_ALWAYS, 0, ~0 );
}
return true;
}
@ -2517,13 +2653,22 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
bench.numscissorculled++;
return; //was culled.
}
qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
//so state doesn't linger
qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
break;
#endif
}
bench.numlights++;
GLBE_SelectDLight(dl, colour);
BE_SelectDLight(dl, colour);
BE_SelectMode(BEM_LIGHT);
Sh_DrawEntLighting(dl, colour);
}
@ -2531,6 +2676,7 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop);
void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches)
{
#ifdef GLQUAKE
static mesh_t mesh;
static vecV_t xyz[4] =
{
@ -2551,12 +2697,15 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches)
0,1,2,
0,2,3
};
if (qrenderer != QR_OPENGL)
return;
mesh.numindexes = 6;
mesh.numvertexes = 4;
mesh.xyz_array = xyz;
mesh.st_array = tc;
mesh.indexes = idx;
#if 1
/*
a crepuscular light (seriously, that's the correct spelling) is one that gives 'god rays', rather than regular light.
our implementation doesn't cast shadows. this allows it to actually be outside the map, and to shine through cloud layers in the sky.
@ -2666,20 +2815,38 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches)
return;
}
/*no stencil?*/
if (gl_config.nofixedfunc)
switch(qrenderer)
{
Con_Printf("FTE does not support stencil shadows without a fixed-function pipeline\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
return;
}
#ifdef GLQUAKE
case QR_OPENGL:
/*no stencil?*/
if (gl_config.nofixedfunc)
{
Con_Printf("FTE does not support stencil shadows without a fixed-function pipeline\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
return;
}
if (!gl_config.arb_shader_objects)
{
Con_Printf("Missing GL extensions: switching off realtime lighting.\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
if (!gl_config.arb_shader_objects)
{
Con_Printf("Missing GL extensions: switching off realtime lighting.\n");
r_shadow_realtime_world.ival = 0;
r_shadow_realtime_dlight.ival = 0;
return;
}
break;
#endif
#ifdef D3DQUAKE
case QR_DIRECT3D:
#ifdef GLQUAKE
//the code still has a lot of ifdefs, so will crash if you try it in a merged build.
//its not really usable in d3d-only builds either, so no great loss.
return;
#endif
break;
#endif
default:
return;
}
@ -2723,7 +2890,9 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches)
}
else if (dl->flags & LFLAG_SHADOWMAP)
{
#ifdef GLQUAKE
Sh_DrawShadowMapLight(dl, colour, vis);
#endif
}
else
{
@ -2731,9 +2900,17 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches)
}
}
qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
break;
#endif
}
BE_SelectMode(BEM_STANDARD);
// if (developer.value)

View File

@ -196,44 +196,63 @@ BINDTEXFUNCPTR bindTexFunc;
#define DEBUG
#endif
#if defined(DEBUG)
typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,
GLenum category,
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei lengt,
GLsizei length,
const GLchar* message,
GLvoid* userParam);
void (APIENTRY *qglDebugMessageEnableAMD)(GLenum category,
GLenum severity,
void (APIENTRY *qglDebugMessageControlARB)(enum source,
enum type,
enum severity,
GLsizei count,
const GLuint* ids,
GLboolean enabled);
void (APIENTRY *qglDebugMessageInsertAMD)(enum category,
enum severity,
void (APIENTRY *qglDebugMessageInsertARB)(enum source,
enum type,
GLuint id,
enum severity,
GLsizei length,
const char* buf);
void (APIENTRY *qglDebugMessageCallbackAMD)(GLDEBUGPROCAMD callback,
void (APIENTRY *qglDebugMessageCallbackARB)(GLDEBUGPROCARB callback,
void* userParam);
GLuint (APIENTRY *qglGetDebugMessageLogAMD)(GLuint count,
GLuint (APIENTRY *qglGetDebugMessageLogARB)(GLuint count,
GLsizei bufsize,
GLenum* categories,
GLuint* severities,
GLenum* sources,
GLenum* types,
GLuint* ids,
GLsizei* lengths,
char* message);
GLuint* severities,
GLsizei* lengths,
char* messageLog);
#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
#define GL_DEBUG_SOURCE_API_ARB 0x8246
#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
void (APIENTRY myGLDEBUGPROCAMD)(GLuint id,
GLenum category,
void (APIENTRY myGLDEBUGPROCAMD)(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
@ -242,32 +261,26 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLuint id,
#ifndef _WIN32
#define OutputDebugString(s) puts(s)
#endif
switch(category)
switch(type)
{
case GL_DEBUG_CATEGORY_API_ERROR_AMD:
OutputDebugString("glerr: ");
case GL_DEBUG_TYPE_ERROR_ARB:
OutputDebugString("Error: ");
break;
case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
OutputDebugString("glwsys: ");
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
OutputDebugString("Depricated: ");
break;
case GL_DEBUG_CATEGORY_DEPRECATION_AMD:
OutputDebugString("gldepr: ");
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
OutputDebugString("Undefined: ");
break;
case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD:
OutputDebugString("glundef: ");
case GL_DEBUG_TYPE_PORTABILITY_ARB:
OutputDebugString("Portability: ");
break;
case GL_DEBUG_CATEGORY_PERFORMANCE_AMD:
OutputDebugString("glperf: ");
break;
case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD:
OutputDebugString("glshad: ");
break;
case GL_DEBUG_CATEGORY_APPLICATION_AMD:
OutputDebugString("glappm: ");
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
OutputDebugString("Performance: ");
break;
default:
case GL_DEBUG_CATEGORY_OTHER_AMD:
OutputDebugString("glothr: ");
case GL_DEBUG_TYPE_OTHER_ARB:
OutputDebugString("Other: ");
break;
}
OutputDebugString(message);
@ -660,19 +673,19 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
}
#ifdef DEBUG
if (GL_CheckExtension("GL_AMD_debug_output"))
if (GL_CheckExtension("GL_ARB_debug_output"))
{
qglDebugMessageEnableAMD = (void *)getglext("glDebugMessageEnableAMD");
qglDebugMessageInsertAMD = (void *)getglext("glDebugMessageInsertAMD");
qglDebugMessageCallbackAMD = (void *)getglext("glDebugMessageCallbackAMD");
qglGetDebugMessageLogAMD = (void *)getglext("glGetDebugMessageLogAMD");
qglDebugMessageControlARB = (void *)getglext("glDebugMessageControlARB");
qglDebugMessageInsertARB = (void *)getglext("glDebugMessageInsertARB");
qglDebugMessageCallbackARB = (void *)getglext("glDebugMessageCallbackARB");
qglGetDebugMessageLogARB = (void *)getglext("glGetDebugMessageLogARB");
}
else
{
qglDebugMessageEnableAMD = NULL;
qglDebugMessageInsertAMD = NULL;
qglDebugMessageCallbackAMD = NULL;
qglGetDebugMessageLogAMD = NULL;
qglDebugMessageControlARB = NULL;
qglDebugMessageInsertARB = NULL;
qglDebugMessageCallbackARB = NULL;
qglGetDebugMessageLogARB = NULL;
}
#endif
}
@ -1334,10 +1347,10 @@ void GL_Init(void *(*getglfunction) (char *name))
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#ifdef DEBUG
if (qglDebugMessageEnableAMD)
qglDebugMessageEnableAMD(0, 0, 0, NULL, true);
if (qglDebugMessageCallbackAMD)
qglDebugMessageCallbackAMD(myGLDEBUGPROCAMD, NULL);
if (qglDebugMessageControlARB)
qglDebugMessageControlARB(0, 0, 0, 0, NULL, true);
if (qglDebugMessageCallbackARB)
qglDebugMessageCallbackARB(myGLDEBUGPROCAMD, NULL);
qglGetError(); /*suck up the invalid operation error for non-debug contexts*/
#endif
}

View File

@ -173,7 +173,6 @@ typedef struct {
qboolean ext_stencil_wrap;
qboolean arb_depth_clamp;
int ext_texture_filter_anisotropic;
int maxtmus; //max texture units
} gl_config_t;
extern gl_config_t gl_config;
@ -350,9 +349,9 @@ void GL_SetupSceneProcessingTextures (void);
//
// gl_alias.c
//
#ifdef GLQUAKE
void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius);
#ifdef GLQUAKE
//misc model formats
void R_DrawHLModel(entity_t *curent);
@ -371,6 +370,10 @@ void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node);
int GLR_LightPoint (vec3_t p);
#endif
void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
void R_ReloadRTLights_f(void);
void R_LoadRTLights(void);
void R_ImportRTLights(char *entlump);
void R_SaveRTLights_f(void);
//
// gl_heightmap.c

View File

@ -702,5 +702,10 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
#define GL_DEPTH_CLAMP_ARB 0x864F
#endif
#ifndef GL_TEXTURE_BASE_LEVEL //GL_SGIS_texture_lod (core gl 1.2)
#define GL_TEXTURE_BASE_LEVEL 0x813c
#define GL_TEXTURE_MAX_LEVEL 0x813d
#endif
#endif