diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index a522d78f8..f84d3b455 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -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; } } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index f4b65158e..fdc08b169 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -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); } diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 873dace60..daad58519 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -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 +#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); diff --git a/engine/client/m_options.c b/engine/client/m_options.c index eff8f347f..0c5b2e942 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -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() }; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 570b13d04..2844909f3 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -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; } diff --git a/engine/client/render.h b/engine/client/render.h index 77f7582ba..35c075e13 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -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; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index b177b2ea5..ffe3da2a9 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -3,6 +3,7 @@ #include "pr_common.h" #include "gl_draw.h" #include "shader.h" +#include "glquake.h" #include @@ -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++) { diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index c7d4396c2..27a0a5522 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -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); } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 61bb2fb1d..ecffefc18 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -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" diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index a663da627..9c408df9a 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -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 diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 4a5ea9d0a..f14482c28 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -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 #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) diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index a46322092..ab02beb20 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -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) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 2109e591a..c7be1e8b0 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -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) diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 7d3a1685e..04fbccdc9 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -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; idie) + 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 + /* ============================================================================= diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 61790585b..5705c6712 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -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; idie) - 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 diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index cbf5fdc5b..38af4a34a 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -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) diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 745c3cabc..c8439afec 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -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 +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<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<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) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 9320f2494..9d811fca4 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -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 } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 7dc138e31..661f52573 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -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 diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index d02d6297a..59ba6d428 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -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