mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-24 21:21:48 +00:00
Updating ioq3 dates March 03 2016
This commit is contained in:
parent
c3cc9fb7f7
commit
854aa04376
54 changed files with 3249 additions and 1798 deletions
86
Makefile
86
Makefile
|
@ -202,10 +202,6 @@ ifndef USE_INTERNAL_LIBS
|
||||||
USE_INTERNAL_LIBS=1
|
USE_INTERNAL_LIBS=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef USE_INTERNAL_SPEEX
|
|
||||||
USE_INTERNAL_SPEEX=$(USE_INTERNAL_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifndef USE_INTERNAL_OGG
|
ifndef USE_INTERNAL_OGG
|
||||||
USE_INTERNAL_OGG=$(USE_INTERNAL_LIBS)
|
USE_INTERNAL_OGG=$(USE_INTERNAL_LIBS)
|
||||||
endif
|
endif
|
||||||
|
@ -258,7 +254,6 @@ NDIR=$(MOUNT_DIR)/null
|
||||||
UIDIR=$(MOUNT_DIR)/ui
|
UIDIR=$(MOUNT_DIR)/ui
|
||||||
Q3UIDIR=$(MOUNT_DIR)/ui
|
Q3UIDIR=$(MOUNT_DIR)/ui
|
||||||
JPDIR=$(MOUNT_DIR)/jpeg-8c
|
JPDIR=$(MOUNT_DIR)/jpeg-8c
|
||||||
SPEEXDIR=$(MOUNT_DIR)/libspeex
|
|
||||||
OGGDIR=$(MOUNT_DIR)/libogg-1.3.1
|
OGGDIR=$(MOUNT_DIR)/libogg-1.3.1
|
||||||
VORBISDIR=$(MOUNT_DIR)/libvorbis-1.3.4
|
VORBISDIR=$(MOUNT_DIR)/libvorbis-1.3.4
|
||||||
OPUSDIR=$(MOUNT_DIR)/opus-1.1
|
OPUSDIR=$(MOUNT_DIR)/opus-1.1
|
||||||
|
@ -571,7 +566,7 @@ ifdef MINGW
|
||||||
|
|
||||||
SHLIBEXT=dll
|
SHLIBEXT=dll
|
||||||
SHLIBCFLAGS=
|
SHLIBCFLAGS=
|
||||||
SHLIBLDFLAGS=-shared -static-libgcc $(LDFLAGS)
|
SHLIBLDFLAGS=-shared $(LDFLAGS)
|
||||||
|
|
||||||
BINEXT=.exe
|
BINEXT=.exe
|
||||||
|
|
||||||
|
@ -991,8 +986,18 @@ ifeq ($(USE_CURL),1)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_VOIP),1)
|
||||||
|
CLIENT_CFLAGS += -DUSE_VOIP
|
||||||
|
SERVER_CFLAGS += -DUSE_VOIP
|
||||||
|
NEED_OPUS=1
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_CODEC_OPUS),1)
|
ifeq ($(USE_CODEC_OPUS),1)
|
||||||
CLIENT_CFLAGS += -DUSE_CODEC_OPUS
|
CLIENT_CFLAGS += -DUSE_CODEC_OPUS
|
||||||
|
NEED_OPUS=1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(NEED_OPUS),1)
|
||||||
ifeq ($(USE_INTERNAL_OPUS),1)
|
ifeq ($(USE_INTERNAL_OPUS),1)
|
||||||
OPUS_CFLAGS = -DOPUS_BUILD -DHAVE_LRINTF -DFLOATING_POINT -DUSE_ALLOCA \
|
OPUS_CFLAGS = -DOPUS_BUILD -DHAVE_LRINTF -DFLOATING_POINT -DUSE_ALLOCA \
|
||||||
-I$(OPUSDIR)/include -I$(OPUSDIR)/celt -I$(OPUSDIR)/silk \
|
-I$(OPUSDIR)/include -I$(OPUSDIR)/celt -I$(OPUSDIR)/silk \
|
||||||
|
@ -1038,19 +1043,6 @@ ifeq ($(USE_MUMBLE),1)
|
||||||
CLIENT_CFLAGS += -DUSE_MUMBLE
|
CLIENT_CFLAGS += -DUSE_MUMBLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_VOIP),1)
|
|
||||||
CLIENT_CFLAGS += -DUSE_VOIP
|
|
||||||
SERVER_CFLAGS += -DUSE_VOIP
|
|
||||||
ifeq ($(USE_INTERNAL_SPEEX),1)
|
|
||||||
SPEEX_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include
|
|
||||||
else
|
|
||||||
SPEEX_CFLAGS ?= $(shell pkg-config --silence-errors --cflags speex speexdsp || true)
|
|
||||||
SPEEX_LIBS ?= $(shell pkg-config --silence-errors --libs speex speexdsp || echo -lspeex -lspeexdsp)
|
|
||||||
endif
|
|
||||||
CLIENT_CFLAGS += $(SPEEX_CFLAGS)
|
|
||||||
CLIENT_LIBS += $(SPEEX_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(USE_INTERNAL_ZLIB),1)
|
ifeq ($(USE_INTERNAL_ZLIB),1)
|
||||||
ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR)
|
ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR)
|
||||||
else
|
else
|
||||||
|
@ -1261,7 +1253,7 @@ endif
|
||||||
|
|
||||||
NAKED_TARGETS=$(shell echo $(TARGETS) | sed -e "s!$(B)/!!g")
|
NAKED_TARGETS=$(shell echo $(TARGETS) | sed -e "s!$(B)/!!g")
|
||||||
|
|
||||||
print_list=@for i in $(1); \
|
print_list=-@for i in $(1); \
|
||||||
do \
|
do \
|
||||||
echo " $$i"; \
|
echo " $$i"; \
|
||||||
done
|
done
|
||||||
|
@ -1652,6 +1644,7 @@ Q3R2OBJ = \
|
||||||
$(B)/renderergl2/tr_bsp.o \
|
$(B)/renderergl2/tr_bsp.o \
|
||||||
$(B)/renderergl2/tr_cmds.o \
|
$(B)/renderergl2/tr_cmds.o \
|
||||||
$(B)/renderergl2/tr_curve.o \
|
$(B)/renderergl2/tr_curve.o \
|
||||||
|
$(B)/renderergl2/tr_dsa.o \
|
||||||
$(B)/renderergl2/tr_extramath.o \
|
$(B)/renderergl2/tr_extramath.o \
|
||||||
$(B)/renderergl2/tr_extensions.o \
|
$(B)/renderergl2/tr_extensions.o \
|
||||||
$(B)/renderergl2/tr_fbo.o \
|
$(B)/renderergl2/tr_fbo.o \
|
||||||
|
@ -1664,6 +1657,7 @@ Q3R2OBJ = \
|
||||||
$(B)/renderergl2/tr_image_pcx.o \
|
$(B)/renderergl2/tr_image_pcx.o \
|
||||||
$(B)/renderergl2/tr_image_png.o \
|
$(B)/renderergl2/tr_image_png.o \
|
||||||
$(B)/renderergl2/tr_image_tga.o \
|
$(B)/renderergl2/tr_image_tga.o \
|
||||||
|
$(B)/renderergl2/tr_image_dds.o \
|
||||||
$(B)/renderergl2/tr_init.o \
|
$(B)/renderergl2/tr_init.o \
|
||||||
$(B)/renderergl2/tr_light.o \
|
$(B)/renderergl2/tr_light.o \
|
||||||
$(B)/renderergl2/tr_main.o \
|
$(B)/renderergl2/tr_main.o \
|
||||||
|
@ -1827,53 +1821,7 @@ ifeq ($(ARCH),x86_64)
|
||||||
$(B)/client/ftola.o
|
$(B)/client/ftola.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_VOIP),1)
|
ifeq ($(NEED_OPUS),1)
|
||||||
ifeq ($(USE_INTERNAL_SPEEX),1)
|
|
||||||
Q3OBJ += \
|
|
||||||
$(B)/client/bits.o \
|
|
||||||
$(B)/client/buffer.o \
|
|
||||||
$(B)/client/cb_search.o \
|
|
||||||
$(B)/client/exc_10_16_table.o \
|
|
||||||
$(B)/client/exc_10_32_table.o \
|
|
||||||
$(B)/client/exc_20_32_table.o \
|
|
||||||
$(B)/client/exc_5_256_table.o \
|
|
||||||
$(B)/client/exc_5_64_table.o \
|
|
||||||
$(B)/client/exc_8_128_table.o \
|
|
||||||
$(B)/client/fftwrap.o \
|
|
||||||
$(B)/client/filterbank.o \
|
|
||||||
$(B)/client/filters.o \
|
|
||||||
$(B)/client/gain_table.o \
|
|
||||||
$(B)/client/gain_table_lbr.o \
|
|
||||||
$(B)/client/hexc_10_32_table.o \
|
|
||||||
$(B)/client/hexc_table.o \
|
|
||||||
$(B)/client/high_lsp_tables.o \
|
|
||||||
$(B)/client/jitter.o \
|
|
||||||
$(B)/client/kiss_fft.o \
|
|
||||||
$(B)/client/kiss_fftr.o \
|
|
||||||
$(B)/client/lpc.o \
|
|
||||||
$(B)/client/lsp.o \
|
|
||||||
$(B)/client/lsp_tables_nb.o \
|
|
||||||
$(B)/client/ltp.o \
|
|
||||||
$(B)/client/mdf.o \
|
|
||||||
$(B)/client/modes.o \
|
|
||||||
$(B)/client/modes_wb.o \
|
|
||||||
$(B)/client/nb_celp.o \
|
|
||||||
$(B)/client/preprocess.o \
|
|
||||||
$(B)/client/quant_lsp.o \
|
|
||||||
$(B)/client/resample.o \
|
|
||||||
$(B)/client/sb_celp.o \
|
|
||||||
$(B)/client/smallft.o \
|
|
||||||
$(B)/client/speex.o \
|
|
||||||
$(B)/client/speex_callbacks.o \
|
|
||||||
$(B)/client/speex_header.o \
|
|
||||||
$(B)/client/stereo.o \
|
|
||||||
$(B)/client/vbr.o \
|
|
||||||
$(B)/client/vq.o \
|
|
||||||
$(B)/client/window.o
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(USE_CODEC_OPUS),1)
|
|
||||||
ifeq ($(USE_INTERNAL_OPUS),1)
|
ifeq ($(USE_INTERNAL_OPUS),1)
|
||||||
Q3OBJ += \
|
Q3OBJ += \
|
||||||
$(B)/client/opus/analysis.o \
|
$(B)/client/opus/analysis.o \
|
||||||
|
@ -2556,9 +2504,6 @@ $(B)/client/%.o: $(CMDIR)/%.c
|
||||||
$(B)/client/%.o: $(BLIBDIR)/%.c
|
$(B)/client/%.o: $(BLIBDIR)/%.c
|
||||||
$(DO_BOT_CC)
|
$(DO_BOT_CC)
|
||||||
|
|
||||||
$(B)/client/%.o: $(SPEEXDIR)/%.c
|
|
||||||
$(DO_CC)
|
|
||||||
|
|
||||||
$(B)/client/%.o: $(OGGDIR)/src/%.c
|
$(B)/client/%.o: $(OGGDIR)/src/%.c
|
||||||
$(DO_CC)
|
$(DO_CC)
|
||||||
|
|
||||||
|
@ -2849,7 +2794,6 @@ ifdef MINGW
|
||||||
USE_OPENAL_DLOPEN=$(USE_OPENAL_DLOPEN) \
|
USE_OPENAL_DLOPEN=$(USE_OPENAL_DLOPEN) \
|
||||||
USE_CURL_DLOPEN=$(USE_CURL_DLOPEN) \
|
USE_CURL_DLOPEN=$(USE_CURL_DLOPEN) \
|
||||||
USE_INTERNAL_OPUS=$(USE_INTERNAL_OPUS) \
|
USE_INTERNAL_OPUS=$(USE_INTERNAL_OPUS) \
|
||||||
USE_INTERNAL_SPEEX=$(USE_INTERNAL_SPEEX) \
|
|
||||||
USE_INTERNAL_ZLIB=$(USE_INTERNAL_ZLIB) \
|
USE_INTERNAL_ZLIB=$(USE_INTERNAL_ZLIB) \
|
||||||
USE_INTERNAL_JPEG=$(USE_INTERNAL_JPEG)
|
USE_INTERNAL_JPEG=$(USE_INTERNAL_JPEG)
|
||||||
else
|
else
|
||||||
|
|
|
@ -919,37 +919,27 @@ void CL_FirstSnapshot( void ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
if (!clc.speexInitialized) {
|
if (!clc.voipCodecInitialized) {
|
||||||
int i;
|
int i;
|
||||||
speex_bits_init(&clc.speexEncoderBits);
|
int error;
|
||||||
speex_bits_reset(&clc.speexEncoderBits);
|
|
||||||
|
|
||||||
clc.speexEncoder = speex_encoder_init(&speex_nb_mode);
|
clc.opusEncoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error);
|
||||||
|
|
||||||
speex_encoder_ctl(clc.speexEncoder, SPEEX_GET_FRAME_SIZE,
|
if ( error ) {
|
||||||
&clc.speexFrameSize);
|
Com_DPrintf("VoIP: Error opus_encoder_create %d\n", error);
|
||||||
speex_encoder_ctl(clc.speexEncoder, SPEEX_GET_SAMPLING_RATE,
|
return;
|
||||||
&clc.speexSampleRate);
|
}
|
||||||
|
|
||||||
clc.speexPreprocessor = speex_preprocess_state_init(clc.speexFrameSize,
|
|
||||||
clc.speexSampleRate);
|
|
||||||
|
|
||||||
i = 1;
|
|
||||||
speex_preprocess_ctl(clc.speexPreprocessor,
|
|
||||||
SPEEX_PREPROCESS_SET_DENOISE, &i);
|
|
||||||
|
|
||||||
i = 1;
|
|
||||||
speex_preprocess_ctl(clc.speexPreprocessor,
|
|
||||||
SPEEX_PREPROCESS_SET_AGC, &i);
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_CLIENTS; i++) {
|
for (i = 0; i < MAX_CLIENTS; i++) {
|
||||||
speex_bits_init(&clc.speexDecoderBits[i]);
|
clc.opusDecoder[i] = opus_decoder_create(48000, 1, &error);
|
||||||
speex_bits_reset(&clc.speexDecoderBits[i]);
|
if ( error ) {
|
||||||
clc.speexDecoder[i] = speex_decoder_init(&speex_nb_mode);
|
Com_DPrintf("VoIP: Error opus_decoder_create(%d) %d\n", i, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
clc.voipIgnore[i] = qfalse;
|
clc.voipIgnore[i] = qfalse;
|
||||||
clc.voipGain[i] = 1.0f;
|
clc.voipGain[i] = 1.0f;
|
||||||
}
|
}
|
||||||
clc.speexInitialized = qtrue;
|
clc.voipCodecInitialized = qtrue;
|
||||||
clc.voipMuteAll = qfalse;
|
clc.voipMuteAll = qfalse;
|
||||||
Cmd_AddCommand ("voip", CL_Voip_f);
|
Cmd_AddCommand ("voip", CL_Voip_f);
|
||||||
Cvar_Set("cl_voipSendTarget", "spatial");
|
Cvar_Set("cl_voipSendTarget", "spatial");
|
||||||
|
|
|
@ -632,6 +632,12 @@ void CL_CreateNewCommands( void ) {
|
||||||
|
|
||||||
frame_msec = com_frameTime - old_com_frameTime;
|
frame_msec = com_frameTime - old_com_frameTime;
|
||||||
|
|
||||||
|
// if running over 1000fps, act as if each frame is 1ms
|
||||||
|
// prevents divisions by zero
|
||||||
|
if ( frame_msec < 1 ) {
|
||||||
|
frame_msec = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// if running less than 5fps, truncate the extra time to prevent
|
// if running less than 5fps, truncate the extra time to prevent
|
||||||
// unexpected moves after a hitch
|
// unexpected moves after a hitch
|
||||||
if ( frame_msec > 200 ) {
|
if ( frame_msec > 200 ) {
|
||||||
|
@ -788,7 +794,7 @@ void CL_WritePacket( void ) {
|
||||||
{
|
{
|
||||||
if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1))
|
if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1))
|
||||||
{
|
{
|
||||||
MSG_WriteByte (&buf, clc_voip);
|
MSG_WriteByte (&buf, clc_voipOpus);
|
||||||
MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
|
MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
|
||||||
MSG_WriteLong (&buf, clc.voipOutgoingSequence);
|
MSG_WriteLong (&buf, clc.voipOutgoingSequence);
|
||||||
MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
|
MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
|
||||||
|
@ -809,7 +815,7 @@ void CL_WritePacket( void ) {
|
||||||
MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
|
MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
|
||||||
MSG_Bitstream (&fakemsg);
|
MSG_Bitstream (&fakemsg);
|
||||||
MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
|
MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
|
||||||
MSG_WriteByte (&fakemsg, svc_voip);
|
MSG_WriteByte (&fakemsg, svc_voipOpus);
|
||||||
MSG_WriteShort (&fakemsg, clc.clientNum);
|
MSG_WriteShort (&fakemsg, clc.clientNum);
|
||||||
MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
|
MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
|
||||||
MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
|
MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
|
||||||
|
|
|
@ -44,6 +44,7 @@ cvar_t *cl_voipSendTarget;
|
||||||
cvar_t *cl_voipGainDuringCapture;
|
cvar_t *cl_voipGainDuringCapture;
|
||||||
cvar_t *cl_voipCaptureMult;
|
cvar_t *cl_voipCaptureMult;
|
||||||
cvar_t *cl_voipShowMeter;
|
cvar_t *cl_voipShowMeter;
|
||||||
|
cvar_t *cl_voipProtocol;
|
||||||
cvar_t *cl_voip;
|
cvar_t *cl_voip;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -250,8 +251,8 @@ void CL_Voip_f( void )
|
||||||
|
|
||||||
if (clc.state != CA_ACTIVE)
|
if (clc.state != CA_ACTIVE)
|
||||||
reason = "Not connected to a server";
|
reason = "Not connected to a server";
|
||||||
else if (!clc.speexInitialized)
|
else if (!clc.voipCodecInitialized)
|
||||||
reason = "Speex not initialized";
|
reason = "Voip codec not initialized";
|
||||||
else if (!clc.voipEnabled)
|
else if (!clc.voipEnabled)
|
||||||
reason = "Server doesn't support VoIP";
|
reason = "Server doesn't support VoIP";
|
||||||
else if (!clc.demoplaying && (Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")))
|
else if (!clc.demoplaying && (Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")))
|
||||||
|
@ -306,6 +307,8 @@ void CL_VoipNewGeneration(void)
|
||||||
clc.voipOutgoingGeneration = 1;
|
clc.voipOutgoingGeneration = 1;
|
||||||
clc.voipPower = 0.0f;
|
clc.voipPower = 0.0f;
|
||||||
clc.voipOutgoingSequence = 0;
|
clc.voipOutgoingSequence = 0;
|
||||||
|
|
||||||
|
opus_encoder_ctl(clc.opusEncoder, OPUS_RESET_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -394,7 +397,7 @@ void CL_VoipParseTargets(void)
|
||||||
===============
|
===============
|
||||||
CL_CaptureVoip
|
CL_CaptureVoip
|
||||||
|
|
||||||
Record more audio from the hardware if required and encode it into Speex
|
Record more audio from the hardware if required and encode it into Opus
|
||||||
data for later transmission.
|
data for later transmission.
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
|
@ -424,11 +427,12 @@ void CL_CaptureVoip(void)
|
||||||
Com_Printf("Until then, VoIP is disabled.\n");
|
Com_Printf("Until then, VoIP is disabled.\n");
|
||||||
Cvar_Set("cl_voip", "0");
|
Cvar_Set("cl_voip", "0");
|
||||||
}
|
}
|
||||||
|
Cvar_Set("cl_voipProtocol", cl_voip->integer ? "opus" : "");
|
||||||
cl_voip->modified = qfalse;
|
cl_voip->modified = qfalse;
|
||||||
cl_rate->modified = qfalse;
|
cl_rate->modified = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clc.speexInitialized)
|
if (!clc.voipCodecInitialized)
|
||||||
return; // just in case this gets called at a bad time.
|
return; // just in case this gets called at a bad time.
|
||||||
|
|
||||||
if (clc.voipOutgoingDataSize > 0)
|
if (clc.voipOutgoingDataSize > 0)
|
||||||
|
@ -481,80 +485,67 @@ void CL_CaptureVoip(void)
|
||||||
|
|
||||||
if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio?
|
if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio?
|
||||||
int samples = S_AvailableCaptureSamples();
|
int samples = S_AvailableCaptureSamples();
|
||||||
const int mult = (finalFrame) ? 1 : 4; // 4 == 80ms of audio.
|
const int packetSamples = (finalFrame) ? VOIP_MAX_FRAME_SAMPLES : VOIP_MAX_PACKET_SAMPLES;
|
||||||
|
|
||||||
// enough data buffered in audio hardware to process yet?
|
// enough data buffered in audio hardware to process yet?
|
||||||
if (samples >= (clc.speexFrameSize * mult)) {
|
if (samples >= packetSamples) {
|
||||||
// audio capture is always MONO16 (and that's what speex wants!).
|
// audio capture is always MONO16.
|
||||||
// 2048 will cover 12 uncompressed frames in narrowband mode.
|
static int16_t sampbuffer[VOIP_MAX_PACKET_SAMPLES];
|
||||||
static int16_t sampbuffer[2048];
|
|
||||||
float voipPower = 0.0f;
|
float voipPower = 0.0f;
|
||||||
int speexFrames = 0;
|
int voipFrames;
|
||||||
int wpos = 0;
|
int i, bytes;
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
if (samples > (clc.speexFrameSize * 4))
|
if (samples > VOIP_MAX_PACKET_SAMPLES)
|
||||||
samples = (clc.speexFrameSize * 4);
|
samples = VOIP_MAX_PACKET_SAMPLES;
|
||||||
|
|
||||||
// !!! FIXME: maybe separate recording from encoding, so voipPower
|
// !!! FIXME: maybe separate recording from encoding, so voipPower
|
||||||
// !!! FIXME: updates faster than 4Hz?
|
// !!! FIXME: updates faster than 4Hz?
|
||||||
|
|
||||||
samples -= samples % clc.speexFrameSize;
|
samples -= samples % VOIP_MAX_FRAME_SAMPLES;
|
||||||
|
if (samples != 120 && samples != 240 && samples != 480 && samples != 960 && samples != 1920 && samples != 2880 ) {
|
||||||
|
Com_Printf("Voip: bad number of samples %d\n", samples);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
voipFrames = samples / VOIP_MAX_FRAME_SAMPLES;
|
||||||
|
|
||||||
S_Capture(samples, (byte *) sampbuffer); // grab from audio card.
|
S_Capture(samples, (byte *) sampbuffer); // grab from audio card.
|
||||||
|
|
||||||
// this will probably generate multiple speex packets each time.
|
// check the "power" of this packet...
|
||||||
while (samples > 0) {
|
for (i = 0; i < samples; i++) {
|
||||||
int16_t *sampptr = &sampbuffer[pos];
|
const float flsamp = (float) sampbuffer[i];
|
||||||
int i, bytes;
|
const float s = fabs(flsamp);
|
||||||
|
voipPower += s * s;
|
||||||
|
sampbuffer[i] = (int16_t) ((flsamp) * audioMult);
|
||||||
|
}
|
||||||
|
|
||||||
// preprocess samples to remove noise...
|
// encode raw audio samples into Opus data...
|
||||||
speex_preprocess_run(clc.speexPreprocessor, sampptr);
|
bytes = opus_encode(clc.opusEncoder, sampbuffer, samples,
|
||||||
|
(unsigned char *) clc.voipOutgoingData,
|
||||||
// check the "power" of this packet...
|
sizeof (clc.voipOutgoingData));
|
||||||
for (i = 0; i < clc.speexFrameSize; i++) {
|
if ( bytes <= 0 ) {
|
||||||
const float flsamp = (float) sampptr[i];
|
Com_DPrintf("VoIP: Error encoding %d samples\n", samples);
|
||||||
const float s = fabs(flsamp);
|
bytes = 0;
|
||||||
voipPower += s * s;
|
|
||||||
sampptr[i] = (int16_t) ((flsamp) * audioMult);
|
|
||||||
}
|
|
||||||
|
|
||||||
// encode raw audio samples into Speex data...
|
|
||||||
speex_bits_reset(&clc.speexEncoderBits);
|
|
||||||
speex_encode_int(clc.speexEncoder, sampptr,
|
|
||||||
&clc.speexEncoderBits);
|
|
||||||
bytes = speex_bits_write(&clc.speexEncoderBits,
|
|
||||||
(char *) &clc.voipOutgoingData[wpos+1],
|
|
||||||
sizeof (clc.voipOutgoingData) - (wpos+1));
|
|
||||||
assert((bytes > 0) && (bytes < 256));
|
|
||||||
clc.voipOutgoingData[wpos] = (byte) bytes;
|
|
||||||
wpos += bytes + 1;
|
|
||||||
|
|
||||||
// look at the data for the next packet...
|
|
||||||
pos += clc.speexFrameSize;
|
|
||||||
samples -= clc.speexFrameSize;
|
|
||||||
speexFrames++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clc.voipPower = (voipPower / (32768.0f * 32768.0f *
|
clc.voipPower = (voipPower / (32768.0f * 32768.0f *
|
||||||
((float) (clc.speexFrameSize * speexFrames)))) *
|
((float) samples))) * 100.0f;
|
||||||
100.0f;
|
|
||||||
|
|
||||||
if ((useVad) && (clc.voipPower < cl_voipVADThreshold->value)) {
|
if ((useVad) && (clc.voipPower < cl_voipVADThreshold->value)) {
|
||||||
CL_VoipNewGeneration(); // no "talk" for at least 1/4 second.
|
CL_VoipNewGeneration(); // no "talk" for at least 1/4 second.
|
||||||
} else {
|
} else {
|
||||||
clc.voipOutgoingDataSize = wpos;
|
clc.voipOutgoingDataSize = bytes;
|
||||||
clc.voipOutgoingDataFrames = speexFrames;
|
clc.voipOutgoingDataFrames = voipFrames;
|
||||||
|
|
||||||
Com_DPrintf("VoIP: Send %d frames, %d bytes, %f power\n",
|
Com_DPrintf("VoIP: Send %d frames, %d bytes, %f power\n",
|
||||||
speexFrames, wpos, clc.voipPower);
|
voipFrames, bytes, clc.voipPower);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static FILE *encio = NULL;
|
static FILE *encio = NULL;
|
||||||
if (encio == NULL) encio = fopen("voip-outgoing-encoded.bin", "wb");
|
if (encio == NULL) encio = fopen("voip-outgoing-encoded.bin", "wb");
|
||||||
if (encio != NULL) { fwrite(clc.voipOutgoingData, wpos, 1, encio); fflush(encio); }
|
if (encio != NULL) { fwrite(clc.voipOutgoingData, bytes, 1, encio); fflush(encio); }
|
||||||
static FILE *decio = NULL;
|
static FILE *decio = NULL;
|
||||||
if (decio == NULL) decio = fopen("voip-outgoing-decoded.bin", "wb");
|
if (decio == NULL) decio = fopen("voip-outgoing-decoded.bin", "wb");
|
||||||
if (decio != NULL) { fwrite(sampbuffer, speexFrames * clc.speexFrameSize * 2, 1, decio); fflush(decio); }
|
if (decio != NULL) { fwrite(sampbuffer, voipFrames * VOIP_MAX_FRAME_SAMPLES * 2, 1, decio); fflush(decio); }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1420,14 +1411,11 @@ void CL_Disconnect( qboolean showMainMenu ) {
|
||||||
cl_voipUseVAD->integer = tmp;
|
cl_voipUseVAD->integer = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clc.speexInitialized) {
|
if (clc.voipCodecInitialized) {
|
||||||
int i;
|
int i;
|
||||||
speex_bits_destroy(&clc.speexEncoderBits);
|
opus_encoder_destroy(clc.opusEncoder);
|
||||||
speex_encoder_destroy(clc.speexEncoder);
|
|
||||||
speex_preprocess_state_destroy(clc.speexPreprocessor);
|
|
||||||
for (i = 0; i < MAX_CLIENTS; i++) {
|
for (i = 0; i < MAX_CLIENTS; i++) {
|
||||||
speex_bits_destroy(&clc.speexDecoderBits[i]);
|
opus_decoder_destroy(clc.opusDecoder[i]);
|
||||||
speex_decoder_destroy(clc.speexDecoder[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Cmd_RemoveCommand ("voip");
|
Cmd_RemoveCommand ("voip");
|
||||||
|
@ -1808,6 +1796,50 @@ static void CL_CompleteRcon( char *args, int argNum )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CL_CompletePlayerName
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void CL_CompletePlayerName( char *args, int argNum )
|
||||||
|
{
|
||||||
|
if( argNum == 2 )
|
||||||
|
{
|
||||||
|
char names[MAX_CLIENTS][MAX_NAME_LENGTH];
|
||||||
|
char *namesPtr[MAX_CLIENTS];
|
||||||
|
int i;
|
||||||
|
int clientCount;
|
||||||
|
int nameCount;
|
||||||
|
const char *info;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
//configstring
|
||||||
|
info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO];
|
||||||
|
clientCount = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
|
||||||
|
|
||||||
|
nameCount = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < clientCount; i++ ) {
|
||||||
|
if( i == clc.clientNum )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_PLAYERS+i];
|
||||||
|
|
||||||
|
name = Info_ValueForKey( info, "n" );
|
||||||
|
if( name[0] == '\0' )
|
||||||
|
continue;
|
||||||
|
Q_strncpyz( names[nameCount], name, sizeof(names[nameCount]) );
|
||||||
|
Q_CleanStr( names[nameCount] );
|
||||||
|
|
||||||
|
namesPtr[nameCount] = names[nameCount];
|
||||||
|
nameCount++;
|
||||||
|
}
|
||||||
|
qsort( (void*)namesPtr, nameCount, sizeof( namesPtr[0] ), Com_strCompare );
|
||||||
|
|
||||||
|
Field_CompletePlayerName( namesPtr, nameCount );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
CL_Rcon_f
|
CL_Rcon_f
|
||||||
|
@ -1820,7 +1852,7 @@ void CL_Rcon_f( void ) {
|
||||||
char message[MAX_RCON_MESSAGE];
|
char message[MAX_RCON_MESSAGE];
|
||||||
netadr_t to;
|
netadr_t to;
|
||||||
|
|
||||||
if ( !rcon_client_password->string ) {
|
if ( !rcon_client_password->string[0] ) {
|
||||||
Com_Printf ("You must set 'rconpassword' before\n"
|
Com_Printf ("You must set 'rconpassword' before\n"
|
||||||
"issuing an rcon command.\n");
|
"issuing an rcon command.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -3396,6 +3428,56 @@ static void CL_GenerateQKey(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CL_Sayto_f( void ) {
|
||||||
|
char *rawname;
|
||||||
|
char name[MAX_NAME_LENGTH];
|
||||||
|
char cleanName[MAX_NAME_LENGTH];
|
||||||
|
const char *info;
|
||||||
|
int count;
|
||||||
|
int i;
|
||||||
|
int clientNum;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if ( Cmd_Argc() < 3 ) {
|
||||||
|
Com_Printf ("sayto <player name> <text>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rawname = Cmd_Argv(1);
|
||||||
|
|
||||||
|
Com_FieldStringToPlayerName( name, MAX_NAME_LENGTH, rawname );
|
||||||
|
|
||||||
|
info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO];
|
||||||
|
count = atoi( Info_ValueForKey( info, "sv_maxclients" ) );
|
||||||
|
|
||||||
|
clientNum = -1;
|
||||||
|
for( i = 0; i < count; i++ ) {
|
||||||
|
|
||||||
|
info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_PLAYERS+i];
|
||||||
|
Q_strncpyz( cleanName, Info_ValueForKey( info, "n" ), sizeof(cleanName) );
|
||||||
|
Q_CleanStr( cleanName );
|
||||||
|
|
||||||
|
if ( !Q_stricmp( cleanName, name ) ) {
|
||||||
|
clientNum = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( clientNum <= -1 )
|
||||||
|
{
|
||||||
|
Com_Printf ("No such player name: %s.\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = Cmd_ArgsFrom(2);
|
||||||
|
|
||||||
|
if ( *p == '"' ) {
|
||||||
|
p++;
|
||||||
|
p[strlen(p)-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CL_AddReliableCommand(va("tell %i \"%s\"", clientNum, p ), qfalse);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
CL_Init
|
CL_Init
|
||||||
|
@ -3559,9 +3641,9 @@ void CL_Init( void ) {
|
||||||
cl_voipVADThreshold = Cvar_Get ("cl_voipVADThreshold", "0.25", CVAR_ARCHIVE);
|
cl_voipVADThreshold = Cvar_Get ("cl_voipVADThreshold", "0.25", CVAR_ARCHIVE);
|
||||||
cl_voipShowMeter = Cvar_Get ("cl_voipShowMeter", "1", CVAR_ARCHIVE);
|
cl_voipShowMeter = Cvar_Get ("cl_voipShowMeter", "1", CVAR_ARCHIVE);
|
||||||
|
|
||||||
// This is a protocol version number.
|
cl_voip = Cvar_Get ("cl_voip", "1", CVAR_ARCHIVE);
|
||||||
cl_voip = Cvar_Get ("cl_voip", "1", CVAR_USERINFO | CVAR_ARCHIVE);
|
|
||||||
Cvar_CheckRange( cl_voip, 0, 1, qtrue );
|
Cvar_CheckRange( cl_voip, 0, 1, qtrue );
|
||||||
|
cl_voipProtocol = Cvar_Get ("cl_voipProtocol", cl_voip->integer ? "opus" : "", CVAR_USERINFO | CVAR_ROM);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -3598,6 +3680,10 @@ void CL_Init( void ) {
|
||||||
Cmd_AddCommand ("model", CL_SetModel_f );
|
Cmd_AddCommand ("model", CL_SetModel_f );
|
||||||
Cmd_AddCommand ("video", CL_Video_f );
|
Cmd_AddCommand ("video", CL_Video_f );
|
||||||
Cmd_AddCommand ("stopvideo", CL_StopVideo_f );
|
Cmd_AddCommand ("stopvideo", CL_StopVideo_f );
|
||||||
|
if( !com_dedicated->integer ) {
|
||||||
|
Cmd_AddCommand ("sayto", CL_Sayto_f );
|
||||||
|
Cmd_SetCommandCompletionFunc( "sayto", CL_CompletePlayerName );
|
||||||
|
}
|
||||||
CL_InitRef();
|
CL_InitRef();
|
||||||
|
|
||||||
SCR_Init ();
|
SCR_Init ();
|
||||||
|
|
|
@ -34,7 +34,8 @@ char *svc_strings[256] = {
|
||||||
"svc_download",
|
"svc_download",
|
||||||
"svc_snapshot",
|
"svc_snapshot",
|
||||||
"svc_EOF",
|
"svc_EOF",
|
||||||
"svc_voip",
|
"svc_voipSpeex",
|
||||||
|
"svc_voipOpus",
|
||||||
};
|
};
|
||||||
|
|
||||||
void SHOWNET( msg_t *msg, char *s) {
|
void SHOWNET( msg_t *msg, char *s) {
|
||||||
|
@ -359,8 +360,8 @@ void CL_SystemInfoChanged( void ) {
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
s = Info_ValueForKey( systemInfo, "sv_voip" );
|
s = Info_ValueForKey( systemInfo, "sv_voipProtocol" );
|
||||||
clc.voipEnabled = atoi(s);
|
clc.voipEnabled = !Q_stricmp(s, "opus");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -680,13 +681,13 @@ static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags)
|
||||||
{
|
{
|
||||||
if(flags & VOIP_DIRECT)
|
if(flags & VOIP_DIRECT)
|
||||||
{
|
{
|
||||||
S_RawSamples(sender + 1, samplecnt, clc.speexSampleRate, 2, 1,
|
S_RawSamples(sender + 1, samplecnt, 48000, 2, 1,
|
||||||
data, clc.voipGain[sender], -1);
|
data, clc.voipGain[sender], -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & VOIP_SPATIAL)
|
if(flags & VOIP_SPATIAL)
|
||||||
{
|
{
|
||||||
S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, clc.speexSampleRate, 2, 1,
|
S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, 48000, 2, 1,
|
||||||
data, 1.0f, sender);
|
data, 1.0f, sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,8 +700,8 @@ A VoIP message has been received from the server
|
||||||
=====================
|
=====================
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void CL_ParseVoip ( msg_t *msg ) {
|
void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) {
|
||||||
static short decoded[4096]; // !!! FIXME: don't hardcode.
|
static short decoded[VOIP_MAX_PACKET_SAMPLES*4]; // !!! FIXME: don't hard code
|
||||||
|
|
||||||
const int sender = MSG_ReadShort(msg);
|
const int sender = MSG_ReadShort(msg);
|
||||||
const int generation = MSG_ReadByte(msg);
|
const int generation = MSG_ReadByte(msg);
|
||||||
|
@ -708,7 +709,8 @@ void CL_ParseVoip ( msg_t *msg ) {
|
||||||
const int frames = MSG_ReadByte(msg);
|
const int frames = MSG_ReadByte(msg);
|
||||||
const int packetsize = MSG_ReadShort(msg);
|
const int packetsize = MSG_ReadShort(msg);
|
||||||
const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
|
const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
|
||||||
char encoded[1024];
|
unsigned char encoded[4000];
|
||||||
|
int numSamples;
|
||||||
int seqdiff;
|
int seqdiff;
|
||||||
int written = 0;
|
int written = 0;
|
||||||
int i;
|
int i;
|
||||||
|
@ -738,14 +740,15 @@ void CL_ParseVoip ( msg_t *msg ) {
|
||||||
return; // overlarge packet, bail.
|
return; // overlarge packet, bail.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clc.speexInitialized) {
|
MSG_ReadData(msg, encoded, packetsize);
|
||||||
MSG_ReadData(msg, encoded, packetsize); // skip payload.
|
|
||||||
return; // can't handle VoIP without libspeex!
|
if (ignoreData) {
|
||||||
|
return; // just ignore legacy speex voip data
|
||||||
|
} else if (!clc.voipCodecInitialized) {
|
||||||
|
return; // can't handle VoIP without libopus!
|
||||||
} else if (sender >= MAX_CLIENTS) {
|
} else if (sender >= MAX_CLIENTS) {
|
||||||
MSG_ReadData(msg, encoded, packetsize); // skip payload.
|
|
||||||
return; // bogus sender.
|
return; // bogus sender.
|
||||||
} else if (CL_ShouldIgnoreVoipSender(sender)) {
|
} else if (CL_ShouldIgnoreVoipSender(sender)) {
|
||||||
MSG_ReadData(msg, encoded, packetsize); // skip payload.
|
|
||||||
return; // Channel is muted, bail.
|
return; // Channel is muted, bail.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,70 +761,59 @@ void CL_ParseVoip ( msg_t *msg ) {
|
||||||
// This is a new "generation" ... a new recording started, reset the bits.
|
// This is a new "generation" ... a new recording started, reset the bits.
|
||||||
if (generation != clc.voipIncomingGeneration[sender]) {
|
if (generation != clc.voipIncomingGeneration[sender]) {
|
||||||
Com_DPrintf("VoIP: new generation %d!\n", generation);
|
Com_DPrintf("VoIP: new generation %d!\n", generation);
|
||||||
speex_bits_reset(&clc.speexDecoderBits[sender]);
|
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
|
||||||
clc.voipIncomingGeneration[sender] = generation;
|
clc.voipIncomingGeneration[sender] = generation;
|
||||||
seqdiff = 0;
|
seqdiff = 0;
|
||||||
} else if (seqdiff < 0) { // we're ahead of the sequence?!
|
} else if (seqdiff < 0) { // we're ahead of the sequence?!
|
||||||
// This shouldn't happen unless the packet is corrupted or something.
|
// This shouldn't happen unless the packet is corrupted or something.
|
||||||
Com_DPrintf("VoIP: misordered sequence! %d < %d!\n",
|
Com_DPrintf("VoIP: misordered sequence! %d < %d!\n",
|
||||||
sequence, clc.voipIncomingSequence[sender]);
|
sequence, clc.voipIncomingSequence[sender]);
|
||||||
// reset the bits just in case.
|
// reset the decoder just in case.
|
||||||
speex_bits_reset(&clc.speexDecoderBits[sender]);
|
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
|
||||||
seqdiff = 0;
|
seqdiff = 0;
|
||||||
} else if (seqdiff * clc.speexFrameSize * 2 >= sizeof (decoded)) { // dropped more than we can handle?
|
} else if (seqdiff * VOIP_MAX_PACKET_SAMPLES*2 >= sizeof (decoded)) { // dropped more than we can handle?
|
||||||
// just start over.
|
// just start over.
|
||||||
Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n",
|
Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n",
|
||||||
seqdiff, sender);
|
seqdiff, sender);
|
||||||
speex_bits_reset(&clc.speexDecoderBits[sender]);
|
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
|
||||||
seqdiff = 0;
|
seqdiff = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seqdiff != 0) {
|
if (seqdiff != 0) {
|
||||||
Com_DPrintf("VoIP: Dropped %d frames from client #%d\n",
|
Com_DPrintf("VoIP: Dropped %d frames from client #%d\n",
|
||||||
seqdiff, sender);
|
seqdiff, sender);
|
||||||
// tell speex that we're missing frames...
|
// tell opus that we're missing frames...
|
||||||
for (i = 0; i < seqdiff; i++) {
|
for (i = 0; i < seqdiff; i++) {
|
||||||
assert((written + clc.speexFrameSize) * 2 < sizeof (decoded));
|
assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded));
|
||||||
speex_decode_int(clc.speexDecoder[sender], NULL, decoded + written);
|
numSamples = opus_decode(clc.opusDecoder[sender], NULL, 0, decoded + written, VOIP_MAX_PACKET_SAMPLES, 0);
|
||||||
written += clc.speexFrameSize;
|
if ( numSamples <= 0 ) {
|
||||||
|
Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
written += numSamples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < frames; i++) {
|
numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, ARRAY_LEN(decoded) - written, 0);
|
||||||
const int len = MSG_ReadByte(msg);
|
|
||||||
if (len < 0) {
|
|
||||||
Com_DPrintf("VoIP: Short packet!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MSG_ReadData(msg, encoded, len);
|
|
||||||
|
|
||||||
// shouldn't happen, but just in case...
|
if ( numSamples <= 0 ) {
|
||||||
if ((written + clc.speexFrameSize) * 2 > sizeof (decoded)) {
|
Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender);
|
||||||
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
|
numSamples = 0;
|
||||||
written * 2, written, i);
|
|
||||||
|
|
||||||
CL_PlayVoip(sender, written, (const byte *) decoded, flags);
|
|
||||||
written = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
speex_bits_read_from(&clc.speexDecoderBits[sender], encoded, len);
|
|
||||||
speex_decode_int(clc.speexDecoder[sender],
|
|
||||||
&clc.speexDecoderBits[sender], decoded + written);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static FILE *encio = NULL;
|
|
||||||
if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb");
|
|
||||||
if (encio != NULL) { fwrite(encoded, len, 1, encio); fflush(encio); }
|
|
||||||
static FILE *decio = NULL;
|
|
||||||
if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb");
|
|
||||||
if (decio != NULL) { fwrite(decoded+written, clc.speexFrameSize*2, 1, decio); fflush(decio); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
written += clc.speexFrameSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static FILE *encio = NULL;
|
||||||
|
if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb");
|
||||||
|
if (encio != NULL) { fwrite(encoded, len, 1, encio); fflush(encio); }
|
||||||
|
static FILE *decio = NULL;
|
||||||
|
if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb");
|
||||||
|
if (decio != NULL) { fwrite(decoded+written, clc.speexFrameSize*2, 1, decio); fflush(decio); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
written += numSamples;
|
||||||
|
|
||||||
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
|
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
|
||||||
written * 2, written, i);
|
written * 2, written, frames);
|
||||||
|
|
||||||
if(written > 0)
|
if(written > 0)
|
||||||
CL_PlayVoip(sender, written, (const byte *) decoded, flags);
|
CL_PlayVoip(sender, written, (const byte *) decoded, flags);
|
||||||
|
@ -924,9 +916,14 @@ void CL_ParseServerMessage( msg_t *msg ) {
|
||||||
case svc_download:
|
case svc_download:
|
||||||
CL_ParseDownload( msg );
|
CL_ParseDownload( msg );
|
||||||
break;
|
break;
|
||||||
case svc_voip:
|
case svc_voipSpeex:
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
CL_ParseVoip( msg );
|
CL_ParseVoip( msg, qtrue );
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case svc_voipOpus:
|
||||||
|
#ifdef USE_VOIP
|
||||||
|
CL_ParseVoip( msg, !clc.voipEnabled );
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#endif /* USE_CURL */
|
#endif /* USE_CURL */
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
#include "speex/speex.h"
|
#include <opus.h>
|
||||||
#include "speex/speex_preprocess.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// file full of random crap that gets used to create cl_guid
|
// file full of random crap that gets used to create cl_guid
|
||||||
|
@ -238,14 +237,11 @@ typedef struct {
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
qboolean voipEnabled;
|
qboolean voipEnabled;
|
||||||
qboolean speexInitialized;
|
qboolean voipCodecInitialized;
|
||||||
int speexFrameSize;
|
|
||||||
int speexSampleRate;
|
|
||||||
|
|
||||||
// incoming data...
|
// incoming data...
|
||||||
// !!! FIXME: convert from parallel arrays to array of a struct.
|
// !!! FIXME: convert from parallel arrays to array of a struct.
|
||||||
SpeexBits speexDecoderBits[MAX_CLIENTS];
|
OpusDecoder *opusDecoder[MAX_CLIENTS];
|
||||||
void *speexDecoder[MAX_CLIENTS];
|
|
||||||
byte voipIncomingGeneration[MAX_CLIENTS];
|
byte voipIncomingGeneration[MAX_CLIENTS];
|
||||||
int voipIncomingSequence[MAX_CLIENTS];
|
int voipIncomingSequence[MAX_CLIENTS];
|
||||||
float voipGain[MAX_CLIENTS];
|
float voipGain[MAX_CLIENTS];
|
||||||
|
@ -257,9 +253,7 @@ typedef struct {
|
||||||
// then we are sending to clientnum i.
|
// then we are sending to clientnum i.
|
||||||
uint8_t voipTargets[(MAX_CLIENTS + 7) / 8];
|
uint8_t voipTargets[(MAX_CLIENTS + 7) / 8];
|
||||||
uint8_t voipFlags;
|
uint8_t voipFlags;
|
||||||
SpeexPreprocessState *speexPreprocessor;
|
OpusEncoder *opusEncoder;
|
||||||
SpeexBits speexEncoderBits;
|
|
||||||
void *speexEncoder;
|
|
||||||
int voipOutgoingDataSize;
|
int voipOutgoingDataSize;
|
||||||
int voipOutgoingDataFrames;
|
int voipOutgoingDataFrames;
|
||||||
int voipOutgoingSequence;
|
int voipOutgoingSequence;
|
||||||
|
@ -447,6 +441,13 @@ extern cvar_t *cl_voipGainDuringCapture;
|
||||||
extern cvar_t *cl_voipCaptureMult;
|
extern cvar_t *cl_voipCaptureMult;
|
||||||
extern cvar_t *cl_voipShowMeter;
|
extern cvar_t *cl_voipShowMeter;
|
||||||
extern cvar_t *cl_voip;
|
extern cvar_t *cl_voip;
|
||||||
|
|
||||||
|
// 20ms at 48k
|
||||||
|
#define VOIP_MAX_FRAME_SAMPLES ( 20 * 48 )
|
||||||
|
|
||||||
|
// 3 frame is 60ms of audio, the max opus will encode at once
|
||||||
|
#define VOIP_MAX_PACKET_FRAMES 3
|
||||||
|
#define VOIP_MAX_PACKET_SAMPLES ( VOIP_MAX_FRAME_SAMPLES * VOIP_MAX_PACKET_FRAMES )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=================================================
|
//=================================================
|
||||||
|
|
|
@ -3443,16 +3443,12 @@ qboolean S_AL_Init( soundInterface_t *si )
|
||||||
|
|
||||||
s_alAvailableInputDevices = Cvar_Get("s_alAvailableInputDevices", inputdevicenames, CVAR_ROM | CVAR_NORESTART);
|
s_alAvailableInputDevices = Cvar_Get("s_alAvailableInputDevices", inputdevicenames, CVAR_ROM | CVAR_NORESTART);
|
||||||
|
|
||||||
// !!! FIXME: 8000Hz is what Speex narrowband mode needs, but we
|
|
||||||
// !!! FIXME: should probably open the capture device after
|
|
||||||
// !!! FIXME: initializing Speex so we can change to wideband
|
|
||||||
// !!! FIXME: if we like.
|
|
||||||
Com_Printf("OpenAL default capture device is '%s'\n", defaultinputdevice ? defaultinputdevice : "none");
|
Com_Printf("OpenAL default capture device is '%s'\n", defaultinputdevice ? defaultinputdevice : "none");
|
||||||
alCaptureDevice = qalcCaptureOpenDevice(inputdevice, 8000, AL_FORMAT_MONO16, 4096);
|
alCaptureDevice = qalcCaptureOpenDevice(inputdevice, 48000, AL_FORMAT_MONO16, VOIP_MAX_PACKET_SAMPLES*4);
|
||||||
if( !alCaptureDevice && inputdevice )
|
if( !alCaptureDevice && inputdevice )
|
||||||
{
|
{
|
||||||
Com_Printf( "Failed to open OpenAL Input device '%s', trying default.\n", inputdevice );
|
Com_Printf( "Failed to open OpenAL Input device '%s', trying default.\n", inputdevice );
|
||||||
alCaptureDevice = qalcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 4096);
|
alCaptureDevice = qalcCaptureOpenDevice(NULL, 48000, AL_FORMAT_MONO16, VOIP_MAX_PACKET_SAMPLES*4);
|
||||||
}
|
}
|
||||||
Com_Printf( "OpenAL capture device %s.\n",
|
Com_Printf( "OpenAL capture device %s.\n",
|
||||||
(alCaptureDevice == NULL) ? "failed to open" : "opened");
|
(alCaptureDevice == NULL) ? "failed to open" : "opened");
|
||||||
|
|
|
@ -1752,7 +1752,7 @@ static void Cmd_Tell_f(gentity_t * ent)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Slicer : no TELL FOR TP
|
//Slicer : no TELL FOR TP
|
||||||
if (!g_gametype.integer < GT_TEAM)
|
if (g_gametype.integer >= GT_TEAM)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trap_Argv(1, arg, sizeof(arg));
|
trap_Argv(1, arg, sizeof(arg));
|
||||||
|
|
|
@ -3585,3 +3585,177 @@ qboolean Com_IsVoipTarget(uint8_t *voipTargets, int voipTargetsSize, int clientN
|
||||||
|
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
Field_CompletePlayerName
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static qboolean Field_CompletePlayerNameFinal( qboolean whitespace )
|
||||||
|
{
|
||||||
|
int completionOffset;
|
||||||
|
|
||||||
|
if( matchCount == 0 )
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
completionOffset = strlen( completionField->buffer ) - strlen( completionString );
|
||||||
|
|
||||||
|
Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch,
|
||||||
|
sizeof( completionField->buffer ) - completionOffset );
|
||||||
|
|
||||||
|
completionField->cursor = strlen( completionField->buffer );
|
||||||
|
|
||||||
|
if( matchCount == 1 && whitespace )
|
||||||
|
{
|
||||||
|
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
|
||||||
|
completionField->cursor++;
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Name_PlayerNameCompletion( const char **names, int nameCount, void(*callback)(const char *s) )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < nameCount; i++ ) {
|
||||||
|
callback( names[ i ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Com_FieldStringToPlayerName( char *name, int length, const char *rawname )
|
||||||
|
{
|
||||||
|
char hex[5];
|
||||||
|
int i;
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
if( name == NULL || rawname == NULL )
|
||||||
|
return qfalse;
|
||||||
|
|
||||||
|
if( length <= 0 )
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
for( i = 0; *rawname && i + 1 <= length; rawname++, i++ ) {
|
||||||
|
if( *rawname == '\\' ) {
|
||||||
|
Q_strncpyz( hex, rawname + 1, sizeof(hex) );
|
||||||
|
ch = Com_HexStrToInt( hex );
|
||||||
|
if( ch > -1 ) {
|
||||||
|
name[i] = ch;
|
||||||
|
rawname += 4; //hex string length, 0xXX
|
||||||
|
} else {
|
||||||
|
name[i] = *rawname;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
name[i] = *rawname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name[i] = '\0';
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Com_PlayerNameToFieldString( char *str, int length, const char *name )
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
int i;
|
||||||
|
int x1, x2;
|
||||||
|
|
||||||
|
if( str == NULL || name == NULL )
|
||||||
|
return qfalse;
|
||||||
|
|
||||||
|
if( length <= 0 )
|
||||||
|
return qtrue;
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
p = name;
|
||||||
|
|
||||||
|
for( i = 0; *p != '\0'; i++, p++ )
|
||||||
|
{
|
||||||
|
if( i + 1 >= length )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( *p <= ' ' )
|
||||||
|
{
|
||||||
|
if( i + 5 + 1 >= length )
|
||||||
|
break;
|
||||||
|
|
||||||
|
x1 = *p >> 4;
|
||||||
|
x2 = *p & 15;
|
||||||
|
|
||||||
|
str[i+0] = '\\';
|
||||||
|
str[i+1] = '0';
|
||||||
|
str[i+2] = 'x';
|
||||||
|
str[i+3] = x1 > 9 ? x1 - 10 + 'a' : x1 + '0';
|
||||||
|
str[i+4] = x2 > 9 ? x2 - 10 + 'a' : x2 + '0';
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
} else {
|
||||||
|
str[i] = *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str[i] = '\0';
|
||||||
|
|
||||||
|
return qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Field_CompletePlayerName( char **names, int nameCount )
|
||||||
|
{
|
||||||
|
qboolean whitespace;
|
||||||
|
|
||||||
|
matchCount = 0;
|
||||||
|
shortestMatch[ 0 ] = 0;
|
||||||
|
|
||||||
|
if( nameCount <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Name_PlayerNameCompletion( names, nameCount, FindMatches );
|
||||||
|
|
||||||
|
if( completionString[0] == '\0' )
|
||||||
|
{
|
||||||
|
Com_PlayerNameToFieldString( shortestMatch, sizeof( shortestMatch ), names[ 0 ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
//allow to tab player names
|
||||||
|
//if full player name switch to next player name
|
||||||
|
if( completionString[0] != '\0'
|
||||||
|
&& Q_stricmp( shortestMatch, completionString ) == 0
|
||||||
|
&& nameCount > 1 )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < nameCount; i++ ) {
|
||||||
|
if( Q_stricmp( names[ i ], completionString ) == 0 )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if( i >= nameCount )
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Com_PlayerNameToFieldString( shortestMatch, sizeof( shortestMatch ), names[ i ] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( matchCount > 1 )
|
||||||
|
{
|
||||||
|
Com_Printf( "]%s\n", completionField->buffer );
|
||||||
|
|
||||||
|
Name_PlayerNameCompletion( names, nameCount, PrintMatches );
|
||||||
|
}
|
||||||
|
|
||||||
|
whitespace = nameCount == 1? qtrue: qfalse;
|
||||||
|
if( !Field_CompletePlayerNameFinal( whitespace ) )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int QDECL Com_strCompare( const void *a, const void *b )
|
||||||
|
{
|
||||||
|
const char **pa = (const char **)a;
|
||||||
|
const char **pb = (const char **)b;
|
||||||
|
return strcmp( *pa, *pb );
|
||||||
|
}
|
||||||
|
|
353
code/qcommon/json.h
Normal file
353
code/qcommon/json.h
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2016 James Canete
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_H
|
||||||
|
#define JSON_H
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
JSONTYPE_STRING, // string
|
||||||
|
JSONTYPE_OBJECT, // object
|
||||||
|
JSONTYPE_ARRAY, // array
|
||||||
|
JSONTYPE_VALUE, // number, true, false, or null
|
||||||
|
JSONTYPE_ERROR // out of data
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Array Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get pointer to first value in array
|
||||||
|
// When given pointer to an array, returns pointer to the first
|
||||||
|
// returns NULL if array is empty or not an array.
|
||||||
|
const char *JSON_ArrayGetFirstValue(const char *json, const char *jsonEnd);
|
||||||
|
|
||||||
|
// Get pointer to next value in array
|
||||||
|
// When given pointer to a value, returns pointer to the next value
|
||||||
|
// returns NULL when no next value.
|
||||||
|
const char *JSON_ArrayGetNextValue(const char *json, const char *jsonEnd);
|
||||||
|
|
||||||
|
// Get pointers to values in an array
|
||||||
|
// returns 0 if not an array, array is empty, or out of data
|
||||||
|
// returns number of values in the array and copies into index if successful
|
||||||
|
unsigned int JSON_ArrayGetIndex(const char *json, const char *jsonEnd, const char **indexes, unsigned int numIndexes);
|
||||||
|
|
||||||
|
// Get pointer to indexed value from array
|
||||||
|
// returns NULL if not an array, no index, or out of data
|
||||||
|
const char *JSON_ArrayGetValue(const char *json, const char *jsonEnd, unsigned int index);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Object Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get pointer to named value from object
|
||||||
|
// returns NULL if not an object, name not found, or out of data
|
||||||
|
const char *JSON_ObjectGetNamedValue(const char *json, const char *jsonEnd, const char *name);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Value Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Get type of value
|
||||||
|
// returns JSONTYPE_ERROR if out of data
|
||||||
|
unsigned int JSON_ValueGetType(const char *json, const char *jsonEnd);
|
||||||
|
|
||||||
|
// Get value as string
|
||||||
|
// returns 0 if out of data
|
||||||
|
// returns length and copies into string if successful, including terminating nul.
|
||||||
|
// string values are stripped of enclosing quotes but not escaped
|
||||||
|
unsigned int JSON_ValueGetString(const char *json, const char *jsonEnd, char *outString, unsigned int stringLen);
|
||||||
|
|
||||||
|
// Get value as appropriate type
|
||||||
|
// returns 0 if value is false, value is null, or out of data
|
||||||
|
// returns 1 if value is true
|
||||||
|
// returns value otherwise
|
||||||
|
double JSON_ValueGetDouble(const char *json, const char *jsonEnd);
|
||||||
|
float JSON_ValueGetFloat(const char *json, const char *jsonEnd);
|
||||||
|
int JSON_ValueGetInt(const char *json, const char *jsonEnd);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JSON_IMPLEMENTATION
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Internal Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static const char *JSON_SkipSeparators(const char *json, const char *jsonEnd);
|
||||||
|
static const char *JSON_SkipString(const char *json, const char *jsonEnd);
|
||||||
|
static const char *JSON_SkipStruct(const char *json, const char *jsonEnd);
|
||||||
|
static const char *JSON_SkipValue(const char *json, const char *jsonEnd);
|
||||||
|
static const char *JSON_SkipValueAndSeparators(const char *json, const char *jsonEnd);
|
||||||
|
|
||||||
|
#define IS_SEPARATOR(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r' || (x) == ',' || (x) == ':')
|
||||||
|
#define IS_STRUCT_OPEN(x) ((x) == '{' || (x) == '[')
|
||||||
|
#define IS_STRUCT_CLOSE(x) ((x) == '}' || (x) == ']')
|
||||||
|
|
||||||
|
static const char *JSON_SkipSeparators(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
while (json < jsonEnd && IS_SEPARATOR(*json))
|
||||||
|
json++;
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *JSON_SkipString(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
for (json++; json < jsonEnd && *json != '"'; json++)
|
||||||
|
if (*json == '\\')
|
||||||
|
json++;
|
||||||
|
|
||||||
|
return (json + 1 > jsonEnd) ? jsonEnd : json + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *JSON_SkipStruct(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
json = JSON_SkipSeparators(json + 1, jsonEnd);
|
||||||
|
while (json < jsonEnd && !IS_STRUCT_CLOSE(*json))
|
||||||
|
json = JSON_SkipValueAndSeparators(json, jsonEnd);
|
||||||
|
|
||||||
|
return (json + 1 > jsonEnd) ? jsonEnd : json + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *JSON_SkipValue(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
if (json >= jsonEnd)
|
||||||
|
return jsonEnd;
|
||||||
|
else if (*json == '"')
|
||||||
|
json = JSON_SkipString(json, jsonEnd);
|
||||||
|
else if (IS_STRUCT_OPEN(*json))
|
||||||
|
json = JSON_SkipStruct(json, jsonEnd);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (json < jsonEnd && !IS_SEPARATOR(*json) && !IS_STRUCT_CLOSE(*json))
|
||||||
|
json++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *JSON_SkipValueAndSeparators(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
json = JSON_SkipValue(json, jsonEnd);
|
||||||
|
return JSON_SkipSeparators(json, jsonEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns 0 if value requires more parsing, 1 if no more data/false/null, 2 if true
|
||||||
|
static unsigned int JSON_NoParse(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
if (!json || json >= jsonEnd || *json == 'f' || *json == 'n')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (*json == 't')
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Array Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char *JSON_ArrayGetFirstValue(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
if (!json || json >= jsonEnd || !IS_STRUCT_OPEN(*json))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
json = JSON_SkipSeparators(json + 1, jsonEnd);
|
||||||
|
|
||||||
|
return (json >= jsonEnd || IS_STRUCT_CLOSE(*json)) ? NULL : json;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *JSON_ArrayGetNextValue(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
if (!json || json >= jsonEnd || IS_STRUCT_CLOSE(*json))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
json = JSON_SkipValueAndSeparators(json, jsonEnd);
|
||||||
|
|
||||||
|
return (json >= jsonEnd || IS_STRUCT_CLOSE(*json)) ? NULL : json;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int JSON_ArrayGetIndex(const char *json, const char *jsonEnd, const char **indexes, unsigned int numIndexes)
|
||||||
|
{
|
||||||
|
unsigned int length = 0;
|
||||||
|
|
||||||
|
for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json; json = JSON_ArrayGetNextValue(json, jsonEnd))
|
||||||
|
{
|
||||||
|
if (indexes && numIndexes)
|
||||||
|
{
|
||||||
|
*indexes++ = json;
|
||||||
|
numIndexes--;
|
||||||
|
}
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *JSON_ArrayGetValue(const char *json, const char *jsonEnd, unsigned int index)
|
||||||
|
{
|
||||||
|
for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json && index; json = JSON_ArrayGetNextValue(json, jsonEnd))
|
||||||
|
index--;
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Object Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const char *JSON_ObjectGetNamedValue(const char *json, const char *jsonEnd, const char *name)
|
||||||
|
{
|
||||||
|
unsigned int nameLen = strlen(name);
|
||||||
|
|
||||||
|
for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json; json = JSON_ArrayGetNextValue(json, jsonEnd))
|
||||||
|
{
|
||||||
|
if (*json == '"')
|
||||||
|
{
|
||||||
|
const char *thisNameStart, *thisNameEnd;
|
||||||
|
|
||||||
|
thisNameStart = json + 1;
|
||||||
|
json = JSON_SkipString(json, jsonEnd);
|
||||||
|
thisNameEnd = json - 1;
|
||||||
|
json = JSON_SkipSeparators(json, jsonEnd);
|
||||||
|
|
||||||
|
if ((unsigned int)(thisNameEnd - thisNameStart) == nameLen)
|
||||||
|
if (strncmp(thisNameStart, name, nameLen) == 0)
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Value Functions
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
unsigned int JSON_ValueGetType(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
if (!json || json >= jsonEnd)
|
||||||
|
return JSONTYPE_ERROR;
|
||||||
|
else if (*json == '"')
|
||||||
|
return JSONTYPE_STRING;
|
||||||
|
else if (*json == '{')
|
||||||
|
return JSONTYPE_OBJECT;
|
||||||
|
else if (*json == '[')
|
||||||
|
return JSONTYPE_ARRAY;
|
||||||
|
|
||||||
|
return JSONTYPE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int JSON_ValueGetString(const char *json, const char *jsonEnd, char *outString, unsigned int stringLen)
|
||||||
|
{
|
||||||
|
const char *stringEnd, *stringStart;
|
||||||
|
|
||||||
|
if (!json)
|
||||||
|
{
|
||||||
|
*outString = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stringStart = json;
|
||||||
|
stringEnd = JSON_SkipValue(stringStart, jsonEnd);
|
||||||
|
if (stringEnd >= jsonEnd)
|
||||||
|
{
|
||||||
|
*outString = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip enclosing quotes if they exist
|
||||||
|
if (*stringStart == '"')
|
||||||
|
stringStart++;
|
||||||
|
|
||||||
|
if (*(stringEnd - 1) == '"')
|
||||||
|
stringEnd--;
|
||||||
|
|
||||||
|
stringLen--;
|
||||||
|
if (stringLen > stringEnd - stringStart)
|
||||||
|
stringLen = stringEnd - stringStart;
|
||||||
|
|
||||||
|
json = stringStart;
|
||||||
|
while (stringLen--)
|
||||||
|
*outString++ = *json++;
|
||||||
|
*outString = '\0';
|
||||||
|
|
||||||
|
return stringEnd - stringStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
double JSON_ValueGetDouble(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
char cValue[256];
|
||||||
|
double dValue = 0.0;
|
||||||
|
unsigned int np = JSON_NoParse(json, jsonEnd);
|
||||||
|
|
||||||
|
if (np)
|
||||||
|
return (double)(np - 1);
|
||||||
|
|
||||||
|
if (!JSON_ValueGetString(json, jsonEnd, cValue, 256))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
sscanf(cValue, "%lf", &dValue);
|
||||||
|
|
||||||
|
return dValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float JSON_ValueGetFloat(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
char cValue[256];
|
||||||
|
float fValue = 0.0f;
|
||||||
|
unsigned int np = JSON_NoParse(json, jsonEnd);
|
||||||
|
|
||||||
|
if (np)
|
||||||
|
return (float)(np - 1);
|
||||||
|
|
||||||
|
if (!JSON_ValueGetString(json, jsonEnd, cValue, 256))
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
sscanf(cValue, "%f", &fValue);
|
||||||
|
|
||||||
|
return fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JSON_ValueGetInt(const char *json, const char *jsonEnd)
|
||||||
|
{
|
||||||
|
char cValue[256];
|
||||||
|
int iValue = 0;
|
||||||
|
unsigned int np = JSON_NoParse(json, jsonEnd);
|
||||||
|
|
||||||
|
if (np)
|
||||||
|
return np - 1;
|
||||||
|
|
||||||
|
if (!JSON_ValueGetString(json, jsonEnd, cValue, 256))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sscanf(cValue, "%d", &iValue);
|
||||||
|
|
||||||
|
return iValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef IS_SEPARATOR
|
||||||
|
#undef IS_STRUCT_OPEN
|
||||||
|
#undef IS_STRUCT_CLOSE
|
||||||
|
|
||||||
|
#endif
|
|
@ -27,26 +27,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// A user mod should never modify this file
|
// A user mod should never modify this file
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
#define PRODUCT_NAME "Reaction"
|
#define PRODUCT_NAME "Reaction"
|
||||||
#define BASEGAME "Boomstick"
|
#define BASEGAME "Boomstick"
|
||||||
#define CLIENT_WINDOW_TITLE "Reaction"
|
#define CLIENT_WINDOW_TITLE "Reaction"
|
||||||
#define CLIENT_WINDOW_MIN_TITLE "Reaction"
|
#define CLIENT_WINDOW_MIN_TITLE "Reaction"
|
||||||
#define HOMEPATH_NAME_UNIX ".Reaction"
|
#define HOMEPATH_NAME_UNIX ".Reaction"
|
||||||
#define HOMEPATH_NAME_WIN "Reaction"
|
#define HOMEPATH_NAME_WIN "Reaction"
|
||||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||||
// #define STEAMPATH_NAME "Foo Bar"
|
// #define STEAMPATH_NAME "Foo Bar"
|
||||||
// #define STEAMPATH_APPID ""
|
// #define STEAMPATH_APPID ""
|
||||||
#define GAMENAME_FOR_MASTER "Reaction"
|
#define GAMENAME_FOR_MASTER "Reaction"
|
||||||
// #define LEGACY_PROTOCOL // You probably don't need this for your standalone game
|
// #define LEGACY_PROTOCOL // You probably don't need this for your standalone game
|
||||||
#else
|
#else
|
||||||
#define PRODUCT_NAME "Reaction"
|
#define PRODUCT_NAME "Reaction"
|
||||||
#define BASEGAME "Boomstick"
|
#define BASEGAME "Boomstick"
|
||||||
#define CLIENT_WINDOW_TITLE "Reaction"
|
#define CLIENT_WINDOW_TITLE "Reaction"
|
||||||
#define CLIENT_WINDOW_MIN_TITLE "Reaction"
|
#define CLIENT_WINDOW_MIN_TITLE "Reaction"
|
||||||
#define HOMEPATH_NAME_UNIX ".Reaction"
|
#define HOMEPATH_NAME_UNIX ".Reaction"
|
||||||
#define HOMEPATH_NAME_WIN "Reaction"
|
#define HOMEPATH_NAME_WIN "Reaction"
|
||||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||||
// #define STEAMPATH_NAME "Foo Bar"
|
// #define STEAMPATH_NAME "Foo Bar"
|
||||||
// #define STEAMPATH_APPID ""
|
// #define STEAMPATH_APPID ""
|
||||||
#define GAMENAME_FOR_MASTER "Reaction"
|
#define GAMENAME_FOR_MASTER "Reaction"
|
||||||
// #define LEGACY_PROTOCOL
|
// #define LEGACY_PROTOCOL
|
||||||
|
|
|
@ -300,7 +300,8 @@ enum svc_ops_e {
|
||||||
svc_EOF,
|
svc_EOF,
|
||||||
|
|
||||||
// new commands, supported only by ioquake3 protocol but not legacy
|
// new commands, supported only by ioquake3 protocol but not legacy
|
||||||
svc_voip, // not wrapped in USE_VOIP, so this value is reserved.
|
svc_voipSpeex, // not wrapped in USE_VOIP, so this value is reserved.
|
||||||
|
svc_voipOpus, //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,7 +317,8 @@ enum clc_ops_e {
|
||||||
clc_EOF,
|
clc_EOF,
|
||||||
|
|
||||||
// new commands, supported only by ioquake3 protocol but not legacy
|
// new commands, supported only by ioquake3 protocol but not legacy
|
||||||
clc_voip, // not wrapped in USE_VOIP, so this value is reserved.
|
clc_voipSpeex, // not wrapped in USE_VOIP, so this value is reserved.
|
||||||
|
clc_voipOpus, //
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -760,6 +762,7 @@ void Field_CompleteFilename( const char *dir,
|
||||||
const char *ext, qboolean stripExt, qboolean allowNonPureFilesOnDisk );
|
const char *ext, qboolean stripExt, qboolean allowNonPureFilesOnDisk );
|
||||||
void Field_CompleteCommand( char *cmd,
|
void Field_CompleteCommand( char *cmd,
|
||||||
qboolean doCommands, qboolean doCvars );
|
qboolean doCommands, qboolean doCvars );
|
||||||
|
void Field_CompletePlayerName( char **names, int count );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================
|
==============================================================
|
||||||
|
@ -839,6 +842,10 @@ void Com_StartupVariable( const char *match );
|
||||||
// if match is NULL, all set commands will be executed, otherwise
|
// if match is NULL, all set commands will be executed, otherwise
|
||||||
// only a set with the exact name. Only used during startup.
|
// only a set with the exact name. Only used during startup.
|
||||||
|
|
||||||
|
qboolean Com_PlayerNameToFieldString( char *str, int length, const char *name );
|
||||||
|
qboolean Com_FieldStringToPlayerName( char *name, int length, const char *rawname );
|
||||||
|
int QDECL Com_strCompare( const void *a, const void *b );
|
||||||
|
|
||||||
|
|
||||||
extern cvar_t *com_developer;
|
extern cvar_t *com_developer;
|
||||||
extern cvar_t *com_dedicated;
|
extern cvar_t *com_dedicated;
|
||||||
|
|
|
@ -677,12 +677,12 @@ extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLs
|
||||||
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
|
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GL_EXT_texture_compression_latc
|
#ifndef GL_ARB_texture_compression_rgtc
|
||||||
#define GL_EXT_texture_compression_latc
|
#define GL_ARB_texture_compression_rgtc
|
||||||
#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
|
#define GL_COMPRESSED_RED_RGTC1 0x8DBB
|
||||||
#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
|
#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
|
||||||
#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
|
#define GL_COMPRESSED_RG_RGTC2 0x8DBD
|
||||||
#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
|
#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GL_ARB_texture_compression_bptc
|
#ifndef GL_ARB_texture_compression_bptc
|
||||||
|
@ -736,6 +736,51 @@ extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
|
||||||
#define GL_VERTEX_ARRAY_BINDING_ARB 0x85B5
|
#define GL_VERTEX_ARRAY_BINDING_ARB 0x85B5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// GL_EXT_direct_state_access
|
||||||
|
extern GLvoid(APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
extern GLvoid(APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, GLenum pname, GLfloat param);
|
||||||
|
extern GLvoid(APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, GLenum pname, GLint param);
|
||||||
|
extern GLvoid(APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
extern GLvoid(APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
extern GLvoid(APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||||
|
extern GLvoid(APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||||
|
extern GLvoid(APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data);
|
||||||
|
extern GLvoid(APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target);
|
||||||
|
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, GLint v0);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, GLfloat v0);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value);
|
||||||
|
extern GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value);
|
||||||
|
|
||||||
|
extern GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
extern GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
extern GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target);
|
||||||
|
extern GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
|
extern GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
// WGL_ARB_create_context
|
// WGL_ARB_create_context
|
||||||
|
|
|
@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
#include "tr_common.h"
|
#include "tr_common.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -42,16 +44,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void __attribute__((__noreturn__)) R_JPGErrorExit(j_common_ptr cinfo)
|
/* Catching errors, as done in libjpeg's example.c */
|
||||||
|
typedef struct q_jpeg_error_mgr_s
|
||||||
|
{
|
||||||
|
struct jpeg_error_mgr pub; /* "public" fields */
|
||||||
|
|
||||||
|
jmp_buf setjmp_buffer; /* for return to caller */
|
||||||
|
} q_jpeg_error_mgr_t;
|
||||||
|
|
||||||
|
static void R_JPGErrorExit(j_common_ptr cinfo)
|
||||||
{
|
{
|
||||||
char buffer[JMSG_LENGTH_MAX];
|
char buffer[JMSG_LENGTH_MAX];
|
||||||
|
|
||||||
|
/* cinfo->err really points to a q_jpeg_error_mgr_s struct, so coerce pointer */
|
||||||
|
q_jpeg_error_mgr_t *jerr = (q_jpeg_error_mgr_t *)cinfo->err;
|
||||||
|
|
||||||
(*cinfo->err->format_message) (cinfo, buffer);
|
(*cinfo->err->format_message) (cinfo, buffer);
|
||||||
|
|
||||||
/* Let the memory manager delete any temp files before we die */
|
ri.Printf(PRINT_ALL, "Error: %s", buffer);
|
||||||
jpeg_destroy(cinfo);
|
|
||||||
|
/* Return control to the setjmp point */
|
||||||
ri.Error(ERR_FATAL, "%s", buffer);
|
longjmp(jerr->setjmp_buffer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void R_JPGOutputMessage(j_common_ptr cinfo)
|
static void R_JPGOutputMessage(j_common_ptr cinfo)
|
||||||
|
@ -83,7 +96,7 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
|
||||||
* Note that this struct must live as long as the main JPEG parameter
|
* Note that this struct must live as long as the main JPEG parameter
|
||||||
* struct, to avoid dangling-pointer problems.
|
* struct, to avoid dangling-pointer problems.
|
||||||
*/
|
*/
|
||||||
struct jpeg_error_mgr jerr;
|
q_jpeg_error_mgr_t jerr;
|
||||||
/* More stuff */
|
/* More stuff */
|
||||||
JSAMPARRAY buffer; /* Output row buffer */
|
JSAMPARRAY buffer; /* Output row buffer */
|
||||||
unsigned int row_stride; /* physical row width in output buffer */
|
unsigned int row_stride; /* physical row width in output buffer */
|
||||||
|
@ -115,10 +128,24 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh
|
||||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||||
* address which we place into the link field in cinfo.
|
* address which we place into the link field in cinfo.
|
||||||
*/
|
*/
|
||||||
cinfo.err = jpeg_std_error(&jerr);
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
cinfo.err->error_exit = R_JPGErrorExit;
|
cinfo.err->error_exit = R_JPGErrorExit;
|
||||||
cinfo.err->output_message = R_JPGOutputMessage;
|
cinfo.err->output_message = R_JPGOutputMessage;
|
||||||
|
|
||||||
|
/* Establish the setjmp return context for R_JPGErrorExit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer))
|
||||||
|
{
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object, close the input file, and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_decompress(&cinfo);
|
||||||
|
ri.FS_FreeFile(fbuffer.v);
|
||||||
|
|
||||||
|
/* Append the filename to the error for easier debugging */
|
||||||
|
ri.Printf(PRINT_ALL, ", loading file %s\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can initialize the JPEG decompression object. */
|
/* Now we can initialize the JPEG decompression object. */
|
||||||
jpeg_create_decompress(&cinfo);
|
jpeg_create_decompress(&cinfo);
|
||||||
|
|
||||||
|
@ -361,17 +388,29 @@ size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
|
||||||
int image_width, int image_height, byte *image_buffer, int padding)
|
int image_width, int image_height, byte *image_buffer, int padding)
|
||||||
{
|
{
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
q_jpeg_error_mgr_t jerr;
|
||||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||||
my_dest_ptr dest;
|
my_dest_ptr dest;
|
||||||
int row_stride; /* physical row width in image buffer */
|
int row_stride; /* physical row width in image buffer */
|
||||||
size_t outcount;
|
size_t outcount;
|
||||||
|
|
||||||
/* Step 1: allocate and initialize JPEG compression object */
|
/* Step 1: allocate and initialize JPEG compression object */
|
||||||
cinfo.err = jpeg_std_error(&jerr);
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||||
cinfo.err->error_exit = R_JPGErrorExit;
|
cinfo.err->error_exit = R_JPGErrorExit;
|
||||||
cinfo.err->output_message = R_JPGOutputMessage;
|
cinfo.err->output_message = R_JPGOutputMessage;
|
||||||
|
|
||||||
|
/* Establish the setjmp return context for R_JPGErrorExit to use. */
|
||||||
|
if (setjmp(jerr.setjmp_buffer))
|
||||||
|
{
|
||||||
|
/* If we get here, the JPEG code has signaled an error.
|
||||||
|
* We need to clean up the JPEG object and return.
|
||||||
|
*/
|
||||||
|
jpeg_destroy_compress(&cinfo);
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can initialize the JPEG compression object. */
|
/* Now we can initialize the JPEG compression object. */
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
|
|
||||||
|
|
|
@ -495,8 +495,6 @@ void RB_BeginDrawingView (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MAC_EVENT_PUMP_MSEC 5
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
RB_RenderDrawSurfList
|
RB_RenderDrawSurfList
|
||||||
|
|
|
@ -114,20 +114,20 @@ void R_IssuePendingRenderCommands( void ) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
R_GetCommandBuffer
|
R_GetCommandBufferReserved
|
||||||
|
|
||||||
make sure there is enough command space
|
make sure there is enough command space
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void *R_GetCommandBuffer( int bytes ) {
|
void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) {
|
||||||
renderCommandList_t *cmdList;
|
renderCommandList_t *cmdList;
|
||||||
|
|
||||||
cmdList = &backEndData->commands;
|
cmdList = &backEndData->commands;
|
||||||
bytes = PAD(bytes, sizeof(void *));
|
bytes = PAD(bytes, sizeof(void *));
|
||||||
|
|
||||||
// always leave room for the end of list command
|
// always leave room for the end of list command
|
||||||
if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
|
if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) {
|
||||||
if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
|
if ( bytes > MAX_RENDER_COMMANDS - sizeof( int ) ) {
|
||||||
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
|
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
|
||||||
}
|
}
|
||||||
// if we run out of room, just start dropping commands
|
// if we run out of room, just start dropping commands
|
||||||
|
@ -139,6 +139,17 @@ void *R_GetCommandBuffer( int bytes ) {
|
||||||
return cmdList->cmds + cmdList->used - bytes;
|
return cmdList->cmds + cmdList->used - bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_GetCommandBuffer
|
||||||
|
|
||||||
|
returns NULL if there is not enough space for important commands
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void *R_GetCommandBuffer( int bytes ) {
|
||||||
|
return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
|
@ -454,7 +465,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
|
||||||
if ( !tr.registered ) {
|
if ( !tr.registered ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
cmd = R_GetCommandBufferReserved( sizeof( *cmd ), 0 );
|
||||||
if ( !cmd ) {
|
if ( !cmd ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -557,6 +557,7 @@ static void Upload32( unsigned *data,
|
||||||
qboolean mipmap,
|
qboolean mipmap,
|
||||||
qboolean picmip,
|
qboolean picmip,
|
||||||
qboolean lightMap,
|
qboolean lightMap,
|
||||||
|
qboolean allowCompression,
|
||||||
int *format,
|
int *format,
|
||||||
int *pUploadWidth, int *pUploadHeight )
|
int *pUploadWidth, int *pUploadHeight )
|
||||||
{
|
{
|
||||||
|
@ -692,11 +693,11 @@ static void Upload32( unsigned *data,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( glConfig.textureCompression == TC_S3TC_ARB )
|
if ( allowCompression && glConfig.textureCompression == TC_S3TC_ARB )
|
||||||
{
|
{
|
||||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
}
|
}
|
||||||
else if ( glConfig.textureCompression == TC_S3TC )
|
else if ( allowCompression && glConfig.textureCompression == TC_S3TC )
|
||||||
{
|
{
|
||||||
internalFormat = GL_RGB4_S3TC;
|
internalFormat = GL_RGB4_S3TC;
|
||||||
}
|
}
|
||||||
|
@ -892,6 +893,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height,
|
||||||
image->flags & IMGFLAG_MIPMAP,
|
image->flags & IMGFLAG_MIPMAP,
|
||||||
image->flags & IMGFLAG_PICMIP,
|
image->flags & IMGFLAG_PICMIP,
|
||||||
isLightmap,
|
isLightmap,
|
||||||
|
!(image->flags & IMGFLAG_NO_COMPRESSION),
|
||||||
&image->internalFormat,
|
&image->internalFormat,
|
||||||
&image->uploadWidth,
|
&image->uploadWidth,
|
||||||
&image->uploadHeight );
|
&image->uploadHeight );
|
||||||
|
|
|
@ -1146,13 +1146,6 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we overflowed MAX_DRAWSURFS, the drawsurfs
|
|
||||||
// wrapped around in the buffer and we will be missing
|
|
||||||
// the first surfaces, not the last ones
|
|
||||||
if ( numDrawSurfs > MAX_DRAWSURFS ) {
|
|
||||||
numDrawSurfs = MAX_DRAWSURFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the drawsurfs by sort type, then orientation, then shader
|
// sort the drawsurfs by sort type, then orientation, then shader
|
||||||
R_RadixSort( drawSurfs, numDrawSurfs );
|
R_RadixSort( drawSurfs, numDrawSurfs );
|
||||||
|
|
||||||
|
@ -1361,6 +1354,7 @@ or a mirror / remote location
|
||||||
*/
|
*/
|
||||||
void R_RenderView (viewParms_t *parms) {
|
void R_RenderView (viewParms_t *parms) {
|
||||||
int firstDrawSurf;
|
int firstDrawSurf;
|
||||||
|
int numDrawSurfs;
|
||||||
|
|
||||||
if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
|
if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
|
||||||
return;
|
return;
|
||||||
|
@ -1383,7 +1377,15 @@ void R_RenderView (viewParms_t *parms) {
|
||||||
|
|
||||||
R_GenerateDrawSurfs();
|
R_GenerateDrawSurfs();
|
||||||
|
|
||||||
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
|
// if we overflowed MAX_DRAWSURFS, the drawsurfs
|
||||||
|
// wrapped around in the buffer and we will be missing
|
||||||
|
// the first surfaces, not the last ones
|
||||||
|
numDrawSurfs = tr.refdef.numDrawSurfs;
|
||||||
|
if ( numDrawSurfs > MAX_DRAWSURFS ) {
|
||||||
|
numDrawSurfs = MAX_DRAWSURFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf );
|
||||||
|
|
||||||
// draw main system development information (surface outlines, etc)
|
// draw main system development information (surface outlines, etc)
|
||||||
R_DebugGraphics();
|
R_DebugGraphics();
|
||||||
|
|
|
@ -14,8 +14,8 @@ vec3 GetValues(vec2 offset, vec3 current)
|
||||||
|
|
||||||
#ifdef FIRST_PASS
|
#ifdef FIRST_PASS
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
minAvgMax = pow(minAvgMax, vec3(r_framebufferGamma));
|
minAvgMax *= minAvgMax;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
|
float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
|
||||||
|
|
|
@ -29,11 +29,6 @@ uniform samplerCube u_CubeMap;
|
||||||
uniform vec4 u_EnableTextures;
|
uniform vec4 u_EnableTextures;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
|
|
||||||
uniform vec3 u_DirectedLight;
|
|
||||||
uniform vec3 u_AmbientLight;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
uniform vec3 u_PrimaryLightColor;
|
uniform vec3 u_PrimaryLightColor;
|
||||||
uniform vec3 u_PrimaryLightAmbient;
|
uniform vec3 u_PrimaryLightAmbient;
|
||||||
|
@ -53,6 +48,9 @@ uniform vec4 u_CubeMapInfo;
|
||||||
varying vec4 var_TexCoords;
|
varying vec4 var_TexCoords;
|
||||||
|
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
||||||
|
varying vec4 var_ColorAmbient;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
#if defined(USE_VERT_TANGENT_SPACE)
|
||||||
|
@ -150,156 +148,35 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 CalcDiffuse(vec3 diffuseAlbedo, vec3 N, vec3 L, vec3 E, float NE, float NL, float shininess)
|
vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
|
||||||
{
|
{
|
||||||
#if defined(USE_OREN_NAYAR) || defined(USE_TRIACE_OREN_NAYAR)
|
#if defined(USE_BURLEY)
|
||||||
float gamma = dot(E, L) - NE * NL;
|
// modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf
|
||||||
float B = 2.22222 + 0.1 * shininess;
|
float fd90 = -0.5 + EH * EH * roughness;
|
||||||
|
float burley = 1.0 + fd90 * 0.04 / NH;
|
||||||
#if defined(USE_OREN_NAYAR)
|
burley *= burley;
|
||||||
float A = 1.0 - 1.0 / (2.0 + 0.33 * shininess);
|
return diffuseAlbedo * burley;
|
||||||
gamma = clamp(gamma, 0.0, 1.0);
|
#else
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_TRIACE_OREN_NAYAR)
|
|
||||||
float A = 1.0 - 1.0 / (2.0 + 0.65 * shininess);
|
|
||||||
|
|
||||||
if (gamma >= 0.0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
B = max(B * max(NL, NE), EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
return diffuseAlbedo * (A + gamma / B);
|
|
||||||
#else
|
|
||||||
return diffuseAlbedo;
|
return diffuseAlbedo;
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 EnvironmentBRDF(float gloss, float NE, vec3 specular)
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
// from http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
vec4 t = vec4( 1.0/0.96, 0.475, (0.0275 - 0.25 * 0.04)/0.96,0.25 ) * gloss;
|
|
||||||
t += vec4( 0.0, 0.0, (0.015 - 0.75 * 0.04)/0.96,0.75 );
|
|
||||||
float a0 = t.x * min( t.y, exp2( -9.28 * NE ) ) + t.z;
|
|
||||||
float a1 = t.w;
|
|
||||||
return clamp( a0 + specular * ( a1 - a0 ), 0.0, 1.0 );
|
|
||||||
#elif 0
|
|
||||||
// from http://seblagarde.wordpress.com/2011/08/17/hello-world/
|
|
||||||
return specular + CalcFresnel(NE) * clamp(vec3(gloss) - specular, 0.0, 1.0);
|
|
||||||
#else
|
|
||||||
// from http://advances.realtimerendering.com/s2011/Lazarov-Physically-Based-Lighting-in-Black-Ops%20%28Siggraph%202011%20Advances%20in%20Real-Time%20Rendering%20Course%29.pptx
|
|
||||||
return mix(specular.rgb, vec3(1.0), CalcFresnel(NE) / (4.0 - 3.0 * gloss));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcBlinn(float NH, float shininess)
|
|
||||||
{
|
|
||||||
#if defined(USE_BLINN) || defined(USE_BLINN_FRESNEL)
|
|
||||||
// Normalized Blinn-Phong
|
|
||||||
float norm = shininess * 0.125 + 1.0;
|
|
||||||
#elif defined(USE_MCAULEY)
|
|
||||||
// Cook-Torrance as done by Stephen McAuley
|
|
||||||
// http://blog.selfshadow.com/publications/s2012-shading-course/mcauley/s2012_pbs_farcry3_notes_v2.pdf
|
|
||||||
float norm = shininess * 0.25 + 0.125;
|
|
||||||
#elif defined(USE_GOTANDA)
|
|
||||||
// Neumann-Neumann as done by Yoshiharu Gotanda
|
|
||||||
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
|
|
||||||
float norm = shininess * 0.124858 + 0.269182;
|
|
||||||
#elif defined(USE_LAZAROV)
|
|
||||||
// Cook-Torrance as done by Dimitar Lazarov
|
|
||||||
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
float norm = shininess * 0.125 + 0.25;
|
|
||||||
#else
|
|
||||||
float norm = 1.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// from http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
|
|
||||||
float a = shininess + 0.775;
|
|
||||||
return norm * exp(a * NH - a);
|
|
||||||
#else
|
|
||||||
return norm * pow(NH, shininess);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float CalcGGX(float NH, float gloss)
|
vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular)
|
||||||
{
|
{
|
||||||
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
float a_sq = exp2(gloss * -13.0 + 1.0);
|
float v = 1.0 - max(roughness, NE);
|
||||||
float d = ((NH * NH) * (a_sq - 1.0) + 1.0);
|
v *= v * v;
|
||||||
return a_sq / (d * d);
|
return vec3(v) + specular;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CalcFresnel(float EH)
|
vec3 CalcSpecular(vec3 specular, float NH, float EH, float roughness)
|
||||||
{
|
{
|
||||||
#if 1
|
// from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf
|
||||||
// From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
float rr = roughness*roughness;
|
||||||
// not accurate, but fast
|
float rrrr = rr*rr;
|
||||||
return exp2(-10.0 * EH);
|
float d = (NH * NH) * (rrrr - 1.0) + 1.0;
|
||||||
#elif 0
|
float v = (EH * EH) * (roughness + 0.5);
|
||||||
// From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
|
return specular * (rrrr / (4.0 * d * d * v));
|
||||||
return exp2((-5.55473 * EH - 6.98316) * EH);
|
|
||||||
#elif 0
|
|
||||||
float blend = 1.0 - EH;
|
|
||||||
float blend2 = blend * blend;
|
|
||||||
blend *= blend2 * blend2;
|
|
||||||
|
|
||||||
return blend;
|
|
||||||
#else
|
|
||||||
return pow(1.0 - EH, 5.0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
float CalcVisibility(float NH, float NL, float NE, float EH, float gloss)
|
|
||||||
{
|
|
||||||
#if defined(USE_GOTANDA)
|
|
||||||
// Neumann-Neumann as done by Yoshiharu Gotanda
|
|
||||||
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
|
|
||||||
return 1.0 / max(max(NL, NE), EPSILON);
|
|
||||||
#elif defined(USE_LAZAROV)
|
|
||||||
// Cook-Torrance as done by Dimitar Lazarov
|
|
||||||
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
|
|
||||||
float k = min(1.0, gloss + 0.545);
|
|
||||||
return 1.0 / (k * (EH * EH - 1.0) + 1.0);
|
|
||||||
#elif defined(USE_GGX)
|
|
||||||
float roughness = exp2(gloss * -6.5);
|
|
||||||
|
|
||||||
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
|
|
||||||
// NL, NE in numerator factored out from cook-torrance
|
|
||||||
float k = roughness + 1.0;
|
|
||||||
k *= k * 0.125;
|
|
||||||
|
|
||||||
float k2 = 1.0 - k;
|
|
||||||
|
|
||||||
float invGeo1 = NL * k2 + k;
|
|
||||||
float invGeo2 = NE * k2 + k;
|
|
||||||
|
|
||||||
return 1.0 / (invGeo1 * invGeo2);
|
|
||||||
#else
|
|
||||||
return 1.0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess)
|
|
||||||
{
|
|
||||||
#if defined(USE_GGX)
|
|
||||||
float distrib = CalcGGX(NH, gloss);
|
|
||||||
#else
|
|
||||||
float distrib = CalcBlinn(NH, shininess);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_BLINN)
|
|
||||||
vec3 fSpecular = specular;
|
|
||||||
#else
|
|
||||||
vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float vis = CalcVisibility(NH, NL, NE, EH, gloss);
|
|
||||||
|
|
||||||
return fSpecular * (distrib * vis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,7 +218,7 @@ mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv )
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 viewDir, lightColor, ambientColor;
|
vec3 viewDir, lightColor, ambientColor, reflectance;
|
||||||
vec3 L, N, E, H;
|
vec3 L, N, E, H;
|
||||||
float NL, NH, NE, EH, attenuation;
|
float NL, NH, NE, EH, attenuation;
|
||||||
|
|
||||||
|
@ -353,21 +230,20 @@ void main()
|
||||||
mat3 tangentToWorld = cotangent_frame(var_Normal, -var_ViewDir, var_TexCoords.xy);
|
mat3 tangentToWorld = cotangent_frame(var_Normal, -var_ViewDir, var_TexCoords.xy);
|
||||||
viewDir = var_ViewDir;
|
viewDir = var_ViewDir;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
E = normalize(viewDir);
|
E = normalize(viewDir);
|
||||||
|
|
||||||
L = var_LightDir.xyz;
|
|
||||||
#if defined(USE_DELUXEMAP)
|
|
||||||
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
|
|
||||||
#endif
|
|
||||||
float sqrLightDist = dot(L, L);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
lightColor = var_Color.rgb;
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP)
|
#if defined(USE_LIGHTMAP)
|
||||||
vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
|
vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw);
|
||||||
#if defined(RGBM_LIGHTMAP)
|
#if defined(RGBM_LIGHTMAP)
|
||||||
lightmapColor.rgb *= lightmapColor.a;
|
lightmapColor.rgb *= lightmapColor.a;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(USE_PBR) && !defined(USE_FAST_LIGHT)
|
||||||
|
lightmapColor.rgb *= lightmapColor.rgb;
|
||||||
|
#endif
|
||||||
|
lightColor *= lightmapColor.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec2 texCoords = var_TexCoords.xy;
|
vec2 texCoords = var_TexCoords.xy;
|
||||||
|
@ -383,17 +259,16 @@ void main()
|
||||||
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
|
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
#if defined(USE_LIGHTMAP)
|
L = var_LightDir.xyz;
|
||||||
lightColor = lightmapColor.rgb * var_Color.rgb;
|
#if defined(USE_DELUXEMAP)
|
||||||
ambientColor = vec3(0.0);
|
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
|
||||||
attenuation = 1.0;
|
#endif
|
||||||
#elif defined(USE_LIGHT_VECTOR)
|
float sqrLightDist = dot(L, L);
|
||||||
lightColor = u_DirectedLight * var_Color.rgb;
|
L /= sqrt(sqrLightDist);
|
||||||
ambientColor = u_AmbientLight * var_Color.rgb;
|
|
||||||
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
|
attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
|
||||||
#elif defined(USE_LIGHT_VERTEX)
|
#else
|
||||||
lightColor = var_Color.rgb;
|
|
||||||
ambientColor = vec3(0.0);
|
|
||||||
attenuation = 1.0;
|
attenuation = 1.0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -411,33 +286,20 @@ void main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
N = normalize(N);
|
N = normalize(N);
|
||||||
L /= sqrt(sqrLightDist);
|
|
||||||
|
|
||||||
#if defined(USE_SHADOWMAP)
|
#if defined(USE_SHADOWMAP)
|
||||||
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
|
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
|
||||||
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
|
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
|
||||||
|
|
||||||
// surfaces not facing the light are always shadowed
|
// surfaces not facing the light are always shadowed
|
||||||
shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0);
|
shadowValue *= clamp(dot(var_Normal.xyz, var_PrimaryLightDir.xyz), 0.0, 1.0);
|
||||||
|
|
||||||
#if defined(SHADOWMAP_MODULATE)
|
#if defined(SHADOWMAP_MODULATE)
|
||||||
//vec3 shadowColor = min(u_PrimaryLightAmbient, lightColor);
|
lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r;
|
||||||
vec3 shadowColor = u_PrimaryLightAmbient * lightColor;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Only shadow when the world light is parallel to the primary light
|
|
||||||
shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0);
|
|
||||||
#endif
|
|
||||||
lightColor = mix(shadowColor, lightColor, shadowValue);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(r_lightGamma)
|
#if !defined(USE_LIGHT_VECTOR)
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
|
||||||
ambientColor = pow(ambientColor, vec3(r_lightGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)
|
|
||||||
ambientColor = lightColor;
|
ambientColor = lightColor;
|
||||||
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
|
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
|
||||||
|
|
||||||
|
@ -447,10 +309,10 @@ void main()
|
||||||
|
|
||||||
// Recover any unused light as ambient, in case attenuation is over 4x or
|
// Recover any unused light as ambient, in case attenuation is over 4x or
|
||||||
// light is below the surface
|
// light is below the surface
|
||||||
ambientColor = clamp(ambientColor - lightColor * surfNL, 0.0, 1.0);
|
ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0));
|
||||||
|
#else
|
||||||
|
ambientColor = var_ColorAmbient.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 reflectance;
|
|
||||||
|
|
||||||
NL = clamp(dot(N, L), 0.0, 1.0);
|
NL = clamp(dot(N, L), 0.0, 1.0);
|
||||||
NE = clamp(dot(N, E), 0.0, 1.0);
|
NE = clamp(dot(N, E), 0.0, 1.0);
|
||||||
|
@ -460,70 +322,36 @@ void main()
|
||||||
#else
|
#else
|
||||||
vec4 specular = vec4(1.0);
|
vec4 specular = vec4(1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
specular *= u_SpecularScale;
|
specular *= u_SpecularScale;
|
||||||
|
|
||||||
#if defined(r_materialGamma)
|
#if defined(USE_PBR)
|
||||||
diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma));
|
diffuse.rgb *= diffuse.rgb;
|
||||||
specular.rgb = pow(specular.rgb, vec3(r_materialGamma));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float gloss = specular.a;
|
#if defined(USE_PBR)
|
||||||
float shininess = exp2(gloss * 13.0);
|
// diffuse rgb is base color
|
||||||
|
// specular red is smoothness
|
||||||
#if defined(SPECULAR_IS_METALLIC)
|
// specular green is metallicness
|
||||||
// diffuse is actually base color, and red of specular is metallicness
|
float roughness = 1.0 - specular.r;
|
||||||
float metallic = specular.r;
|
specular.rgb = specular.g * diffuse.rgb + vec3(0.04 - 0.04 * specular.g);
|
||||||
|
diffuse.rgb *= 1.0 - specular.g;
|
||||||
specular.rgb = (0.96 * metallic) * diffuse.rgb + vec3(0.04);
|
|
||||||
diffuse.rgb *= 1.0 - metallic;
|
|
||||||
#else
|
#else
|
||||||
|
// diffuse rgb is diffuse
|
||||||
|
// specular rgb is specular reflectance at normal incidence
|
||||||
|
// specular alpha is gloss
|
||||||
|
float roughness = exp2(-3.0 * specular.a);
|
||||||
|
|
||||||
// adjust diffuse by specular reflectance, to maintain energy conservation
|
// adjust diffuse by specular reflectance, to maintain energy conservation
|
||||||
diffuse.rgb *= vec3(1.0) - specular.rgb;
|
diffuse.rgb *= vec3(1.0) - specular.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
|
reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness);
|
||||||
|
|
||||||
#if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR)
|
|
||||||
float adjGloss = gloss;
|
|
||||||
float adjShininess = shininess;
|
|
||||||
|
|
||||||
#if !defined(USE_LIGHT_VECTOR)
|
|
||||||
adjGloss *= r_deluxeSpecular;
|
|
||||||
adjShininess = exp2(adjGloss * 13.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
H = normalize(L + E);
|
|
||||||
|
|
||||||
EH = clamp(dot(E, H), 0.0, 1.0);
|
|
||||||
NH = clamp(dot(N, H), 0.0, 1.0);
|
|
||||||
|
|
||||||
#if !defined(USE_LIGHT_VECTOR)
|
|
||||||
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular;
|
|
||||||
#else
|
|
||||||
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
|
gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL);
|
||||||
|
gl_FragColor.rgb += ambientColor * diffuse.rgb;
|
||||||
#if 0
|
|
||||||
vec3 aSpecular = EnvironmentBRDF(gloss, NE, specular.rgb);
|
|
||||||
|
|
||||||
// do ambient as two hemisphere lights, one straight up one straight down
|
|
||||||
float hemiDiffuseUp = N.z * 0.5 + 0.5;
|
|
||||||
float hemiDiffuseDown = 1.0 - hemiDiffuseUp;
|
|
||||||
float hemiSpecularUp = mix(hemiDiffuseUp, float(N.z >= 0.0), gloss);
|
|
||||||
float hemiSpecularDown = 1.0 - hemiSpecularUp;
|
|
||||||
|
|
||||||
gl_FragColor.rgb += ambientColor * 0.75 * (diffuse.rgb * hemiDiffuseUp + aSpecular * hemiSpecularUp);
|
|
||||||
gl_FragColor.rgb += ambientColor * 0.25 * (diffuse.rgb * hemiDiffuseDown + aSpecular * hemiSpecularDown);
|
|
||||||
#else
|
|
||||||
gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_CUBEMAP)
|
#if defined(USE_CUBEMAP)
|
||||||
reflectance = EnvironmentBRDF(gloss, NE, specular.rgb);
|
reflectance = EnvironmentBRDF(roughness, NE, specular.rgb);
|
||||||
|
|
||||||
vec3 R = reflect(E, N);
|
vec3 R = reflect(E, N);
|
||||||
|
|
||||||
|
@ -531,15 +359,15 @@ void main()
|
||||||
// from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
// from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||||
vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
|
vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir;
|
||||||
|
|
||||||
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w;
|
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 * roughness).rgb * u_EnableTextures.w;
|
||||||
|
|
||||||
// normalize cubemap based on lowest mip (~diffuse)
|
// normalize cubemap based on lowest mip (~diffuse)
|
||||||
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
|
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
|
||||||
//vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, 6.0).rgb, 0.5 / 255.0);
|
//vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, 6.0).rgb, 0.5 / 255.0);
|
||||||
//cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
|
//cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721));
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
cubeLightColor = pow(cubeLightColor, vec3(r_framebufferGamma));
|
cubeLightColor *= cubeLightColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// multiply cubemap values by lighting
|
// multiply cubemap values by lighting
|
||||||
|
@ -549,7 +377,7 @@ void main()
|
||||||
gl_FragColor.rgb += cubeLightColor * reflectance;
|
gl_FragColor.rgb += cubeLightColor * reflectance;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT)
|
#if defined(USE_PRIMARY_LIGHT) || defined(SHADOWMAP_MODULATE)
|
||||||
vec3 L2, H2;
|
vec3 L2, H2;
|
||||||
float NL2, EH2, NH2;
|
float NL2, EH2, NH2;
|
||||||
|
|
||||||
|
@ -560,20 +388,19 @@ void main()
|
||||||
//L2 /= sqrt(sqrLightDist);
|
//L2 /= sqrt(sqrLightDist);
|
||||||
|
|
||||||
NL2 = clamp(dot(N, L2), 0.0, 1.0);
|
NL2 = clamp(dot(N, L2), 0.0, 1.0);
|
||||||
|
|
||||||
H2 = normalize(L2 + E);
|
H2 = normalize(L2 + E);
|
||||||
EH2 = clamp(dot(E, H2), 0.0, 1.0);
|
EH2 = clamp(dot(E, H2), 0.0, 1.0);
|
||||||
NH2 = clamp(dot(N, H2), 0.0, 1.0);
|
NH2 = clamp(dot(N, H2), 0.0, 1.0);
|
||||||
|
|
||||||
reflectance = CalcDiffuse(diffuse.rgb, N, L2, E, NE, NL2, shininess);
|
reflectance = CalcSpecular(specular.rgb, NH2, EH2, roughness);
|
||||||
reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, gloss, shininess);
|
|
||||||
|
|
||||||
lightColor = u_PrimaryLightColor * var_Color.rgb;
|
// bit of a hack, with modulated shadowmaps, ignore diffuse
|
||||||
|
#if !defined(SHADOWMAP_MODULATE)
|
||||||
#if defined(r_lightGamma)
|
reflectance += CalcDiffuse(diffuse.rgb, NH2, EH2, roughness);
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
lightColor = u_PrimaryLightColor;
|
||||||
|
|
||||||
#if defined(USE_SHADOWMAP)
|
#if defined(USE_SHADOWMAP)
|
||||||
lightColor *= shadowValue;
|
lightColor *= shadowValue;
|
||||||
#endif
|
#endif
|
||||||
|
@ -583,28 +410,16 @@ void main()
|
||||||
|
|
||||||
gl_FragColor.rgb += lightColor * reflectance * NL2;
|
gl_FragColor.rgb += lightColor * reflectance * NL2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_PBR)
|
||||||
|
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
lightColor = var_Color.rgb;
|
|
||||||
|
|
||||||
#if defined(USE_LIGHTMAP)
|
|
||||||
lightColor *= lightmapColor.rgb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(r_lightGamma)
|
|
||||||
lightColor = pow(lightColor, vec3(r_lightGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(r_materialGamma)
|
|
||||||
diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor.rgb = diffuse.rgb * lightColor;
|
gl_FragColor.rgb = diffuse.rgb * lightColor;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
|
||||||
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / r_framebufferGamma));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor.a = diffuse.a * var_Color.a;
|
gl_FragColor.a = diffuse.a * var_Color.a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,8 @@ uniform float u_VertexLerp;
|
||||||
#if defined(USE_LIGHT_VECTOR)
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
uniform vec4 u_LightOrigin;
|
uniform vec4 u_LightOrigin;
|
||||||
uniform float u_LightRadius;
|
uniform float u_LightRadius;
|
||||||
#if defined(USE_FAST_LIGHT)
|
|
||||||
uniform vec3 u_DirectedLight;
|
uniform vec3 u_DirectedLight;
|
||||||
uniform vec3 u_AmbientLight;
|
uniform vec3 u_AmbientLight;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
|
@ -71,6 +69,9 @@ uniform float u_PrimaryLightRadius;
|
||||||
varying vec4 var_TexCoords;
|
varying vec4 var_TexCoords;
|
||||||
|
|
||||||
varying vec4 var_Color;
|
varying vec4 var_Color;
|
||||||
|
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
|
||||||
|
varying vec4 var_ColorAmbient;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
|
||||||
#if defined(USE_VERT_TANGENT_SPACE)
|
#if defined(USE_VERT_TANGENT_SPACE)
|
||||||
|
@ -208,12 +209,24 @@ void main()
|
||||||
|
|
||||||
var_Color = u_VertColor * attr_Color + u_BaseColor;
|
var_Color = u_VertColor * attr_Color + u_BaseColor;
|
||||||
|
|
||||||
#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
|
#if defined(USE_LIGHT_VECTOR)
|
||||||
|
#if defined(USE_FAST_LIGHT)
|
||||||
float sqrLightDist = dot(L, L);
|
float sqrLightDist = dot(L, L);
|
||||||
float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist);
|
|
||||||
float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0);
|
float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0);
|
||||||
|
float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist);
|
||||||
|
|
||||||
var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight;
|
var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight;
|
||||||
|
#else
|
||||||
|
var_ColorAmbient.rgb = u_AmbientLight * var_Color.rgb;
|
||||||
|
var_Color.rgb *= u_DirectedLight;
|
||||||
|
#if defined(USE_PBR)
|
||||||
|
var_ColorAmbient.rgb *= var_ColorAmbient.rgb;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) && defined(USE_PBR)
|
||||||
|
var_Color.rgb *= var_Color.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
|
||||||
|
|
|
@ -28,8 +28,8 @@ void main()
|
||||||
{
|
{
|
||||||
vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
|
vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
|
||||||
|
|
||||||
#if defined(r_framebufferGamma)
|
#if defined(USE_PBR)
|
||||||
color.rgb = pow(color.rgb, vec3(r_framebufferGamma));
|
color.rgb *= color.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
|
vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
|
||||||
|
@ -46,9 +46,12 @@ void main()
|
||||||
|
|
||||||
color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0);
|
color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0);
|
||||||
|
|
||||||
#if defined(r_tonemapGamma)
|
#if defined(USE_PBR)
|
||||||
color.rgb = pow(color.rgb, vec3(1.0 / r_tonemapGamma));
|
color.rgb = sqrt(color.rgb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// add a bit of dither to reduce banding
|
||||||
|
color.rgb += vec3(1.0/510.0 * mod(gl_FragCoord.x + gl_FragCoord.y, 2.0) - 1.0/1020.0);
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
#include "tr_fbo.h"
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
backEndData_t *backEndData;
|
backEndData_t *backEndData;
|
||||||
backEndState_t backEnd;
|
backEndState_t backEnd;
|
||||||
|
@ -35,81 +37,28 @@ static float s_flipMatrix[16] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** GL_Bind
|
|
||||||
*/
|
|
||||||
void GL_Bind( image_t *image ) {
|
|
||||||
int texnum;
|
|
||||||
|
|
||||||
if ( !image ) {
|
|
||||||
ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
|
|
||||||
texnum = tr.defaultImage->texnum;
|
|
||||||
} else {
|
|
||||||
texnum = image->texnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
|
|
||||||
texnum = tr.dlightImage->texnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( glState.currenttextures[glState.currenttmu] != texnum ) {
|
|
||||||
if ( image ) {
|
|
||||||
image->frameUsed = tr.frameCount;
|
|
||||||
}
|
|
||||||
glState.currenttextures[glState.currenttmu] = texnum;
|
|
||||||
if (image && image->flags & IMGFLAG_CUBEMAP)
|
|
||||||
qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum );
|
|
||||||
else
|
|
||||||
qglBindTexture( GL_TEXTURE_2D, texnum );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** GL_SelectTexture
|
|
||||||
*/
|
|
||||||
void GL_SelectTexture( int unit )
|
|
||||||
{
|
|
||||||
if ( glState.currenttmu == unit )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(unit >= 0 && unit <= 31))
|
|
||||||
ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
|
|
||||||
|
|
||||||
if (!qglActiveTextureARB)
|
|
||||||
ri.Error( ERR_DROP, "GL_SelectTexture: multitexture disabled" );
|
|
||||||
|
|
||||||
qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
|
|
||||||
|
|
||||||
glState.currenttmu = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** GL_BindToTMU
|
** GL_BindToTMU
|
||||||
*/
|
*/
|
||||||
void GL_BindToTMU( image_t *image, int tmu )
|
void GL_BindToTMU( image_t *image, int tmu )
|
||||||
{
|
{
|
||||||
int texnum;
|
GLuint texture = (tmu == TB_COLORMAP) ? tr.defaultImage->texnum : 0;
|
||||||
int oldtmu = glState.currenttmu;
|
GLenum target = GL_TEXTURE_2D;
|
||||||
|
|
||||||
if (!image)
|
if (image)
|
||||||
texnum = 0;
|
{
|
||||||
else
|
if (image->flags & IMGFLAG_CUBEMAP)
|
||||||
texnum = image->texnum;
|
target = GL_TEXTURE_CUBE_MAP;
|
||||||
|
|
||||||
if ( glState.currenttextures[tmu] != texnum ) {
|
image->frameUsed = tr.frameCount;
|
||||||
GL_SelectTexture( tmu );
|
texture = image->texnum;
|
||||||
if (image)
|
|
||||||
image->frameUsed = tr.frameCount;
|
|
||||||
glState.currenttextures[tmu] = texnum;
|
|
||||||
|
|
||||||
if (image && (image->flags & IMGFLAG_CUBEMAP))
|
|
||||||
qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum );
|
|
||||||
else
|
|
||||||
qglBindTexture( GL_TEXTURE_2D, texnum );
|
|
||||||
GL_SelectTexture( oldtmu );
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "GL_BindToTMU: NULL image\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_BindMultiTexture(GL_TEXTURE0_ARB + tmu, target, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,39 +90,6 @@ void GL_Cull( int cullType ) {
|
||||||
glState.faceCulling = cullType;
|
glState.faceCulling = cullType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** GL_TexEnv
|
|
||||||
*/
|
|
||||||
void GL_TexEnv( int env )
|
|
||||||
{
|
|
||||||
if ( env == glState.texEnv[glState.currenttmu] )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glState.texEnv[glState.currenttmu] = env;
|
|
||||||
|
|
||||||
|
|
||||||
switch ( env )
|
|
||||||
{
|
|
||||||
case GL_MODULATE:
|
|
||||||
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
|
||||||
break;
|
|
||||||
case GL_REPLACE:
|
|
||||||
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
|
||||||
break;
|
|
||||||
case GL_DECAL:
|
|
||||||
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
|
|
||||||
break;
|
|
||||||
case GL_ADD:
|
|
||||||
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** GL_State
|
** GL_State
|
||||||
**
|
**
|
||||||
|
@ -462,30 +378,20 @@ void RB_BeginDrawingView (void) {
|
||||||
|
|
||||||
if (glRefConfig.framebufferObject)
|
if (glRefConfig.framebufferObject)
|
||||||
{
|
{
|
||||||
|
FBO_t *fbo = backEnd.viewParms.targetFbo;
|
||||||
|
|
||||||
// FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world
|
// FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world
|
||||||
// drawing more world check is in case of double renders, such as skyportals
|
// drawing more world check is in case of double renders, such as skyportals
|
||||||
if (backEnd.viewParms.targetFbo == NULL)
|
if (fbo == NULL && !(backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
|
||||||
{
|
fbo = tr.renderFbo;
|
||||||
if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
|
|
||||||
{
|
|
||||||
FBO_Bind(NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FBO_Bind(tr.renderFbo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FBO_Bind(backEnd.viewParms.targetFbo);
|
|
||||||
|
|
||||||
// FIXME: hack for cubemap testing
|
if (tr.renderCubeFbo && fbo == tr.renderCubeFbo)
|
||||||
if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
|
{
|
||||||
{
|
cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex];
|
||||||
//qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0);
|
FBO_AttachImage(fbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, backEnd.viewParms.targetFboLayer);
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]->texnum, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FBO_Bind(fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -549,8 +455,6 @@ void RB_BeginDrawingView (void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MAC_EVENT_PUMP_MSEC 5
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
RB_RenderDrawSurfList
|
RB_RenderDrawSurfList
|
||||||
|
@ -856,6 +760,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
||||||
}
|
}
|
||||||
|
|
||||||
RE_UploadCinematic (w, h, cols, rows, data, client, dirty);
|
RE_UploadCinematic (w, h, cols, rows, data, client, dirty);
|
||||||
|
GL_BindToTMU(tr.scratchImage[client], TB_COLORMAP);
|
||||||
|
|
||||||
if ( r_speeds->integer ) {
|
if ( r_speeds->integer ) {
|
||||||
end = ri.Milliseconds();
|
end = ri.Milliseconds();
|
||||||
|
@ -865,14 +770,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
||||||
// FIXME: HUGE hack
|
// FIXME: HUGE hack
|
||||||
if (glRefConfig.framebufferObject)
|
if (glRefConfig.framebufferObject)
|
||||||
{
|
{
|
||||||
if (!tr.renderFbo || backEnd.framePostProcessed)
|
FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo);
|
||||||
{
|
|
||||||
FBO_Bind(NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FBO_Bind(tr.renderFbo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RB_SetGL2D();
|
RB_SetGL2D();
|
||||||
|
@ -896,23 +794,30 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
||||||
}
|
}
|
||||||
|
|
||||||
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
|
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
|
||||||
|
GLuint texture;
|
||||||
|
|
||||||
GL_Bind( tr.scratchImage[client] );
|
if (!tr.scratchImage[client])
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "RE_UploadCinematic: scratch images not initialized\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = tr.scratchImage[client]->texnum;
|
||||||
|
|
||||||
// if the scratchImage isn't in the format we want, specify it as a new texture
|
// if the scratchImage isn't in the format we want, specify it as a new texture
|
||||||
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
|
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
|
||||||
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
|
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
|
||||||
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
|
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
|
||||||
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
qglTextureImage2D(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
|
qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
|
qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
} else {
|
} else {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
||||||
// it and don't try and do a texture compression
|
// it and don't try and do a texture compression
|
||||||
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -951,16 +856,7 @@ const void *RB_StretchPic ( const void *data ) {
|
||||||
|
|
||||||
// FIXME: HUGE hack
|
// FIXME: HUGE hack
|
||||||
if (glRefConfig.framebufferObject)
|
if (glRefConfig.framebufferObject)
|
||||||
{
|
FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo);
|
||||||
if (!tr.renderFbo || backEnd.framePostProcessed)
|
|
||||||
{
|
|
||||||
FBO_Bind(NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FBO_Bind(tr.renderFbo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_SetGL2D();
|
RB_SetGL2D();
|
||||||
|
|
||||||
|
@ -1072,11 +968,10 @@ const void *RB_DrawSurfs( const void *data ) {
|
||||||
// If we're using multisampling, resolve the depth first
|
// If we're using multisampling, resolve the depth first
|
||||||
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
}
|
}
|
||||||
else if (tr.renderFbo == NULL)
|
else if (tr.renderFbo == NULL && tr.renderDepthImage)
|
||||||
{
|
{
|
||||||
// If we're rendering directly to the screen, copy the depth to a texture
|
// If we're rendering directly to the screen, copy the depth to a texture
|
||||||
GL_BindToTMU(tr.renderDepthImage, 0);
|
qglCopyTextureImage2D(tr.renderDepthImage->texnum, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0);
|
||||||
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_ssao->integer)
|
if (r_ssao->integer)
|
||||||
|
@ -1313,11 +1208,11 @@ const void *RB_DrawSurfs( const void *data ) {
|
||||||
|
|
||||||
if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
|
if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
|
||||||
{
|
{
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex];
|
||||||
|
|
||||||
FBO_Bind(NULL);
|
FBO_Bind(NULL);
|
||||||
GL_SelectTexture(TB_CUBEMAP);
|
if (cubemap && cubemap->image)
|
||||||
GL_BindToTMU(tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex], TB_CUBEMAP);
|
qglGenerateTextureMipmap(cubemap->image->texnum, GL_TEXTURE_CUBE_MAP);
|
||||||
qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
|
|
||||||
GL_SelectTexture(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (const void *)(cmd + 1);
|
return (const void *)(cmd + 1);
|
||||||
|
@ -1394,7 +1289,7 @@ void RB_ShowImages( void ) {
|
||||||
{
|
{
|
||||||
vec4_t quadVerts[4];
|
vec4_t quadVerts[4];
|
||||||
|
|
||||||
GL_Bind(image);
|
GL_BindToTMU(image, TB_COLORMAP);
|
||||||
|
|
||||||
VectorSet4(quadVerts[0], x, y, 0, 1);
|
VectorSet4(quadVerts[0], x, y, 0, 1);
|
||||||
VectorSet4(quadVerts[1], x + w, y, 0, 1);
|
VectorSet4(quadVerts[1], x + w, y, 0, 1);
|
||||||
|
@ -1570,21 +1465,18 @@ const void *RB_CapShadowMap(const void *data)
|
||||||
|
|
||||||
if (cmd->map != -1)
|
if (cmd->map != -1)
|
||||||
{
|
{
|
||||||
GL_SelectTexture(0);
|
|
||||||
if (cmd->cubeSide != -1)
|
if (cmd->cubeSide != -1)
|
||||||
{
|
{
|
||||||
if (tr.shadowCubemaps[cmd->map])
|
if (tr.shadowCubemaps[cmd->map])
|
||||||
{
|
{
|
||||||
GL_Bind(tr.shadowCubemaps[cmd->map]);
|
qglCopyTextureImage2D(tr.shadowCubemaps[cmd->map]->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
|
||||||
qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tr.pshadowMaps[cmd->map])
|
if (tr.pshadowMaps[cmd->map])
|
||||||
{
|
{
|
||||||
GL_Bind(tr.pshadowMaps[cmd->map]);
|
qglCopyTextureImage2D(tr.pshadowMaps[cmd->map]->texnum, GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - (backEnd.refdef.y + PSHADOW_MAP_SIZE), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
|
||||||
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1657,7 +1549,7 @@ const void *RB_PostProcess(const void *data)
|
||||||
|
|
||||||
if (srcFbo)
|
if (srcFbo)
|
||||||
{
|
{
|
||||||
if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer) && qglActiveTextureARB)
|
if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer))
|
||||||
{
|
{
|
||||||
autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer;
|
autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer;
|
||||||
RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure);
|
RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure);
|
||||||
|
@ -1726,7 +1618,7 @@ const void *RB_PostProcess(const void *data)
|
||||||
{
|
{
|
||||||
VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256);
|
VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256);
|
||||||
//FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
|
//FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
|
||||||
FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1], NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
|
FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1736,6 +1628,74 @@ const void *RB_PostProcess(const void *data)
|
||||||
return (const void *)(cmd + 1);
|
return (const void *)(cmd + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: put this function declaration elsewhere
|
||||||
|
void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
RB_ExportCubemaps
|
||||||
|
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
const void *RB_ExportCubemaps(const void *data)
|
||||||
|
{
|
||||||
|
const exportCubemapsCommand_t *cmd = data;
|
||||||
|
|
||||||
|
// finish any 2D drawing if needed
|
||||||
|
if (tess.numIndexes)
|
||||||
|
RB_EndSurface();
|
||||||
|
|
||||||
|
if (!glRefConfig.framebufferObject || !tr.world || tr.numCubemaps == 0)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
ri.Printf(PRINT_ALL, "Nothing to export!\n");
|
||||||
|
return (const void *)(cmd + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
FBO_t *oldFbo = glState.currentFBO;
|
||||||
|
int sideSize = r_cubemapSize->integer * r_cubemapSize->integer * 4;
|
||||||
|
byte *cubemapPixels = ri.Malloc(sideSize * 6);
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
FBO_Bind(tr.renderCubeFbo);
|
||||||
|
|
||||||
|
for (i = 0; i < tr.numCubemaps; i++)
|
||||||
|
{
|
||||||
|
char filename[MAX_QPATH];
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[i];
|
||||||
|
byte *p = cubemapPixels;
|
||||||
|
|
||||||
|
for (j = 0; j < 6; j++)
|
||||||
|
{
|
||||||
|
FBO_AttachImage(tr.renderCubeFbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, j);
|
||||||
|
qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p);
|
||||||
|
p += sideSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cubemap->name[0])
|
||||||
|
{
|
||||||
|
COM_StripExtension(cubemap->name, filename, MAX_QPATH);
|
||||||
|
Q_strcat(filename, MAX_QPATH, ".dds");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6);
|
||||||
|
ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
FBO_Bind(oldFbo);
|
||||||
|
|
||||||
|
ri.Free(cubemapPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (const void *)(cmd + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
|
@ -1784,6 +1744,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
|
||||||
case RC_POSTPROCESS:
|
case RC_POSTPROCESS:
|
||||||
data = RB_PostProcess(data);
|
data = RB_PostProcess(data);
|
||||||
break;
|
break;
|
||||||
|
case RC_EXPORT_CUBEMAPS:
|
||||||
|
data = RB_ExportCubemaps(data);
|
||||||
|
break;
|
||||||
case RC_END_OF_LIST:
|
case RC_END_OF_LIST:
|
||||||
default:
|
default:
|
||||||
// finish any 2D drawing if needed
|
// finish any 2D drawing if needed
|
||||||
|
|
|
@ -23,6 +23,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#define JSON_IMPLEMENTATION
|
||||||
|
#include "../qcommon/json.h"
|
||||||
|
#undef JSON_IMPLEMENTATION
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Loads and prepares a map file for scene rendering.
|
Loads and prepares a map file for scene rendering.
|
||||||
|
@ -101,7 +105,11 @@ static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) {
|
||||||
int shift, r, g, b;
|
int shift, r, g, b;
|
||||||
|
|
||||||
// shift the color data based on overbright range
|
// shift the color data based on overbright range
|
||||||
|
#if defined(USE_OVERBRIGHT)
|
||||||
shift = r_mapOverBrightBits->integer - tr.overbrightBits;
|
shift = r_mapOverBrightBits->integer - tr.overbrightBits;
|
||||||
|
#else
|
||||||
|
shift = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// shift the data based on overbright range
|
// shift the data based on overbright range
|
||||||
r = in[0] << shift;
|
r = in[0] << shift;
|
||||||
|
@ -136,7 +144,9 @@ static void R_ColorShiftLightingFloats(float in[4], float out[4], float scale )
|
||||||
{
|
{
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
|
|
||||||
scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits);
|
#if defined(USE_OVERBRIGHT)
|
||||||
|
scale *= 1 << (r_mapOverBrightBits->integer - tr.overbrightBits);
|
||||||
|
#endif
|
||||||
|
|
||||||
r = in[0] * scale;
|
r = in[0] * scale;
|
||||||
g = in[1] * scale;
|
g = in[1] * scale;
|
||||||
|
@ -2755,7 +2765,11 @@ void R_LoadLightGrid( lump_t *l ) {
|
||||||
|
|
||||||
if (hdrLightGrid)
|
if (hdrLightGrid)
|
||||||
{
|
{
|
||||||
float lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits);
|
#if defined(USE_OVERBRIGHT)
|
||||||
|
float lightScale = 1 << (r_mapOverBrightBits->integer - tr.overbrightBits);
|
||||||
|
#else
|
||||||
|
float lightScale = 1.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
//ri.Printf(PRINT_ALL, "found!\n");
|
//ri.Printf(PRINT_ALL, "found!\n");
|
||||||
|
|
||||||
|
@ -2962,6 +2976,78 @@ qboolean R_ParseSpawnVars( char *spawnVarChars, int maxSpawnVarChars, int *numSp
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R_LoadEnvironmentJson(const char *baseName)
|
||||||
|
{
|
||||||
|
char filename[MAX_QPATH];
|
||||||
|
|
||||||
|
union {
|
||||||
|
char *c;
|
||||||
|
void *v;
|
||||||
|
} buffer;
|
||||||
|
char *bufferEnd;
|
||||||
|
|
||||||
|
const char *cubemapArrayJson;
|
||||||
|
int filelen, i;
|
||||||
|
|
||||||
|
Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/env.json", baseName);
|
||||||
|
|
||||||
|
filelen = ri.FS_ReadFile(filename, &buffer.v);
|
||||||
|
if (!buffer.c)
|
||||||
|
return;
|
||||||
|
bufferEnd = buffer.c + filelen;
|
||||||
|
|
||||||
|
if (JSON_ValueGetType(buffer.c, bufferEnd) != JSONTYPE_OBJECT)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "Bad %s: does not start with a object\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cubemapArrayJson = JSON_ObjectGetNamedValue(buffer.c, bufferEnd, "Cubemaps");
|
||||||
|
if (!cubemapArrayJson)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "Bad %s: no Cubemaps\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSON_ValueGetType(cubemapArrayJson, bufferEnd) != JSONTYPE_ARRAY)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "Bad %s: Cubemaps not an array\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.numCubemaps = JSON_ArrayGetIndex(cubemapArrayJson, bufferEnd, NULL, 0);
|
||||||
|
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
|
||||||
|
memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps));
|
||||||
|
|
||||||
|
for (i = 0; i < tr.numCubemaps; i++)
|
||||||
|
{
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[i];
|
||||||
|
const char *cubemapJson, *keyValueJson, *indexes[3];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
cubemapJson = JSON_ArrayGetValue(cubemapArrayJson, bufferEnd, i);
|
||||||
|
|
||||||
|
keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Name");
|
||||||
|
if (!JSON_ValueGetString(keyValueJson, bufferEnd, cubemap->name, MAX_QPATH))
|
||||||
|
cubemap->name[0] = '\0';
|
||||||
|
|
||||||
|
keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Position");
|
||||||
|
JSON_ArrayGetIndex(keyValueJson, bufferEnd, indexes, 3);
|
||||||
|
for (j = 0; j < 3; j++)
|
||||||
|
cubemap->origin[j] = JSON_ValueGetFloat(indexes[j], bufferEnd);
|
||||||
|
|
||||||
|
cubemap->parallaxRadius = 1000.0f;
|
||||||
|
keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Radius");
|
||||||
|
if (keyValueJson)
|
||||||
|
cubemap->parallaxRadius = JSON_ValueGetFloat(keyValueJson, bufferEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
}
|
||||||
|
|
||||||
void R_LoadCubemapEntities(char *cubemapEntityName)
|
void R_LoadCubemapEntities(char *cubemapEntityName)
|
||||||
{
|
{
|
||||||
char spawnVarChars[2048];
|
char spawnVarChars[2048];
|
||||||
|
@ -2986,33 +3072,45 @@ void R_LoadCubemapEntities(char *cubemapEntityName)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tr.numCubemaps = numCubemaps;
|
tr.numCubemaps = numCubemaps;
|
||||||
tr.cubemapOrigins = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemapOrigins), h_low);
|
tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
|
||||||
tr.cubemaps = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemaps), h_low);
|
memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps));
|
||||||
|
|
||||||
numCubemaps = 0;
|
numCubemaps = 0;
|
||||||
while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars))
|
while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
char name[MAX_QPATH];
|
||||||
qboolean isCubemap = qfalse;
|
qboolean isCubemap = qfalse;
|
||||||
qboolean positionSet = qfalse;
|
qboolean originSet = qfalse;
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
|
float parallaxRadius = 1000.0f;
|
||||||
|
|
||||||
|
name[0] = '\0';
|
||||||
for (i = 0; i < numSpawnVars; i++)
|
for (i = 0; i < numSpawnVars; i++)
|
||||||
{
|
{
|
||||||
if (!Q_stricmp(spawnVars[i][0], "classname") && !Q_stricmp(spawnVars[i][1], cubemapEntityName))
|
if (!Q_stricmp(spawnVars[i][0], "classname") && !Q_stricmp(spawnVars[i][1], cubemapEntityName))
|
||||||
isCubemap = qtrue;
|
isCubemap = qtrue;
|
||||||
|
|
||||||
|
if (!Q_stricmp(spawnVars[i][0], "name"))
|
||||||
|
Q_strncpyz(name, spawnVars[i][1], MAX_QPATH);
|
||||||
|
|
||||||
if (!Q_stricmp(spawnVars[i][0], "origin"))
|
if (!Q_stricmp(spawnVars[i][0], "origin"))
|
||||||
{
|
{
|
||||||
sscanf(spawnVars[i][1], "%f %f %f", &origin[0], &origin[1], &origin[2]);
|
sscanf(spawnVars[i][1], "%f %f %f", &origin[0], &origin[1], &origin[2]);
|
||||||
positionSet = qtrue;
|
originSet = qtrue;
|
||||||
|
}
|
||||||
|
else if (!Q_stricmp(spawnVars[i][0], "radius"))
|
||||||
|
{
|
||||||
|
sscanf(spawnVars[i][1], "%f", ¶llaxRadius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCubemap && positionSet)
|
if (isCubemap && originSet)
|
||||||
{
|
{
|
||||||
//ri.Printf(PRINT_ALL, "cubemap at %f %f %f\n", origin[0], origin[1], origin[2]);
|
cubemap_t *cubemap = &tr.cubemaps[numCubemaps];
|
||||||
VectorCopy(origin, tr.cubemapOrigins[numCubemaps]);
|
Q_strncpyz(cubemap->name, name, MAX_QPATH);
|
||||||
|
VectorCopy(origin, cubemap->origin);
|
||||||
|
cubemap->parallaxRadius = parallaxRadius;
|
||||||
numCubemaps++;
|
numCubemaps++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3052,23 +3150,41 @@ void R_AssignCubemapsToWorldSurfaces(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void R_RenderAllCubemaps(void)
|
void R_LoadCubemaps(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
|
imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
|
||||||
|
|
||||||
for (i = 0; i < tr.numCubemaps; i++)
|
for (i = 0; i < tr.numCubemaps; i++)
|
||||||
{
|
{
|
||||||
tr.cubemaps[i] = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8);
|
char filename[MAX_QPATH];
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[i];
|
||||||
|
|
||||||
|
Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i);
|
||||||
|
|
||||||
|
cubemap->image = R_FindImageFile(filename, IMGTYPE_COLORALPHA, flags);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void R_RenderMissingCubemaps(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
imgFlags_t flags = IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
|
||||||
|
|
||||||
for (i = 0; i < tr.numCubemaps; i++)
|
for (i = 0; i < tr.numCubemaps; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < 6; j++)
|
if (!tr.cubemaps[i].image)
|
||||||
{
|
{
|
||||||
RE_ClearScene();
|
tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, flags, GL_RGBA8);
|
||||||
R_RenderCubemapSide(i, j, qfalse);
|
|
||||||
R_IssuePendingRenderCommands();
|
for (j = 0; j < 6; j++)
|
||||||
R_InitNextFrame();
|
{
|
||||||
|
RE_ClearScene();
|
||||||
|
R_RenderCubemapSide(i, j, qfalse);
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
R_InitNextFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3385,7 +3501,14 @@ void RE_LoadWorldMap( const char *name ) {
|
||||||
// load cubemaps
|
// load cubemaps
|
||||||
if (r_cubeMapping->integer)
|
if (r_cubeMapping->integer)
|
||||||
{
|
{
|
||||||
R_LoadCubemapEntities("misc_cubemap");
|
// Try loading an env.json file first
|
||||||
|
R_LoadEnvironmentJson(s_worldData.baseName);
|
||||||
|
|
||||||
|
if (!tr.numCubemaps)
|
||||||
|
{
|
||||||
|
R_LoadCubemapEntities("misc_cubemap");
|
||||||
|
}
|
||||||
|
|
||||||
if (!tr.numCubemaps)
|
if (!tr.numCubemaps)
|
||||||
{
|
{
|
||||||
// use deathmatch spawn points as cubemaps
|
// use deathmatch spawn points as cubemaps
|
||||||
|
@ -3409,10 +3532,11 @@ void RE_LoadWorldMap( const char *name ) {
|
||||||
// make sure the VAO glState entry is safe
|
// make sure the VAO glState entry is safe
|
||||||
R_BindNullVao();
|
R_BindNullVao();
|
||||||
|
|
||||||
// Render all cubemaps
|
// Render or load all cubemaps
|
||||||
if (r_cubeMapping->integer && tr.numCubemaps)
|
if (r_cubeMapping->integer && tr.numCubemaps)
|
||||||
{
|
{
|
||||||
R_RenderAllCubemaps();
|
R_LoadCubemaps();
|
||||||
|
R_RenderMissingCubemaps();
|
||||||
}
|
}
|
||||||
|
|
||||||
ri.FS_FreeFile( buffer.v );
|
ri.FS_FreeFile( buffer.v );
|
||||||
|
|
|
@ -121,20 +121,20 @@ void R_IssuePendingRenderCommands( void ) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
R_GetCommandBuffer
|
R_GetCommandBufferReserved
|
||||||
|
|
||||||
make sure there is enough command space
|
make sure there is enough command space
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void *R_GetCommandBuffer( int bytes ) {
|
void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) {
|
||||||
renderCommandList_t *cmdList;
|
renderCommandList_t *cmdList;
|
||||||
|
|
||||||
cmdList = &backEndData->commands;
|
cmdList = &backEndData->commands;
|
||||||
bytes = PAD(bytes, sizeof(void *));
|
bytes = PAD(bytes, sizeof(void *));
|
||||||
|
|
||||||
// always leave room for the end of list command
|
// always leave room for the end of list command
|
||||||
if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
|
if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) {
|
||||||
if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
|
if ( bytes > MAX_RENDER_COMMANDS - sizeof( int ) ) {
|
||||||
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
|
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
|
||||||
}
|
}
|
||||||
// if we run out of room, just start dropping commands
|
// if we run out of room, just start dropping commands
|
||||||
|
@ -146,6 +146,17 @@ void *R_GetCommandBuffer( int bytes ) {
|
||||||
return cmdList->cmds + cmdList->used - bytes;
|
return cmdList->cmds + cmdList->used - bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_GetCommandBuffer
|
||||||
|
|
||||||
|
returns NULL if there is not enough space for important commands
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void *R_GetCommandBuffer( int bytes ) {
|
||||||
|
return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
|
@ -525,7 +536,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
|
||||||
if ( !tr.registered ) {
|
if ( !tr.registered ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmd = R_GetCommandBuffer( sizeof( *cmd ) );
|
cmd = R_GetCommandBufferReserved( sizeof( *cmd ), 0 );
|
||||||
if ( !cmd ) {
|
if ( !cmd ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
287
code/renderergl2/tr_dsa.c
Normal file
287
code/renderergl2/tr_dsa.c
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2016 James Canete
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
GLuint textures[NUM_TEXTURE_BUNDLES];
|
||||||
|
GLenum texunit;
|
||||||
|
|
||||||
|
GLuint program;
|
||||||
|
|
||||||
|
GLuint drawFramebuffer;
|
||||||
|
GLuint readFramebuffer;
|
||||||
|
GLuint renderbuffer;
|
||||||
|
}
|
||||||
|
glDsaState;
|
||||||
|
|
||||||
|
void GL_BindNullTextures()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (glRefConfig.directStateAccess)
|
||||||
|
{
|
||||||
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
|
{
|
||||||
|
qglBindMultiTexture(GL_TEXTURE0_ARB + i, GL_TEXTURE_2D, 0);
|
||||||
|
glDsaState.textures[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
|
||||||
|
{
|
||||||
|
qglActiveTextureARB(GL_TEXTURE0_ARB + i);
|
||||||
|
qglBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glDsaState.textures[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglActiveTextureARB(GL_TEXTURE0_ARB);
|
||||||
|
glDsaState.texunit = GL_TEXTURE0_ARB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
GLuint tmu = texunit - GL_TEXTURE0_ARB;
|
||||||
|
|
||||||
|
if (glDsaState.textures[tmu] == texture)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
|
||||||
|
target = GL_TEXTURE_CUBE_MAP;
|
||||||
|
|
||||||
|
qglBindMultiTexture(texunit, target, texture);
|
||||||
|
glDsaState.textures[tmu] = texture;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture)
|
||||||
|
{
|
||||||
|
if (glDsaState.texunit != texunit)
|
||||||
|
{
|
||||||
|
qglActiveTextureARB(texunit);
|
||||||
|
glDsaState.texunit = texunit;
|
||||||
|
}
|
||||||
|
|
||||||
|
qglBindTexture(target, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexParameterf(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexParameteri(target, pname, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target)
|
||||||
|
{
|
||||||
|
GL_BindMultiTexture(glDsaState.texunit, target, texture);
|
||||||
|
qglGenerateMipmapEXT(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindNullProgram()
|
||||||
|
{
|
||||||
|
qglUseProgramObjectARB(0);
|
||||||
|
glDsaState.program = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_UseProgramObject(GLuint program)
|
||||||
|
{
|
||||||
|
if (glDsaState.program == program)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
qglUseProgramObjectARB(program);
|
||||||
|
glDsaState.program = program;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint v0)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform1iARB(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform1fARB(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform2fARB(location, v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform3fARB(location, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform4fARB(location, v0, v1, v2, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniform1fvARB(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value)
|
||||||
|
{
|
||||||
|
GL_UseProgramObject(program);
|
||||||
|
qglUniformMatrix4fvARB(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindNullFramebuffers()
|
||||||
|
{
|
||||||
|
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0;
|
||||||
|
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
glDsaState.renderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindFramebuffer(GLenum target, GLuint framebuffer)
|
||||||
|
{
|
||||||
|
switch (target)
|
||||||
|
{
|
||||||
|
case GL_FRAMEBUFFER_EXT:
|
||||||
|
if (framebuffer != glDsaState.drawFramebuffer || framebuffer != glDsaState.readFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebufferEXT(target, framebuffer);
|
||||||
|
glDsaState.drawFramebuffer = glDsaState.readFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_DRAW_FRAMEBUFFER_EXT:
|
||||||
|
if (framebuffer != glDsaState.drawFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebufferEXT(target, framebuffer);
|
||||||
|
glDsaState.drawFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_READ_FRAMEBUFFER_EXT:
|
||||||
|
if (framebuffer != glDsaState.readFramebuffer)
|
||||||
|
{
|
||||||
|
qglBindFramebufferEXT(target, framebuffer);
|
||||||
|
glDsaState.readFramebuffer = framebuffer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_BindRenderbuffer(GLuint renderbuffer)
|
||||||
|
{
|
||||||
|
if (renderbuffer != glDsaState.renderbuffer)
|
||||||
|
{
|
||||||
|
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
|
||||||
|
glDsaState.renderbuffer = renderbuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
GL_BindRenderbuffer(renderbuffer);
|
||||||
|
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
|
||||||
|
{
|
||||||
|
GL_BindRenderbuffer(renderbuffer);
|
||||||
|
qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internalformat, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(target, framebuffer);
|
||||||
|
return qglCheckFramebufferStatusEXT(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
|
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, textarget, texture, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
|
||||||
|
{
|
||||||
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
|
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, renderbuffertarget, renderbuffer);
|
||||||
|
}
|
80
code/renderergl2/tr_dsa.h
Normal file
80
code/renderergl2/tr_dsa.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 2016 James Canete
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TR_DSA_H__
|
||||||
|
#define __TR_DSA_H__
|
||||||
|
|
||||||
|
#include "../renderercommon/qgl.h"
|
||||||
|
|
||||||
|
void GL_BindNullTextures(void);
|
||||||
|
int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||||
|
GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target);
|
||||||
|
|
||||||
|
void GL_BindNullProgram(void);
|
||||||
|
int GL_UseProgramObject(GLuint program);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint v0);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat v0);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value);
|
||||||
|
GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value);
|
||||||
|
|
||||||
|
void GL_BindNullFramebuffers(void);
|
||||||
|
void GL_BindFramebuffer(GLenum target, GLuint framebuffer);
|
||||||
|
void GL_BindRenderbuffer(GLuint renderbuffer);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target);
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
|
GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
// GL_EXT_draw_range_elements
|
// GL_EXT_draw_range_elements
|
||||||
void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
|
void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
|
||||||
|
@ -184,6 +185,50 @@ void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays);
|
||||||
void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
|
void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays);
|
||||||
GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
|
GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array);
|
||||||
|
|
||||||
|
// GL_EXT_direct_state_access
|
||||||
|
GLvoid (APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, GLuint texture);
|
||||||
|
GLvoid (APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, GLenum pname, GLfloat param);
|
||||||
|
GLvoid (APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, GLenum pname, GLint param);
|
||||||
|
GLvoid (APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, GLint level, GLint internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid (APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
|
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||||
|
GLvoid (APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
|
||||||
|
GLvoid (APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||||
|
GLvoid (APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum target, GLint level,
|
||||||
|
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format,
|
||||||
|
GLsizei imageSize, const GLvoid *data);
|
||||||
|
GLvoid (APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target);
|
||||||
|
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, GLint v0);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, GLfloat v0);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location,
|
||||||
|
GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location,
|
||||||
|
GLsizei count, const GLfloat *value);
|
||||||
|
GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location,
|
||||||
|
GLsizei count, GLboolean transpose,
|
||||||
|
const GLfloat *value);
|
||||||
|
|
||||||
|
GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer,
|
||||||
|
GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint renderbuffer,
|
||||||
|
GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
|
|
||||||
|
GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target);
|
||||||
|
GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||||
|
GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer,
|
||||||
|
GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
|
||||||
|
|
||||||
|
|
||||||
static qboolean GLimp_HaveExtension(const char *ext)
|
static qboolean GLimp_HaveExtension(const char *ext)
|
||||||
{
|
{
|
||||||
const char *ptr = Q_stristr( glConfig.extensions_string, ext );
|
const char *ptr = Q_stristr( glConfig.extensions_string, ext );
|
||||||
|
@ -585,6 +630,22 @@ void GLimp_InitExtraExtensions()
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GL_ARB_texture_compression
|
||||||
|
extension = "GL_ARB_texture_compression";
|
||||||
|
glRefConfig.arbTextureCompression = qfalse;
|
||||||
|
if (GLimp_HaveExtension(extension))
|
||||||
|
{
|
||||||
|
qglCompressedTexImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage3DARB");
|
||||||
|
qglCompressedTexImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage2DARB");
|
||||||
|
qglCompressedTexImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage1DARB");
|
||||||
|
qglCompressedTexSubImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage3DARB");
|
||||||
|
qglCompressedTexSubImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage2DARB");
|
||||||
|
qglCompressedTexSubImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage1DARB");
|
||||||
|
qglGetCompressedTexImageARB = (void *)SDL_GL_GetProcAddress("glGetCompressedTexImageARB");
|
||||||
|
glRefConfig.arbTextureCompression = qtrue;
|
||||||
|
ri.Printf(PRINT_ALL, result[glRefConfig.arbTextureCompression], extension);
|
||||||
|
}
|
||||||
|
|
||||||
// GL_EXT_framebuffer_multisample
|
// GL_EXT_framebuffer_multisample
|
||||||
extension = "GL_EXT_framebuffer_multisample";
|
extension = "GL_EXT_framebuffer_multisample";
|
||||||
glRefConfig.framebufferMultisample = qfalse;
|
glRefConfig.framebufferMultisample = qfalse;
|
||||||
|
@ -601,12 +662,12 @@ void GLimp_InitExtraExtensions()
|
||||||
|
|
||||||
glRefConfig.textureCompression = TCR_NONE;
|
glRefConfig.textureCompression = TCR_NONE;
|
||||||
|
|
||||||
// GL_EXT_texture_compression_latc
|
// GL_ARB_texture_compression_rgtc
|
||||||
extension = "GL_EXT_texture_compression_latc";
|
extension = "GL_ARB_texture_compression_rgtc";
|
||||||
if (GLimp_HaveExtension(extension))
|
if (GLimp_HaveExtension(extension))
|
||||||
{
|
{
|
||||||
if (r_ext_compressed_textures->integer)
|
if (r_ext_compressed_textures->integer && glRefConfig.arbTextureCompression)
|
||||||
glRefConfig.textureCompression |= TCR_LATC;
|
glRefConfig.textureCompression |= TCR_RGTC;
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension);
|
ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension);
|
||||||
}
|
}
|
||||||
|
@ -615,6 +676,8 @@ void GLimp_InitExtraExtensions()
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glRefConfig.swizzleNormalmap = r_ext_compressed_textures->integer && !(glRefConfig.textureCompression & TCR_RGTC);
|
||||||
|
|
||||||
// GL_ARB_texture_compression_bptc
|
// GL_ARB_texture_compression_bptc
|
||||||
extension = "GL_ARB_texture_compression_bptc";
|
extension = "GL_ARB_texture_compression_bptc";
|
||||||
if (GLimp_HaveExtension(extension))
|
if (GLimp_HaveExtension(extension))
|
||||||
|
@ -732,4 +795,68 @@ void GLimp_InitExtraExtensions()
|
||||||
ri.Printf(PRINT_ALL, result[2], extension);
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GL_EXT_direct_state_access
|
||||||
|
extension = "GL_EXT_direct_state_access";
|
||||||
|
|
||||||
|
qglBindMultiTexture = GLDSA_BindMultiTexture;
|
||||||
|
qglTextureParameterf = GLDSA_TextureParameterf;
|
||||||
|
qglTextureParameteri = GLDSA_TextureParameteri;
|
||||||
|
qglTextureImage2D = GLDSA_TextureImage2D;
|
||||||
|
qglTextureSubImage2D = GLDSA_TextureSubImage2D;
|
||||||
|
qglCopyTextureImage2D = GLDSA_CopyTextureImage2D;
|
||||||
|
qglCompressedTextureImage2D = GLDSA_CompressedTextureImage2D;
|
||||||
|
qglCompressedTextureSubImage2D = GLDSA_CompressedTextureSubImage2D;
|
||||||
|
qglGenerateTextureMipmap = GLDSA_GenerateTextureMipmap;
|
||||||
|
|
||||||
|
qglProgramUniform1i = GLDSA_ProgramUniform1i;
|
||||||
|
qglProgramUniform1f = GLDSA_ProgramUniform1f;
|
||||||
|
qglProgramUniform2f = GLDSA_ProgramUniform2f;
|
||||||
|
qglProgramUniform3f = GLDSA_ProgramUniform3f;
|
||||||
|
qglProgramUniform4f = GLDSA_ProgramUniform4f;
|
||||||
|
qglProgramUniform1fv = GLDSA_ProgramUniform1fv;
|
||||||
|
qglProgramUniformMatrix4fv = GLDSA_ProgramUniformMatrix4fv;
|
||||||
|
|
||||||
|
qglNamedRenderbufferStorage = GLDSA_NamedRenderbufferStorage;
|
||||||
|
qglNamedRenderbufferStorageMultisample = GLDSA_NamedRenderbufferStorageMultisample;
|
||||||
|
qglCheckNamedFramebufferStatus = GLDSA_CheckNamedFramebufferStatus;
|
||||||
|
qglNamedFramebufferTexture2D = GLDSA_NamedFramebufferTexture2D;
|
||||||
|
qglNamedFramebufferRenderbuffer = GLDSA_NamedFramebufferRenderbuffer;
|
||||||
|
|
||||||
|
glRefConfig.directStateAccess = qfalse;
|
||||||
|
if (GLimp_HaveExtension(extension))
|
||||||
|
{
|
||||||
|
if (r_ext_direct_state_access->integer)
|
||||||
|
{
|
||||||
|
glRefConfig.directStateAccess = qtrue;
|
||||||
|
qglBindMultiTexture = (void *)SDL_GL_GetProcAddress("glBindMultiTextureEXT");
|
||||||
|
qglTextureParameterf = (void *)SDL_GL_GetProcAddress("glTextureParameterfEXT");
|
||||||
|
qglTextureParameteri = (void *)SDL_GL_GetProcAddress("glTextureParameteriEXT");
|
||||||
|
qglTextureImage2D = (void *)SDL_GL_GetProcAddress("glTextureImage2DEXT");
|
||||||
|
qglTextureSubImage2D = (void *)SDL_GL_GetProcAddress("glTextureSubImage2DEXT");
|
||||||
|
qglCopyTextureImage2D = (void *)SDL_GL_GetProcAddress("glCopyTextureImage2DEXT");
|
||||||
|
qglCompressedTextureImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureImage2DEXT");
|
||||||
|
qglCompressedTextureSubImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureSubImage2DEXT");
|
||||||
|
qglGenerateTextureMipmap = (void *)SDL_GL_GetProcAddress("glGenerateTextureMipmapEXT");
|
||||||
|
|
||||||
|
qglProgramUniform1i = (void *)SDL_GL_GetProcAddress("glProgramUniform1iEXT");
|
||||||
|
qglProgramUniform1f = (void *)SDL_GL_GetProcAddress("glProgramUniform1fEXT");
|
||||||
|
qglProgramUniform2f = (void *)SDL_GL_GetProcAddress("glProgramUniform2fEXT");
|
||||||
|
qglProgramUniform3f = (void *)SDL_GL_GetProcAddress("glProgramUniform3fEXT");
|
||||||
|
qglProgramUniform4f = (void *)SDL_GL_GetProcAddress("glProgramUniform4fEXT");
|
||||||
|
qglProgramUniform1fv = (void *)SDL_GL_GetProcAddress("glProgramUniform1fvEXT");
|
||||||
|
qglProgramUniformMatrix4fv = (void *)SDL_GL_GetProcAddress("glProgramUniformMatrix4fvEXT");
|
||||||
|
|
||||||
|
qglNamedRenderbufferStorage = (void *)SDL_GL_GetProcAddress("glNamedRenderbufferStorageEXT");
|
||||||
|
qglNamedRenderbufferStorageMultisample = (void *)SDL_GL_GetProcAddress("glNamedRenderbufferStorageMultisampleEXT");
|
||||||
|
qglCheckNamedFramebufferStatus = (void *)SDL_GL_GetProcAddress("glCheckNamedFramebufferStatusEXT");
|
||||||
|
qglNamedFramebufferTexture2D = (void *)SDL_GL_GetProcAddress("glNamedFramebufferTexture2DEXT");
|
||||||
|
qglNamedFramebufferRenderbuffer = (void *)SDL_GL_GetProcAddress("glNamedFramebufferRenderbufferEXT");
|
||||||
|
}
|
||||||
|
|
||||||
|
ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess ? 1 : 0], extension);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, result[2], extension);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_fbo.c
|
// tr_fbo.c
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
R_CheckFBO
|
R_CheckFBO
|
||||||
|
@ -30,19 +32,10 @@ R_CheckFBO
|
||||||
*/
|
*/
|
||||||
qboolean R_CheckFBO(const FBO_t * fbo)
|
qboolean R_CheckFBO(const FBO_t * fbo)
|
||||||
{
|
{
|
||||||
int code;
|
GLenum code = qglCheckNamedFramebufferStatus(fbo->frameBuffer, GL_FRAMEBUFFER_EXT);
|
||||||
int id;
|
|
||||||
|
|
||||||
qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id);
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
|
|
||||||
|
|
||||||
code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
|
||||||
|
|
||||||
if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
|
if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
{
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
|
||||||
|
|
||||||
// an error occured
|
// an error occured
|
||||||
switch (code)
|
switch (code)
|
||||||
|
@ -83,13 +76,9 @@ qboolean R_CheckFBO(const FBO_t * fbo)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
|
ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
|
||||||
//ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code);
|
|
||||||
//assert(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
|
|
||||||
|
|
||||||
return qfalse;
|
return qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +122,11 @@ FBO_t *FBO_Create(const char *name, int width, int height)
|
||||||
return fbo;
|
return fbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
FBO_CreateBuffer
|
||||||
|
=================
|
||||||
|
*/
|
||||||
void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
{
|
{
|
||||||
uint32_t *pRenderBuffer;
|
uint32_t *pRenderBuffer;
|
||||||
|
@ -189,115 +183,45 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
|
||||||
if (absent)
|
if (absent)
|
||||||
qglGenRenderbuffersEXT(1, pRenderBuffer);
|
qglGenRenderbuffersEXT(1, pRenderBuffer);
|
||||||
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
|
||||||
if (multisample && glRefConfig.framebufferMultisample)
|
if (multisample && glRefConfig.framebufferMultisample)
|
||||||
{
|
qglNamedRenderbufferStorageMultisample(*pRenderBuffer, multisample, format, fbo->width, fbo->height);
|
||||||
qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
qglNamedRenderbufferStorage(*pRenderBuffer, format, fbo->width, fbo->height);
|
||||||
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(absent)
|
if(absent)
|
||||||
{
|
{
|
||||||
if (attachment == 0)
|
if (attachment == 0)
|
||||||
{
|
{
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
qglNamedFramebufferRenderbuffer(fbo->frameBuffer, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
qglNamedFramebufferRenderbuffer(fbo->frameBuffer, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
{
|
||||||
|
qglNamedFramebufferRenderbuffer(fbo->frameBuffer, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
R_AttachFBOTexture1D
|
FBO_AttachImage
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
void R_AttachFBOTexture1D(int texId, int index)
|
void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside)
|
||||||
{
|
{
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
GLenum target = GL_TEXTURE_2D;
|
||||||
{
|
int index;
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0);
|
if (image->flags & IMGFLAG_CUBEMAP)
|
||||||
|
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubemapside;
|
||||||
|
|
||||||
|
qglNamedFramebufferTexture2D(fbo->frameBuffer, attachment, target, image->texnum, 0);
|
||||||
|
index = attachment - GL_COLOR_ATTACHMENT0_EXT;
|
||||||
|
if (index >= 0 && index <= 15)
|
||||||
|
fbo->colorImage[index] = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexture2D
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexture2D(int target, int texId, int index)
|
|
||||||
{
|
|
||||||
if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB))
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexture3D
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexture3D(int texId, int index, int zOffset)
|
|
||||||
{
|
|
||||||
if(index < 0 || index >= glRefConfig.maxColorAttachments)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTextureDepth
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTextureDepth(int texId)
|
|
||||||
{
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=================
|
|
||||||
R_AttachFBOTexturePackedDepthStencil
|
|
||||||
=================
|
|
||||||
*/
|
|
||||||
void R_AttachFBOTexturePackedDepthStencil(int texId)
|
|
||||||
{
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBO_AttachTextureImage(image_t *img, int index)
|
|
||||||
{
|
|
||||||
if (!glState.currentFBO)
|
|
||||||
{
|
|
||||||
ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture image with no FBO bound!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index);
|
|
||||||
glState.currentFBO->colorImage[index] = img;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
|
@ -312,38 +236,10 @@ void FBO_Bind(FBO_t * fbo)
|
||||||
if (r_logFile->integer)
|
if (r_logFile->integer)
|
||||||
{
|
{
|
||||||
// don't just call LogComment, or we will get a call to va() every frame!
|
// don't just call LogComment, or we will get a call to va() every frame!
|
||||||
if (fbo)
|
GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo ? fbo->name : "NULL"));
|
||||||
GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo->name));
|
|
||||||
else
|
|
||||||
GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fbo)
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, fbo ? fbo->frameBuffer : 0);
|
||||||
{
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
//qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
|
||||||
glState.currentFBO = NULL;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(fbo->colorBuffers[0])
|
|
||||||
{
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(fbo->depthBuffer)
|
|
||||||
{
|
|
||||||
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
|
|
||||||
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
glState.currentFBO = fbo;
|
glState.currentFBO = fbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +251,7 @@ FBO_Init
|
||||||
void FBO_Init(void)
|
void FBO_Init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
// int width, height, hdrFormat, multisample;
|
int hdrFormat, multisample = 0;
|
||||||
int hdrFormat, multisample;
|
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
|
ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
|
||||||
|
|
||||||
|
@ -369,73 +264,41 @@ void FBO_Init(void)
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
/* if(glRefConfig.textureNonPowerOfTwo)
|
|
||||||
{
|
|
||||||
width = glConfig.vidWidth;
|
|
||||||
height = glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = NextPowerOfTwo(glConfig.vidWidth);
|
|
||||||
height = NextPowerOfTwo(glConfig.vidHeight);
|
|
||||||
} */
|
|
||||||
|
|
||||||
hdrFormat = GL_RGBA8;
|
hdrFormat = GL_RGBA8;
|
||||||
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
|
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
|
||||||
{
|
|
||||||
hdrFormat = GL_RGBA16F_ARB;
|
hdrFormat = GL_RGBA16F_ARB;
|
||||||
}
|
|
||||||
|
|
||||||
qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
|
if (glRefConfig.framebufferMultisample)
|
||||||
|
qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
|
||||||
|
|
||||||
if (r_ext_framebuffer_multisample->integer < multisample)
|
if (r_ext_framebuffer_multisample->integer < multisample)
|
||||||
{
|
|
||||||
multisample = r_ext_framebuffer_multisample->integer;
|
multisample = r_ext_framebuffer_multisample->integer;
|
||||||
}
|
|
||||||
|
|
||||||
if (multisample < 2 || !glRefConfig.framebufferBlit)
|
if (multisample < 2 || !glRefConfig.framebufferBlit)
|
||||||
multisample = 0;
|
multisample = 0;
|
||||||
|
|
||||||
if (multisample != r_ext_framebuffer_multisample->integer)
|
if (multisample != r_ext_framebuffer_multisample->integer)
|
||||||
{
|
|
||||||
ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
|
ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
|
||||||
}
|
|
||||||
|
|
||||||
// only create a render FBO if we need to resolve MSAA or do HDR
|
// only create a render FBO if we need to resolve MSAA or do HDR
|
||||||
// otherwise just render straight to the screen (tr.renderFbo = NULL)
|
// otherwise just render straight to the screen (tr.renderFbo = NULL)
|
||||||
if (multisample && glRefConfig.framebufferMultisample)
|
if (multisample && glRefConfig.framebufferMultisample)
|
||||||
{
|
{
|
||||||
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.renderFbo);
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
|
FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
|
||||||
FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample);
|
FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample);
|
||||||
|
|
||||||
R_CheckFBO(tr.renderFbo);
|
R_CheckFBO(tr.renderFbo);
|
||||||
|
|
||||||
|
|
||||||
tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.msaaResolveFbo);
|
FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0);
|
||||||
//FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.renderImage, 0);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.msaaResolveFbo);
|
R_CheckFBO(tr.msaaResolveFbo);
|
||||||
}
|
}
|
||||||
else if (r_hdr->integer)
|
else if (r_hdr->integer)
|
||||||
{
|
{
|
||||||
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.renderFbo);
|
FBO_AttachImage(tr.renderFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0);
|
||||||
//FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.renderImage, 0);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.renderFbo);
|
R_CheckFBO(tr.renderFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,20 +306,15 @@ void FBO_Init(void)
|
||||||
// this fixes the corrupt screen bug with r_hdr 1 on older hardware
|
// this fixes the corrupt screen bug with r_hdr 1 on older hardware
|
||||||
if (tr.renderFbo)
|
if (tr.renderFbo)
|
||||||
{
|
{
|
||||||
FBO_Bind(tr.renderFbo);
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, tr.renderFbo->frameBuffer);
|
||||||
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
FBO_Bind(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_drawSunRays->integer)
|
if (r_drawSunRays->integer)
|
||||||
{
|
{
|
||||||
tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
|
||||||
FBO_Bind(tr.sunRaysFbo);
|
FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0);
|
||||||
FBO_AttachTextureImage(tr.sunRaysImage, 0);
|
|
||||||
|
|
||||||
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.sunRaysFbo);
|
R_CheckFBO(tr.sunRaysFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,14 +324,8 @@ void FBO_Init(void)
|
||||||
for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
|
for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
|
||||||
{
|
{
|
||||||
tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
|
tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
|
||||||
FBO_Bind(tr.pshadowFbos[i]);
|
FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.pshadowMaps[i], 0);
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
||||||
//R_AttachFBOTextureDepth(tr.textureDepthImage->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.pshadowFbos[i]);
|
R_CheckFBO(tr.pshadowFbos[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,104 +335,67 @@ void FBO_Init(void)
|
||||||
for ( i = 0; i < 4; i++)
|
for ( i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
|
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
|
||||||
FBO_Bind(tr.sunShadowFbo[i]);
|
// FIXME: this next line wastes 16mb with 4x1024x1024 sun shadow maps, skip if OpenGL 4.3+ or ARB_framebuffer_no_attachments
|
||||||
|
// This at least gets sun shadows working on older GPUs (Intel)
|
||||||
//FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
|
FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
|
||||||
//FBO_AttachTextureImage(tr.sunShadowImage, 0);
|
FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT, 0);
|
||||||
qglDrawBuffer(GL_NONE);
|
|
||||||
qglReadBuffer(GL_NONE);
|
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
|
||||||
R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.sunShadowFbo[i]);
|
R_CheckFBO(tr.sunShadowFbo[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
|
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
|
||||||
FBO_Bind(tr.screenShadowFbo);
|
FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.screenShadowImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.screenShadowFbo);
|
R_CheckFBO(tr.screenShadowFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
|
tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
|
||||||
FBO_Bind(tr.textureScratchFbo[i]);
|
FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.textureScratchImage[i], 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.textureScratchFbo[i]);
|
R_CheckFBO(tr.textureScratchFbo[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
|
tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
|
||||||
FBO_Bind(tr.calcLevelsFbo);
|
FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.calcLevelsImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.calcLevelsFbo);
|
R_CheckFBO(tr.calcLevelsFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
|
tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
|
||||||
FBO_Bind(tr.targetLevelsFbo);
|
FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.targetLevelsImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.targetLevelsFbo);
|
R_CheckFBO(tr.targetLevelsFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
|
tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
|
||||||
FBO_Bind(tr.quarterFbo[i]);
|
FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0);
|
|
||||||
FBO_AttachTextureImage(tr.quarterImage[i], 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.quarterFbo[i]);
|
R_CheckFBO(tr.quarterFbo[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_ssao->integer)
|
if (r_ssao->integer)
|
||||||
{
|
{
|
||||||
tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
|
tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
|
||||||
FBO_Bind(tr.hdrDepthFbo);
|
FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.hdrDepthImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.hdrDepthFbo);
|
R_CheckFBO(tr.hdrDepthFbo);
|
||||||
|
|
||||||
tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
|
tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
|
||||||
FBO_Bind(tr.screenSsaoFbo);
|
FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
FBO_AttachTextureImage(tr.screenSsaoImage, 0);
|
|
||||||
|
|
||||||
R_CheckFBO(tr.screenSsaoFbo);
|
R_CheckFBO(tr.screenSsaoFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tr.renderCubeImage)
|
if (tr.renderCubeImage)
|
||||||
{
|
{
|
||||||
tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
|
tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
|
||||||
FBO_Bind(tr.renderCubeFbo);
|
FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, GL_COLOR_ATTACHMENT0_EXT, 0);
|
||||||
|
|
||||||
//FBO_AttachTextureImage(tr.renderCubeImage, 0);
|
|
||||||
R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tr.renderCubeImage->texnum, 0);
|
|
||||||
glState.currentFBO->colorImage[0] = tr.renderCubeImage;
|
|
||||||
|
|
||||||
FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
|
||||||
|
|
||||||
R_CheckFBO(tr.renderCubeFbo);
|
R_CheckFBO(tr.renderCubeFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_CheckErrors();
|
GL_CheckErrors();
|
||||||
|
|
||||||
FBO_Bind(NULL);
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
glState.currentFBO = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -663,7 +478,10 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
if (!src)
|
if (!src)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (inSrcBox)
|
if (inSrcBox)
|
||||||
{
|
{
|
||||||
|
@ -849,12 +667,12 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu
|
||||||
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
|
VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb);
|
GL_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, srcFb);
|
||||||
qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
|
GL_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
|
||||||
qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
|
qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
|
||||||
dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
|
dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
|
||||||
buffers, filter);
|
buffers, filter);
|
||||||
|
|
||||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
|
||||||
glState.currentFBO = NULL;
|
glState.currentFBO = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ typedef struct FBO_s
|
||||||
int height;
|
int height;
|
||||||
} FBO_t;
|
} FBO_t;
|
||||||
|
|
||||||
|
void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside);
|
||||||
void FBO_Bind(FBO_t *fbo);
|
void FBO_Bind(FBO_t *fbo);
|
||||||
void FBO_Init(void);
|
void FBO_Init(void);
|
||||||
void FBO_Shutdown(void);
|
void FBO_Shutdown(void);
|
||||||
|
|
|
@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
// tr_glsl.c
|
// tr_glsl.c
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
void GLSL_BindNullProgram(void);
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
extern const char *fallbackShader_bokeh_vp;
|
extern const char *fallbackShader_bokeh_vp;
|
||||||
extern const char *fallbackShader_bokeh_fp;
|
extern const char *fallbackShader_bokeh_fp;
|
||||||
|
@ -322,17 +322,8 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha
|
||||||
Q_strcat(dest, size,
|
Q_strcat(dest, size,
|
||||||
va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale));
|
va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale));
|
||||||
|
|
||||||
if (r_materialGamma->value != 1.0f)
|
if (r_pbr->integer)
|
||||||
Q_strcat(dest, size, va("#ifndef r_materialGamma\n#define r_materialGamma %f\n#endif\n", r_materialGamma->value));
|
Q_strcat(dest, size, "#define USE_PBR\n");
|
||||||
|
|
||||||
if (r_lightGamma->value != 1.0f)
|
|
||||||
Q_strcat(dest, size, va("#ifndef r_lightGamma\n#define r_lightGamma %f\n#endif\n", r_lightGamma->value));
|
|
||||||
|
|
||||||
if (r_framebufferGamma->value != 1.0f)
|
|
||||||
Q_strcat(dest, size, va("#ifndef r_framebufferGamma\n#define r_framebufferGamma %f\n#endif\n", r_framebufferGamma->value));
|
|
||||||
|
|
||||||
if (r_tonemapGamma->value != 1.0f)
|
|
||||||
Q_strcat(dest, size, va("#ifndef r_tonemapGamma\n#define r_tonemapGamma %f\n#endif\n", r_tonemapGamma->value));
|
|
||||||
|
|
||||||
if (extra)
|
if (extra)
|
||||||
{
|
{
|
||||||
|
@ -482,11 +473,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program)
|
||||||
GLenum type;
|
GLenum type;
|
||||||
char uniformName[1000];
|
char uniformName[1000];
|
||||||
|
|
||||||
// install the executables in the program object as part of current state.
|
|
||||||
qglUseProgramObjectARB(program);
|
|
||||||
|
|
||||||
// check for GL Errors
|
|
||||||
|
|
||||||
// query the number of active uniforms
|
// query the number of active uniforms
|
||||||
qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count);
|
qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count);
|
||||||
|
|
||||||
|
@ -497,8 +483,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program)
|
||||||
|
|
||||||
ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName);
|
ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName);
|
||||||
}
|
}
|
||||||
|
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode)
|
static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode)
|
||||||
|
@ -703,7 +687,7 @@ void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value)
|
||||||
|
|
||||||
*compare = value;
|
*compare = value;
|
||||||
|
|
||||||
qglUniform1iARB(uniforms[uniformNum], value);
|
qglProgramUniform1i(program->program, uniforms[uniformNum], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value)
|
void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value)
|
||||||
|
@ -727,7 +711,7 @@ void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat valu
|
||||||
|
|
||||||
*compare = value;
|
*compare = value;
|
||||||
|
|
||||||
qglUniform1fARB(uniforms[uniformNum], value);
|
qglProgramUniform1f(program->program, uniforms[uniformNum], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v)
|
void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v)
|
||||||
|
@ -752,7 +736,7 @@ void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t
|
||||||
compare[0] = v[0];
|
compare[0] = v[0];
|
||||||
compare[1] = v[1];
|
compare[1] = v[1];
|
||||||
|
|
||||||
qglUniform2fARB(uniforms[uniformNum], v[0], v[1]);
|
qglProgramUniform2f(program->program, uniforms[uniformNum], v[0], v[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v)
|
void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v)
|
||||||
|
@ -776,7 +760,7 @@ void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t
|
||||||
|
|
||||||
VectorCopy(v, compare);
|
VectorCopy(v, compare);
|
||||||
|
|
||||||
qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]);
|
qglProgramUniform3f(program->program, uniforms[uniformNum], v[0], v[1], v[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v)
|
void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v)
|
||||||
|
@ -800,7 +784,7 @@ void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t
|
||||||
|
|
||||||
VectorCopy4(v, compare);
|
VectorCopy4(v, compare);
|
||||||
|
|
||||||
qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
|
qglProgramUniform4f(program->program, uniforms[uniformNum], v[0], v[1], v[2], v[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v)
|
void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v)
|
||||||
|
@ -824,7 +808,7 @@ void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_
|
||||||
|
|
||||||
VectorCopy5(v, compare);
|
VectorCopy5(v, compare);
|
||||||
|
|
||||||
qglUniform1fvARB(uniforms[uniformNum], 5, v);
|
qglProgramUniform1fv(program->program, uniforms[uniformNum], 5, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix)
|
void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix)
|
||||||
|
@ -848,7 +832,7 @@ void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t
|
||||||
|
|
||||||
Mat4Copy(matrix, compare);
|
Mat4Copy(matrix, compare);
|
||||||
|
|
||||||
qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
|
qglProgramUniformMatrix4fv(program->program, uniforms[uniformNum], 1, GL_FALSE, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSL_DeleteGPUShader(shaderProgram_t *program)
|
void GLSL_DeleteGPUShader(shaderProgram_t *program)
|
||||||
|
@ -925,10 +909,8 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.genericShader[i]);
|
GLSL_InitUniforms(&tr.genericShader[i]);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.genericShader[i].program);
|
|
||||||
GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
||||||
GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP);
|
GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.genericShader[i]);
|
GLSL_FinishGPUShader(&tr.genericShader[i]);
|
||||||
|
|
||||||
|
@ -945,9 +927,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.textureColorShader);
|
GLSL_InitUniforms(&tr.textureColorShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.textureColorShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.textureColorShader);
|
GLSL_FinishGPUShader(&tr.textureColorShader);
|
||||||
|
|
||||||
|
@ -993,9 +973,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.dlightShader[i]);
|
GLSL_InitUniforms(&tr.dlightShader[i]);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.dlightShader[i].program);
|
|
||||||
GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.dlightShader[i]);
|
GLSL_FinishGPUShader(&tr.dlightShader[i]);
|
||||||
|
|
||||||
|
@ -1022,16 +1000,10 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
extradefines[0] = '\0';
|
extradefines[0] = '\0';
|
||||||
|
|
||||||
if (r_deluxeSpecular->value > 0.000001f)
|
|
||||||
Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value));
|
|
||||||
|
|
||||||
if (r_specularIsMetallic->value)
|
|
||||||
Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n");
|
|
||||||
|
|
||||||
if (r_dlightMode->integer >= 2)
|
if (r_dlightMode->integer >= 2)
|
||||||
Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
|
Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
|
||||||
|
|
||||||
if (1)
|
if (glRefConfig.swizzleNormalmap)
|
||||||
Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
|
Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
|
||||||
|
|
||||||
if (r_hdr->integer && !glRefConfig.floatLightmap)
|
if (r_hdr->integer && !glRefConfig.floatLightmap)
|
||||||
|
@ -1067,12 +1039,6 @@ void GLSL_InitGPUShaders(void)
|
||||||
{
|
{
|
||||||
Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n");
|
Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n");
|
||||||
|
|
||||||
if (r_normalMapping->integer == 2)
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n");
|
|
||||||
|
|
||||||
if (r_normalMapping->integer == 3)
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n");
|
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
#ifdef USE_VERT_TANGENT_SPACE
|
||||||
Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n");
|
Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n");
|
||||||
attribs |= ATTR_TANGENT;
|
attribs |= ATTR_TANGENT;
|
||||||
|
@ -1087,34 +1053,8 @@ void GLSL_InitGPUShaders(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_specularMapping->integer)
|
if (r_specularMapping->integer)
|
||||||
{
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n");
|
Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n");
|
||||||
|
|
||||||
switch (r_specularMapping->integer)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_BLINN\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_BLINN_FRESNEL\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_MCAULEY\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_GOTANDA\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
Q_strcat(extradefines, 1024, "#define USE_LAZAROV\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r_cubeMapping->integer)
|
if (r_cubeMapping->integer)
|
||||||
Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n");
|
Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n");
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1095,6 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.lightallShader[i]);
|
GLSL_InitUniforms(&tr.lightallShader[i]);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.lightallShader[i].program);
|
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP);
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP, TB_NORMALMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP, TB_NORMALMAP);
|
||||||
|
@ -1163,7 +1102,6 @@ void GLSL_InitGPUShaders(void)
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, TB_SPECULARMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, TB_SPECULARMAP);
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP, TB_SHADOWMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP, TB_SHADOWMAP);
|
||||||
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP, TB_CUBEMAP);
|
GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP, TB_CUBEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.lightallShader[i]);
|
GLSL_FinishGPUShader(&tr.lightallShader[i]);
|
||||||
|
|
||||||
|
@ -1196,9 +1134,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.pshadowShader);
|
GLSL_InitUniforms(&tr.pshadowShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.pshadowShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.pshadowShader);
|
GLSL_FinishGPUShader(&tr.pshadowShader);
|
||||||
|
|
||||||
|
@ -1215,9 +1151,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.down4xShader);
|
GLSL_InitUniforms(&tr.down4xShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.down4xShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.down4xShader);
|
GLSL_FinishGPUShader(&tr.down4xShader);
|
||||||
|
|
||||||
|
@ -1234,9 +1168,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.bokehShader);
|
GLSL_InitUniforms(&tr.bokehShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.bokehShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.bokehShader);
|
GLSL_FinishGPUShader(&tr.bokehShader);
|
||||||
|
|
||||||
|
@ -1253,10 +1185,8 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.tonemapShader);
|
GLSL_InitUniforms(&tr.tonemapShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.tonemapShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
|
GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
|
||||||
GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP, TB_LEVELSMAP);
|
GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP, TB_LEVELSMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.tonemapShader);
|
GLSL_FinishGPUShader(&tr.tonemapShader);
|
||||||
|
|
||||||
|
@ -1278,9 +1208,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.calclevels4xShader[i]);
|
GLSL_InitUniforms(&tr.calclevels4xShader[i]);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.calclevels4xShader[i].program);
|
|
||||||
GLSL_SetUniformInt(&tr.calclevels4xShader[i], UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
GLSL_SetUniformInt(&tr.calclevels4xShader[i], UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.calclevels4xShader[i]);
|
GLSL_FinishGPUShader(&tr.calclevels4xShader[i]);
|
||||||
|
|
||||||
|
@ -1311,13 +1239,11 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.shadowmaskShader);
|
GLSL_InitUniforms(&tr.shadowmaskShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.shadowmaskShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
|
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
|
||||||
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP);
|
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP);
|
||||||
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2);
|
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2);
|
||||||
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3);
|
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3);
|
||||||
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4);
|
GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.shadowmaskShader);
|
GLSL_FinishGPUShader(&tr.shadowmaskShader);
|
||||||
|
|
||||||
|
@ -1334,9 +1260,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.ssaoShader);
|
GLSL_InitUniforms(&tr.ssaoShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.ssaoShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
|
GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.ssaoShader);
|
GLSL_FinishGPUShader(&tr.ssaoShader);
|
||||||
|
|
||||||
|
@ -1361,10 +1285,8 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.depthBlurShader[i]);
|
GLSL_InitUniforms(&tr.depthBlurShader[i]);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.depthBlurShader[i].program);
|
|
||||||
GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENIMAGEMAP, TB_COLORMAP);
|
GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENIMAGEMAP, TB_COLORMAP);
|
||||||
GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP);
|
GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.depthBlurShader[i]);
|
GLSL_FinishGPUShader(&tr.depthBlurShader[i]);
|
||||||
|
|
||||||
|
@ -1382,9 +1304,7 @@ void GLSL_InitGPUShaders(void)
|
||||||
|
|
||||||
GLSL_InitUniforms(&tr.testcubeShader);
|
GLSL_InitUniforms(&tr.testcubeShader);
|
||||||
|
|
||||||
qglUseProgramObjectARB(tr.testcubeShader.program);
|
|
||||||
GLSL_SetUniformInt(&tr.testcubeShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
|
GLSL_SetUniformInt(&tr.testcubeShader, UNIFORM_TEXTUREMAP, TB_COLORMAP);
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
GLSL_FinishGPUShader(&tr.testcubeShader);
|
GLSL_FinishGPUShader(&tr.testcubeShader);
|
||||||
|
|
||||||
|
@ -1408,7 +1328,7 @@ void GLSL_ShutdownGPUShaders(void)
|
||||||
for (i = 0; i < ATTR_INDEX_COUNT; i++)
|
for (i = 0; i < ATTR_INDEX_COUNT; i++)
|
||||||
qglDisableVertexAttribArrayARB(i);
|
qglDisableVertexAttribArrayARB(i);
|
||||||
|
|
||||||
GLSL_BindNullProgram();
|
GL_BindNullProgram();
|
||||||
|
|
||||||
for ( i = 0; i < GENERICDEF_COUNT; i++)
|
for ( i = 0; i < GENERICDEF_COUNT; i++)
|
||||||
GLSL_DeleteGPUShader(&tr.genericShader[i]);
|
GLSL_DeleteGPUShader(&tr.genericShader[i]);
|
||||||
|
@ -1438,47 +1358,22 @@ void GLSL_ShutdownGPUShaders(void)
|
||||||
|
|
||||||
for ( i = 0; i < 2; i++)
|
for ( i = 0; i < 2; i++)
|
||||||
GLSL_DeleteGPUShader(&tr.depthBlurShader[i]);
|
GLSL_DeleteGPUShader(&tr.depthBlurShader[i]);
|
||||||
|
|
||||||
glState.currentProgram = 0;
|
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLSL_BindProgram(shaderProgram_t * program)
|
void GLSL_BindProgram(shaderProgram_t * program)
|
||||||
{
|
{
|
||||||
if(!program)
|
GLuint programObject = program ? program->program : 0;
|
||||||
{
|
char *name = program ? program->name : "NULL";
|
||||||
GLSL_BindNullProgram();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r_logFile->integer)
|
if(r_logFile->integer)
|
||||||
{
|
{
|
||||||
// don't just call LogComment, or we will get a call to va() every frame!
|
// don't just call LogComment, or we will get a call to va() every frame!
|
||||||
GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name));
|
GLimp_LogComment(va("--- GLSL_BindProgram( %s ) ---\n", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(glState.currentProgram != program)
|
if (GL_UseProgramObject(programObject))
|
||||||
{
|
|
||||||
qglUseProgramObjectARB(program->program);
|
|
||||||
glState.currentProgram = program;
|
|
||||||
backEnd.pc.c_glslShaderBinds++;
|
backEnd.pc.c_glslShaderBinds++;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GLSL_BindNullProgram(void)
|
|
||||||
{
|
|
||||||
if(r_logFile->integer)
|
|
||||||
{
|
|
||||||
GLimp_LogComment("--- GL_BindNullProgram ---\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(glState.currentProgram)
|
|
||||||
{
|
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
glState.currentProgram = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
498
code/renderergl2/tr_image_dds.c
Normal file
498
code/renderergl2/tr_image_dds.c
Normal file
|
@ -0,0 +1,498 @@
|
||||||
|
/*
|
||||||
|
===========================================================================
|
||||||
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
2015 James Canete
|
||||||
|
|
||||||
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
|
Quake III Arena source code is free software; you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
|
or (at your option) any later version.
|
||||||
|
|
||||||
|
Quake III Arena source code is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Quake III Arena source code; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
===========================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../renderercommon/tr_common.h"
|
||||||
|
|
||||||
|
typedef unsigned int ui32_t;
|
||||||
|
|
||||||
|
typedef struct ddsHeader_s
|
||||||
|
{
|
||||||
|
ui32_t headerSize;
|
||||||
|
ui32_t flags;
|
||||||
|
ui32_t height;
|
||||||
|
ui32_t width;
|
||||||
|
ui32_t pitchOrFirstMipSize;
|
||||||
|
ui32_t volumeDepth;
|
||||||
|
ui32_t numMips;
|
||||||
|
ui32_t reserved1[11];
|
||||||
|
ui32_t always_0x00000020;
|
||||||
|
ui32_t pixelFormatFlags;
|
||||||
|
ui32_t fourCC;
|
||||||
|
ui32_t rgbBitCount;
|
||||||
|
ui32_t rBitMask;
|
||||||
|
ui32_t gBitMask;
|
||||||
|
ui32_t bBitMask;
|
||||||
|
ui32_t aBitMask;
|
||||||
|
ui32_t caps;
|
||||||
|
ui32_t caps2;
|
||||||
|
ui32_t caps3;
|
||||||
|
ui32_t caps4;
|
||||||
|
ui32_t reserved2;
|
||||||
|
}
|
||||||
|
ddsHeader_t;
|
||||||
|
|
||||||
|
// flags:
|
||||||
|
#define _DDSFLAGS_REQUIRED 0x001007
|
||||||
|
#define _DDSFLAGS_PITCH 0x8
|
||||||
|
#define _DDSFLAGS_MIPMAPCOUNT 0x20000
|
||||||
|
#define _DDSFLAGS_FIRSTMIPSIZE 0x80000
|
||||||
|
#define _DDSFLAGS_VOLUMEDEPTH 0x800000
|
||||||
|
|
||||||
|
// pixelFormatFlags:
|
||||||
|
#define DDSPF_ALPHAPIXELS 0x1
|
||||||
|
#define DDSPF_ALPHA 0x2
|
||||||
|
#define DDSPF_FOURCC 0x4
|
||||||
|
#define DDSPF_RGB 0x40
|
||||||
|
#define DDSPF_YUV 0x200
|
||||||
|
#define DDSPF_LUMINANCE 0x20000
|
||||||
|
|
||||||
|
// caps:
|
||||||
|
#define DDSCAPS_COMPLEX 0x8
|
||||||
|
#define DDSCAPS_MIPMAP 0x400000
|
||||||
|
#define DDSCAPS_REQUIRED 0x1000
|
||||||
|
|
||||||
|
// caps2:
|
||||||
|
#define DDSCAPS2_CUBEMAP 0xFE00
|
||||||
|
#define DDSCAPS2_VOLUME 0x200000
|
||||||
|
|
||||||
|
typedef struct ddsHeaderDxt10_s
|
||||||
|
{
|
||||||
|
ui32_t dxgiFormat;
|
||||||
|
ui32_t dimensions;
|
||||||
|
ui32_t miscFlags;
|
||||||
|
ui32_t arraySize;
|
||||||
|
ui32_t miscFlags2;
|
||||||
|
}
|
||||||
|
ddsHeaderDxt10_t;
|
||||||
|
|
||||||
|
// dxgiFormat
|
||||||
|
// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
|
||||||
|
typedef enum DXGI_FORMAT {
|
||||||
|
DXGI_FORMAT_UNKNOWN = 0,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_UINT = 3,
|
||||||
|
DXGI_FORMAT_R32G32B32A32_SINT = 4,
|
||||||
|
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
|
||||||
|
DXGI_FORMAT_R32G32B32_FLOAT = 6,
|
||||||
|
DXGI_FORMAT_R32G32B32_UINT = 7,
|
||||||
|
DXGI_FORMAT_R32G32B32_SINT = 8,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_UINT = 12,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
|
||||||
|
DXGI_FORMAT_R16G16B16A16_SINT = 14,
|
||||||
|
DXGI_FORMAT_R32G32_TYPELESS = 15,
|
||||||
|
DXGI_FORMAT_R32G32_FLOAT = 16,
|
||||||
|
DXGI_FORMAT_R32G32_UINT = 17,
|
||||||
|
DXGI_FORMAT_R32G32_SINT = 18,
|
||||||
|
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
|
||||||
|
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
|
||||||
|
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
|
||||||
|
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
|
||||||
|
DXGI_FORMAT_R10G10B10A2_UINT = 25,
|
||||||
|
DXGI_FORMAT_R11G11B10_FLOAT = 26,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UINT = 30,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_SINT = 32,
|
||||||
|
DXGI_FORMAT_R16G16_TYPELESS = 33,
|
||||||
|
DXGI_FORMAT_R16G16_FLOAT = 34,
|
||||||
|
DXGI_FORMAT_R16G16_UNORM = 35,
|
||||||
|
DXGI_FORMAT_R16G16_UINT = 36,
|
||||||
|
DXGI_FORMAT_R16G16_SNORM = 37,
|
||||||
|
DXGI_FORMAT_R16G16_SINT = 38,
|
||||||
|
DXGI_FORMAT_R32_TYPELESS = 39,
|
||||||
|
DXGI_FORMAT_D32_FLOAT = 40,
|
||||||
|
DXGI_FORMAT_R32_FLOAT = 41,
|
||||||
|
DXGI_FORMAT_R32_UINT = 42,
|
||||||
|
DXGI_FORMAT_R32_SINT = 43,
|
||||||
|
DXGI_FORMAT_R24G8_TYPELESS = 44,
|
||||||
|
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
|
||||||
|
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
|
||||||
|
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
|
||||||
|
DXGI_FORMAT_R8G8_TYPELESS = 48,
|
||||||
|
DXGI_FORMAT_R8G8_UNORM = 49,
|
||||||
|
DXGI_FORMAT_R8G8_UINT = 50,
|
||||||
|
DXGI_FORMAT_R8G8_SNORM = 51,
|
||||||
|
DXGI_FORMAT_R8G8_SINT = 52,
|
||||||
|
DXGI_FORMAT_R16_TYPELESS = 53,
|
||||||
|
DXGI_FORMAT_R16_FLOAT = 54,
|
||||||
|
DXGI_FORMAT_D16_UNORM = 55,
|
||||||
|
DXGI_FORMAT_R16_UNORM = 56,
|
||||||
|
DXGI_FORMAT_R16_UINT = 57,
|
||||||
|
DXGI_FORMAT_R16_SNORM = 58,
|
||||||
|
DXGI_FORMAT_R16_SINT = 59,
|
||||||
|
DXGI_FORMAT_R8_TYPELESS = 60,
|
||||||
|
DXGI_FORMAT_R8_UNORM = 61,
|
||||||
|
DXGI_FORMAT_R8_UINT = 62,
|
||||||
|
DXGI_FORMAT_R8_SNORM = 63,
|
||||||
|
DXGI_FORMAT_R8_SINT = 64,
|
||||||
|
DXGI_FORMAT_A8_UNORM = 65,
|
||||||
|
DXGI_FORMAT_R1_UNORM = 66,
|
||||||
|
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
|
||||||
|
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
|
||||||
|
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
|
||||||
|
DXGI_FORMAT_BC1_TYPELESS = 70,
|
||||||
|
DXGI_FORMAT_BC1_UNORM = 71,
|
||||||
|
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
|
||||||
|
DXGI_FORMAT_BC2_TYPELESS = 73,
|
||||||
|
DXGI_FORMAT_BC2_UNORM = 74,
|
||||||
|
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
|
||||||
|
DXGI_FORMAT_BC3_TYPELESS = 76,
|
||||||
|
DXGI_FORMAT_BC3_UNORM = 77,
|
||||||
|
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
|
||||||
|
DXGI_FORMAT_BC4_TYPELESS = 79,
|
||||||
|
DXGI_FORMAT_BC4_UNORM = 80,
|
||||||
|
DXGI_FORMAT_BC4_SNORM = 81,
|
||||||
|
DXGI_FORMAT_BC5_TYPELESS = 82,
|
||||||
|
DXGI_FORMAT_BC5_UNORM = 83,
|
||||||
|
DXGI_FORMAT_BC5_SNORM = 84,
|
||||||
|
DXGI_FORMAT_B5G6R5_UNORM = 85,
|
||||||
|
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
|
||||||
|
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
|
||||||
|
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
|
||||||
|
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
|
||||||
|
DXGI_FORMAT_BC6H_TYPELESS = 94,
|
||||||
|
DXGI_FORMAT_BC6H_UF16 = 95,
|
||||||
|
DXGI_FORMAT_BC6H_SF16 = 96,
|
||||||
|
DXGI_FORMAT_BC7_TYPELESS = 97,
|
||||||
|
DXGI_FORMAT_BC7_UNORM = 98,
|
||||||
|
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
|
||||||
|
DXGI_FORMAT_AYUV = 100,
|
||||||
|
DXGI_FORMAT_Y410 = 101,
|
||||||
|
DXGI_FORMAT_Y416 = 102,
|
||||||
|
DXGI_FORMAT_NV12 = 103,
|
||||||
|
DXGI_FORMAT_P010 = 104,
|
||||||
|
DXGI_FORMAT_P016 = 105,
|
||||||
|
DXGI_FORMAT_420_OPAQUE = 106,
|
||||||
|
DXGI_FORMAT_YUY2 = 107,
|
||||||
|
DXGI_FORMAT_Y210 = 108,
|
||||||
|
DXGI_FORMAT_Y216 = 109,
|
||||||
|
DXGI_FORMAT_NV11 = 110,
|
||||||
|
DXGI_FORMAT_AI44 = 111,
|
||||||
|
DXGI_FORMAT_IA44 = 112,
|
||||||
|
DXGI_FORMAT_P8 = 113,
|
||||||
|
DXGI_FORMAT_A8P8 = 114,
|
||||||
|
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
|
||||||
|
DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
|
||||||
|
} DXGI_FORMAT;
|
||||||
|
|
||||||
|
#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
|
||||||
|
(((ui32_t)((x)[1])) << 8 ) | \
|
||||||
|
(((ui32_t)((x)[2])) << 16) | \
|
||||||
|
(((ui32_t)((x)[3])) << 24) )
|
||||||
|
|
||||||
|
|
||||||
|
void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
byte *b;
|
||||||
|
void *v;
|
||||||
|
} buffer;
|
||||||
|
int len;
|
||||||
|
ddsHeader_t *ddsHeader = NULL;
|
||||||
|
ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL;
|
||||||
|
byte *data;
|
||||||
|
|
||||||
|
if (!picFormat)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
if (picFormat)
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
if (numMips)
|
||||||
|
*numMips = 1;
|
||||||
|
|
||||||
|
*pic = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// load the file
|
||||||
|
//
|
||||||
|
len = ri.FS_ReadFile( ( char * ) filename, &buffer.v);
|
||||||
|
if (!buffer.b || len < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// reject files that are too small to hold even a header
|
||||||
|
//
|
||||||
|
if (len < 4 + sizeof(*ddsHeader))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// reject files that don't start with "DDS "
|
||||||
|
//
|
||||||
|
if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS "))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// parse header and dx10 header if available
|
||||||
|
//
|
||||||
|
ddsHeader = (ddsHeader_t *)(buffer.b + 4);
|
||||||
|
if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
|
||||||
|
{
|
||||||
|
if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t));
|
||||||
|
data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
|
||||||
|
len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = buffer.b + 4 + sizeof(*ddsHeader);
|
||||||
|
len -= 4 + sizeof(*ddsHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = ddsHeader->width;
|
||||||
|
if (height)
|
||||||
|
*height = ddsHeader->height;
|
||||||
|
|
||||||
|
if (numMips)
|
||||||
|
{
|
||||||
|
if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
|
||||||
|
*numMips = ddsHeader->numMips;
|
||||||
|
else
|
||||||
|
*numMips = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: handle cube map
|
||||||
|
//if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Convert DXGI format/FourCC into OpenGL format
|
||||||
|
//
|
||||||
|
if (ddsHeaderDxt10)
|
||||||
|
{
|
||||||
|
switch (ddsHeaderDxt10->dxgiFormat)
|
||||||
|
{
|
||||||
|
case DXGI_FORMAT_BC1_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC1_UNORM:
|
||||||
|
// FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||||
|
// FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC2_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC2_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC3_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC3_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC4_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC4_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC4_SNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC5_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC5_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC5_SNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC6H_UF16:
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC6H_SF16:
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC7_TYPELESS:
|
||||||
|
case DXGI_FORMAT_BC7_UNORM:
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||||
|
*picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||||
|
*picFormat = GL_SRGB8_ALPHA8_EXT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
|
||||||
|
{
|
||||||
|
if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
|
||||||
|
*picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("ATI1"))
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC4U"))
|
||||||
|
*picFormat = GL_COMPRESSED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC4S"))
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("ATI2"))
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC5U"))
|
||||||
|
*picFormat = GL_COMPRESSED_RG_RGTC2;
|
||||||
|
else if (ddsHeader->fourCC == EncodeFourCC("BC5S"))
|
||||||
|
*picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
|
||||||
|
&& ddsHeader->rgbBitCount == 32
|
||||||
|
&& ddsHeader->rBitMask == 0x000000ff
|
||||||
|
&& ddsHeader->gBitMask == 0x0000ff00
|
||||||
|
&& ddsHeader->bBitMask == 0x00ff0000
|
||||||
|
&& ddsHeader->aBitMask == 0xff000000)
|
||||||
|
{
|
||||||
|
*picFormat = GL_RGBA8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename);
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pic = ri.Malloc(len);
|
||||||
|
Com_Memcpy(*pic, data, len);
|
||||||
|
|
||||||
|
ri.FS_FreeFile(buffer.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth)
|
||||||
|
{
|
||||||
|
byte *data;
|
||||||
|
ddsHeader_t *ddsHeader;
|
||||||
|
int picSize, size;
|
||||||
|
|
||||||
|
if (!depth)
|
||||||
|
depth = 1;
|
||||||
|
|
||||||
|
picSize = width * height * depth * 4;
|
||||||
|
size = 4 + sizeof(*ddsHeader) + picSize;
|
||||||
|
data = ri.Malloc(size);
|
||||||
|
|
||||||
|
data[0] = 'D';
|
||||||
|
data[1] = 'D';
|
||||||
|
data[2] = 'S';
|
||||||
|
data[3] = ' ';
|
||||||
|
|
||||||
|
ddsHeader = (ddsHeader_t *)(data + 4);
|
||||||
|
memset(ddsHeader, 0, sizeof(ddsHeader_t));
|
||||||
|
|
||||||
|
ddsHeader->headerSize = 0x7c;
|
||||||
|
ddsHeader->flags = _DDSFLAGS_REQUIRED;
|
||||||
|
ddsHeader->height = height;
|
||||||
|
ddsHeader->width = width;
|
||||||
|
ddsHeader->always_0x00000020 = 0x00000020;
|
||||||
|
ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED;
|
||||||
|
|
||||||
|
if (depth == 6)
|
||||||
|
ddsHeader->caps2 = DDSCAPS2_CUBEMAP;
|
||||||
|
|
||||||
|
ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS;
|
||||||
|
ddsHeader->rgbBitCount = 32;
|
||||||
|
ddsHeader->rBitMask = 0x000000ff;
|
||||||
|
ddsHeader->gBitMask = 0x0000ff00;
|
||||||
|
ddsHeader->bBitMask = 0x00ff0000;
|
||||||
|
ddsHeader->aBitMask = 0xff000000;
|
||||||
|
|
||||||
|
Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize);
|
||||||
|
|
||||||
|
ri.FS_WriteFile(filename, data, size);
|
||||||
|
|
||||||
|
ri.Free(data);
|
||||||
|
}
|
|
@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
#include "tr_dsa.h"
|
||||||
|
|
||||||
glconfig_t glConfig;
|
glconfig_t glConfig;
|
||||||
glRefConfig_t glRefConfig;
|
glRefConfig_t glRefConfig;
|
||||||
qboolean textureFilterAnisotropic = qfalse;
|
qboolean textureFilterAnisotropic = qfalse;
|
||||||
|
@ -106,6 +108,7 @@ cvar_t *r_ext_framebuffer_multisample;
|
||||||
cvar_t *r_arb_seamless_cube_map;
|
cvar_t *r_arb_seamless_cube_map;
|
||||||
cvar_t *r_arb_vertex_type_2_10_10_10_rev;
|
cvar_t *r_arb_vertex_type_2_10_10_10_rev;
|
||||||
cvar_t *r_arb_vertex_array_object;
|
cvar_t *r_arb_vertex_array_object;
|
||||||
|
cvar_t *r_ext_direct_state_access;
|
||||||
|
|
||||||
cvar_t *r_mergeMultidraws;
|
cvar_t *r_mergeMultidraws;
|
||||||
cvar_t *r_mergeLeafSurfaces;
|
cvar_t *r_mergeLeafSurfaces;
|
||||||
|
@ -129,11 +132,6 @@ cvar_t *r_forceAutoExposure;
|
||||||
cvar_t *r_forceAutoExposureMin;
|
cvar_t *r_forceAutoExposureMin;
|
||||||
cvar_t *r_forceAutoExposureMax;
|
cvar_t *r_forceAutoExposureMax;
|
||||||
|
|
||||||
cvar_t *r_materialGamma;
|
|
||||||
cvar_t *r_lightGamma;
|
|
||||||
cvar_t *r_framebufferGamma;
|
|
||||||
cvar_t *r_tonemapGamma;
|
|
||||||
|
|
||||||
cvar_t *r_depthPrepass;
|
cvar_t *r_depthPrepass;
|
||||||
cvar_t *r_ssao;
|
cvar_t *r_ssao;
|
||||||
|
|
||||||
|
@ -142,8 +140,8 @@ cvar_t *r_specularMapping;
|
||||||
cvar_t *r_deluxeMapping;
|
cvar_t *r_deluxeMapping;
|
||||||
cvar_t *r_parallaxMapping;
|
cvar_t *r_parallaxMapping;
|
||||||
cvar_t *r_cubeMapping;
|
cvar_t *r_cubeMapping;
|
||||||
cvar_t *r_deluxeSpecular;
|
cvar_t *r_cubemapSize;
|
||||||
cvar_t *r_specularIsMetallic;
|
cvar_t *r_pbr;
|
||||||
cvar_t *r_baseNormalX;
|
cvar_t *r_baseNormalX;
|
||||||
cvar_t *r_baseNormalY;
|
cvar_t *r_baseNormalY;
|
||||||
cvar_t *r_baseParallax;
|
cvar_t *r_baseParallax;
|
||||||
|
@ -455,6 +453,7 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa
|
||||||
buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
|
buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
|
||||||
|
|
||||||
bufstart = PADP((intptr_t) buffer + *offset, packAlign);
|
bufstart = PADP((intptr_t) buffer + *offset, packAlign);
|
||||||
|
|
||||||
qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
|
qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
|
||||||
|
|
||||||
*offset = bufstart - buffer;
|
*offset = bufstart - buffer;
|
||||||
|
@ -830,6 +829,35 @@ void R_ScreenShotJPEG_f (void) {
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_ExportCubemaps
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_ExportCubemaps(void)
|
||||||
|
{
|
||||||
|
exportCubemapsCommand_t *cmd;
|
||||||
|
|
||||||
|
cmd = R_GetCommandBuffer(sizeof(*cmd));
|
||||||
|
if (!cmd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmd->commandId = RC_EXPORT_CUBEMAPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_ExportCubemaps_f
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_ExportCubemaps_f(void)
|
||||||
|
{
|
||||||
|
R_ExportCubemaps();
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
RB_TakeVideoFrameCmd
|
RB_TakeVideoFrameCmd
|
||||||
|
@ -924,19 +952,11 @@ void GL_SetDefaultState( void )
|
||||||
|
|
||||||
qglColor4f (1,1,1,1);
|
qglColor4f (1,1,1,1);
|
||||||
|
|
||||||
// initialize downstream texture unit if we're running
|
GL_BindNullTextures();
|
||||||
// in a multitexture environment
|
GL_BindNullFramebuffers();
|
||||||
if ( qglActiveTextureARB ) {
|
|
||||||
GL_SelectTexture( 1 );
|
|
||||||
GL_TextureMode( r_textureMode->string );
|
|
||||||
GL_TexEnv( GL_MODULATE );
|
|
||||||
qglDisable( GL_TEXTURE_2D );
|
|
||||||
GL_SelectTexture( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
qglEnable(GL_TEXTURE_2D);
|
qglEnable(GL_TEXTURE_2D);
|
||||||
GL_TextureMode( r_textureMode->string );
|
GL_TextureMode( r_textureMode->string );
|
||||||
GL_TexEnv( GL_MODULATE );
|
|
||||||
|
|
||||||
//qglShadeModel( GL_SMOOTH );
|
//qglShadeModel( GL_SMOOTH );
|
||||||
qglDepthFunc( GL_LEQUAL );
|
qglDepthFunc( GL_LEQUAL );
|
||||||
|
@ -949,8 +969,7 @@ void GL_SetDefaultState( void )
|
||||||
glState.faceCulling = CT_TWO_SIDED;
|
glState.faceCulling = CT_TWO_SIDED;
|
||||||
glState.faceCullFront = qtrue;
|
glState.faceCullFront = qtrue;
|
||||||
|
|
||||||
glState.currentProgram = 0;
|
GL_BindNullProgram();
|
||||||
qglUseProgramObjectARB(0);
|
|
||||||
|
|
||||||
if (glRefConfig.vertexArrayObject)
|
if (glRefConfig.vertexArrayObject)
|
||||||
qglBindVertexArrayARB(0);
|
qglBindVertexArrayARB(0);
|
||||||
|
@ -1149,6 +1168,7 @@ void R_Register( void )
|
||||||
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", "1", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
|
|
||||||
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
|
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
|
||||||
"0", CVAR_ARCHIVE | CVAR_LATCH );
|
"0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1187,7 +1207,7 @@ void R_Register( void )
|
||||||
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
|
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
|
||||||
|
|
||||||
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE );
|
||||||
r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
|
r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
|
||||||
r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT );
|
r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT );
|
||||||
r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT );
|
r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT );
|
||||||
|
@ -1200,11 +1220,6 @@ void R_Register( void )
|
||||||
|
|
||||||
r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT );
|
r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT );
|
||||||
|
|
||||||
r_materialGamma = ri.Cvar_Get( "r_materialGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_lightGamma = ri.Cvar_Get( "r_lightGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_framebufferGamma = ri.Cvar_Get( "r_framebufferGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
r_tonemapGamma = ri.Cvar_Get( "r_tonemapGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
|
||||||
|
|
||||||
r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
|
r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
|
||||||
r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
|
r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
|
||||||
|
|
||||||
|
@ -1213,8 +1228,8 @@ void R_Register( void )
|
||||||
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_deluxeSpecular = ri.Cvar_Get( "r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH );
|
r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_pbr = ri.Cvar_Get("r_pbr", "0", CVAR_ARCHIVE | CVAR_LATCH);
|
||||||
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH );
|
r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH );
|
||||||
|
@ -1352,6 +1367,7 @@ void R_Register( void )
|
||||||
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
|
||||||
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
|
||||||
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
|
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
|
||||||
|
ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f );
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_InitQueries(void)
|
void R_InitQueries(void)
|
||||||
|
@ -1497,6 +1513,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
|
||||||
ri.Cmd_RemoveCommand( "modelist" );
|
ri.Cmd_RemoveCommand( "modelist" );
|
||||||
ri.Cmd_RemoveCommand( "shaderstate" );
|
ri.Cmd_RemoveCommand( "shaderstate" );
|
||||||
ri.Cmd_RemoveCommand( "gfxmeminfo" );
|
ri.Cmd_RemoveCommand( "gfxmeminfo" );
|
||||||
|
ri.Cmd_RemoveCommand( "exportCubemaps" );
|
||||||
|
|
||||||
|
|
||||||
if ( tr.registered ) {
|
if ( tr.registered ) {
|
||||||
|
|
|
@ -471,7 +471,7 @@ int R_CubemapForPoint( vec3_t point )
|
||||||
vec3_t diff;
|
vec3_t diff;
|
||||||
vec_t length;
|
vec_t length;
|
||||||
|
|
||||||
VectorSubtract(point, tr.cubemapOrigins[i], diff);
|
VectorSubtract(point, tr.cubemaps[i].origin, diff);
|
||||||
length = DotProduct(diff, diff);
|
length = DotProduct(diff, diff);
|
||||||
|
|
||||||
if (shortest > length)
|
if (shortest > length)
|
||||||
|
|
|
@ -54,10 +54,16 @@ typedef unsigned int glIndex_t;
|
||||||
#define MAX_CALC_PSHADOWS 64
|
#define MAX_CALC_PSHADOWS 64
|
||||||
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
|
#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
|
||||||
#define PSHADOW_MAP_SIZE 512
|
#define PSHADOW_MAP_SIZE 512
|
||||||
#define CUBE_MAP_MIPS 7
|
|
||||||
#define CUBE_MAP_SIZE (1 << CUBE_MAP_MIPS)
|
|
||||||
|
|
||||||
#define USE_VERT_TANGENT_SPACE
|
#define USE_VERT_TANGENT_SPACE
|
||||||
|
#define USE_OVERBRIGHT
|
||||||
|
|
||||||
|
typedef struct cubemap_s {
|
||||||
|
char name[MAX_QPATH];
|
||||||
|
vec3_t origin;
|
||||||
|
float parallaxRadius;
|
||||||
|
image_t *image;
|
||||||
|
} cubemap_t;
|
||||||
|
|
||||||
typedef struct dlight_s {
|
typedef struct dlight_s {
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
|
@ -1346,8 +1352,6 @@ typedef struct {
|
||||||
|
|
||||||
// the renderer front end should never modify glstate_t
|
// the renderer front end should never modify glstate_t
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int currenttextures[NUM_TEXTURE_BUNDLES];
|
|
||||||
int currenttmu;
|
|
||||||
qboolean finishCalled;
|
qboolean finishCalled;
|
||||||
int texEnv[2];
|
int texEnv[2];
|
||||||
int faceCulling;
|
int faceCulling;
|
||||||
|
@ -1357,7 +1361,6 @@ typedef struct {
|
||||||
float vertexAttribsInterpolation;
|
float vertexAttribsInterpolation;
|
||||||
qboolean vertexAnimation;
|
qboolean vertexAnimation;
|
||||||
uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise
|
uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise
|
||||||
shaderProgram_t *currentProgram;
|
|
||||||
FBO_t *currentFBO;
|
FBO_t *currentFBO;
|
||||||
vao_t *currentVao;
|
vao_t *currentVao;
|
||||||
mat4_t modelview;
|
mat4_t modelview;
|
||||||
|
@ -1373,7 +1376,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TCR_NONE = 0x0000,
|
TCR_NONE = 0x0000,
|
||||||
TCR_LATC = 0x0001,
|
TCR_RGTC = 0x0001,
|
||||||
TCR_BPTC = 0x0002,
|
TCR_BPTC = 0x0002,
|
||||||
} textureCompressionRef_t;
|
} textureCompressionRef_t;
|
||||||
|
|
||||||
|
@ -1397,7 +1400,9 @@ typedef struct {
|
||||||
qboolean textureFloat;
|
qboolean textureFloat;
|
||||||
qboolean halfFloatPixel;
|
qboolean halfFloatPixel;
|
||||||
qboolean packedDepthStencil;
|
qboolean packedDepthStencil;
|
||||||
|
qboolean arbTextureCompression;
|
||||||
textureCompressionRef_t textureCompression;
|
textureCompressionRef_t textureCompression;
|
||||||
|
qboolean swizzleNormalmap;
|
||||||
|
|
||||||
qboolean framebufferMultisample;
|
qboolean framebufferMultisample;
|
||||||
qboolean framebufferBlit;
|
qboolean framebufferBlit;
|
||||||
|
@ -1413,6 +1418,7 @@ typedef struct {
|
||||||
|
|
||||||
qboolean floatLightmap;
|
qboolean floatLightmap;
|
||||||
qboolean vertexArrayObject;
|
qboolean vertexArrayObject;
|
||||||
|
qboolean directStateAccess;
|
||||||
} glRefConfig_t;
|
} glRefConfig_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1559,8 +1565,7 @@ typedef struct {
|
||||||
int fatLightmapStep;
|
int fatLightmapStep;
|
||||||
|
|
||||||
int numCubemaps;
|
int numCubemaps;
|
||||||
vec3_t *cubemapOrigins;
|
cubemap_t *cubemaps;
|
||||||
image_t **cubemaps;
|
|
||||||
|
|
||||||
trRefEntity_t *currentEntity;
|
trRefEntity_t *currentEntity;
|
||||||
trRefEntity_t worldEntity; // point currentEntity at this when rendering world
|
trRefEntity_t worldEntity; // point currentEntity at this when rendering world
|
||||||
|
@ -1712,6 +1717,7 @@ extern cvar_t *r_ext_framebuffer_multisample;
|
||||||
extern cvar_t *r_arb_seamless_cube_map;
|
extern cvar_t *r_arb_seamless_cube_map;
|
||||||
extern cvar_t *r_arb_vertex_type_2_10_10_10_rev;
|
extern cvar_t *r_arb_vertex_type_2_10_10_10_rev;
|
||||||
extern cvar_t *r_arb_vertex_array_object;
|
extern cvar_t *r_arb_vertex_array_object;
|
||||||
|
extern cvar_t *r_ext_direct_state_access;
|
||||||
|
|
||||||
extern cvar_t *r_nobind; // turns off binding to appropriate textures
|
extern cvar_t *r_nobind; // turns off binding to appropriate textures
|
||||||
extern cvar_t *r_singleShader; // make most world faces use default shader
|
extern cvar_t *r_singleShader; // make most world faces use default shader
|
||||||
|
@ -1771,11 +1777,6 @@ extern cvar_t *r_forceAutoExposureMax;
|
||||||
|
|
||||||
extern cvar_t *r_cameraExposure;
|
extern cvar_t *r_cameraExposure;
|
||||||
|
|
||||||
extern cvar_t *r_materialGamma;
|
|
||||||
extern cvar_t *r_lightGamma;
|
|
||||||
extern cvar_t *r_framebufferGamma;
|
|
||||||
extern cvar_t *r_tonemapGamma;
|
|
||||||
|
|
||||||
extern cvar_t *r_depthPrepass;
|
extern cvar_t *r_depthPrepass;
|
||||||
extern cvar_t *r_ssao;
|
extern cvar_t *r_ssao;
|
||||||
|
|
||||||
|
@ -1784,8 +1785,8 @@ extern cvar_t *r_specularMapping;
|
||||||
extern cvar_t *r_deluxeMapping;
|
extern cvar_t *r_deluxeMapping;
|
||||||
extern cvar_t *r_parallaxMapping;
|
extern cvar_t *r_parallaxMapping;
|
||||||
extern cvar_t *r_cubeMapping;
|
extern cvar_t *r_cubeMapping;
|
||||||
extern cvar_t *r_deluxeSpecular;
|
extern cvar_t *r_cubemapSize;
|
||||||
extern cvar_t *r_specularIsMetallic;
|
extern cvar_t *r_pbr;
|
||||||
extern cvar_t *r_baseNormalX;
|
extern cvar_t *r_baseNormalX;
|
||||||
extern cvar_t *r_baseNormalY;
|
extern cvar_t *r_baseNormalY;
|
||||||
extern cvar_t *r_baseParallax;
|
extern cvar_t *r_baseParallax;
|
||||||
|
@ -1875,17 +1876,14 @@ void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms,
|
||||||
/*
|
/*
|
||||||
** GL wrapper/helper functions
|
** GL wrapper/helper functions
|
||||||
*/
|
*/
|
||||||
void GL_Bind( image_t *image );
|
|
||||||
void GL_BindToTMU( image_t *image, int tmu );
|
void GL_BindToTMU( image_t *image, int tmu );
|
||||||
void GL_SetDefaultState (void);
|
void GL_SetDefaultState (void);
|
||||||
void GL_SelectTexture( int unit );
|
|
||||||
void GL_TextureMode( const char *string );
|
void GL_TextureMode( const char *string );
|
||||||
void GL_CheckErrs( char *file, int line );
|
void GL_CheckErrs( char *file, int line );
|
||||||
#define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__)
|
#define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__)
|
||||||
void GL_State( unsigned long stateVector );
|
void GL_State( unsigned long stateVector );
|
||||||
void GL_SetProjectionMatrix(mat4_t matrix);
|
void GL_SetProjectionMatrix(mat4_t matrix);
|
||||||
void GL_SetModelviewMatrix(mat4_t matrix);
|
void GL_SetModelviewMatrix(mat4_t matrix);
|
||||||
void GL_TexEnv( int env );
|
|
||||||
void GL_Cull( int cullType );
|
void GL_Cull( int cullType );
|
||||||
|
|
||||||
#define GLS_SRCBLEND_ZERO 0x00000001
|
#define GLS_SRCBLEND_ZERO 0x00000001
|
||||||
|
@ -2209,7 +2207,6 @@ void GLSL_InitGPUShaders(void);
|
||||||
void GLSL_ShutdownGPUShaders(void);
|
void GLSL_ShutdownGPUShaders(void);
|
||||||
void GLSL_VertexAttribPointers(uint32_t attribBits);
|
void GLSL_VertexAttribPointers(uint32_t attribBits);
|
||||||
void GLSL_BindProgram(shaderProgram_t * program);
|
void GLSL_BindProgram(shaderProgram_t * program);
|
||||||
void GLSL_BindNullProgram(void);
|
|
||||||
|
|
||||||
void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value);
|
void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value);
|
||||||
void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value);
|
void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value);
|
||||||
|
@ -2411,6 +2408,10 @@ typedef struct {
|
||||||
viewParms_t viewParms;
|
viewParms_t viewParms;
|
||||||
} postProcessCommand_t;
|
} postProcessCommand_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int commandId;
|
||||||
|
} exportCubemapsCommand_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RC_END_OF_LIST,
|
RC_END_OF_LIST,
|
||||||
RC_SET_COLOR,
|
RC_SET_COLOR,
|
||||||
|
@ -2423,7 +2424,8 @@ typedef enum {
|
||||||
RC_COLORMASK,
|
RC_COLORMASK,
|
||||||
RC_CLEARDEPTH,
|
RC_CLEARDEPTH,
|
||||||
RC_CAPSHADOWMAP,
|
RC_CAPSHADOWMAP,
|
||||||
RC_POSTPROCESS
|
RC_POSTPROCESS,
|
||||||
|
RC_EXPORT_CUBEMAPS
|
||||||
} renderCommand_t;
|
} renderCommand_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1820,13 +1820,6 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we overflowed MAX_DRAWSURFS, the drawsurfs
|
|
||||||
// wrapped around in the buffer and we will be missing
|
|
||||||
// the first surfaces, not the last ones
|
|
||||||
if ( numDrawSurfs > MAX_DRAWSURFS ) {
|
|
||||||
numDrawSurfs = MAX_DRAWSURFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the drawsurfs by sort type, then orientation, then shader
|
// sort the drawsurfs by sort type, then orientation, then shader
|
||||||
R_RadixSort( drawSurfs, numDrawSurfs );
|
R_RadixSort( drawSurfs, numDrawSurfs );
|
||||||
|
|
||||||
|
@ -2037,7 +2030,7 @@ void R_DebugGraphics( void ) {
|
||||||
|
|
||||||
R_IssuePendingRenderCommands();
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage);
|
GL_BindToTMU(tr.whiteImage, TB_COLORMAP);
|
||||||
GL_Cull( CT_FRONT_SIDED );
|
GL_Cull( CT_FRONT_SIDED );
|
||||||
ri.CM_DrawDebugSurface( R_DebugPolygon );
|
ri.CM_DrawDebugSurface( R_DebugPolygon );
|
||||||
}
|
}
|
||||||
|
@ -2053,6 +2046,7 @@ or a mirror / remote location
|
||||||
*/
|
*/
|
||||||
void R_RenderView (viewParms_t *parms) {
|
void R_RenderView (viewParms_t *parms) {
|
||||||
int firstDrawSurf;
|
int firstDrawSurf;
|
||||||
|
int numDrawSurfs;
|
||||||
|
|
||||||
if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
|
if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
|
||||||
return;
|
return;
|
||||||
|
@ -2075,7 +2069,15 @@ void R_RenderView (viewParms_t *parms) {
|
||||||
|
|
||||||
R_GenerateDrawSurfs();
|
R_GenerateDrawSurfs();
|
||||||
|
|
||||||
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
|
// if we overflowed MAX_DRAWSURFS, the drawsurfs
|
||||||
|
// wrapped around in the buffer and we will be missing
|
||||||
|
// the first surfaces, not the last ones
|
||||||
|
numDrawSurfs = tr.refdef.numDrawSurfs;
|
||||||
|
if ( numDrawSurfs > MAX_DRAWSURFS ) {
|
||||||
|
numDrawSurfs = MAX_DRAWSURFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf );
|
||||||
|
|
||||||
// draw main system development information (surface outlines, etc)
|
// draw main system development information (surface outlines, etc)
|
||||||
R_DebugGraphics();
|
R_DebugGraphics();
|
||||||
|
@ -2860,7 +2862,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
|
||||||
|
|
||||||
memset( &refdef, 0, sizeof( refdef ) );
|
memset( &refdef, 0, sizeof( refdef ) );
|
||||||
refdef.rdflags = 0;
|
refdef.rdflags = 0;
|
||||||
VectorCopy(tr.cubemapOrigins[cubemapIndex], refdef.vieworg);
|
VectorCopy(tr.cubemaps[cubemapIndex].origin, refdef.vieworg);
|
||||||
|
|
||||||
switch(cubemapSide)
|
switch(cubemapSide)
|
||||||
{
|
{
|
||||||
|
@ -2934,7 +2936,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
|
||||||
// only print message for first side
|
// only print message for first side
|
||||||
if (directed[0] + directed[1] + directed[2] == 0 && cubemapSide == 0)
|
if (directed[0] + directed[1] + directed[2] == 0 && cubemapSide == 0)
|
||||||
{
|
{
|
||||||
ri.Printf(PRINT_ALL, "cubemap %d (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]);
|
ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float
|
||||||
FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
|
FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0);
|
FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
#else // higher quality blur, but slower
|
#else // higher quality blur, but slower
|
||||||
else if (blur > 1.0f)
|
else if (blur > 1.0f)
|
||||||
|
@ -217,7 +217,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float
|
||||||
FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0);
|
FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -232,49 +232,44 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretc
|
||||||
const float mul = powf(stretch, inc);
|
const float mul = powf(stretch, inc);
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
{
|
alpha *= inc;
|
||||||
vec2_t texScale;
|
VectorSet4(color, alpha, alpha, alpha, 1.0f);
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
alpha *= inc;
|
|
||||||
VectorSet4(color, alpha, alpha, alpha, 1.0f);
|
|
||||||
|
|
||||||
|
if (srcFbo)
|
||||||
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
||||||
VectorSet4(dstBox, x, y, w, h);
|
else
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0);
|
VectorSet4(srcBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||||
|
|
||||||
--passes;
|
VectorSet4(dstBox, x, y, w, h);
|
||||||
scale = mul;
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
|
||||||
while (passes > 0)
|
|
||||||
|
--passes;
|
||||||
|
scale = mul;
|
||||||
|
while (passes > 0)
|
||||||
|
{
|
||||||
|
float iscale = 1.f / scale;
|
||||||
|
float s0 = xcenter * (1.f - iscale);
|
||||||
|
float t0 = (1.0f - ycenter) * (1.f - iscale);
|
||||||
|
|
||||||
|
if (srcFbo)
|
||||||
{
|
{
|
||||||
float iscale = 1.f / scale;
|
srcBox[0] = s0 * srcFbo->width;
|
||||||
float s0 = xcenter * (1.f - iscale);
|
srcBox[1] = t0 * srcFbo->height;
|
||||||
float t0 = (1.0f - ycenter) * (1.f - iscale);
|
srcBox[2] = iscale * srcFbo->width;
|
||||||
float s1 = iscale + s0;
|
srcBox[3] = iscale * srcFbo->height;
|
||||||
float t1 = iscale + t0;
|
|
||||||
|
|
||||||
if (srcFbo)
|
|
||||||
{
|
|
||||||
srcBox[0] = s0 * srcFbo->width;
|
|
||||||
srcBox[1] = t0 * srcFbo->height;
|
|
||||||
srcBox[2] = (s1 - s0) * srcFbo->width;
|
|
||||||
srcBox[3] = (t1 - t0) * srcFbo->height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
srcBox[0] = s0 * glConfig.vidWidth;
|
|
||||||
srcBox[1] = t0 * glConfig.vidHeight;
|
|
||||||
srcBox[2] = (s1 - s0) * glConfig.vidWidth;
|
|
||||||
srcBox[3] = (t1 - t0) * glConfig.vidHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
|
||||||
|
|
||||||
scale *= mul;
|
|
||||||
--passes;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srcBox[0] = s0 * glConfig.vidWidth;
|
||||||
|
srcBox[1] = t0 * glConfig.vidHeight;
|
||||||
|
srcBox[2] = iscale * glConfig.vidWidth;
|
||||||
|
srcBox[3] = iscale * glConfig.vidHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
||||||
|
|
||||||
|
scale *= mul;
|
||||||
|
--passes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +324,7 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// From RB_DrawSun()
|
// From RB_DrawSun()
|
||||||
{
|
{
|
||||||
float dist;
|
float dist;
|
||||||
mat4_t trans, model, mvp;
|
mat4_t trans, model;
|
||||||
|
|
||||||
Mat4Translation( backEnd.viewParms.or.origin, trans );
|
Mat4Translation( backEnd.viewParms.or.origin, trans );
|
||||||
Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
|
Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
|
||||||
|
@ -353,12 +348,8 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// initialize quarter buffers
|
// initialize quarter buffers
|
||||||
{
|
{
|
||||||
float mul = 1.f;
|
float mul = 1.f;
|
||||||
vec2_t texScale;
|
|
||||||
ivec4_t rayBox, quarterBox;
|
ivec4_t rayBox, quarterBox;
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, mul, mul, mul, 1);
|
VectorSet4(color, mul, mul, mul, 1);
|
||||||
|
|
||||||
if (srcFbo)
|
if (srcFbo)
|
||||||
|
@ -408,14 +399,10 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
|
||||||
// add result back on top of the main buffer
|
// add result back on top of the main buffer
|
||||||
{
|
{
|
||||||
float mul = 1.f;
|
float mul = 1.f;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, mul, mul, mul, 1);
|
VectorSet4(color, mul, mul, mul, 1);
|
||||||
|
|
||||||
FBO_Blit(tr.quarterFbo[0], NULL, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
FBO_Blit(tr.quarterFbo[0], NULL, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,31 +430,27 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean h
|
||||||
{
|
{
|
||||||
ivec4_t srcBox, dstBox;
|
ivec4_t srcBox, dstBox;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
|
VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
|
||||||
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
|
||||||
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
|
VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0 );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0);
|
||||||
|
|
||||||
VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
|
VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
|
||||||
dx = offsets[1] * xmul;
|
dx = offsets[1] * xmul;
|
||||||
dy = offsets[1] * ymul;
|
dy = offsets[1] * ymul;
|
||||||
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
|
|
||||||
VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
|
VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
|
||||||
dx = offsets[2] * xmul;
|
dx = offsets[2] * xmul;
|
||||||
dy = offsets[2] * ymul;
|
dy = offsets[2] * ymul;
|
||||||
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
|
||||||
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,10 +475,6 @@ void RB_GaussianBlur(float blur)
|
||||||
{
|
{
|
||||||
ivec4_t srcBox, dstBox;
|
ivec4_t srcBox, dstBox;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
vec2_t texScale;
|
|
||||||
|
|
||||||
texScale[0] =
|
|
||||||
texScale[1] = 1.0f;
|
|
||||||
|
|
||||||
VectorSet4(color, 1, 1, 1, 1);
|
VectorSet4(color, 1, 1, 1, 1);
|
||||||
|
|
||||||
|
@ -507,7 +486,7 @@ void RB_GaussianBlur(float blur)
|
||||||
VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height);
|
VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height);
|
||||||
VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
||||||
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||||
FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, GLS_DEPTHTEST_DISABLE);
|
FBO_BlitFromTexture(tr.whiteImage, srcBox, NULL, tr.textureScratchFbo[0], dstBox, NULL, color, GLS_DEPTHTEST_DISABLE);
|
||||||
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
// blur the tiny buffer horizontally and vertically
|
// blur the tiny buffer horizontally and vertically
|
||||||
|
@ -518,6 +497,6 @@ void RB_GaussianBlur(float blur)
|
||||||
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
|
||||||
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
|
||||||
color[3] = factor;
|
color[3] = factor;
|
||||||
FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, NULL, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, NULL, dstBox, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,31 +335,30 @@ void RE_BeginScene(const refdef_t *fd)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if defined(USE_OVERBRIGHT)
|
||||||
|
float scale = (1 << (r_mapOverBrightBits->integer - tr.overbrightBits)) / 255.0f;
|
||||||
|
#else
|
||||||
|
float scale = (1 << r_mapOverBrightBits->integer) / 255.0f;
|
||||||
|
#endif
|
||||||
tr.refdef.colorScale = r_forceSun->integer ? r_forceSunMapLightScale->value : tr.mapLightScale;
|
tr.refdef.colorScale = r_forceSun->integer ? r_forceSunMapLightScale->value : tr.mapLightScale;
|
||||||
|
|
||||||
|
if (r_forceSun->integer)
|
||||||
|
VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
|
||||||
|
else
|
||||||
|
VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
|
||||||
|
|
||||||
if (r_sunlightMode->integer == 1)
|
if (r_sunlightMode->integer == 1)
|
||||||
{
|
{
|
||||||
tr.refdef.sunCol[0] =
|
|
||||||
tr.refdef.sunCol[1] =
|
|
||||||
tr.refdef.sunCol[2] = 1.0f;
|
|
||||||
|
|
||||||
tr.refdef.sunAmbCol[0] =
|
tr.refdef.sunAmbCol[0] =
|
||||||
tr.refdef.sunAmbCol[1] =
|
tr.refdef.sunAmbCol[1] =
|
||||||
tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale;
|
tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8);
|
|
||||||
if (r_forceSun->integer)
|
if (r_forceSun->integer)
|
||||||
{
|
|
||||||
VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
|
|
||||||
VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
|
VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
|
|
||||||
VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol);
|
VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,11 +101,9 @@ static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
if ( bundle->isVideoMap ) {
|
if ( bundle->isVideoMap ) {
|
||||||
int oldtmu = glState.currenttmu;
|
|
||||||
GL_SelectTexture(tmu);
|
|
||||||
ri.CIN_RunCinematic(bundle->videoMapHandle);
|
ri.CIN_RunCinematic(bundle->videoMapHandle);
|
||||||
ri.CIN_UploadCinematic(bundle->videoMapHandle);
|
ri.CIN_UploadCinematic(bundle->videoMapHandle);
|
||||||
GL_SelectTexture(oldtmu);
|
GL_BindToTMU(tr.scratchImage[bundle->videoMapHandle], tmu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +134,7 @@ Draws triangle outlines for debugging
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
static void DrawTris (shaderCommands_t *input) {
|
static void DrawTris (shaderCommands_t *input) {
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
|
|
||||||
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
|
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
|
||||||
qglDepthRange( 0, 0 );
|
qglDepthRange( 0, 0 );
|
||||||
|
@ -414,7 +412,7 @@ static void ProjectDlightTexture( void ) {
|
||||||
vector[3] = scale;
|
vector[3] = scale;
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector);
|
GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector);
|
||||||
|
|
||||||
GL_Bind( tr.dlightImage );
|
GL_BindToTMU( tr.dlightImage, TB_COLORMAP );
|
||||||
|
|
||||||
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
|
||||||
// where they aren't rendered
|
// where they aren't rendered
|
||||||
|
@ -444,9 +442,21 @@ static void ProjectDlightTexture( void ) {
|
||||||
|
|
||||||
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend )
|
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend )
|
||||||
{
|
{
|
||||||
|
qboolean isBlend = ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR)
|
||||||
|
|| ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR)
|
||||||
|
|| ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR)
|
||||||
|
|| ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
|
||||||
|
|
||||||
|
#if defined(USE_OVERBRIGHT)
|
||||||
|
float exactLight = 1.0f;
|
||||||
|
#else
|
||||||
|
qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL);
|
||||||
|
float exactLight = (isBlend || !isWorldDraw) ? 1.0f : (float)(1 << r_mapOverBrightBits->integer);
|
||||||
|
#endif
|
||||||
|
|
||||||
baseColor[0] =
|
baseColor[0] =
|
||||||
baseColor[1] =
|
baseColor[1] =
|
||||||
baseColor[2] =
|
baseColor[2] = exactLight;
|
||||||
baseColor[3] = 1.0f;
|
baseColor[3] = 1.0f;
|
||||||
|
|
||||||
vertColor[0] =
|
vertColor[0] =
|
||||||
|
@ -473,7 +483,7 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
|
|
||||||
vertColor[0] =
|
vertColor[0] =
|
||||||
vertColor[1] =
|
vertColor[1] =
|
||||||
vertColor[2] =
|
vertColor[2] = exactLight;
|
||||||
vertColor[3] = 1.0f;
|
vertColor[3] = 1.0f;
|
||||||
break;
|
break;
|
||||||
case CGEN_CONST:
|
case CGEN_CONST:
|
||||||
|
@ -601,11 +611,7 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiply color by overbrightbits if this isn't a blend
|
// multiply color by overbrightbits if this isn't a blend
|
||||||
if (tr.overbrightBits
|
if (tr.overbrightBits && !isBlend)
|
||||||
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR)
|
|
||||||
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR)
|
|
||||||
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR)
|
|
||||||
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR))
|
|
||||||
{
|
{
|
||||||
float scale = 1 << tr.overbrightBits;
|
float scale = 1 << tr.overbrightBits;
|
||||||
|
|
||||||
|
@ -854,11 +860,7 @@ static void ForwardDlight( void ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_dlightMode->integer >= 2)
|
if (r_dlightMode->integer >= 2)
|
||||||
{
|
GL_BindToTMU(tr.shadowCubemaps[l], TB_SHADOWMAP);
|
||||||
GL_SelectTexture(TB_SHADOWMAP);
|
|
||||||
GL_Bind(tr.shadowCubemaps[l]);
|
|
||||||
GL_SelectTexture(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
|
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
|
||||||
|
@ -1258,7 +1260,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
if ( backEnd.depthFill )
|
if ( backEnd.depthFill )
|
||||||
{
|
{
|
||||||
if (!(pStage->stateBits & GLS_ATEST_BITS))
|
if (!(pStage->stateBits & GLS_ATEST_BITS))
|
||||||
GL_BindToTMU( tr.whiteImage, 0 );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
|
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
|
||||||
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
|
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
|
||||||
}
|
}
|
||||||
|
@ -1271,7 +1273,19 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
{
|
{
|
||||||
GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
|
GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol);
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol);
|
||||||
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol);
|
if (r_pbr->integer)
|
||||||
|
{
|
||||||
|
vec3_t color;
|
||||||
|
|
||||||
|
color[0] = backEnd.refdef.sunCol[0] * backEnd.refdef.sunCol[0];
|
||||||
|
color[1] = backEnd.refdef.sunCol[1] * backEnd.refdef.sunCol[1];
|
||||||
|
color[2] = backEnd.refdef.sunCol[2] * backEnd.refdef.sunCol[2];
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol);
|
||||||
|
}
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir);
|
GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,15 +1381,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
|
||||||
if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer)
|
if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer)
|
||||||
{
|
{
|
||||||
vec4_t vec;
|
vec4_t vec;
|
||||||
|
cubemap_t *cubemap = &tr.cubemaps[input->cubemapIndex - 1];
|
||||||
|
|
||||||
GL_BindToTMU( tr.cubemaps[input->cubemapIndex - 1], TB_CUBEMAP);
|
GL_BindToTMU( cubemap->image, TB_CUBEMAP);
|
||||||
|
|
||||||
vec[0] = tr.cubemapOrigins[input->cubemapIndex - 1][0] - backEnd.viewParms.or.origin[0];
|
VectorSubtract(cubemap->origin, backEnd.viewParms.or.origin, vec);
|
||||||
vec[1] = tr.cubemapOrigins[input->cubemapIndex - 1][1] - backEnd.viewParms.or.origin[1];
|
|
||||||
vec[2] = tr.cubemapOrigins[input->cubemapIndex - 1][2] - backEnd.viewParms.or.origin[2];
|
|
||||||
vec[3] = 1.0f;
|
vec[3] = 1.0f;
|
||||||
|
|
||||||
VectorScale4(vec, 1.0f / 1000.0f, vec);
|
VectorScale4(vec, 1.0f / cubemap->parallaxRadius, vec);
|
||||||
|
|
||||||
GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec);
|
GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -934,9 +934,18 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
|
ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
stage->specularScale[0] =
|
|
||||||
stage->specularScale[1] =
|
if (r_pbr->integer)
|
||||||
stage->specularScale[2] = atof( token );
|
{
|
||||||
|
// interpret specularReflectance < 0.5 as nonmetal
|
||||||
|
stage->specularScale[1] = (atof(token) < 0.5f) ? 0.0f : 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stage->specularScale[0] =
|
||||||
|
stage->specularScale[1] =
|
||||||
|
stage->specularScale[2] = atof( token );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// specularExponent <value>
|
// specularExponent <value>
|
||||||
|
@ -954,17 +963,23 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
|
|
||||||
exponent = atof( token );
|
exponent = atof( token );
|
||||||
|
|
||||||
// Change shininess to gloss
|
if (r_pbr->integer)
|
||||||
// FIXME: assumes max exponent of 8192 and min of 1, must change here if altered in lightall_fp.glsl
|
stage->specularScale[0] = 1.0f - powf(2.0f / (exponent + 2.0), 0.25);
|
||||||
exponent = CLAMP(exponent, 1.0, 8192.0);
|
else
|
||||||
|
{
|
||||||
stage->specularScale[3] = log(exponent) / log(8192.0);
|
// Change shininess to gloss
|
||||||
|
// Assumes max exponent of 8190 and min of 0, must change here if altered in lightall_fp.glsl
|
||||||
|
exponent = CLAMP(exponent, 0.0f, 8190.0f);
|
||||||
|
stage->specularScale[3] = (log2f(exponent + 2.0f) - 1.0f) / 12.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// gloss <value>
|
// gloss <value>
|
||||||
//
|
//
|
||||||
else if (!Q_stricmp(token, "gloss"))
|
else if (!Q_stricmp(token, "gloss"))
|
||||||
{
|
{
|
||||||
|
float gloss;
|
||||||
|
|
||||||
token = COM_ParseExt(text, qfalse);
|
token = COM_ParseExt(text, qfalse);
|
||||||
if ( token[0] == 0 )
|
if ( token[0] == 0 )
|
||||||
{
|
{
|
||||||
|
@ -972,7 +987,38 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage->specularScale[3] = atof( token );
|
gloss = atof(token);
|
||||||
|
|
||||||
|
if (r_pbr->integer)
|
||||||
|
stage->specularScale[0] = 1.0f - exp2f(-3.0f * gloss);
|
||||||
|
else
|
||||||
|
stage->specularScale[3] = gloss;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// roughness <value>
|
||||||
|
//
|
||||||
|
else if (!Q_stricmp(token, "roughness"))
|
||||||
|
{
|
||||||
|
float roughness;
|
||||||
|
|
||||||
|
token = COM_ParseExt(text, qfalse);
|
||||||
|
if (token[0] == 0)
|
||||||
|
{
|
||||||
|
ri.Printf(PRINT_WARNING, "WARNING: missing parameter for roughness in shader '%s'\n", shader.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
roughness = atof(token);
|
||||||
|
|
||||||
|
if (r_pbr->integer)
|
||||||
|
stage->specularScale[0] = 1.0 - roughness;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (roughness >= 0.125)
|
||||||
|
stage->specularScale[3] = log2f(1.0f / roughness) / 3.0f;
|
||||||
|
else
|
||||||
|
stage->specularScale[3] = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// parallaxDepth <value>
|
// parallaxDepth <value>
|
||||||
|
@ -1025,6 +1071,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// specularScale <rgb> <gloss>
|
// specularScale <rgb> <gloss>
|
||||||
|
// or specularScale <metallic> <smoothness> with r_pbr 1
|
||||||
// or specularScale <r> <g> <b>
|
// or specularScale <r> <g> <b>
|
||||||
// or specularScale <r> <g> <b> <gloss>
|
// or specularScale <r> <g> <b> <gloss>
|
||||||
//
|
//
|
||||||
|
@ -1051,10 +1098,19 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
|
||||||
token = COM_ParseExt(text, qfalse);
|
token = COM_ParseExt(text, qfalse);
|
||||||
if ( token[0] == 0 )
|
if ( token[0] == 0 )
|
||||||
{
|
{
|
||||||
// two values, rgb then gloss
|
if (r_pbr->integer)
|
||||||
stage->specularScale[3] = stage->specularScale[1];
|
{
|
||||||
stage->specularScale[1] =
|
// two values, metallic then smoothness
|
||||||
stage->specularScale[2] = stage->specularScale[0];
|
float smoothness = stage->specularScale[1];
|
||||||
|
stage->specularScale[1] = (stage->specularScale[0] < 0.5f) ? 0.0f : 1.0f;
|
||||||
|
stage->specularScale[0] = smoothness;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// two values, rgb then gloss
|
||||||
|
stage->specularScale[3] = stage->specularScale[1];
|
||||||
|
stage->specularScale[1] =
|
||||||
|
stage->specularScale[2] = stage->specularScale[0];
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2212,12 +2268,33 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
|
||||||
|
|
||||||
if (r_specularMapping->integer)
|
if (r_specularMapping->integer)
|
||||||
{
|
{
|
||||||
|
image_t *diffuseImg;
|
||||||
if (specular)
|
if (specular)
|
||||||
{
|
{
|
||||||
//ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
|
//ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
|
||||||
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
|
diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
|
||||||
VectorCopy4(specular->specularScale, diffuse->specularScale);
|
VectorCopy4(specular->specularScale, diffuse->specularScale);
|
||||||
}
|
}
|
||||||
|
else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0]))
|
||||||
|
{
|
||||||
|
char specularName[MAX_QPATH];
|
||||||
|
image_t *specularImg;
|
||||||
|
imgFlags_t specularFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
|
||||||
|
|
||||||
|
COM_StripExtension(diffuseImg->imgName, specularName, MAX_QPATH);
|
||||||
|
Q_strcat(specularName, MAX_QPATH, "_s");
|
||||||
|
|
||||||
|
specularImg = R_FindImageFile(specularName, IMGTYPE_COLORALPHA, specularFlags);
|
||||||
|
|
||||||
|
if (specularImg)
|
||||||
|
{
|
||||||
|
diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
|
||||||
|
diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0;
|
||||||
|
diffuse->bundle[TB_SPECULARMAP].image[0] = specularImg;
|
||||||
|
|
||||||
|
VectorSet4(diffuse->specularScale, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcgen || diffuse->bundle[0].numTexMods)
|
if (tcgen || diffuse->bundle[0].numTexMods)
|
||||||
|
@ -2799,10 +2876,17 @@ static void InitShader( const char *name, int lightmapIndex ) {
|
||||||
|
|
||||||
// default normal/specular
|
// default normal/specular
|
||||||
VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
|
VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
stages[i].specularScale[0] =
|
if (r_pbr->integer)
|
||||||
stages[i].specularScale[1] =
|
{
|
||||||
stages[i].specularScale[2] = r_baseSpecular->value;
|
stages[i].specularScale[0] = r_baseGloss->value;
|
||||||
stages[i].specularScale[3] = r_baseGloss->value;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stages[i].specularScale[0] =
|
||||||
|
stages[i].specularScale[1] =
|
||||||
|
stages[i].specularScale[2] = r_baseSpecular->value;
|
||||||
|
stages[i].specularScale[3] = r_baseGloss->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,7 @@ void RB_ShadowTessEnd( void ) {
|
||||||
|
|
||||||
// draw the silhouette edges
|
// draw the silhouette edges
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
|
||||||
qglColor3f( 0.2f, 0.2f, 0.2f );
|
qglColor3f( 0.2f, 0.2f, 0.2f );
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ void RB_ShadowFinish( void ) {
|
||||||
qglDisable (GL_CLIP_PLANE0);
|
qglDisable (GL_CLIP_PLANE0);
|
||||||
GL_Cull( CT_TWO_SIDED );
|
GL_Cull( CT_TWO_SIDED );
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
|
|
||||||
qglLoadIdentity ();
|
qglLoadIdentity ();
|
||||||
|
|
||||||
|
|
|
@ -374,7 +374,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
|
||||||
//tess.numIndexes = 0;
|
//tess.numIndexes = 0;
|
||||||
tess.firstIndex = tess.numIndexes;
|
tess.firstIndex = tess.numIndexes;
|
||||||
|
|
||||||
GL_Bind( image );
|
GL_BindToTMU( image, TB_COLORMAP );
|
||||||
GL_Cull( CT_TWO_SIDED );
|
GL_Cull( CT_TWO_SIDED );
|
||||||
|
|
||||||
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
|
||||||
|
|
|
@ -575,7 +575,7 @@ static void RB_SurfaceBeam( void )
|
||||||
VectorAdd( start_points[i], direction, end_points[i] );
|
VectorAdd( start_points[i], direction, end_points[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
|
|
||||||
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
|
||||||
|
|
||||||
|
@ -1518,7 +1518,7 @@ Draws x/y/z lines from the origin for orientation debugging
|
||||||
static void RB_SurfaceAxis( void ) {
|
static void RB_SurfaceAxis( void ) {
|
||||||
// FIXME: implement this
|
// FIXME: implement this
|
||||||
#if 0
|
#if 0
|
||||||
GL_Bind( tr.whiteImage );
|
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
|
||||||
GL_State( GLS_DEFAULT );
|
GL_State( GLS_DEFAULT );
|
||||||
qglLineWidth( 3 );
|
qglLineWidth( 3 );
|
||||||
qglBegin( GL_LINES );
|
qglBegin( GL_LINES );
|
||||||
|
|
|
@ -44,7 +44,7 @@ typedef struct voipServerPacket_s
|
||||||
int len;
|
int len;
|
||||||
int sender;
|
int sender;
|
||||||
int flags;
|
int flags;
|
||||||
byte data[1024];
|
byte data[4000];
|
||||||
} voipServerPacket_t;
|
} voipServerPacket_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -299,6 +299,7 @@ extern int serverBansCount;
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
extern cvar_t *sv_voip;
|
extern cvar_t *sv_voip;
|
||||||
|
extern cvar_t *sv_voipProtocol;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1303,6 +1303,71 @@ static void SV_ConTell_f(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
SV_ConSayto_f
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void SV_ConSayto_f(void) {
|
||||||
|
char *p;
|
||||||
|
char text[1024];
|
||||||
|
client_t *cl;
|
||||||
|
char *rawname;
|
||||||
|
char name[MAX_NAME_LENGTH];
|
||||||
|
char cleanName[MAX_NAME_LENGTH];
|
||||||
|
client_t *saytocl;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// make sure server is running
|
||||||
|
if ( !com_sv_running->integer ) {
|
||||||
|
Com_Printf( "Server is not running.\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Cmd_Argc() < 3 ) {
|
||||||
|
Com_Printf ("Usage: sayto <player name> <text>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rawname = Cmd_Argv(1);
|
||||||
|
|
||||||
|
//allowing special characters in the console
|
||||||
|
//with hex strings for player names
|
||||||
|
Com_FieldStringToPlayerName( name, MAX_NAME_LENGTH, rawname );
|
||||||
|
|
||||||
|
saytocl = NULL;
|
||||||
|
for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) {
|
||||||
|
if ( !cl->state ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Q_strncpyz( cleanName, cl->name, sizeof(cleanName) );
|
||||||
|
Q_CleanStr( cleanName );
|
||||||
|
|
||||||
|
if ( !Q_stricmp( cleanName, name ) ) {
|
||||||
|
saytocl = cl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !saytocl )
|
||||||
|
{
|
||||||
|
Com_Printf ("No such player name: %s.\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy (text, "console_sayto: ");
|
||||||
|
p = Cmd_ArgsFrom(2);
|
||||||
|
|
||||||
|
if ( *p == '"' ) {
|
||||||
|
p++;
|
||||||
|
p[strlen(p)-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(text, p);
|
||||||
|
|
||||||
|
SV_SendServerCommand(saytocl, "chat \"%s\"", text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
SV_Heartbeat_f
|
SV_Heartbeat_f
|
||||||
|
@ -1407,6 +1472,43 @@ static void SV_CompleteMapName( char *args, int argNum ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
SV_CompletePlayerName
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static void SV_CompletePlayerName( char *args, int argNum ) {
|
||||||
|
if( argNum == 2 ) {
|
||||||
|
char names[MAX_CLIENTS][MAX_NAME_LENGTH];
|
||||||
|
char *namesPtr[MAX_CLIENTS];
|
||||||
|
client_t *cl;
|
||||||
|
int i;
|
||||||
|
int nameCount;
|
||||||
|
int clientCount;
|
||||||
|
|
||||||
|
nameCount = 0;
|
||||||
|
clientCount = sv_maxclients->integer;
|
||||||
|
|
||||||
|
for ( i=0, cl=svs.clients ; i < clientCount; i++,cl++ ) {
|
||||||
|
if ( !cl->state ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( i >= MAX_CLIENTS ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Q_strncpyz( names[nameCount], cl->name, sizeof(names[nameCount]) );
|
||||||
|
Q_CleanStr( names[nameCount] );
|
||||||
|
|
||||||
|
namesPtr[nameCount] = names[nameCount];
|
||||||
|
|
||||||
|
nameCount++;
|
||||||
|
}
|
||||||
|
qsort( (void*)namesPtr, nameCount, sizeof( namesPtr[0] ), Com_strCompare );
|
||||||
|
|
||||||
|
Field_CompletePlayerName( namesPtr, nameCount );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
SV_AddOperatorCommands
|
SV_AddOperatorCommands
|
||||||
|
@ -1453,6 +1555,8 @@ void SV_AddOperatorCommands( void ) {
|
||||||
if( com_dedicated->integer ) {
|
if( com_dedicated->integer ) {
|
||||||
Cmd_AddCommand ("say", SV_ConSay_f);
|
Cmd_AddCommand ("say", SV_ConSay_f);
|
||||||
Cmd_AddCommand ("tell", SV_ConTell_f);
|
Cmd_AddCommand ("tell", SV_ConTell_f);
|
||||||
|
Cmd_AddCommand ("sayto", SV_ConSayto_f);
|
||||||
|
Cmd_SetCommandCompletionFunc( "sayto", SV_CompletePlayerName );
|
||||||
}
|
}
|
||||||
|
|
||||||
Cmd_AddCommand("rehashbans", SV_RehashBans_f);
|
Cmd_AddCommand("rehashbans", SV_RehashBans_f);
|
||||||
|
|
|
@ -1459,8 +1459,8 @@ void SV_UserinfoChanged( client_t *cl ) {
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
val = Info_ValueForKey(cl->userinfo, "cl_voip");
|
val = Info_ValueForKey(cl->userinfo, "cl_voipProtocol");
|
||||||
cl->hasVoip = atoi(val);
|
cl->hasVoip = !Q_stricmp( val, "opus" );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1794,7 +1794,7 @@ static qboolean SV_ShouldIgnoreVoipSender(const client_t *cl)
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void SV_UserVoip(client_t *cl, msg_t *msg)
|
void SV_UserVoip(client_t *cl, msg_t *msg, qboolean ignoreData)
|
||||||
{
|
{
|
||||||
int sender, generation, sequence, frames, packetsize;
|
int sender, generation, sequence, frames, packetsize;
|
||||||
uint8_t recips[(MAX_CLIENTS + 7) / 8];
|
uint8_t recips[(MAX_CLIENTS + 7) / 8];
|
||||||
|
@ -1829,12 +1829,12 @@ void SV_UserVoip(client_t *cl, msg_t *msg)
|
||||||
|
|
||||||
MSG_ReadData(msg, encoded, packetsize);
|
MSG_ReadData(msg, encoded, packetsize);
|
||||||
|
|
||||||
if (SV_ShouldIgnoreVoipSender(cl))
|
if (ignoreData || SV_ShouldIgnoreVoipSender(cl))
|
||||||
return; // Blacklisted, disabled, etc.
|
return; // Blacklisted, disabled, etc.
|
||||||
|
|
||||||
// !!! FIXME: see if we read past end of msg...
|
// !!! FIXME: see if we read past end of msg...
|
||||||
|
|
||||||
// !!! FIXME: reject if not speex narrowband codec.
|
// !!! FIXME: reject if not opus data.
|
||||||
// !!! FIXME: decide if this is bogus data?
|
// !!! FIXME: decide if this is bogus data?
|
||||||
|
|
||||||
// decide who needs this VoIP packet sent to them...
|
// decide who needs this VoIP packet sent to them...
|
||||||
|
@ -1983,10 +1983,18 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
|
||||||
}
|
}
|
||||||
} while ( 1 );
|
} while ( 1 );
|
||||||
|
|
||||||
// read optional voip data
|
// skip legacy speex voip data
|
||||||
if ( c == clc_voip ) {
|
if ( c == clc_voipSpeex ) {
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
SV_UserVoip( cl, msg );
|
SV_UserVoip( cl, msg, qtrue );
|
||||||
|
c = MSG_ReadByte( msg );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// read optional voip data
|
||||||
|
if ( c == clc_voipOpus ) {
|
||||||
|
#ifdef USE_VOIP
|
||||||
|
SV_UserVoip( cl, msg, qfalse );
|
||||||
c = MSG_ReadByte( msg );
|
c = MSG_ReadByte( msg );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,8 +656,9 @@ void SV_Init (void)
|
||||||
sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM );
|
sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM );
|
||||||
sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO );
|
sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO );
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
sv_voip = Cvar_Get("sv_voip", "1", CVAR_SYSTEMINFO | CVAR_LATCH);
|
sv_voip = Cvar_Get("sv_voip", "1", CVAR_LATCH);
|
||||||
Cvar_CheckRange(sv_voip, 0, 1, qtrue);
|
Cvar_CheckRange(sv_voip, 0, 1, qtrue);
|
||||||
|
sv_voipProtocol = Cvar_Get("sv_voipProtocol", sv_voip->integer ? "opus" : "", CVAR_SYSTEMINFO | CVAR_ROM );
|
||||||
#endif
|
#endif
|
||||||
Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM );
|
Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM );
|
||||||
Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM );
|
Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM );
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
cvar_t *sv_voip;
|
cvar_t *sv_voip;
|
||||||
|
cvar_t *sv_voipProtocol;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
serverStatic_t svs; // persistant server info
|
serverStatic_t svs; // persistant server info
|
||||||
|
@ -665,8 +666,8 @@ void SVC_Info( netadr_t from ) {
|
||||||
Info_SetValueForKey(infostring, "g_needpass", va("%d", Cvar_VariableIntegerValue("g_needpass")));
|
Info_SetValueForKey(infostring, "g_needpass", va("%d", Cvar_VariableIntegerValue("g_needpass")));
|
||||||
|
|
||||||
#ifdef USE_VOIP
|
#ifdef USE_VOIP
|
||||||
if (sv_voip->integer) {
|
if (sv_voipProtocol->string && *sv_voipProtocol->string) {
|
||||||
Info_SetValueForKey( infostring, "voip", va("%i", sv_voip->integer ) );
|
Info_SetValueForKey( infostring, "voip", sv_voipProtocol->string );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -547,7 +547,7 @@ static void SV_WriteVoipToClient(client_t *cl, msg_t *msg)
|
||||||
if (totalbytes > (msg->maxsize - msg->cursize) / 2)
|
if (totalbytes > (msg->maxsize - msg->cursize) / 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
MSG_WriteByte(msg, svc_voip);
|
MSG_WriteByte(msg, svc_voipOpus);
|
||||||
MSG_WriteShort(msg, packet->sender);
|
MSG_WriteShort(msg, packet->sender);
|
||||||
MSG_WriteByte(msg, (byte) packet->generation);
|
MSG_WriteByte(msg, (byte) packet->generation);
|
||||||
MSG_WriteLong(msg, packet->sequence);
|
MSG_WriteLong(msg, packet->sequence);
|
||||||
|
|
|
@ -644,12 +644,6 @@ int main( int argc, char **argv )
|
||||||
// Set the initial time base
|
// Set the initial time base
|
||||||
Sys_Milliseconds( );
|
Sys_Milliseconds( );
|
||||||
|
|
||||||
#ifdef MACOS_X
|
|
||||||
// This is passed if we are launched by double-clicking
|
|
||||||
if ( argc >= 2 && Q_strncmp ( argv[1], "-psn", 4 ) == 0 )
|
|
||||||
argc = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MACOS_X
|
#ifdef MACOS_X
|
||||||
// This is passed if we are launched by double-clicking
|
// This is passed if we are launched by double-clicking
|
||||||
if ( argc >= 2 && Q_strncmp ( argv[1], "-psn", 4 ) == 0 )
|
if ( argc >= 2 && Q_strncmp ( argv[1], "-psn", 4 ) == 0 )
|
||||||
|
|
|
@ -142,14 +142,8 @@ char *Sys_SteamPath( void )
|
||||||
qboolean finishPath = qfalse;
|
qboolean finishPath = qfalse;
|
||||||
|
|
||||||
#ifdef STEAMPATH_APPID
|
#ifdef STEAMPATH_APPID
|
||||||
if (!steamPath[0] && !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App " STEAMPATH_APPID, 0, KEY_QUERY_VALUE, &steamRegKey))
|
// Assuming Steam is a 32-bit app
|
||||||
{
|
if (!steamPath[0] && !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App " STEAMPATH_APPID, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &steamRegKey))
|
||||||
pathLen = MAX_OSPATH;
|
|
||||||
if (RegQueryValueEx(steamRegKey, "InstallLocation", NULL, NULL, (LPBYTE)steamPath, &pathLen))
|
|
||||||
steamPath[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!steamPath[0] && !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App " STEAMPATH_APPID, 0, KEY_QUERY_VALUE, &steamRegKey))
|
|
||||||
{
|
{
|
||||||
pathLen = MAX_OSPATH;
|
pathLen = MAX_OSPATH;
|
||||||
if (RegQueryValueEx(steamRegKey, "InstallLocation", NULL, NULL, (LPBYTE)steamPath, &pathLen))
|
if (RegQueryValueEx(steamRegKey, "InstallLocation", NULL, NULL, (LPBYTE)steamPath, &pathLen))
|
||||||
|
|
|
@ -18,7 +18,7 @@ compatibility with existing Quake 3 mods.
|
||||||
- Texture upsampling.
|
- Texture upsampling.
|
||||||
- Advanced materials support.
|
- Advanced materials support.
|
||||||
- Advanced shading and specular methods.
|
- Advanced shading and specular methods.
|
||||||
- LATC and BPTC texture compression support.
|
- RGTC and BPTC texture compression support.
|
||||||
- Screen-space ambient occlusion.
|
- Screen-space ambient occlusion.
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ Cvars for simple rendering features:
|
||||||
|
|
||||||
* `r_ext_compressed_textures` - Automatically compress textures.
|
* `r_ext_compressed_textures` - Automatically compress textures.
|
||||||
0 - No texture compression. (default)
|
0 - No texture compression. (default)
|
||||||
1 - DXT/LATC texture compression if
|
1 - DXT/RGTC texture compression if
|
||||||
supported.
|
supported.
|
||||||
2 - BPTC texture compression if supported.
|
2 - BPTC texture compression if supported.
|
||||||
|
|
||||||
|
@ -160,24 +160,15 @@ Cvars for HDR and tonemapping:
|
||||||
|
|
||||||
Cvars for advanced material usage:
|
Cvars for advanced material usage:
|
||||||
|
|
||||||
* `r_normalMapping` - Enable normal mapping for materials that
|
* `r_normalMapping` - Enable normal maps for materials that
|
||||||
support it, and also specify advanced
|
support it.
|
||||||
shading techniques.
|
|
||||||
0 - No.
|
0 - No.
|
||||||
1 - Yes. (default)
|
1 - Yes. (default)
|
||||||
2 - Yes, and use Oren-Nayar reflectance
|
|
||||||
model.
|
|
||||||
3 - Yes, and use tri-Ace's Oren-Nayar
|
|
||||||
reflectance model.
|
|
||||||
|
|
||||||
* `r_specularMapping` - Enable specular mapping for materials that
|
* `r_specularMapping` - Enable specular maps for materials that
|
||||||
support it, and also specify advanced
|
support it.
|
||||||
specular techniques.
|
|
||||||
0 - No.
|
0 - No.
|
||||||
1 - Yes, and use tri-Ace. (default)
|
1 - Yes. (default)
|
||||||
2 - Yes, and use Blinn-Phong.
|
|
||||||
3 - Yes, and use Cook-Torrance.
|
|
||||||
4 - Yes, and use Torrance-Sparrow.
|
|
||||||
|
|
||||||
* `r_deluxeMapping` - Enable deluxe mapping. (Map is compiled
|
* `r_deluxeMapping` - Enable deluxe mapping. (Map is compiled
|
||||||
with light directions.) Even if the map
|
with light directions.) Even if the map
|
||||||
|
@ -231,6 +222,12 @@ Cvars for advanced material usage:
|
||||||
0.05 - Standard depth. (default)
|
0.05 - Standard depth. (default)
|
||||||
0.1 - Looks broken.
|
0.1 - Looks broken.
|
||||||
|
|
||||||
|
* `r_pbr` - Enable physically based rendering.
|
||||||
|
Experimental, will not look correct without
|
||||||
|
assets meant for it.
|
||||||
|
0 - No. (default)
|
||||||
|
1 - Yes.
|
||||||
|
|
||||||
Cvars for image interpolation and generation:
|
Cvars for image interpolation and generation:
|
||||||
|
|
||||||
* `r_imageUpsample` - Use interpolation to artifically increase
|
* `r_imageUpsample` - Use interpolation to artifically increase
|
||||||
|
@ -333,13 +330,6 @@ Cvars that you probably don't care about or shouldn't mess with:
|
||||||
0 - No.
|
0 - No.
|
||||||
1 - Yes. (default)
|
1 - Yes. (default)
|
||||||
|
|
||||||
* `r_normalAmbient` - Split map light into ambient and directed
|
|
||||||
portions when doing deluxe mapping. Not
|
|
||||||
very useful.
|
|
||||||
0 - Don't. (default).
|
|
||||||
0.3 - 30% ambient, 70% directed.
|
|
||||||
1.0 - 100% ambient.
|
|
||||||
|
|
||||||
* `r_mergeLightmaps` - Merge the small (128x128) lightmaps into
|
* `r_mergeLightmaps` - Merge the small (128x128) lightmaps into
|
||||||
2 or fewer giant (4096x4096) lightmaps.
|
2 or fewer giant (4096x4096) lightmaps.
|
||||||
Easy speedup.
|
Easy speedup.
|
||||||
|
@ -355,20 +345,6 @@ Cvars that you probably don't care about or shouldn't mess with:
|
||||||
* `r_shadowCascadeZBias` - Z-bias for shadow cascade frustums.
|
* `r_shadowCascadeZBias` - Z-bias for shadow cascade frustums.
|
||||||
-256 - Default.
|
-256 - Default.
|
||||||
|
|
||||||
* `r_materialGamma` - Gamma level for material textures.
|
|
||||||
(diffuse, specular)
|
|
||||||
1.0 - Quake 3, fastest. (default)
|
|
||||||
|
|
||||||
* `r_lightGamma` - Gamma level for light.
|
|
||||||
(lightmap, lightgrid, vertex lights)
|
|
||||||
1.0 - Quake 3, fastest. (default)
|
|
||||||
|
|
||||||
* `r_framebufferGamma` - Gamma level for framebuffers.
|
|
||||||
1.0 - Quake 3, fastest. (default)
|
|
||||||
|
|
||||||
* `r_tonemapGamma` - Gamma applied after tonemapping.
|
|
||||||
1.0 - Quake 3, fastest. (default)
|
|
||||||
|
|
||||||
Cvars that have broken bits:
|
Cvars that have broken bits:
|
||||||
|
|
||||||
* `r_dlightMode` - Change how dynamic lights look.
|
* `r_dlightMode` - Change how dynamic lights look.
|
||||||
|
|
|
@ -6,9 +6,10 @@ failed=0;
|
||||||
(make clean release) || failed=1;
|
(make clean release) || failed=1;
|
||||||
|
|
||||||
if [ $failed -eq 1 ]; then
|
if [ $failed -eq 1 ]; then
|
||||||
echo "Build failure.";
|
echo "Build failure.";
|
||||||
else
|
else
|
||||||
echo "Build successful.";
|
echo "Build successful.";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit $failed;
|
exit $failed;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue