Compare commits

...

46 commits

Author SHA1 Message Date
Zack Middleton
23b9481646 Merge branch 'master' into game/eliteforce 2019-05-12 14:50:03 -05:00
Zack Middleton
95b9cab4d6 Fix warnings that IQM blendWeights may not be initialized 2019-04-29 15:01:47 -05:00
Zack Middleton
d404519cce Fix rendering IQM models between model frames
For lerped frames (refEntity_t frame not equal oldframe) IQM joint
matrices may have incorrect axis scale. This can cause significant model
distortion. The matrix lerp is linear causing each vector to move in a
straight line between frames instead of arcing like a circle. Each joint
frame can have a different scale so can't just normalize the joint
matrix.

Store joints as quaternions and spherical lerp between them and then
convert to a matrix. For my test model, setting up the skeleton is four
times slower now but it still seems to be fast enough to be usable.
2019-04-29 15:01:47 -05:00
Zack Middleton
d13d06424e OpenGL2: Disable r_cubeMapping if not OpenGL 3.0+
r_cubeMapping requires textureCubeLod() which is only in OpenGL 3.0
(GLSL 1.30) and later. It's not in OpenGL ES 3.0 / GLSL ES 3.00.
This needs to be checked before R_InitImages() so can't just check in
GLSL_InitGPUShaders().
2019-04-16 11:48:10 -05:00
Zack Middleton
9fcb2bb336 Override video mode list in Team Arena UI
Override the video mode list in the Team Arena data files with detected
modes from SDL like in ioquake3's Q3 UI. Add the aspect ratio to the
end of the video resolution (i.e., "640x480 (4:3)"). Add the current
(custom) video mode to the list.

Before when using a custom resolution in the menu you could not change
the video mode using the mouse because the resolution text was blank.
Now custom video resolution is displayed and can be clicked.
2019-04-16 00:02:27 -05:00
Zack Middleton
c61417b8e2 Add current (custom) resolution to Q3 UI video mode list
Custom resolution is displayed when entering system options menu and
settings can be changed without being forced to change video resolution.
2019-04-15 23:50:46 -05:00
Zack Middleton
9b4dcc809e OpenGL2: Fix compiling lightall GLSL on OpenGL 2.1
textureCubeLod() requires OpenGL 3.0 / GLSL 1.30. Added in
2018-12-21 commit e5da13f146
"OpenGL2: r_cubemapping 2 for box cubemap parallax."

Report by brugal and Simon McVittie.

Bug-Debian: https://bugs.debian.org/923226
2019-04-15 23:40:32 -05:00
Ane-Jouke Schat
44b18d72ac Fix PRINT_ERROR print level missing from CL_RefPrintf
It's used for one message in the OpenGL2 renderer.
2019-04-15 23:13:36 -05:00
James Canete
d068e1dce1 Add r_parallaxMapShadows. 2019-02-06 01:10:42 -08:00
James Canete
e5da13f146 OpenGL2: r_cubemapping 2 for box cubemap parallax. 2018-12-21 19:53:18 -08:00
kungfooman
b0d2b141e7 Add .gitignore for misc/msvc12 2018-12-14 10:00:58 +00:00
kungfooman
a6df505d59 Prevent Q_IsColorString from asserting on negative ascii chars 2018-12-14 10:00:24 +00:00
Zack Middleton
e7ab67a17f Merge branch 'master' into game/eliteforce 2018-11-16 22:02:24 -06:00
Zack Middleton
09166ba05e Make Team Arena prevTeamMember command loop around player list
Team Arena HUD's team member info box can be cycled through using
nextTeamMember and prevTeamMember commands. nextTeamMember command loops
around when end of list is reached but prevTeamMember command got stuck
at last entry in list (team overview).
2018-10-17 13:32:53 -05:00
Zack Middleton
302f12b8f6 Don't use host pkg-config when cross-compiling
Fix cross-compiling using mingw-w64 on Ubuntu 18.04.

pkg-config --cflags libcurl is now pulling in a Linux include directory
which breaks compiling.
2018-10-01 23:48:45 -05:00
Zack Middleton
0cf10d2b77 Make s_info command display channels instead of stereo
channels-1 was displayed as '# stereo', affectively a boolean for
mono or stereo. However '3 stereo' for quad surround sound doesn't
make sense.
2018-10-01 22:31:36 -05:00
Zack Middleton
58b0fb07cd Fix SDL audio playback with 16-bit stereo sound
My commit last month "Fix SDL audio playback with surround sound" broke
16-bit stereo sound. S_TransferStereo16() still assumed that dma.samples
was a power of two. I also cleaned up code related to the previously
mentioned commit.
2018-10-01 22:28:51 -05:00
Zack Middleton
93dd14c9fb Disable pulseaudio capture regardless of SDL version
SDL changed version to 2.0.9 but the pulseaudio capture bug isn't fixed
yet. Remove my version check.
2018-09-30 14:53:18 -05:00
Zack Middleton
aab1d92b13 Allow binds to use hex values for all key codes 2018-09-30 14:40:02 -05:00
Zack Middleton
33a899d6dd Fix predicting entity origin on rotating mover
Based on G_TryPushingEntity() in code/game/g_mover.c.
2018-09-15 12:06:34 -05:00
Zack Middleton
812a3dbfa5 Fix SDL audio playback with surround sound
If user has surround sound enabled, ioq3 would not play any sound.
Fix painting sound buffer for 4/5.1 audio channels. Extra channels
currently play no audio.
2018-09-13 12:58:23 -05:00
Zack Middleton
e4208cf5a7 Improve finding obelisk entitynum for bot AI
BotSetEntityNumForGoal() was checking all entities that are not
team_redobelisk (which is the obelisk visual entity) to find the
untitled obelisk collision entity. This may fail in rare cases where
there is an another entity within 10 units of the obelisk origin.
Failing to find the correct entity may cause bots to not attack the
obelisk.

Instead add BotSetEntityNumForGoalWithActivator() for looking for the
obelisk collision entity by activator classname (team_redobelisk) which
should be less likely to find the wrong entity.

This doesn't affect official Team Arena maps (unknown if it affects any
others).

Reversed strcmp check was reported by Thomas Köppe.
2018-09-12 16:26:39 -05:00
Zack Middleton
29db64070a Fix loading favorites as initial source in server browser
When I added UIAS_GLOBAL0 in 2017 I missed changing ui_browserMaster
range clamp from 6 to 7.

Reported by cdev-tux.
2018-08-28 21:35:06 -05:00
Zack Middleton
ac85e2da6f The forum is now archived 2018-08-13 16:31:25 -05:00
Zack Middleton
d717aaf01e Merge branch 'master' into game/eliteforce
Conflicts:
	code/renderergl1/tr_init.c
	code/renderergl2/tr_init.c
2018-08-13 16:31:09 -05:00
Zack Middleton
c7ebe82131 Calculate bounds for unanimated IQM models
Bounds are optional for animated IQM models but are not possible to
include with unanimated models (seems intended for use with separate
model containing animations and bounds). Calculating bounds for
unanimated IQM models fixes culling and head model on HUD which
calculates position from model bounds.
2018-08-02 18:20:18 -05:00
Zack Middleton
1994801e1c Fix axis returned by IQM's LerpTag
The axis returned for IQM tag was the animation's joint rotation without
the base frame joint rotation. It only worked correct for models that
did not rotate the base frame joints.
2018-07-31 13:59:56 -05:00
Zack Middleton
11337c9fa2 OpenGL2: Add GPU vertex skinning for IQM models
Using GPU vertex skinning is significantly faster than CPU vertex
skinning. Especially since OpenGL2 has to run R_VaoPackNormal() and
R_VaoPackTangent() each vertex each frame which causes CPU vertex
skinning to be significantly slower than OpenGL1 renderer.
2018-07-27 17:40:25 -05:00
Zack Middleton
cccd283be8 Improve IQM CPU vertex skinning performance
Only calculate vertex blend matrix for each unique bone indexes/weights
combination once per-surface instead of recalculating for each vertex.
For best performance the model surfaces needs to use few vertex bone
indexes and weights combinations.

Unroll loops so GCC better optimizes them.

In my tests drawing animated IQM may take 50% as long in opengl1 and
70% as long in opengl2. It will vary by model though and might not
help much at all.

Made unanimated IQM models skip matrix math altogether.
2018-07-27 17:40:21 -05:00
Zack Middleton
fdc08e860e Improve IQM loading
- Only allocate memory for vertex arrays that are present in the IQM
file and are actually used (may not have colors or blend index/weights,
don't load tangents in opengl1). (Colors is fixed to next commit.)
- Explicitly handle loading IQM files without meshes (bones only).
- Better IQM validation. Header data offset 0 mean data is not present
in file. Check if required vertex arrays are present.

This involved a lot of white space changes and moving code around.
2018-07-27 17:40:16 -05:00
Zack Middleton
6c3d92133d Fix IQM root joint backlerp when joint number is more than 0
Backlerp for root joint (joint with no parent) was always applied to
joint 0. This is an issue when a model has multiple root joints.
2018-07-27 17:40:09 -05:00
Zack Middleton
39e2113c73 OpenGL2: Misc fixes and cleanup
Fix two constants in GLSL shaders. Remove f suffix from float and fix
int to float assignment. They were causing shader compile errors in
OpenGL ES 2 context.

Remove disabling clip plane. Clip plane is unused and never enabled in
the opengl2 renderer. Remove disabling it to avoid causing a GL error
when using OpenGL 3.2 core profile or OpenGL ES.

Make VAO cache vertex stride be size of srfVert_t since that is what
is uploaded to the GPU. No behavior change. There is a disabled debug
id in srfVert_t though which if enabled changes srfVert_t size.
2018-07-20 23:40:35 -05:00
Zack Middleton
14cc4cc6cb OpenGL2: Fix world VAO cache drawing when glIndex_t is unsigned short
OpenGL ES is only required to support unsigned short for element buffer
values.

R_DrawElements() firstIndex argument was glIndex_t which caused element
indexes to wrap around to 0 when glIndex_t is an unsigned short.
(glIndex_t is an index into the vertexes buffer, not element buffer.)
Change it to 'int' like tess.firstIndex which is passed to
R_DrawElements().

World VAO cache buffer size allowed storing more vertexes than unsigned
short glIndex_t could reference. This resulted in the vertex indexes in
the element buffer wrapping around to 0.
2018-07-20 23:40:31 -05:00
Zack Middleton
658165cfbb Don't check fixed function GL extensions when using shader pipeline
GL_TEXTURE_UNITS_ARB is not part of OpenGL ES 2 API and sets GL error.
It's not part of OpenGL 3.2 core profile either.
2018-07-20 23:40:26 -05:00
Zack Middleton
d861a4f427 Load OpenGL ES 2.0 function procs
Load functions procs supported by OpenGL ES 2.0, though there is not a
compatible renderer yet. Change argument for GLimp_Init from coreContext
to fixedFunction.
2018-07-20 23:40:21 -05:00
Zack Middleton
7391215bd4 Don't load non-core GL functions for OpenGL 3.2 core context
Also declare the GL functions in tr_local.h so there is compile error
for non-core GL functions instead of SEGFAULT from dereferencing a NULL
pointer.

Disable the non-functional stencil shadow code that hasn't been updated
to use OpenGL 3.2 core compatible drawing.
2018-07-20 23:40:17 -05:00
Zack Middleton
255c33b367 OpenGL1: Use RE_UploadCinematic() instead of duplicate code
Already done in opengl2 renderer.
2018-07-20 23:40:12 -05:00
Zack Middleton
476134f5a6 Don't upload 8 bit grayscale images as 16 bit luminance
Using more color bits than the source image provides shouldn't improve
the quality.
2018-07-20 23:40:07 -05:00
Zack Middleton
bead4aa8c7 Fix renderer not clearing some GL extension variables at vid_restart
If renderer is compiled into client (USE_RENDERER_DLOPEN=0) and after
start up set r_allowExtension to 0 and run vid_restart, some extension
were still used.
2018-07-20 23:40:02 -05:00
Zack Middleton
c74b9a4452 Remove unused renderer_buffer variable 2018-07-20 23:39:54 -05:00
Zack Middleton
809a7765b2 Make testgun command without argument disable test gun model 2018-06-24 22:22:25 -05:00
Simon McVittie
fb4b206709 Allow pkg-config binary to be overridden with PKG_CONFIG
This is one of the de facto standard interfaces used in Linux
distributions for cross-compilation (alongside overriding CC and
similar variables), and in particular is used in Debian and its
derivatives.

Signed-off-by: Simon McVittie <smcv@debian.org>
2018-06-12 11:27:42 +01:00
Zack Middleton
38a2f4d938 Fix in_restart causing fatal error while video is shutdown
Connecting to a server running a different fs_game and using a
autoexec.cfg containing in_restart would hit a fatal error in IN_Init().

    IN_Init called before SDL_Init( SDL_INIT_VIDEO )

Reported by smokey2k on the ioquake3 forum.
2018-06-10 15:13:10 -05:00
Zack Middleton
38e06ac920 Update README.md 2018-06-10 03:32:36 -05:00
Zack Middleton
1b1d0c55f6 Fix Linux uninstaller redirecting stderr to stdout in preuninstall.sh
Last commit accidently made stderr redirect to stdout tty instead of
/dev/null.

Reported by @illwieckz.
2018-06-03 16:23:46 -05:00
Zack Middleton
466952b320 Fix Linux uninstaller requiring Bash
Linux loki-setup uninstaller is failing on distros that have /bin/sh
linked to Dash instead of Bash. Use standard shell method for
redirecting stdout and stderr instead of a Bash specific method.
2018-06-03 15:47:39 -05:00
53 changed files with 3372 additions and 1421 deletions

View file

@ -329,15 +329,28 @@ bin_path=$(shell which $(1) 2> /dev/null)
# The autoupdater uses curl, so figure out its flags no matter what.
# We won't need this if we only build the server
# set PKG_CONFIG_PATH to influence this, e.g.
# PKG_CONFIG_PATH=/opt/cross/i386-mingw32msvc/lib/pkgconfig
ifneq ($(call bin_path, pkg-config),)
CURL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags libcurl)
CURL_LIBS ?= $(shell pkg-config --silence-errors --libs libcurl)
OPENAL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags openal)
OPENAL_LIBS ?= $(shell pkg-config --silence-errors --libs openal)
SDL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags sdl2|sed 's/-Dmain=SDL_main//')
SDL_LIBS ?= $(shell pkg-config --silence-errors --libs sdl2)
# set PKG_CONFIG_PATH or PKG_CONFIG to influence this, e.g.
# PKG_CONFIG_PATH=/opt/cross/i386-mingw32msvc/lib/pkgconfig or
# PKG_CONFIG=arm-linux-gnueabihf-pkg-config
ifeq ($(CROSS_COMPILING),0)
PKG_CONFIG ?= pkg-config
else
ifneq ($(PKG_CONFIG_PATH),)
PKG_CONFIG ?= pkg-config
else
# Don't use host pkg-config when cross-compiling.
# (unknown-pkg-config is meant to be a non-existant command.)
PKG_CONFIG ?= unknown-pkg-config
endif
endif
ifneq ($(call bin_path, $(PKG_CONFIG)),)
CURL_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags libcurl)
CURL_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs libcurl)
OPENAL_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags openal)
OPENAL_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs openal)
SDL_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags sdl2|sed 's/-Dmain=SDL_main//')
SDL_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs sdl2)
else
# assume they're in the system default paths (no -I or -L needed)
CURL_LIBS ?= -lcurl
@ -1158,8 +1171,8 @@ ifeq ($(NEED_OPUS),1)
-I$(OPUSDIR)/include -I$(OPUSDIR)/celt -I$(OPUSDIR)/silk \
-I$(OPUSDIR)/silk/float -I$(OPUSFILEDIR)/include
else
OPUS_CFLAGS ?= $(shell pkg-config --silence-errors --cflags opusfile opus || true)
OPUS_LIBS ?= $(shell pkg-config --silence-errors --libs opusfile opus || echo -lopusfile -lopus)
OPUS_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags opusfile opus || true)
OPUS_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs opusfile opus || echo -lopusfile -lopus)
endif
CLIENT_CFLAGS += $(OPUS_CFLAGS)
CLIENT_LIBS += $(OPUS_LIBS)
@ -1171,8 +1184,8 @@ ifeq ($(USE_CODEC_VORBIS),1)
ifeq ($(USE_INTERNAL_VORBIS),1)
CLIENT_CFLAGS += -I$(VORBISDIR)/include -I$(VORBISDIR)/lib
else
VORBIS_CFLAGS ?= $(shell pkg-config --silence-errors --cflags vorbisfile vorbis || true)
VORBIS_LIBS ?= $(shell pkg-config --silence-errors --libs vorbisfile vorbis || echo -lvorbisfile -lvorbis)
VORBIS_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags vorbisfile vorbis || true)
VORBIS_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs vorbisfile vorbis || echo -lvorbisfile -lvorbis)
endif
CLIENT_CFLAGS += $(VORBIS_CFLAGS)
CLIENT_LIBS += $(VORBIS_LIBS)
@ -1183,8 +1196,8 @@ ifeq ($(NEED_OGG),1)
ifeq ($(USE_INTERNAL_OGG),1)
OGG_CFLAGS = -I$(OGGDIR)/include
else
OGG_CFLAGS ?= $(shell pkg-config --silence-errors --cflags ogg || true)
OGG_LIBS ?= $(shell pkg-config --silence-errors --libs ogg || echo -logg)
OGG_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags ogg || true)
OGG_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs ogg || echo -logg)
endif
CLIENT_CFLAGS += $(OGG_CFLAGS)
CLIENT_LIBS += $(OGG_LIBS)
@ -1201,8 +1214,8 @@ endif
ifeq ($(USE_INTERNAL_ZLIB),1)
ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR)
else
ZLIB_CFLAGS ?= $(shell pkg-config --silence-errors --cflags zlib || true)
ZLIB_LIBS ?= $(shell pkg-config --silence-errors --libs zlib || echo -lz)
ZLIB_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags zlib || true)
ZLIB_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs zlib || echo -lz)
endif
BASE_CFLAGS += $(ZLIB_CFLAGS)
LIBS += $(ZLIB_LIBS)
@ -1213,15 +1226,15 @@ ifeq ($(USE_INTERNAL_JPEG),1)
else
# IJG libjpeg doesn't have pkg-config, but libjpeg-turbo uses libjpeg.pc;
# we fall back to hard-coded answers if libjpeg.pc is unavailable
JPEG_CFLAGS ?= $(shell pkg-config --silence-errors --cflags libjpeg || true)
JPEG_LIBS ?= $(shell pkg-config --silence-errors --libs libjpeg || echo -ljpeg)
JPEG_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags libjpeg || true)
JPEG_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs libjpeg || echo -ljpeg)
BASE_CFLAGS += $(JPEG_CFLAGS)
RENDERER_LIBS += $(JPEG_LIBS)
endif
ifeq ($(USE_FREETYPE),1)
FREETYPE_CFLAGS ?= $(shell pkg-config --silence-errors --cflags freetype2 || true)
FREETYPE_LIBS ?= $(shell pkg-config --silence-errors --libs freetype2 || echo -lfreetype)
FREETYPE_CFLAGS ?= $(shell $(PKG_CONFIG) --silence-errors --cflags freetype2 || true)
FREETYPE_LIBS ?= $(shell $(PKG_CONFIG) --silence-errors --libs freetype2 || echo -lfreetype)
BASE_CFLAGS += -DBUILD_FREETYPE $(FREETYPE_CFLAGS)
RENDERER_LIBS += $(FREETYPE_LIBS)
@ -1454,6 +1467,7 @@ targets: makedirs
@echo " COMPILE_PLATFORM: $(COMPILE_PLATFORM)"
@echo " COMPILE_ARCH: $(COMPILE_ARCH)"
@echo " HAVE_VM_COMPILED: $(HAVE_VM_COMPILED)"
@echo " PKG_CONFIG: $(PKG_CONFIG)"
@echo " CC: $(CC)"
ifeq ($(PLATFORM),mingw32)
@echo " WINDRES: $(WINDRES)"

View file

@ -1,10 +1,10 @@
<img src="https://raw.githubusercontent.com/zturtleman/lilium-voyager/master/misc/lilium.png" width="64">
**Lilium Voyager** is a fork of [ioquake3](https://github.com/ioquake/ioq3) for running _Star Trek Voyager: Elite Force_ multiplayer. It is based on Thilo Schulz' [ioEF engine](http://thilo.kickchat.com/efport-progress/) (also known as iostvoyHM). The focus for Lilium Voyager is to maintain Elite Force multiplayer support on newer ioquake3 versions.
**Lilium Voyager** is a fork of [ioquake3](https://github.com/ioquake/ioq3) for running _Star Trek Voyager: Elite Force Holomatch_ (multiplayer). It is based on Thilo Schulz' [ioEF engine](http://thilo.kickchat.com/efport-progress/) (also known as iostvoyHM). The focus for Lilium Voyager is to maintain Elite Force multiplayer support on newer ioquake3 versions.
Differences from ioEF 1.38-rc1 (2011):
* Player origin rounding is compatible with the original QVMs.
* Player origin rounding is compatible with the original QVMs (x86, x86_64).
* Fixed "read past end of server message" error after downloading a pk3 using EF 1.2 protocol (24).
* Network compatible with ioEF 1.37.
* Dedicated servers are listed on official Raven master server.
@ -31,7 +31,7 @@ Additional make variables not in ioquake3:
## Discussion
[Magical Clover Forum](https://forum.clover.moe). It supports creating an account or logging in using a GitHub account.
* [Discord (Fragmint★Wonderland)](https://discord.gg/7J2pjGD)
## License
@ -49,6 +49,5 @@ Lilium Voyager is licensed under [the GNU GPLv2](COPYING.txt) (or at your option
## Contributing
Please submit all patches at the [Magical Clover Forum](https://forum.clover.moe)
or as a GitHub pull request.
Please submit all patches as a GitHub pull request.

View file

@ -664,6 +664,44 @@ static void CG_Portal( centity_t *cent ) {
}
/*
================
CG_CreateRotationMatrix
================
*/
void CG_CreateRotationMatrix(vec3_t angles, vec3_t matrix[3]) {
AngleVectors(angles, matrix[0], matrix[1], matrix[2]);
VectorInverse(matrix[1]);
}
/*
================
CG_TransposeMatrix
================
*/
void CG_TransposeMatrix(vec3_t matrix[3], vec3_t transpose[3]) {
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
transpose[i][j] = matrix[j][i];
}
}
}
/*
================
CG_RotatePoint
================
*/
void CG_RotatePoint(vec3_t point, vec3_t matrix[3]) {
vec3_t tvec;
VectorCopy(point, tvec);
point[0] = DotProduct(matrix[0], tvec);
point[1] = DotProduct(matrix[1], tvec);
point[2] = DotProduct(matrix[2], tvec);
}
/*
=========================
CG_AdjustPositionForMover
@ -675,6 +713,8 @@ void CG_AdjustPositionForMover(const vec3_t in, int moverNum, int fromTime, int
centity_t *cent;
vec3_t oldOrigin, origin, deltaOrigin;
vec3_t oldAngles, angles, deltaAngles;
vec3_t matrix[3], transpose[3];
vec3_t org, org2, move2;
if ( moverNum <= 0 || moverNum >= ENTITYNUM_MAX_NORMAL ) {
VectorCopy( in, out );
@ -698,9 +738,17 @@ void CG_AdjustPositionForMover(const vec3_t in, int moverNum, int fromTime, int
VectorSubtract( origin, oldOrigin, deltaOrigin );
VectorSubtract( angles, oldAngles, deltaAngles );
// origin change when on a rotating object
CG_CreateRotationMatrix( deltaAngles, transpose );
CG_TransposeMatrix( transpose, matrix );
VectorSubtract( in, oldOrigin, org );
VectorCopy( org, org2 );
CG_RotatePoint( org2, matrix );
VectorSubtract( org2, org, move2 );
VectorAdd( deltaOrigin, move2, deltaOrigin );
VectorAdd( in, deltaOrigin, out );
VectorAdd( angles_in, deltaAngles, angles_out );
// FIXME: origin change when on a rotating object
}

View file

@ -150,7 +150,7 @@ void CG_SelectNextPlayer( void ) {
void CG_SelectPrevPlayer( void ) {
CG_CheckOrderPending();
if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer <= numSortedTeamPlayers) {
cg_currentSelectedPlayer.integer--;
} else {
cg_currentSelectedPlayer.integer = numSortedTeamPlayers;

View file

@ -71,6 +71,7 @@ can then be moved around
void CG_TestModel_f (void) {
vec3_t angles;
cg.testGun = qfalse;
memset( &cg.testModelEntity, 0, sizeof(cg.testModelEntity) );
if ( trap_Argc() < 2 ) {
return;
@ -96,7 +97,6 @@ void CG_TestModel_f (void) {
angles[ROLL] = 0;
AnglesToAxis( angles, cg.testModelEntity.axis );
cg.testGun = qfalse;
}
/*
@ -108,6 +108,11 @@ Replaces the current view weapon with the given model
*/
void CG_TestGun_f (void) {
CG_TestModel_f();
if ( !cg.testModelEntity.hModel ) {
return;
}
cg.testGun = qtrue;
cg.testModelEntity.renderfx = RF_MINLIGHT | RF_DEPTHHACK | RF_FIRST_PERSON;
}

View file

@ -825,6 +825,7 @@ to be configured even if they don't have defined names.
*/
int Key_StringToKeynum( char *str ) {
keyname_t *kn;
int n;
if ( !str || !str[0] ) {
return -1;
@ -834,12 +835,9 @@ int Key_StringToKeynum( char *str ) {
}
// check for hex code
if ( strlen( str ) == 4 ) {
int n = Com_HexStrToInt( str );
if ( n >= 0 ) {
return n;
}
n = Com_HexStrToInt( str );
if ( n >= 0 && n < MAX_KEYS ) {
return n;
}
// scan for a text match

View file

@ -3186,8 +3186,10 @@ static __attribute__ ((format (printf, 2, 3))) void QDECL CL_RefPrintf( int prin
Com_Printf ("%s", msg);
} else if ( print_level == PRINT_WARNING ) {
Com_Printf (S_COLOR_YELLOW "%s", msg); // yellow
} else if ( print_level == PRINT_ERROR ) {
Com_Printf (S_COLOR_RED "%s", msg); // red
} else if ( print_level == PRINT_DEVELOPER ) {
Com_DPrintf (S_COLOR_RED "%s", msg); // red
Com_DPrintf (S_COLOR_RED "%s", msg); // red - developer only
}
}

View file

@ -98,7 +98,7 @@ void S_Base_SoundInfo(void) {
if (!s_soundStarted) {
Com_Printf ("sound system not started\n");
} else {
Com_Printf("%5d stereo\n", dma.channels - 1);
Com_Printf("%5d channels\n", dma.channels);
Com_Printf("%5d samples\n", dma.samples);
Com_Printf("%5d samplebits (%s)\n", dma.samplebits, dma.isfloat ? "float" : "int");
Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
@ -1256,9 +1256,6 @@ void S_GetSoundtime(void)
int samplepos;
static int buffers;
static int oldsamplepos;
int fullsamples;
fullsamples = dma.samples / dma.channels;
if( CL_VideoRecording( ) )
{
@ -1282,13 +1279,13 @@ void S_GetSoundtime(void)
if (s_paintedtime > 0x40000000)
{ // time to chop things off to avoid 32 bit limits
buffers = 0;
s_paintedtime = fullsamples;
s_paintedtime = dma.fullsamples;
S_Base_StopAllSounds ();
}
}
oldsamplepos = samplepos;
s_soundtime = buffers*fullsamples + samplepos/dma.channels;
s_soundtime = buffers*dma.fullsamples + samplepos/dma.channels;
#if 0
// check to make sure that we haven't overshot
@ -1309,7 +1306,6 @@ void S_GetSoundtime(void)
void S_Update_(void) {
unsigned endtime;
int samps;
static float lastTime = 0.0f;
float ma, op;
float thisTime, sane;
@ -1353,9 +1349,8 @@ void S_Update_(void) {
& ~(dma.submission_chunk-1);
// never mix more than the complete buffer
samps = dma.samples >> (dma.channels-1);
if (endtime - s_soundtime > samps)
endtime = s_soundtime + samps;
if (endtime - s_soundtime > dma.fullsamples)
endtime = s_soundtime + dma.fullsamples;

View file

@ -65,6 +65,7 @@ typedef struct sfx_s {
typedef struct {
int channels;
int samples; // mono samples in buffer
int fullsamples; // samples with all channels in buffer (samples divided by channels)
int submission_chunk; // don't mix less than this #
int samplebits;
int isfloat;

View file

@ -119,24 +119,24 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime)
while (ls_paintedtime < endtime)
{
// handle recirculating buffer issues
lpos = ls_paintedtime & ((dma.samples>>1)-1);
lpos = ls_paintedtime % dma.fullsamples;
snd_out = (short *) pbuf + (lpos<<1);
snd_out = (short *) pbuf + (lpos<<1); // lpos * dma.channels
snd_linear_count = (dma.samples>>1) - lpos;
snd_linear_count = dma.fullsamples - lpos;
if (ls_paintedtime + snd_linear_count > endtime)
snd_linear_count = endtime - ls_paintedtime;
snd_linear_count <<= 1;
snd_linear_count <<= 1; // snd_linear_count *= dma.channels
// write a linear blast of samples
S_WriteLinearBlastStereo16 ();
snd_p += snd_linear_count;
ls_paintedtime += (snd_linear_count>>1);
ls_paintedtime += (snd_linear_count>>1); // snd_linear_count / dma.channels
if( CL_VideoRecording( ) )
CL_WriteAVIAudioFrame( (byte *)snd_out, snd_linear_count << 1 );
CL_WriteAVIAudioFrame( (byte *)snd_out, snd_linear_count << 1 ); // snd_linear_count * (dma.samplebits/8)
}
}
@ -150,18 +150,16 @@ void S_TransferPaintBuffer(int endtime)
{
int out_idx;
int count;
int out_mask;
int *p;
int step;
int val;
int i;
unsigned long *pbuf;
pbuf = (unsigned long *)dma.buffer;
if ( s_testsound->integer ) {
int i;
// write a fixed sine wave
count = (endtime - s_paintedtime);
for (i=0 ; i<count ; i++)
@ -177,53 +175,73 @@ void S_TransferPaintBuffer(int endtime)
{ // general case
p = (int *) paintbuffer;
count = (endtime - s_paintedtime) * dma.channels;
out_mask = dma.samples - 1;
out_idx = s_paintedtime * dma.channels & out_mask;
step = 3 - dma.channels;
out_idx = (s_paintedtime * dma.channels) % dma.samples;
step = 3 - MIN(dma.channels, 2);
if ((dma.isfloat) && (dma.samplebits == 32))
{
float *out = (float *) pbuf;
while (count--)
for (i=0 ; i<count ; i++)
{
val = *p >> 8;
p+= step;
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32767) /* clamp to one less than max to make division max out at -1.0f. */
val = -32767;
out[out_idx] = ((float) val) / 32767.0f;
out_idx = (out_idx + 1) & out_mask;
out_idx = (out_idx + 1) % dma.samples;
}
}
else if (dma.samplebits == 16)
{
short *out = (short *) pbuf;
while (count--)
for (i=0 ; i<count ; i++)
{
val = *p >> 8;
p+= step;
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32768)
val = -32768;
out[out_idx] = val;
out_idx = (out_idx + 1) & out_mask;
out_idx = (out_idx + 1) % dma.samples;
}
}
else if (dma.samplebits == 8)
{
unsigned char *out = (unsigned char *) pbuf;
while (count--)
for (i=0 ; i<count ; i++)
{
val = *p >> 8;
p+= step;
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32768)
val = -32768;
out[out_idx] = (val>>8) + 128;
out_idx = (out_idx + 1) & out_mask;
out_idx = (out_idx + 1) % dma.samples;
}
}
}

View file

@ -5346,7 +5346,33 @@ void BotSetEntityNumForGoal(bot_goal_t *goal, char *classname) {
if ( !ent->inuse ) {
continue;
}
if ( !Q_stricmp(ent->classname, classname) ) {
if ( Q_stricmp(ent->classname, classname) != 0 ) {
continue;
}
VectorSubtract(goal->origin, ent->s.origin, dir);
if (VectorLengthSquared(dir) < Square(10)) {
goal->entitynum = i;
return;
}
}
}
/*
==================
BotSetEntityNumForGoalWithActivator
==================
*/
void BotSetEntityNumForGoalWithActivator(bot_goal_t *goal, char *classname) {
gentity_t *ent;
int i;
vec3_t dir;
ent = &g_entities[0];
for (i = 0; i < level.num_entities; i++, ent++) {
if ( !ent->inuse || !ent->activator ) {
continue;
}
if ( Q_stricmp(ent->activator->classname, classname) != 0 ) {
continue;
}
VectorSubtract(goal->origin, ent->s.origin, dir);
@ -5427,21 +5453,21 @@ void BotSetupDeathmatchAI(void) {
else if (gametype == GT_OBELISK) {
if (trap_BotGetLevelItemGoal(-1, "Red Obelisk", &redobelisk) < 0)
BotAI_Print(PRT_WARNING, "Overload without Red Obelisk\n");
BotSetEntityNumForGoal(&redobelisk, "team_redobelisk");
BotSetEntityNumForGoalWithActivator(&redobelisk, "team_redobelisk");
if (trap_BotGetLevelItemGoal(-1, "Blue Obelisk", &blueobelisk) < 0)
BotAI_Print(PRT_WARNING, "Overload without Blue Obelisk\n");
BotSetEntityNumForGoal(&blueobelisk, "team_blueobelisk");
BotSetEntityNumForGoalWithActivator(&blueobelisk, "team_blueobelisk");
}
else if (gametype == GT_HARVESTER) {
if (trap_BotGetLevelItemGoal(-1, "Red Obelisk", &redobelisk) < 0)
BotAI_Print(PRT_WARNING, "Harvester without Red Obelisk\n");
BotSetEntityNumForGoal(&redobelisk, "team_redobelisk");
BotSetEntityNumForGoalWithActivator(&redobelisk, "team_redobelisk");
if (trap_BotGetLevelItemGoal(-1, "Blue Obelisk", &blueobelisk) < 0)
BotAI_Print(PRT_WARNING, "Harvester without Blue Obelisk\n");
BotSetEntityNumForGoal(&blueobelisk, "team_blueobelisk");
BotSetEntityNumForGoalWithActivator(&blueobelisk, "team_blueobelisk");
if (trap_BotGetLevelItemGoal(-1, "Neutral Obelisk", &neutralobelisk) < 0)
BotAI_Print(PRT_WARNING, "Harvester without Neutral Obelisk\n");
BotSetEntityNumForGoal(&neutralobelisk, "team_neutralobelisk");
BotSetEntityNumForGoalWithActivator(&neutralobelisk, "team_neutralobelisk");
}
#endif

View file

@ -88,6 +88,7 @@ MULTIPLAYER MENU (SERVER BROWSER)
#define UIAS_GLOBAL4 5
#define UIAS_GLOBAL5 6
#define UIAS_FAVORITES 7
#define UIAS_NUM_SOURCES 8
#define UI_MAX_MASTER_SERVERS 6
@ -96,12 +97,14 @@ MULTIPLAYER MENU (SERVER BROWSER)
#define SORT_CLIENTS 2
#define SORT_GAME 3
#define SORT_PING 4
#define SORT_NUM_SORTS 5
#define GAMES_ALL 0
#define GAMES_FFA 1
#define GAMES_TEAMPLAY 2
#define GAMES_TOURNEY 3
#define GAMES_CTF 4
#define GAMES_NUM_GAMES 5
static const char *master_items[] = {
"Local",
@ -1104,7 +1107,7 @@ int ArenaServers_SetType( int type )
char masterstr[2], cvarname[sizeof("sv_master1")];
int direction;
if (type == g_servertype || type == ((g_servertype+1) % (ARRAY_LEN(master_items)-1))) {
if (type == g_servertype || type == ((g_servertype+1) % UIAS_NUM_SOURCES)) {
direction = 1;
} else {
direction = -1;
@ -1585,12 +1588,12 @@ static void ArenaServers_MenuInit( void ) {
ArenaServers_LoadFavorites();
g_arenaservers.master.curvalue = g_servertype = Com_Clamp( 0, 6, ui_browserMaster.integer );
g_arenaservers.master.curvalue = g_servertype = Com_Clamp( 0, UIAS_NUM_SOURCES-1, ui_browserMaster.integer );
g_gametype = Com_Clamp( 0, 4, ui_browserGameType.integer );
g_gametype = Com_Clamp( 0, GAMES_NUM_GAMES-1, ui_browserGameType.integer );
g_arenaservers.gametype.curvalue = g_gametype;
g_sortkey = Com_Clamp( 0, 4, ui_browserSortKey.integer );
g_sortkey = Com_Clamp( 0, SORT_NUM_SORTS-1, ui_browserSortKey.integer );
g_arenaservers.sortkey.curvalue = g_sortkey;
g_fullservers = Com_Clamp( 0, 1, ui_browserShowFull.integer );

View file

@ -358,6 +358,7 @@ static int resToRatio[ MAX_RESOLUTIONS ];
static char resbuf[ MAX_STRING_CHARS ];
static const char* detectedResolutions[ MAX_RESOLUTIONS ];
static char currentResolution[ 20 ];
static const char** resolutions = builtinResolutions;
static qboolean resolutionsDetected = qfalse;
@ -487,7 +488,7 @@ GraphicsOptions_GetResolutions
*/
static void GraphicsOptions_GetResolutions( void )
{
Q_strncpyz(resbuf, UI_Cvar_VariableString("r_availableModes"), sizeof(resbuf));
trap_Cvar_VariableStringBuffer("r_availableModes", resbuf, sizeof(resbuf));
if(*resbuf)
{
char* s = resbuf;
@ -501,11 +502,26 @@ static void GraphicsOptions_GetResolutions( void )
}
detectedResolutions[ i ] = NULL;
if( i > 0 )
// add custom resolution if not in mode list
if ( i < ARRAY_LEN(detectedResolutions)-1 )
{
resolutions = detectedResolutions;
resolutionsDetected = qtrue;
Com_sprintf( currentResolution, sizeof ( currentResolution ), "%dx%d", uis.glconfig.vidWidth, uis.glconfig.vidHeight );
for( i = 0; detectedResolutions[ i ]; i++ )
{
if ( strcmp( detectedResolutions[ i ], currentResolution ) == 0 )
break;
}
if ( detectedResolutions[ i ] == NULL )
{
detectedResolutions[ i++ ] = currentResolution;
detectedResolutions[ i ] = NULL;
}
}
resolutions = detectedResolutions;
resolutionsDetected = qtrue;
}
}

View file

@ -23,6 +23,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// q_shared.c -- stateless support routines that are included in each code dll
#include "q_shared.h"
// ^[0-9a-zA-Z]
qboolean Q_IsColorString(const char *p) {
if (!p)
return qfalse;
if (p[0] != Q_COLOR_ESCAPE)
return qfalse;
if (p[1] == 0)
return qfalse;
// isalnum expects a signed integer in the range -1 (EOF) to 255, or it might assert on undefined behaviour
// a dereferenced char pointer has the range -128 to 127, so we just need to rangecheck the negative part
if (p[1] < 0)
return qfalse;
if (isalnum(p[1]) == 0)
return qfalse;
return qtrue;
}
float Com_Clamp( float min, float max, float value ) {
if ( value < min ) {
return min;

View file

@ -409,6 +409,8 @@ typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
typedef vec_t vec5_t[5];
typedef vec_t quat_t[4];
typedef int fixed4_t;
typedef int fixed8_t;
typedef int fixed16_t;
@ -450,7 +452,7 @@ extern vec4_t colorMdGrey;
extern vec4_t colorDkGrey;
#define Q_COLOR_ESCAPE '^'
#define Q_IsColorString(p) ((p) && *(p) == Q_COLOR_ESCAPE && *((p)+1) && isalnum(*((p)+1))) // ^[0-9a-zA-Z]
qboolean Q_IsColorString(const char *p); // ^[0-9a-zA-Z]
#define COLOR_BLACK '0'
#define COLOR_RED '1'
@ -619,6 +621,8 @@ typedef struct {
#define Byte4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define QuatCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));}
// just in case you don't want to use the macros
vec_t _DotProduct( const vec3_t v1, const vec3_t v2 );

View file

@ -45,27 +45,22 @@ extern void (APIENTRYP qglUnlockArraysEXT) (void);
// GL function loader, based on https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a
// get missing functions from code/SDL2/include/SDL_opengl.h
// OpenGL 1.0/1.1 and OpenGL ES 1.0
// OpenGL 1.0/1.1, OpenGL ES 1.0, and OpenGL 3.2 core profile
#define QGL_1_1_PROCS \
GLE(void, AlphaFunc, GLenum func, GLclampf ref) \
GLE(void, BindTexture, GLenum target, GLuint texture) \
GLE(void, BlendFunc, GLenum sfactor, GLenum dfactor) \
GLE(void, ClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) \
GLE(void, Clear, GLbitfield mask) \
GLE(void, ClearStencil, GLint s) \
GLE(void, Color4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \
GLE(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) \
GLE(void, ColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
GLE(void, CopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) \
GLE(void, CullFace, GLenum mode) \
GLE(void, DeleteTextures, GLsizei n, const GLuint *textures) \
GLE(void, DepthFunc, GLenum func) \
GLE(void, DepthMask, GLboolean flag) \
GLE(void, DisableClientState, GLenum cap) \
GLE(void, Disable, GLenum cap) \
GLE(void, DrawArrays, GLenum mode, GLint first, GLsizei count) \
GLE(void, DrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) \
GLE(void, EnableClientState, GLenum cap) \
GLE(void, Enable, GLenum cap) \
GLE(void, Finish, void) \
GLE(void, Flush, void) \
@ -75,53 +70,67 @@ extern void (APIENTRYP qglUnlockArraysEXT) (void);
GLE(void, GetIntegerv, GLenum pname, GLint *params) \
GLE(const GLubyte *, GetString, GLenum name) \
GLE(void, LineWidth, GLfloat width) \
GLE(void, LoadIdentity, void) \
GLE(void, LoadMatrixf, const GLfloat *m) \
GLE(void, MatrixMode, GLenum mode) \
GLE(void, PolygonOffset, GLfloat factor, GLfloat units) \
GLE(void, PopMatrix, void) \
GLE(void, PushMatrix, void) \
GLE(void, ReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) \
GLE(void, Scissor, GLint x, GLint y, GLsizei width, GLsizei height) \
GLE(void, ShadeModel, GLenum mode) \
GLE(void, StencilFunc, GLenum func, GLint ref, GLuint mask) \
GLE(void, StencilMask, GLuint mask) \
GLE(void, StencilOp, GLenum fail, GLenum zfail, GLenum zpass) \
GLE(void, TexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
GLE(void, TexEnvf, GLenum target, GLenum pname, GLfloat param) \
GLE(void, TexImage2D, GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) \
GLE(void, TexParameterf, GLenum target, GLenum pname, GLfloat param) \
GLE(void, TexParameteri, GLenum target, GLenum pname, GLint param) \
GLE(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) \
GLE(void, Translatef, GLfloat x, GLfloat y, GLfloat z) \
GLE(void, VertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
GLE(void, Viewport, GLint x, GLint y, GLsizei width, GLsizei height) \
// OpenGL 1.0/1.1 but not OpenGL ES 1.x
// OpenGL 1.0/1.1 and OpenGL ES 1.x but not OpenGL 3.2 core profile
#define QGL_1_1_FIXED_FUNCTION_PROCS \
GLE(void, AlphaFunc, GLenum func, GLclampf ref) \
GLE(void, Color4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) \
GLE(void, ColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
GLE(void, DisableClientState, GLenum cap) \
GLE(void, EnableClientState, GLenum cap) \
GLE(void, LoadIdentity, void) \
GLE(void, LoadMatrixf, const GLfloat *m) \
GLE(void, MatrixMode, GLenum mode) \
GLE(void, PopMatrix, void) \
GLE(void, PushMatrix, void) \
GLE(void, ShadeModel, GLenum mode) \
GLE(void, TexCoordPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
GLE(void, TexEnvf, GLenum target, GLenum pname, GLfloat param) \
GLE(void, VertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) \
// OpenGL 1.0/1.1 and 3.2 core profile but not OpenGL ES 1.x
#define QGL_DESKTOP_1_1_PROCS \
GLE(void, ClearDepth, GLclampd depth) \
GLE(void, DepthRange, GLclampd near_val, GLclampd far_val) \
GLE(void, DrawBuffer, GLenum mode) \
GLE(void, PolygonMode, GLenum face, GLenum mode) \
// OpenGL 1.0/1.1 but not OpenGL 3.2 core profile or OpenGL ES 1.x
#define QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS \
GLE(void, ArrayElement, GLint i) \
GLE(void, Begin, GLenum mode) \
GLE(void, ClearDepth, GLclampd depth) \
GLE(void, ClipPlane, GLenum plane, const GLdouble *equation) \
GLE(void, Color3f, GLfloat red, GLfloat green, GLfloat blue) \
GLE(void, Color4ubv, const GLubyte *v) \
GLE(void, DepthRange, GLclampd near_val, GLclampd far_val) \
GLE(void, DrawBuffer, GLenum mode) \
GLE(void, End, void) \
GLE(void, Frustum, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) \
GLE(void, Ortho, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) \
GLE(void, PolygonMode, GLenum face, GLenum mode) \
GLE(void, TexCoord2f, GLfloat s, GLfloat t) \
GLE(void, TexCoord2fv, const GLfloat *v) \
GLE(void, Vertex2f, GLfloat x, GLfloat y) \
GLE(void, Vertex3f, GLfloat x, GLfloat y, GLfloat z) \
GLE(void, Vertex3fv, const GLfloat *v) \
// OpenGL ES 1.1 but not desktop OpenGL 1.x
// OpenGL ES 1.1 and OpenGL ES 2.0 but not desktop OpenGL 1.x
#define QGL_ES_1_1_PROCS \
GLE(void, ClearDepthf, GLclampf depth) \
GLE(void, ClipPlanef, GLenum plane, const GLfloat *equation) \
GLE(void, DepthRangef, GLclampf near_val, GLclampf far_val) \
// OpenGL ES 1.1 but not OpenGL ES 2.0 or desktop OpenGL 1.x
#define QGL_ES_1_1_FIXED_FUNCTION_PROCS \
GLE(void, ClipPlanef, GLenum plane, const GLfloat *equation) \
GLE(void, Frustumf, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near_val, GLfloat far_val) \
GLE(void, Orthof, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near_val, GLfloat far_val) \
@ -131,14 +140,17 @@ extern void (APIENTRYP qglUnlockArraysEXT) (void);
GLE(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) \
GLE(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) \
// OpenGL 1.5, was GL_ARB_vertex_buffer_object and GL_ARB_occlusion_query
#define QGL_1_5_PROCS \
// GL_ARB_occlusion_query, built-in to OpenGL 1.5 but not OpenGL ES 2.0
#define QGL_ARB_occlusion_query_PROCS \
GLE(void, GenQueries, GLsizei n, GLuint *ids) \
GLE(void, DeleteQueries, GLsizei n, const GLuint *ids) \
GLE(void, BeginQuery, GLenum target, GLuint id) \
GLE(void, EndQuery, GLenum target) \
GLE(void, GetQueryObjectiv, GLuint id, GLenum pname, GLint *params) \
GLE(void, GetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params) \
// OpenGL 1.5, was GL_ARB_vertex_buffer_object
#define QGL_1_5_PROCS \
GLE(void, BindBuffer, GLenum target, GLuint buffer) \
GLE(void, DeleteBuffers, GLsizei n, const GLuint *buffers) \
GLE(void, GenBuffers, GLsizei n, GLuint *buffers) \
@ -301,14 +313,18 @@ extern void (APIENTRYP qglUnlockArraysEXT) (void);
GLE(GLvoid, NamedFramebufferTexture2DEXT, GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level) \
GLE(GLvoid, NamedFramebufferRenderbufferEXT, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) \
#define GLE(ret, name, ...) typedef ret APIENTRY name##proc(__VA_ARGS__); extern name##proc * qgl##name;
#define GLE(ret, name, ...) typedef ret APIENTRY name##proc(__VA_ARGS__);
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS;
QGL_ES_1_1_PROCS;
QGL_ES_1_1_FIXED_FUNCTION_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
QGL_3_0_PROCS;
QGL_ARB_occlusion_query_PROCS;
QGL_ARB_framebuffer_object_PROCS;
QGL_ARB_vertex_array_object_PROCS;
QGL_EXT_direct_state_access_PROCS;

View file

@ -165,7 +165,7 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
====================================================================
*/
void GLimp_Init( qboolean );
void GLimp_Init( qboolean fixedFunction );
void GLimp_Shutdown( void );
void GLimp_EndFrame( void );

View file

@ -766,25 +766,9 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
}
RE_UploadCinematic (w, h, cols, rows, data, client, dirty);
GL_Bind( tr.scratchImage[client] );
// 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 ) {
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
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 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
} else {
if (dirty) {
// 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
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
}
}
if ( r_speeds->integer ) {
end = ri.Milliseconds();
ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );

View file

@ -206,7 +206,6 @@ void R_ImageList_f( void ) {
estSize *= 4;
break;
case GL_LUMINANCE8:
case GL_LUMINANCE16:
case GL_LUMINANCE:
format = "L ";
// 1 byte per pixel?
@ -219,7 +218,6 @@ void R_ImageList_f( void ) {
estSize *= 3;
break;
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE16_ALPHA16:
case GL_LUMINANCE_ALPHA:
format = "LA ";
// 2 bytes per pixel?
@ -684,10 +682,8 @@ static void Upload32( unsigned *data,
{
if(r_greyscale->integer)
{
if(r_texturebits->integer == 16)
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE8;
else if(r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE16;
else
internalFormat = GL_LUMINANCE;
}
@ -719,10 +715,8 @@ static void Upload32( unsigned *data,
{
if(r_greyscale->integer)
{
if(r_texturebits->integer == 16)
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE8_ALPHA8;
else if(r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE16_ALPHA16;
else
internalFormat = GL_LUMINANCE_ALPHA;
}

View file

@ -181,8 +181,6 @@ int max_polyverts;
*/
static void InitOpenGL( void )
{
char renderer_buffer[1024];
//
// initialize OS specific portions of the renderer
//
@ -198,15 +196,12 @@ static void InitOpenGL( void )
{
GLint temp;
GLimp_Init( qfalse );
GLimp_Init( qtrue );
#ifdef ELITEFORCE
glConfig.textureFilterAnisotropicAvailable = textureFilterAnisotropic;
#endif
strcpy( renderer_buffer, glConfig.renderer_string );
Q_strlwr( renderer_buffer );
// OpenGL driver constants
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
glConfig.maxTextureSize = temp;
@ -1322,6 +1317,10 @@ void RE_Shutdown( qboolean destroyWindow ) {
GLimp_Shutdown();
Com_Memset( &glConfig, 0, sizeof( glConfig ) );
textureFilterAnisotropic = qfalse;
maxAnisotropy = 0;
displayAspect = 0.0f;
Com_Memset( &glState, 0, sizeof( glState ) );
}

View file

@ -32,6 +32,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../renderercommon/iqm.h"
#include "../renderercommon/qgl.h"
#define GLE(ret, name, ...) extern name##proc * qgl##name;
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS;
QGL_3_0_PROCS;
#undef GLE
#define GL_INDEX_TYPE GL_UNSIGNED_INT
typedef unsigned int glIndex_t;
@ -582,6 +590,12 @@ typedef struct {
drawVert_t *verts;
} srfTriangles_t;
typedef struct {
vec3_t translate;
quat_t rotate;
vec3_t scale;
} iqmTransform_t;
// inter-quake-model
typedef struct {
int num_vertexes;
@ -592,28 +606,34 @@ typedef struct {
int num_poses;
struct srfIQModel_s *surfaces;
int *triangles;
// vertex arrays
float *positions;
float *texcoords;
float *normals;
float *tangents;
byte *blendIndexes;
byte *colors;
int *influences; // [num_vertexes] indexes into influenceBlendVertexes
// unique list of vertex blend indexes/weights for faster CPU vertex skinning
byte *influenceBlendIndexes; // [num_influences]
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
int *triangles;
} influenceBlendWeights; // [num_influences]
// depending upon the exporter, blend indices and weights might be int/float
// as opposed to the recommended byte/byte, for example Noesis exports
// int/float whereas the official IQM tool exports byte/byte
byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT
int blendWeightsType; // IQM_UBYTE or IQM_FLOAT
char *jointNames;
int *jointParents;
float *jointMats;
float *poseMats;
float *bindJoints; // [num_joints * 12]
float *invBindJoints; // [num_joints * 12]
iqmTransform_t *poses; // [num_frames * num_poses]
float *bounds;
char *names;
} iqmData_t;
// inter-quake-model surface
@ -624,6 +644,7 @@ typedef struct srfIQModel_s {
iqmData_t *data;
int first_vertex, num_vertexes;
int first_triangle, num_triangles;
int first_influence, num_influences;
} srfIQModel_t;

File diff suppressed because it is too large Load diff

View file

@ -56,5 +56,5 @@ void main()
current.y *= 0.0625;
#endif
gl_FragColor = vec4(current, 1.0f);
gl_FragColor = vec4(current, 1.0);
}

View file

@ -6,6 +6,9 @@ attribute vec4 attr_TexCoord0;
#if defined(USE_VERTEX_ANIMATION)
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
#elif defined(USE_BONE_ANIMATION)
attribute vec4 attr_BoneIndexes;
attribute vec4 attr_BoneWeights;
#endif
uniform vec4 u_FogDistance;
@ -22,6 +25,8 @@ uniform mat4 u_ModelViewProjectionMatrix;
#if defined(USE_VERTEX_ANIMATION)
uniform float u_VertexLerp;
#elif defined(USE_BONE_ANIMATION)
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
#endif
uniform vec4 u_Color;
@ -102,6 +107,15 @@ void main()
#if defined(USE_VERTEX_ANIMATION)
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
#elif defined(USE_BONE_ANIMATION)
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
vec3 normal = normalize(nrmMat * attr_Normal);
#else
vec3 position = attr_Position;
vec3 normal = attr_Normal;

View file

@ -4,6 +4,9 @@ attribute vec3 attr_Normal;
#if defined(USE_VERTEX_ANIMATION)
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
#elif defined(USE_BONE_ANIMATION)
attribute vec4 attr_BoneIndexes;
attribute vec4 attr_BoneWeights;
#endif
attribute vec4 attr_Color;
@ -54,6 +57,8 @@ uniform float u_PortalRange;
#if defined(USE_VERTEX_ANIMATION)
uniform float u_VertexLerp;
#elif defined(USE_BONE_ANIMATION)
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
#endif
varying vec2 var_DiffuseTex;
@ -204,6 +209,15 @@ void main()
#if defined(USE_VERTEX_ANIMATION)
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
#elif defined(USE_BONE_ANIMATION)
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
vec3 normal = normalize(nrmMat * attr_Normal);
#else
vec3 position = attr_Position;
vec3 normal = attr_Normal;

View file

@ -143,6 +143,35 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
return bestDepth;
}
float LightRay(vec2 dp, vec2 ds, sampler2D normalMap)
{
const int linearSearchSteps = 16;
// current size of search window
float size = 1.0 / float(linearSearchSteps);
// current height from initial texel depth
float height = 0.0;
float startDepth = SampleDepth(normalMap, dp);
// find a collision or escape
for(int i = 0; i < linearSearchSteps - 1; ++i)
{
height += size;
if (startDepth < height)
return 1.0;
float t = SampleDepth(normalMap, dp + ds * height);
if (startDepth > t + height)
return 0.0;
}
return 1.0;
}
#endif
vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
@ -193,6 +222,37 @@ float CalcLightAttenuation(float point, float normDist)
return attenuation;
}
#if defined(USE_BOX_CUBEMAP_PARALLAX)
vec4 hitCube(vec3 ray, vec3 pos, vec3 invSize, float lod, samplerCube tex)
{
// find any hits on cubemap faces facing the camera
vec3 scale = (sign(ray) - pos) / ray;
// find the nearest hit
float minScale = min(min(scale.x, scale.y), scale.z);
// if the nearest hit is behind the camera, ignore
// should not be necessary as long as pos is inside the cube
//if (minScale < 0.0)
//return vec4(0.0);
// calculate the hit position, that's our texture coordinates
vec3 tc = pos + ray * minScale;
// if the texture coordinates are outside the cube, ignore
// necessary since we're not fading out outside the cube
if (any(greaterThan(abs(tc), vec3(1.00001))))
return vec4(0.0);
// fade out when approaching the cubemap edges
//vec3 fade3 = abs(pos);
//float fade = max(max(fade3.x, fade3.y), fade3.z);
//fade = clamp(1.0 - fade, 0.0, 1.0);
//return vec4(textureCubeLod(tex, tc, lod).rgb * fade, fade);
return vec4(textureCubeLod(tex, tc, lod).rgb, 1.0);
}
#endif
void main()
{
@ -222,7 +282,7 @@ void main()
vec2 texCoords = var_TexCoords.xy;
#if defined(USE_PARALLAXMAP)
vec3 offsetDir = viewDir * tangentToWorld;
vec3 offsetDir = E * tangentToWorld;
offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
@ -289,6 +349,13 @@ void main()
#endif
#endif
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
offsetDir = L * tangentToWorld;
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
#endif
#if !defined(USE_LIGHT_VECTOR)
ambientColor = lightColor;
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
@ -374,7 +441,11 @@ void main()
// 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;
#if defined(USE_BOX_CUBEMAP_PARALLAX)
vec3 cubeLightColor = hitCube(R * u_CubeMapInfo.w, parallax, u_CubeMapInfo.www, ROUGHNESS_MIPS * roughness, u_CubeMap).rgb * u_EnableTextures.w;
#else
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, ROUGHNESS_MIPS * roughness).rgb * u_EnableTextures.w;
#endif
// normalize cubemap based on last roughness mip (~diffuse)
// multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation
@ -423,6 +494,12 @@ void main()
// enable when point lights are supported as primary lights
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
offsetDir = L2 * tangentToWorld;
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
#endif
gl_FragColor.rgb += lightColor * reflectance * NL2;
#endif

View file

@ -12,6 +12,9 @@ attribute vec4 attr_Tangent;
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
attribute vec4 attr_Tangent2;
#elif defined(USE_BONE_ANIMATION)
attribute vec4 attr_BoneIndexes;
attribute vec4 attr_BoneWeights;
#endif
#if defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
@ -48,6 +51,8 @@ uniform mat4 u_ModelMatrix;
#if defined(USE_VERTEX_ANIMATION)
uniform float u_VertexLerp;
#elif defined(USE_BONE_ANIMATION)
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
#endif
#if defined(USE_LIGHT_VECTOR)
@ -151,6 +156,18 @@ void main()
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 tangent = mix(attr_Tangent.xyz, attr_Tangent2.xyz, u_VertexLerp);
#endif
#elif defined(USE_BONE_ANIMATION)
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
vec3 normal = normalize(nrmMat * attr_Normal);
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 tangent = normalize(nrmMat * attr_Tangent.xyz);
#endif
#else
vec3 position = attr_Position;
vec3 normal = attr_Normal;

View file

@ -2,10 +2,13 @@ attribute vec3 attr_Position;
attribute vec3 attr_Normal;
attribute vec4 attr_TexCoord0;
//#if defined(USE_VERTEX_ANIMATION)
#if defined(USE_VERTEX_ANIMATION)
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
//#endif
#elif defined(USE_BONE_ANIMATION)
attribute vec4 attr_BoneIndexes;
attribute vec4 attr_BoneWeights;
#endif
//#if defined(USE_DEFORM_VERTEXES)
uniform int u_DeformGen;
@ -17,9 +20,11 @@ uniform mat4 u_ModelViewProjectionMatrix;
uniform mat4 u_ModelMatrix;
//#if defined(USE_VERTEX_ANIMATION)
#if defined(USE_VERTEX_ANIMATION)
uniform float u_VertexLerp;
//#endif
#elif defined(USE_BONE_ANIMATION)
uniform mat4 u_BoneMatrix[MAX_GLSL_BONES];
#endif
varying vec3 var_Position;
@ -78,8 +83,22 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
void main()
{
#if defined(USE_VERTEX_ANIMATION)
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
#elif defined(USE_BONE_ANIMATION)
mat4 vtxMat = u_BoneMatrix[int(attr_BoneIndexes.x)] * attr_BoneWeights.x;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.y)] * attr_BoneWeights.y;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.z)] * attr_BoneWeights.z;
vtxMat += u_BoneMatrix[int(attr_BoneIndexes.w)] * attr_BoneWeights.w;
mat3 nrmMat = mat3(cross(vtxMat[1].xyz, vtxMat[2].xyz), cross(vtxMat[2].xyz, vtxMat[0].xyz), cross(vtxMat[0].xyz, vtxMat[1].xyz));
vec3 position = vec3(vtxMat * vec4(attr_Position, 1.0));
vec3 normal = normalize(nrmMat * attr_Normal);
#else
vec3 position = attr_Position;
vec3 normal = attr_Normal;
#endif
position = DeformPosition(position, normal, attr_TexCoord0.st);

View file

@ -61,7 +61,7 @@ float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZN
poissonDisc[7] = vec2(-0.5579782, 0.7491854);
poissonDisc[8] = vec2(0.7320465, 0.6317794);
float result = 0;
float result = 0.0;
float sampleZ = getLinearDepth(depthMap, tex, zFarDivZNear);
float scaleZ = zFarDivZNear * sampleZ;

View file

@ -58,7 +58,7 @@ void GL_BindToTMU( image_t *image, int tmu )
ri.Printf(PRINT_WARNING, "GL_BindToTMU: NULL image\n");
}
GL_BindMultiTexture(GL_TEXTURE0_ARB + tmu, target, texture);
GL_BindMultiTexture(GL_TEXTURE0 + tmu, target, texture);
}
@ -441,7 +441,6 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
int oldSort;
double originalTime;
FBO_t* fbo = NULL;
qboolean inQuery = qfalse;
// save original time for entity shader offsets
originalTime = backEnd.refdef.floatTime;
@ -599,10 +598,6 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
RB_EndSurface();
}
if (inQuery) {
qglEndQuery(GL_SAMPLES_PASSED);
}
if (glRefConfig.framebufferObject)
FBO_Bind(fbo);
@ -663,7 +658,6 @@ void RB_SetGL2D (void) {
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
GL_Cull( CT_TWO_SIDED );
qglDisable( GL_CLIP_PLANE0 );
// set time for 2D shaders
backEnd.refdef.time = ri.Milliseconds();

View file

@ -203,11 +203,11 @@ void R_AddCapShadowmapCmd( int map, int cubeSide ) {
/*
=============
R_PostProcessingCmd
R_AddPostProcessCmd
=============
*/
void R_AddPostProcessCmd( ) {
void R_AddPostProcessCmd( void ) {
postProcessCommand_t *cmd;
cmd = R_GetCommandBuffer( sizeof( *cmd ) );

View file

@ -35,7 +35,7 @@ static struct
}
glDsaState;
void GL_BindNullTextures()
void GL_BindNullTextures(void)
{
int i;
@ -141,7 +141,7 @@ GLvoid APIENTRY GLDSA_GenerateTextureMipmapEXT(GLuint texture, GLenum target)
qglGenerateMipmap(target);
}
void GL_BindNullProgram()
void GL_BindNullProgram(void)
{
qglUseProgram(0);
glDsaState.program = 0;
@ -205,7 +205,7 @@ GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fvEXT(GLuint program, GLint location,
qglUniformMatrix4fv(location, count, transpose, value);
}
void GL_BindNullFramebuffers()
void GL_BindNullFramebuffers(void)
{
qglBindFramebuffer(GL_FRAMEBUFFER, 0);
glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0;

View file

@ -30,27 +30,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
#include "tr_dsa.h"
#define GLE(ret, name, ...) name##proc * qgl##name;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
QGL_ARB_framebuffer_object_PROCS;
QGL_ARB_vertex_array_object_PROCS;
QGL_EXT_direct_state_access_PROCS;
#undef GLE
void GLimp_InitExtraExtensions()
void GLimp_InitExtraExtensions(void)
{
char *extension;
const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" };
qboolean q_gl_version_at_least_3_0;
qboolean q_gl_version_at_least_3_2;
// Check OpenGL version
if ( !QGL_VERSION_ATLEAST( 2, 0 ) )
ri.Error(ERR_FATAL, "OpenGL 2.0 required!");
ri.Printf(PRINT_ALL, "...using OpenGL %s\n", glConfig.version_string);
q_gl_version_at_least_3_0 = QGL_VERSION_ATLEAST( 3, 0 );
q_gl_version_at_least_3_2 = QGL_VERSION_ATLEAST( 3, 2 );
@ -67,15 +53,9 @@ void GLimp_InitExtraExtensions()
// GL function loader, based on https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a
#define GLE(ret, name, ...) qgl##name = (name##proc *) SDL_GL_GetProcAddress("gl" #name);
// OpenGL 1.3, was GL_ARB_texture_compression
QGL_1_3_PROCS;
// OpenGL 1.5, was GL_ARB_vertex_buffer_object and GL_ARB_occlusion_query
QGL_1_5_PROCS;
// OpenGL 1.5 - GL_ARB_occlusion_query
glRefConfig.occlusionQuery = qtrue;
// OpenGL 2.0, was GL_ARB_shading_language_100, GL_ARB_vertex_program, GL_ARB_shader_objects, and GL_ARB_vertex_shader
QGL_2_0_PROCS;
QGL_ARB_occlusion_query_PROCS;
// OpenGL 3.0 - GL_ARB_framebuffer_object
extension = "GL_ARB_framebuffer_object";

View file

@ -526,10 +526,6 @@ void RB_RenderFlares (void) {
return; // none visible
}
if ( backEnd.viewParms.isPortal ) {
qglDisable (GL_CLIP_PLANE0);
}
Mat4Copy(glState.projection, oldprojection);
Mat4Copy(glState.modelview, oldmodelview);
Mat4Identity(matrix);

View file

@ -148,6 +148,8 @@ static uniformInfo_t uniformsInfo[] =
{ "u_CubeMapInfo", GLSL_VEC4 },
{ "u_AlphaTest", GLSL_INT },
{ "u_BoneMatrix", GLSL_MAT16_BONEMATRIX },
};
typedef enum
@ -331,17 +333,6 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLchar *extra, char *
AGEN_LIGHTING_SPECULAR,
AGEN_PORTAL));
Q_strcat(dest, size,
va("#ifndef texenv_t\n"
"#define texenv_t\n"
"#define TEXENV_MODULATE %i\n"
"#define TEXENV_ADD %i\n"
"#define TEXENV_REPLACE %i\n"
"#endif\n",
GL_MODULATE,
GL_ADD,
GL_REPLACE));
fbufWidthScale = 1.0f / ((float)glConfig.vidWidth);
fbufHeightScale = 1.0f / ((float)glConfig.vidHeight);
Q_strcat(dest, size,
@ -566,6 +557,12 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int
if(attribs & ATTR_LIGHTDIRECTION)
qglBindAttribLocation(program->program, ATTR_INDEX_LIGHTDIRECTION, "attr_LightDirection");
if(attribs & ATTR_BONE_INDEXES)
qglBindAttribLocation(program->program, ATTR_INDEX_BONE_INDEXES, "attr_BoneIndexes");
if(attribs & ATTR_BONE_WEIGHTS)
qglBindAttribLocation(program->program, ATTR_INDEX_BONE_WEIGHTS, "attr_BoneWeights");
if(attribs & ATTR_POSITION2)
qglBindAttribLocation(program->program, ATTR_INDEX_POSITION2, "attr_Position2");
@ -671,6 +668,9 @@ void GLSL_InitUniforms(shaderProgram_t *program)
case GLSL_MAT16:
size += sizeof(vec_t) * 16;
break;
case GLSL_MAT16_BONEMATRIX:
size += sizeof(vec_t) * 16 * glRefConfig.glslMaxAnimatedBones;
break;
default:
break;
}
@ -854,6 +854,38 @@ void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t
qglProgramUniformMatrix4fvEXT(program->program, uniforms[uniformNum], 1, GL_FALSE, matrix);
}
void GLSL_SetUniformMat4BoneMatrix(shaderProgram_t *program, int uniformNum, /*const*/ mat4_t *matrix, int numMatricies)
{
GLint *uniforms = program->uniforms;
vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
if (uniforms[uniformNum] == -1) {
return;
}
if (uniformsInfo[uniformNum].type != GLSL_MAT16_BONEMATRIX)
{
ri.Printf( PRINT_WARNING, "GLSL_SetUniformMat4BoneMatrix: wrong type for uniform %i in program %s\n", uniformNum, program->name);
return;
}
if (numMatricies > glRefConfig.glslMaxAnimatedBones)
{
ri.Printf( PRINT_WARNING, "GLSL_SetUniformMat4BoneMatrix: too many matricies (%d/%d) for uniform %i in program %s\n",
numMatricies, glRefConfig.glslMaxAnimatedBones, uniformNum, program->name);
return;
}
if (!memcmp(matrix, compare, numMatricies * sizeof(mat4_t)))
{
return;
}
Com_Memcpy(compare, matrix, numMatricies * sizeof(mat4_t));
qglProgramUniformMatrix4fvEXT(program->program, uniforms[uniformNum], numMatricies, GL_FALSE, &matrix[0][0]);
}
void GLSL_DeleteGPUShader(shaderProgram_t *program)
{
if(program->program)
@ -897,6 +929,12 @@ void GLSL_InitGPUShaders(void)
for (i = 0; i < GENERICDEF_COUNT; i++)
{
if ((i & GENERICDEF_USE_VERTEX_ANIMATION) && (i & GENERICDEF_USE_BONE_ANIMATION))
continue;
if ((i & GENERICDEF_USE_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones)
continue;
attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR;
extradefines[0] = '\0';
@ -914,6 +952,11 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
}
else if (i & GENERICDEF_USE_BONE_ANIMATION)
{
Q_strcat(extradefines, 1024, va("#define USE_BONE_ANIMATION\n#define MAX_GLSL_BONES %d\n", glRefConfig.glslMaxAnimatedBones));
attribs |= ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS;
}
if (i & GENERICDEF_USE_FOG)
Q_strcat(extradefines, 1024, "#define USE_FOG\n");
@ -954,14 +997,28 @@ void GLSL_InitGPUShaders(void)
for (i = 0; i < FOGDEF_COUNT; i++)
{
attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
if ((i & FOGDEF_USE_VERTEX_ANIMATION) && (i & FOGDEF_USE_BONE_ANIMATION))
continue;
if ((i & FOGDEF_USE_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones)
continue;
attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD;
extradefines[0] = '\0';
if (i & FOGDEF_USE_DEFORM_VERTEXES)
Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n");
if (i & FOGDEF_USE_VERTEX_ANIMATION)
{
Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
}
else if (i & FOGDEF_USE_BONE_ANIMATION)
{
Q_strcat(extradefines, 1024, va("#define USE_BONE_ANIMATION\n#define MAX_GLSL_BONES %d\n", glRefConfig.glslMaxAnimatedBones));
attribs |= ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS;
}
if (!GLSL_InitGPUShader(&tr.fogShader[i], "fogpass", attribs, qtrue, extradefines, qtrue, fallbackShader_fogpass_vp, fallbackShader_fogpass_fp))
{
@ -1012,6 +1069,12 @@ void GLSL_InitGPUShaders(void)
if ((i & LIGHTDEF_USE_SHADOWMAP) && (!lightType || !r_sunlightMode->integer))
continue;
if ((i & LIGHTDEF_ENTITY_VERTEX_ANIMATION) && (i & LIGHTDEF_ENTITY_BONE_ANIMATION))
continue;
if ((i & LIGHTDEF_ENTITY_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones)
continue;
attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL;
extradefines[0] = '\0';
@ -1054,11 +1117,14 @@ void GLSL_InitGPUShaders(void)
attribs |= ATTR_TANGENT;
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY_VERTEX_ANIMATION) && !(i & LIGHTDEF_ENTITY_BONE_ANIMATION) && r_parallaxMapping->integer)
{
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
if (r_parallaxMapping->integer > 1)
Q_strcat(extradefines, 1024, "#define USE_RELIEFMAP\n");
if (r_parallaxMapShadows->integer)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP_SHADOWS\n");
}
}
@ -1066,9 +1132,15 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n");
if (r_cubeMapping->integer)
{
Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n");
if (r_cubeMapping->integer == 2)
Q_strcat(extradefines, 1024, "#define USE_BOX_CUBEMAP_PARALLAX\n");
}
else if (r_deluxeSpecular->value > 0.000001f)
{
Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value));
}
switch (r_glossType->integer)
{
@ -1104,7 +1176,7 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, "#define USE_TCMOD\n");
}
if (i & LIGHTDEF_ENTITY)
if (i & LIGHTDEF_ENTITY_VERTEX_ANIMATION)
{
Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n");
attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
@ -1114,6 +1186,12 @@ void GLSL_InitGPUShaders(void)
attribs |= ATTR_TANGENT2;
}
}
else if (i & LIGHTDEF_ENTITY_BONE_ANIMATION)
{
Q_strcat(extradefines, 1024, "#define USE_MODELMATRIX\n");
Q_strcat(extradefines, 1024, va("#define USE_BONE_ANIMATION\n#define MAX_GLSL_BONES %d\n", glRefConfig.glslMaxAnimatedBones));
attribs |= ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS;
}
if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackShader_lightall_vp, fallbackShader_lightall_fp))
{
@ -1135,20 +1213,41 @@ void GLSL_InitGPUShaders(void)
numLightShaders++;
}
attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
extradefines[0] = '\0';
if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowfill_vp, fallbackShader_shadowfill_fp))
for (i = 0; i < SHADOWMAPDEF_COUNT; i++)
{
ri.Error(ERR_FATAL, "Could not load shadowfill shader!");
if ((i & SHADOWMAPDEF_USE_VERTEX_ANIMATION) && (i & SHADOWMAPDEF_USE_BONE_ANIMATION))
continue;
if ((i & SHADOWMAPDEF_USE_BONE_ANIMATION) && !glRefConfig.glslMaxAnimatedBones)
continue;
attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD;
extradefines[0] = '\0';
if (i & SHADOWMAPDEF_USE_VERTEX_ANIMATION)
{
Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
}
if (i & SHADOWMAPDEF_USE_BONE_ANIMATION)
{
Q_strcat(extradefines, 1024, va("#define USE_BONE_ANIMATION\n#define MAX_GLSL_BONES %d\n", glRefConfig.glslMaxAnimatedBones));
attribs |= ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS;
}
if (!GLSL_InitGPUShader(&tr.shadowmapShader[i], "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowfill_vp, fallbackShader_shadowfill_fp))
{
ri.Error(ERR_FATAL, "Could not load shadowfill shader!");
}
GLSL_InitUniforms(&tr.shadowmapShader[i]);
GLSL_FinishGPUShader(&tr.shadowmapShader[i]);
numEtcShaders++;
}
GLSL_InitUniforms(&tr.shadowmapShader);
GLSL_FinishGPUShader(&tr.shadowmapShader);
numEtcShaders++;
attribs = ATTR_POSITION | ATTR_NORMAL;
extradefines[0] = '\0';
@ -1374,7 +1473,9 @@ void GLSL_ShutdownGPUShaders(void)
for ( i = 0; i < LIGHTDEF_COUNT; i++)
GLSL_DeleteGPUShader(&tr.lightallShader[i]);
GLSL_DeleteGPUShader(&tr.shadowmapShader);
for ( i = 0; i < SHADOWMAPDEF_COUNT; i++)
GLSL_DeleteGPUShader(&tr.shadowmapShader[i]);
GLSL_DeleteGPUShader(&tr.pshadowShader);
GLSL_DeleteGPUShader(&tr.down4xShader);
GLSL_DeleteGPUShader(&tr.bokehShader);
@ -1450,6 +1551,10 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
{
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
}
else if (glState.boneAnimation)
{
shaderAttribs |= GENERICDEF_USE_BONE_ANIMATION;
}
if (pStage->bundle[0].numTexMods)
{

View file

@ -222,7 +222,6 @@ void R_ImageList_f( void ) {
estSize *= 4;
break;
case GL_LUMINANCE8:
case GL_LUMINANCE16:
case GL_LUMINANCE:
format = "L ";
// 1 byte per pixel?
@ -235,7 +234,6 @@ void R_ImageList_f( void ) {
estSize *= 3;
break;
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE16_ALPHA16:
case GL_LUMINANCE_ALPHA:
format = "LA ";
// 2 bytes per pixel?
@ -1724,10 +1722,8 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
{
if(r_greyscale->integer)
{
if(r_texturebits->integer == 16)
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE8;
else if(r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE16;
else
internalFormat = GL_LUMINANCE;
}
@ -1763,10 +1759,8 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picForm
{
if(r_greyscale->integer)
{
if(r_texturebits->integer == 16)
if(r_texturebits->integer == 16 || r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE8_ALPHA8;
else if(r_texturebits->integer == 32)
internalFormat = GL_LUMINANCE16_ALPHA16;
else
internalFormat = GL_LUMINANCE_ALPHA;
}

View file

@ -134,6 +134,7 @@ cvar_t *r_normalMapping;
cvar_t *r_specularMapping;
cvar_t *r_deluxeMapping;
cvar_t *r_parallaxMapping;
cvar_t *r_parallaxMapShadows;
cvar_t *r_cubeMapping;
cvar_t *r_cubemapSize;
cvar_t *r_deluxeSpecular;
@ -246,8 +247,6 @@ int max_polyverts;
*/
static void InitOpenGL( void )
{
char renderer_buffer[1024];
//
// initialize OS specific portions of the renderer
//
@ -263,16 +262,15 @@ static void InitOpenGL( void )
{
GLint temp;
GLimp_Init( qtrue );
GLimp_Init( qfalse );
GLimp_InitExtraExtensions();
glConfig.textureEnvAddAvailable = qtrue;
#ifdef ELITEFORCE
glConfig.textureFilterAnisotropicAvailable = textureFilterAnisotropic;
#endif
strcpy( renderer_buffer, glConfig.renderer_string );
Q_strlwr( renderer_buffer );
// OpenGL driver constants
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
glConfig.maxTextureSize = temp;
@ -282,6 +280,22 @@ static void InitOpenGL( void )
{
glConfig.maxTextureSize = 0;
}
qglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS, &temp );
glConfig.numTextureUnits = temp;
// reserve 160 components for other uniforms
qglGetIntegerv( GL_MAX_VERTEX_UNIFORM_COMPONENTS, &temp );
glRefConfig.glslMaxAnimatedBones = Com_Clamp( 0, IQM_MAX_JOINTS, ( temp - 160 ) / 16 );
if ( glRefConfig.glslMaxAnimatedBones < 12 ) {
glRefConfig.glslMaxAnimatedBones = 0;
}
}
// check for GLSL function textureCubeLod()
if ( r_cubeMapping->integer && !QGL_VERSION_ATLEAST( 3, 0 ) ) {
ri.Printf( PRINT_WARNING, "WARNING: Disabled r_cubeMapping because it requires OpenGL 3.0\n" );
ri.Cvar_Set( "r_cubeMapping", "0" );
}
// set default state
@ -1056,7 +1070,7 @@ void GfxInfo_f( void )
}
ri.Printf( PRINT_ALL, "\n" );
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits );
ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_IMAGE_UNITS: %d\n", glConfig.numTextureUnits );
ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
if ( glConfig.displayFrequency )
@ -1239,6 +1253,7 @@ void R_Register( void )
r_specularMapping = ri.Cvar_Get( "r_specularMapping", "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_parallaxMapShadows = ri.Cvar_Get( "r_parallaxMapShadows", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
r_deluxeSpecular = ri.Cvar_Get("r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH);
@ -1559,6 +1574,11 @@ void RE_Shutdown( qboolean destroyWindow ) {
GLimp_Shutdown();
Com_Memset( &glConfig, 0, sizeof( glConfig ) );
Com_Memset( &glRefConfig, 0, sizeof( glRefConfig ) );
textureFilterAnisotropic = qfalse;
maxAnisotropy = 0;
displayAspect = 0.0f;
Com_Memset( &glState, 0, sizeof( glState ) );
}

View file

@ -36,6 +36,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../renderercommon/iqm.h"
#include "../renderercommon/qgl.h"
#define GLE(ret, name, ...) extern name##proc * qgl##name;
QGL_1_1_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
QGL_3_0_PROCS;
QGL_ARB_occlusion_query_PROCS;
QGL_ARB_framebuffer_object_PROCS;
QGL_ARB_vertex_array_object_PROCS;
QGL_EXT_direct_state_access_PROCS;
#undef GLE
#define GL_INDEX_TYPE GL_UNSIGNED_INT
typedef unsigned int glIndex_t;
@ -542,16 +555,18 @@ enum
GENERICDEF_USE_VERTEX_ANIMATION = 0x0004,
GENERICDEF_USE_FOG = 0x0008,
GENERICDEF_USE_RGBAGEN = 0x0010,
GENERICDEF_ALL = 0x001F,
GENERICDEF_COUNT = 0x0020,
GENERICDEF_USE_BONE_ANIMATION = 0x0020,
GENERICDEF_ALL = 0x003F,
GENERICDEF_COUNT = 0x0040,
};
enum
{
FOGDEF_USE_DEFORM_VERTEXES = 0x0001,
FOGDEF_USE_VERTEX_ANIMATION = 0x0002,
FOGDEF_ALL = 0x0003,
FOGDEF_COUNT = 0x0004,
FOGDEF_USE_BONE_ANIMATION = 0x0004,
FOGDEF_ALL = 0x0007,
FOGDEF_COUNT = 0x0008,
};
enum
@ -567,12 +582,21 @@ enum
LIGHTDEF_USE_LIGHT_VECTOR = 0x0002,
LIGHTDEF_USE_LIGHT_VERTEX = 0x0003,
LIGHTDEF_LIGHTTYPE_MASK = 0x0003,
LIGHTDEF_ENTITY = 0x0004,
LIGHTDEF_ENTITY_VERTEX_ANIMATION = 0x0004,
LIGHTDEF_USE_TCGEN_AND_TCMOD = 0x0008,
LIGHTDEF_USE_PARALLAXMAP = 0x0010,
LIGHTDEF_USE_SHADOWMAP = 0x0020,
LIGHTDEF_ALL = 0x003F,
LIGHTDEF_COUNT = 0x0040
LIGHTDEF_ENTITY_BONE_ANIMATION = 0x0040,
LIGHTDEF_ALL = 0x007F,
LIGHTDEF_COUNT = 0x0080
};
enum
{
SHADOWMAPDEF_USE_VERTEX_ANIMATION = 0x0001,
SHADOWMAPDEF_USE_BONE_ANIMATION = 0x0002,
SHADOWMAPDEF_ALL = 0x0003,
SHADOWMAPDEF_COUNT = 0x0004
};
enum
@ -583,7 +607,8 @@ enum
GLSL_VEC2,
GLSL_VEC3,
GLSL_VEC4,
GLSL_MAT16
GLSL_MAT16,
GLSL_MAT16_BONEMATRIX
};
typedef enum
@ -674,6 +699,8 @@ typedef enum
UNIFORM_ALPHATEST,
UNIFORM_BONEMATRIX,
UNIFORM_COUNT
} uniform_t;
@ -837,6 +864,7 @@ typedef enum {
SF_FLARE,
SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
SF_VAO_MDVMESH,
SF_VAO_IQM,
SF_NUM_SURFACE_TYPES,
SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
@ -927,6 +955,12 @@ typedef struct srfBspSurface_s
float *heightLodError;
} srfBspSurface_t;
typedef struct {
vec3_t translate;
quat_t rotate;
vec3_t scale;
} iqmTransform_t;
// inter-quake-model
typedef struct {
int num_vertexes;
@ -937,28 +971,37 @@ typedef struct {
int num_poses;
struct srfIQModel_s *surfaces;
int *triangles;
// vertex arrays
float *positions;
float *texcoords;
float *normals;
float *tangents;
byte *blendIndexes;
byte *colors;
int *influences; // [num_vertexes] indexes into influenceBlendVertexes
// unique list of vertex blend indexes/weights for faster CPU vertex skinning
byte *influenceBlendIndexes; // [num_influences]
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
int *triangles;
} influenceBlendWeights; // [num_influences]
// depending upon the exporter, blend indices and weights might be int/float
// as opposed to the recommended byte/byte, for example Noesis exports
// int/float whereas the official IQM tool exports byte/byte
byte blendWeightsType; // IQM_UBYTE or IQM_FLOAT
int blendWeightsType; // IQM_UBYTE or IQM_FLOAT
char *jointNames;
int *jointParents;
float *jointMats;
float *poseMats;
float *bindJoints; // [num_joints * 12]
float *invBindJoints; // [num_joints * 12]
iqmTransform_t *poses; // [num_frames * num_poses]
float *bounds;
char *names;
int numVaoSurfaces;
struct srfVaoIQModel_s *vaoSurfaces;
} iqmData_t;
// inter-quake-model surface
@ -969,8 +1012,24 @@ typedef struct srfIQModel_s {
iqmData_t *data;
int first_vertex, num_vertexes;
int first_triangle, num_triangles;
int first_influence, num_influences;
} srfIQModel_t;
typedef struct srfVaoIQModel_s
{
surfaceType_t surfaceType;
iqmData_t *iqmData;
struct srfIQModel_s *iqmSurface;
// backEnd stats
int numIndexes;
int numVerts;
// static render data
vao_t *vao;
} srfVaoIQModel_t;
typedef struct srfVaoMdvMesh_s
{
surfaceType_t surfaceType;
@ -1309,6 +1368,8 @@ typedef struct {
uint32_t storedGlState;
float vertexAttribsInterpolation;
qboolean vertexAnimation;
int boneAnimation; // number of bones
mat4_t boneMatrix[IQM_MAX_JOINTS];
uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise
FBO_t *currentFBO;
vao_t *currentVao;
@ -1338,6 +1399,7 @@ typedef struct {
int glslMajorVersion;
int glslMinorVersion;
int glslMaxAnimatedBones;
memInfo_t memInfo;
@ -1518,7 +1580,7 @@ typedef struct {
shaderProgram_t fogShader[FOGDEF_COUNT];
shaderProgram_t dlightShader[DLIGHTDEF_COUNT];
shaderProgram_t lightallShader[LIGHTDEF_COUNT];
shaderProgram_t shadowmapShader;
shaderProgram_t shadowmapShader[SHADOWMAPDEF_COUNT];
shaderProgram_t pshadowShader;
shaderProgram_t down4xShader;
shaderProgram_t bokehShader;
@ -1716,6 +1778,7 @@ extern cvar_t *r_normalMapping;
extern cvar_t *r_specularMapping;
extern cvar_t *r_deluxeMapping;
extern cvar_t *r_parallaxMapping;
extern cvar_t *r_parallaxMapShadows;
extern cvar_t *r_cubeMapping;
extern cvar_t *r_cubemapSize;
extern cvar_t *r_deluxeSpecular;
@ -2003,7 +2066,7 @@ void RB_EndSurface(void);
void RB_CheckOverflow( int verts, int indexes );
#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);}
void R_DrawElements( int numIndexes, glIndex_t firstIndex );
void R_DrawElements( int numIndexes, int firstIndex );
void RB_StageIteratorGeneric( void );
void RB_StageIteratorSky( void );
void RB_StageIteratorVertexLitTexture( void );
@ -2171,6 +2234,7 @@ void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t
void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v);
void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v);
void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix);
void GLSL_SetUniformMat4BoneMatrix(shaderProgram_t *program, int uniformNum, /*const*/ mat4_t *matrix, int numMatricies);
shaderProgram_t *GLSL_GetGenericShaderProgram(int stage);
@ -2225,6 +2289,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface );
qboolean R_LoadIQM (model_t *mod, void *buffer, int filesize, const char *name );
void R_AddIQMSurfaces( trRefEntity_t *ent );
void RB_IQMSurfaceAnim( surfaceType_t *surface );
void RB_IQMSurfaceAnimVao( srfVaoIQModel_t *surface );
int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
int startFrame, int endFrame,
float frac, const char *tagName );

File diff suppressed because it is too large Load diff

View file

@ -437,7 +437,7 @@ void RE_BeginScene(const refdef_t *fd)
}
void RE_EndScene()
void RE_EndScene(void)
{
// the next scene rendered in this frame will tack on after this one
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;

View file

@ -38,7 +38,7 @@ R_DrawElements
==================
*/
void R_DrawElements( int numIndexes, glIndex_t firstIndex)
void R_DrawElements( int numIndexes, int firstIndex )
{
qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
}
@ -908,6 +908,8 @@ static void RB_FogPass( void ) {
if (glState.vertexAnimation)
index |= FOGDEF_USE_VERTEX_ANIMATION;
else if (glState.boneAnimation)
index |= FOGDEF_USE_BONE_ANIMATION;
sp = &tr.fogShader[index];
}
@ -921,6 +923,11 @@ static void RB_FogPass( void ) {
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
if (glState.boneAnimation)
{
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
}
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
if (deformGen != DGEN_NONE)
@ -1031,7 +1038,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
{
index |= LIGHTDEF_ENTITY;
if (glState.boneAnimation)
{
index |= LIGHTDEF_ENTITY_BONE_ANIMATION;
}
else
{
index |= LIGHTDEF_ENTITY_VERTEX_ANIMATION;
}
}
if (pStage->stateBits & GLS_ATEST_BITS)
@ -1054,6 +1068,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
}
else if (glState.boneAnimation)
{
shaderAttribs |= GENERICDEF_USE_BONE_ANIMATION;
}
if (pStage->stateBits & GLS_ATEST_BITS)
{
@ -1069,7 +1087,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
{
index |= LIGHTDEF_ENTITY;
if (glState.boneAnimation)
{
index |= LIGHTDEF_ENTITY_BONE_ANIMATION;
}
else
{
index |= LIGHTDEF_ENTITY_VERTEX_ANIMATION;
}
}
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (index & LIGHTDEF_LIGHTTYPE_MASK))
@ -1100,6 +1125,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
if (glState.boneAnimation)
{
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
}
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
if (deformGen != DGEN_NONE)
@ -1402,7 +1432,16 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
ComputeDeformValues(&deformGen, deformParams);
{
shaderProgram_t *sp = &tr.shadowmapShader;
shaderProgram_t *sp = &tr.shadowmapShader[0];
if (glState.vertexAnimation)
{
sp = &tr.shadowmapShader[SHADOWMAPDEF_USE_VERTEX_ANIMATION];
}
else if (glState.boneAnimation)
{
sp = &tr.shadowmapShader[SHADOWMAPDEF_USE_BONE_ANIMATION];
}
vec4_t vector;
@ -1414,6 +1453,11 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
if (glState.boneAnimation)
{
GLSL_SetUniformMat4BoneMatrix(sp, UNIFORM_BONEMATRIX, glState.boneMatrix, glState.boneAnimation);
}
GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen);
if (deformGen != DGEN_NONE)
{

View file

@ -43,8 +43,8 @@ typedef struct {
static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
static int numEdgeDefs[SHADER_MAX_VERTEXES];
static int facing[SHADER_MAX_INDEXES/3];
static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
//static int facing[SHADER_MAX_INDEXES/3];
//static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
void R_AddEdgeDef( int i1, int i2, int facing ) {
int c;
@ -60,6 +60,8 @@ void R_AddEdgeDef( int i1, int i2, int facing ) {
}
void R_RenderShadowEdges( void ) {
// FIXME: implement this
#if 0
int i;
#if 0
@ -138,6 +140,7 @@ void R_RenderShadowEdges( void ) {
}
}
#endif
#endif
}
/*
@ -153,6 +156,8 @@ triangleFromEdge[ v1 ][ v2 ]
=================
*/
void RB_ShadowTessEnd( void ) {
// FIXME: implement this
#if 0
int i;
int numTris;
vec3_t lightDir;
@ -230,6 +235,7 @@ void RB_ShadowTessEnd( void ) {
// reenable writing to the color buffer
qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
#endif
}
@ -244,6 +250,8 @@ overlap and double darken.
=================
*/
void RB_ShadowFinish( void ) {
// FIXME: implement this
#if 0
if ( r_shadows->integer != 2 ) {
return;
}
@ -253,7 +261,6 @@ void RB_ShadowFinish( void ) {
qglEnable( GL_STENCIL_TEST );
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
qglDisable (GL_CLIP_PLANE0);
GL_Cull( CT_TWO_SIDED );
GL_BindToTMU( tr.whiteImage, TB_COLORMAP );
@ -275,6 +282,7 @@ void RB_ShadowFinish( void ) {
qglColor4f(1,1,1,1);
qglDisable( GL_STENCIL_TEST );
#endif
}

View file

@ -1913,4 +1913,5 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
(void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
(void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH
(void(*)(void*))RB_IQMSurfaceAnimVao, // SF_VAO_IQM
};

View file

@ -687,8 +687,13 @@ vcq;
// srfVert_t is 60 bytes
// assuming each vert is referenced 4 times, need 16 bytes (4 glIndex_t) per vert
// -> need about 4/15ths the space for indexes as vertexes
#if GL_INDEX_TYPE == GL_UNSIGNED_SHORT
#define VAOCACHE_VERTEX_BUFFER_SIZE (sizeof(srfVert_t) * USHRT_MAX)
#define VAOCACHE_INDEX_BUFFER_SIZE (sizeof(glIndex_t) * USHRT_MAX * 4)
#else // GL_UNSIGNED_INT
#define VAOCACHE_VERTEX_BUFFER_SIZE (16 * 1024 * 1024)
#define VAOCACHE_INDEX_BUFFER_SIZE (5 * 1024 * 1024)
#endif
typedef struct buffered_s
{
@ -746,7 +751,7 @@ void VaoCache_Commit(void)
if (indexSet < vc.surfaceIndexSets + vc.numSurfaces)
{
tess.firstIndex = indexSet->bufferOffset / sizeof(glIndex_t);
//ri.Printf(PRINT_ALL, "firstIndex %d numIndexes %d as %d\n", tess.firstIndex, tess.numIndexes, batchLength - vc.batchLengths);
//ri.Printf(PRINT_ALL, "firstIndex %d numIndexes %d as %d\n", tess.firstIndex, tess.numIndexes, (int)(batchLength - vc.batchLengths));
//ri.Printf(PRINT_ALL, "vc.numSurfaces %d vc.numBatches %d\n", vc.numSurfaces, vc.numBatches);
}
// If not, rebuffer the batch
@ -787,7 +792,7 @@ void VaoCache_Commit(void)
vcq.indexCommitSize += indexesSize;
}
//ri.Printf(PRINT_ALL, "committing %d to %d, %d to %d as %d\n", vcq.vertexCommitSize, vc.vertexOffset, vcq.indexCommitSize, vc.indexOffset, batchLength - vc.batchLengths);
//ri.Printf(PRINT_ALL, "committing %d to %d, %d to %d as %d\n", vcq.vertexCommitSize, vc.vertexOffset, vcq.indexCommitSize, vc.indexOffset, (int)(batchLength - vc.batchLengths));
if (vcq.vertexCommitSize)
{
@ -807,9 +812,6 @@ void VaoCache_Commit(void)
void VaoCache_Init(void)
{
srfVert_t vert;
int dataSize;
vc.vao = R_CreateVao("VaoCache", NULL, VAOCACHE_VERTEX_BUFFER_SIZE, NULL, VAOCACHE_INDEX_BUFFER_SIZE, VAO_USAGE_DYNAMIC);
vc.vao->attribs[ATTR_INDEX_POSITION].enabled = 1;
@ -844,21 +846,21 @@ void VaoCache_Init(void)
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE;
vc.vao->attribs[ATTR_INDEX_COLOR].normalized = GL_TRUE;
vc.vao->attribs[ATTR_INDEX_POSITION].offset = 0; dataSize = sizeof(vert.xyz);
vc.vao->attribs[ATTR_INDEX_TEXCOORD].offset = dataSize; dataSize += sizeof(vert.st);
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].offset = dataSize; dataSize += sizeof(vert.lightmap);
vc.vao->attribs[ATTR_INDEX_NORMAL].offset = dataSize; dataSize += sizeof(vert.normal);
vc.vao->attribs[ATTR_INDEX_TANGENT].offset = dataSize; dataSize += sizeof(vert.tangent);
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(vert.lightdir);
vc.vao->attribs[ATTR_INDEX_COLOR].offset = dataSize; dataSize += sizeof(vert.color);
vc.vao->attribs[ATTR_INDEX_POSITION].offset = offsetof(srfVert_t, xyz);
vc.vao->attribs[ATTR_INDEX_TEXCOORD].offset = offsetof(srfVert_t, st);
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].offset = offsetof(srfVert_t, lightmap);
vc.vao->attribs[ATTR_INDEX_NORMAL].offset = offsetof(srfVert_t, normal);
vc.vao->attribs[ATTR_INDEX_TANGENT].offset = offsetof(srfVert_t, tangent);
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offsetof(srfVert_t, lightdir);
vc.vao->attribs[ATTR_INDEX_COLOR].offset = offsetof(srfVert_t, color);
vc.vao->attribs[ATTR_INDEX_POSITION].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_TEXCOORD].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_NORMAL].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_TANGENT].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_COLOR].stride = dataSize;
vc.vao->attribs[ATTR_INDEX_POSITION].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_TEXCOORD].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_LIGHTCOORD].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_NORMAL].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_TANGENT].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(srfVert_t);
vc.vao->attribs[ATTR_INDEX_COLOR].stride = sizeof(srfVert_t);
Vao_SetVertexPointers(vc.vao);
@ -883,7 +885,7 @@ void VaoCache_CheckAdd(qboolean *endSurface, qboolean *recycleVertexBuffer, qboo
if (vc.vao->vertexesSize < vc.vertexOffset + vcq.vertexCommitSize + vertexesSize)
{
//ri.Printf(PRINT_ALL, "out of space in vertex cache: %d < %d + %d + %d\n", vc.vao->vertexesSize, vc.vertexOffset, vc.vertexCommitSize, vertexesSize);
//ri.Printf(PRINT_ALL, "out of space in vertex cache: %d < %d + %d + %d\n", vc.vao->vertexesSize, vc.vertexOffset, vcq.vertexCommitSize, vertexesSize);
*recycleVertexBuffer = qtrue;
*recycleIndexBuffer = qtrue;
*endSurface = qtrue;
@ -961,6 +963,6 @@ void VaoCache_AddSurface(srfVert_t *verts, int numVerts, glIndex_t *indexes, int
queueEntry->numIndexes = numIndexes;
vcq.numSurfaces++;
vcq.vertexCommitSize += sizeof(srfVert_t) * numVerts;;
vcq.vertexCommitSize += sizeof(srfVert_t) * numVerts;
vcq.indexCommitSize += sizeof(glIndex_t) * numIndexes;
}

View file

@ -65,9 +65,19 @@ void (APIENTRYP qglUnlockArraysEXT) (void);
#define GLE(ret, name, ...) name##proc * qgl##name;
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS;
QGL_ES_1_1_PROCS;
QGL_ES_1_1_FIXED_FUNCTION_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
QGL_3_0_PROCS;
QGL_ARB_occlusion_query_PROCS;
QGL_ARB_framebuffer_object_PROCS;
QGL_ARB_vertex_array_object_PROCS;
QGL_EXT_direct_state_access_PROCS;
#undef GLE
/*
@ -227,7 +237,7 @@ GLimp_GetProcAddresses
Get addresses for OpenGL functions.
===============
*/
static qboolean GLimp_GetProcAddresses( void ) {
static qboolean GLimp_GetProcAddresses( qboolean fixedFunction ) {
qboolean success = qtrue;
const char *version;
@ -266,17 +276,41 @@ static qboolean GLimp_GetProcAddresses( void ) {
sscanf( version, "%d.%d", &qglMajorVersion, &qglMinorVersion );
}
if ( QGL_VERSION_ATLEAST( 1, 2 ) ) {
QGL_1_1_PROCS;
QGL_DESKTOP_1_1_PROCS;
} else if ( qglesMajorVersion == 1 && qglesMinorVersion >= 1 ) {
// OpenGL ES 1.1 (2.0 is not backward compatible)
QGL_1_1_PROCS;
QGL_ES_1_1_PROCS;
// error so this doesn't segfault due to NULL desktop GL functions being used
Com_Error( ERR_FATAL, "Unsupported OpenGL Version: %s\n", version );
if ( fixedFunction ) {
if ( QGL_VERSION_ATLEAST( 1, 2 ) ) {
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS;
} else if ( qglesMajorVersion == 1 && qglesMinorVersion >= 1 ) {
// OpenGL ES 1.1 (2.0 is not backward compatible)
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_ES_1_1_PROCS;
QGL_ES_1_1_FIXED_FUNCTION_PROCS;
// error so this doesn't segfault due to NULL desktop GL functions being used
Com_Error( ERR_FATAL, "Unsupported OpenGL Version: %s\n", version );
} else {
Com_Error( ERR_FATAL, "Unsupported OpenGL Version (%s), OpenGL 1.2 is required\n", version );
}
} else {
Com_Error( ERR_FATAL, "Unsupported OpenGL Version: %s\n", version );
if ( QGL_VERSION_ATLEAST( 2, 0 ) ) {
QGL_1_1_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
} else if ( QGLES_VERSION_ATLEAST( 2, 0 ) ) {
QGL_1_1_PROCS;
QGL_ES_1_1_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
// error so this doesn't segfault due to NULL desktop GL functions being used
Com_Error( ERR_FATAL, "Unsupported OpenGL Version: %s\n", version );
} else {
Com_Error( ERR_FATAL, "Unsupported OpenGL Version (%s), OpenGL 2.0 is required\n", version );
}
}
if ( QGL_VERSION_ATLEAST( 3, 0 ) || QGLES_VERSION_ATLEAST( 3, 0 ) ) {
@ -304,9 +338,26 @@ static void GLimp_ClearProcAddresses( void ) {
qglesMinorVersion = 0;
QGL_1_1_PROCS;
QGL_1_1_FIXED_FUNCTION_PROCS;
QGL_DESKTOP_1_1_PROCS;
QGL_DESKTOP_1_1_FIXED_FUNCTION_PROCS;
QGL_ES_1_1_PROCS;
QGL_ES_1_1_FIXED_FUNCTION_PROCS;
QGL_1_3_PROCS;
QGL_1_5_PROCS;
QGL_2_0_PROCS;
QGL_3_0_PROCS;
QGL_ARB_occlusion_query_PROCS;
QGL_ARB_framebuffer_object_PROCS;
QGL_ARB_vertex_array_object_PROCS;
QGL_EXT_direct_state_access_PROCS;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
qglMultiTexCoord2fARB = NULL;
qglLockArraysEXT = NULL;
qglUnlockArraysEXT = NULL;
#undef GLE
}
@ -316,7 +367,7 @@ static void GLimp_ClearProcAddresses( void ) {
GLimp_SetMode
===============
*/
static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qboolean coreContext)
static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qboolean fixedFunction)
{
const char *glstring;
int perChannelColorBits;
@ -580,7 +631,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
SDL_SetWindowIcon( SDL_window, icon );
if (coreContext)
if (!fixedFunction)
{
int profileMask, majorVersion, minorVersion;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profileMask);
@ -606,7 +657,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
ri.Printf(PRINT_ALL, "SDL_GL_CreateContext succeeded.\n");
if ( GLimp_GetProcAddresses() )
if ( GLimp_GetProcAddresses( fixedFunction ) )
{
renderer = (const char *)qglGetString(GL_RENDERER);
}
@ -646,7 +697,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder, qbool
continue;
}
if ( !GLimp_GetProcAddresses() )
if ( !GLimp_GetProcAddresses( fixedFunction ) )
{
ri.Printf( PRINT_ALL, "GLimp_GetProcAddresses() failed\n" );
GLimp_ClearProcAddresses();
@ -751,7 +802,7 @@ static qboolean GLimp_StartDriverAndSetMode(int mode, qboolean fullscreen, qbool
GLimp_InitExtensions
===============
*/
static void GLimp_InitExtensions( void )
static void GLimp_InitExtensions( qboolean fixedFunction )
{
if ( !r_allowExtensions->integer )
{
@ -803,88 +854,91 @@ static void GLimp_InitExtensions( void )
}
}
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( SDL_GL_ExtensionSupported( "GL_EXT_texture_env_add" ) )
// OpenGL 1 fixed function pipeline
if ( fixedFunction )
{
if ( r_ext_texture_env_add->integer )
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( SDL_GL_ExtensionSupported( "GL_EXT_texture_env_add" ) )
{
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
}
else
{
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
if ( SDL_GL_ExtensionSupported( "GL_ARB_multitexture" ) )
{
if ( r_ext_multitexture->value )
{
qglMultiTexCoord2fARB = SDL_GL_GetProcAddress( "glMultiTexCoord2fARB" );
qglActiveTextureARB = SDL_GL_GetProcAddress( "glActiveTextureARB" );
qglClientActiveTextureARB = SDL_GL_GetProcAddress( "glClientActiveTextureARB" );
if ( qglActiveTextureARB )
if ( r_ext_texture_env_add->integer )
{
GLint glint = 0;
qglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &glint );
glConfig.numTextureUnits = (int) glint;
if ( glConfig.numTextureUnits > 1 )
{
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
}
else
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
}
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
}
else
{
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
// GL_EXT_compiled_vertex_array
if ( SDL_GL_ExtensionSupported( "GL_EXT_compiled_vertex_array" ) )
{
if ( r_ext_compiled_vertex_array->value )
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
if ( SDL_GL_ExtensionSupported( "GL_ARB_multitexture" ) )
{
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
qglLockArraysEXT = ( void ( APIENTRY * )( GLint, GLint ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" );
qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" );
if (!qglLockArraysEXT || !qglUnlockArraysEXT)
if ( r_ext_multitexture->value )
{
ri.Error (ERR_FATAL, "bad getprocaddress");
qglMultiTexCoord2fARB = SDL_GL_GetProcAddress( "glMultiTexCoord2fARB" );
qglActiveTextureARB = SDL_GL_GetProcAddress( "glActiveTextureARB" );
qglClientActiveTextureARB = SDL_GL_GetProcAddress( "glClientActiveTextureARB" );
if ( qglActiveTextureARB )
{
GLint glint = 0;
qglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &glint );
glConfig.numTextureUnits = (int) glint;
if ( glConfig.numTextureUnits > 1 )
{
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
}
else
{
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
ri.Printf( PRINT_ALL, "...not using GL_ARB_multitexture, < 2 texture units\n" );
}
}
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
// GL_EXT_compiled_vertex_array
if ( SDL_GL_ExtensionSupported( "GL_EXT_compiled_vertex_array" ) )
{
if ( r_ext_compiled_vertex_array->value )
{
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
qglLockArraysEXT = ( void ( APIENTRY * )( GLint, GLint ) ) SDL_GL_GetProcAddress( "glLockArraysEXT" );
qglUnlockArraysEXT = ( void ( APIENTRY * )( void ) ) SDL_GL_GetProcAddress( "glUnlockArraysEXT" );
if (!qglLockArraysEXT || !qglUnlockArraysEXT)
{
ri.Error (ERR_FATAL, "bad getprocaddress");
}
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
}
else
{
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
textureFilterAnisotropic = qfalse;
@ -923,7 +977,7 @@ This routine is responsible for initializing the OS specific portions
of OpenGL
===============
*/
void GLimp_Init( qboolean coreContext)
void GLimp_Init( qboolean fixedFunction )
{
ri.Printf( PRINT_DEVELOPER, "Glimp_Init( )\n" );
@ -943,13 +997,13 @@ void GLimp_Init( qboolean coreContext)
ri.Sys_GLimpInit( );
// Create the window and set up the context
if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer, coreContext))
if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, r_noborder->integer, fixedFunction))
goto success;
// Try again, this time in a platform specific "safe mode"
ri.Sys_GLimpSafeInit( );
if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse, coreContext))
if(GLimp_StartDriverAndSetMode(r_mode->integer, r_fullscreen->integer, qfalse, fixedFunction))
goto success;
// Finally, try the default screen resolution
@ -958,7 +1012,7 @@ void GLimp_Init( qboolean coreContext)
ri.Printf( PRINT_ALL, "Setting r_mode %d failed, falling back on r_mode %d\n",
r_mode->integer, R_MODE_FALLBACK );
if(GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse, coreContext))
if(GLimp_StartDriverAndSetMode(R_MODE_FALLBACK, qfalse, qfalse, fixedFunction))
goto success;
}
@ -1013,7 +1067,7 @@ success:
}
// initialize extensions
GLimp_InitExtensions( );
GLimp_InitExtensions( fixedFunction );
ri.Cvar_Get( "r_availableModes", "", CVAR_ROM );

View file

@ -188,9 +188,6 @@ qboolean SNDDMA_Init(void)
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
int tmp;
#ifdef USE_SDL_AUDIO_CAPTURE
SDL_version sdlVersion;
#endif
if (snd_inited)
return qtrue;
@ -267,20 +264,15 @@ qboolean SNDDMA_Init(void)
if (!tmp)
tmp = (obtained.samples * obtained.channels) * 10;
if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something.
{
int val = 1;
while (val < tmp)
val <<= 1;
tmp = val;
}
// samples must be divisible by number of channels
tmp -= tmp % obtained.channels;
dmapos = 0;
dma.samplebits = SDL_AUDIO_BITSIZE(obtained.format);
dma.isfloat = SDL_AUDIO_ISFLOAT(obtained.format);
dma.channels = obtained.channels;
dma.samples = tmp;
dma.fullsamples = dma.samples / dma.channels;
dma.submission_chunk = 1;
dma.speed = obtained.freq;
dmasize = (dma.samples * (dma.samplebits/8));
@ -289,11 +281,10 @@ qboolean SNDDMA_Init(void)
#ifdef USE_SDL_AUDIO_CAPTURE
// !!! FIXME: some of these SDL_OpenAudioDevice() values should be cvars.
s_sdlCapture = Cvar_Get( "s_sdlCapture", "1", CVAR_ARCHIVE | CVAR_LATCH );
// !!! FIXME: hopefully pulseaudio capture will be fixed in SDL 2.0.9... https://bugzilla.libsdl.org/show_bug.cgi?id=4087
SDL_GetVersion(&sdlVersion);
if (sdlVersion.major == 2 && sdlVersion.minor == 0 && sdlVersion.patch < 9 && Q_stricmp(SDL_GetCurrentAudioDriver(), "pulseaudio") == 0)
// !!! FIXME: pulseaudio capture records audio the entire time the program is running. https://bugzilla.libsdl.org/show_bug.cgi?id=4087
if (Q_stricmp(SDL_GetCurrentAudioDriver(), "pulseaudio") == 0)
{
Com_Printf("SDL audio capture support disabled (pulseaudio capture does not work correctly with SDL %d.%d.%d)\n", sdlVersion.major, sdlVersion.minor, sdlVersion.patch);
Com_Printf("SDL audio capture support disabled for pulseaudio (https://bugzilla.libsdl.org/show_bug.cgi?id=4087)\n");
}
else if (!s_sdlCapture->integer)
{

View file

@ -112,6 +112,14 @@ Restart the input subsystem
*/
void Sys_In_Restart_f( void )
{
#ifndef DEDICATED
if( !SDL_WasInit( SDL_INIT_VIDEO ) )
{
Com_Printf( "in_restart: Cannot restart input while video is shutdown\n" );
return;
}
#endif
IN_Restart( );
}

View file

@ -3086,6 +3086,7 @@ static void UI_Update(const char *name) {
trap_Cvar_SetValue( "r_stencilbits", 8 );
trap_Cvar_SetValue( "r_picmip", 0 );
trap_Cvar_SetValue( "r_mode", 4 );
trap_Cvar_Set( "ui_videomode", "800x600" );
trap_Cvar_SetValue( "r_texturebits", 32 );
trap_Cvar_SetValue( "r_fastSky", 0 );
trap_Cvar_SetValue( "r_inGameVideo", 1 );
@ -3103,6 +3104,7 @@ static void UI_Update(const char *name) {
trap_Cvar_Reset( "r_stencilbits" );
trap_Cvar_SetValue( "r_picmip", 1 );
trap_Cvar_SetValue( "r_mode", 3 );
trap_Cvar_Set( "ui_videomode", "640x480" );
trap_Cvar_SetValue( "r_texturebits", 0 );
trap_Cvar_SetValue( "r_fastSky", 0 );
trap_Cvar_SetValue( "r_inGameVideo", 1 );
@ -3120,6 +3122,7 @@ static void UI_Update(const char *name) {
trap_Cvar_Reset( "r_stencilbits" );
trap_Cvar_SetValue( "r_picmip", 1 );
trap_Cvar_SetValue( "r_mode", 3 );
trap_Cvar_Set( "ui_videomode", "640x480" );
trap_Cvar_SetValue( "r_texturebits", 0 );
trap_Cvar_SetValue( "cg_shadows", 0 );
trap_Cvar_SetValue( "r_fastSky", 1 );
@ -3136,6 +3139,7 @@ static void UI_Update(const char *name) {
trap_Cvar_SetValue( "r_depthbits", 16 );
trap_Cvar_SetValue( "r_stencilbits", 0 );
trap_Cvar_SetValue( "r_mode", 3 );
trap_Cvar_Set( "ui_videomode", "640x480" );
trap_Cvar_SetValue( "r_picmip", 2 );
trap_Cvar_SetValue( "r_texturebits", 16 );
trap_Cvar_SetValue( "cg_shadows", 0 );
@ -5079,6 +5083,8 @@ void _UI_Init( qboolean inGameLoad ) {
// cache redundant calulations
trap_GetGlconfig( &uiInfo.uiDC.glconfig );
trap_Cvar_Set("ui_videomode", va( "%dx%d", uiInfo.uiDC.glconfig.vidWidth, uiInfo.uiDC.glconfig.vidHeight ) );
// for 640x480 virtualized screen
uiInfo.uiDC.yscale = uiInfo.uiDC.glconfig.vidHeight * (1.0/480.0);
uiInfo.uiDC.xscale = uiInfo.uiDC.glconfig.vidWidth * (1.0/640.0);
@ -5871,6 +5877,7 @@ static cvarTable_t cvarTable[] = {
{ &ui_realCaptureLimit, "capturelimit", "8", CVAR_SERVERINFO | CVAR_ARCHIVE | CVAR_NORESTART},
{ &ui_serverStatusTimeOut, "ui_serverStatusTimeOut", "7000", CVAR_ARCHIVE},
{ NULL, "ui_videomode", "", CVAR_ROM },
{ NULL, "g_localTeamPref", "", 0 },
};

View file

@ -2055,6 +2055,26 @@ qboolean Item_Multi_HandleKey(itemDef_t *item, int key) {
} else if ( current >= max ) {
current = 0;
}
if (multiPtr->videoMode) {
if (multiPtr->cvarValue[current] != -1) {
DC->setCVar("r_mode", va("%i", (int) multiPtr->cvarValue[current] ));
} else {
int w, h;
char *x;
char str[8];
x = strchr( multiPtr->cvarStr[current], 'x' ) + 1;
Q_strncpyz( str, multiPtr->cvarStr[current], MIN( x-multiPtr->cvarStr[current], sizeof( str ) ) );
w = atoi( str );
h = atoi( x );
DC->setCVar("r_mode", "-1");
DC->setCVar("r_customwidth", va("%i", w));
DC->setCVar("r_customheight", va("%i", h));
}
}
if (multiPtr->strDef) {
DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
} else {
@ -5003,6 +5023,7 @@ qboolean ItemParse_cvarStrList( itemDef_t *item, int handle ) {
multiPtr = (multiDef_t*)item->typeData;
multiPtr->count = 0;
multiPtr->strDef = qtrue;
multiPtr->videoMode = qfalse;
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
@ -5051,6 +5072,7 @@ qboolean ItemParse_cvarFloatList( itemDef_t *item, int handle ) {
multiPtr = (multiDef_t*)item->typeData;
multiPtr->count = 0;
multiPtr->strDef = qfalse;
multiPtr->videoMode = qfalse;
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
@ -5227,6 +5249,61 @@ void Item_SetupKeywordHash(void) {
}
}
static const char *builtinResolutions[ ] =
{
"320x240",
"400x300",
"512x384",
"640x480",
"800x600",
"960x720",
"1024x768",
"1152x864",
"1280x1024",
"1600x1200",
"2048x1536",
"856x480",
NULL
};
static const char *knownRatios[ ][2] =
{
{ "1.25:1", "5:4" },
{ "1.33:1", "4:3" },
{ "1.50:1", "3:2" },
{ "1.56:1", "14:9" },
{ "1.60:1", "16:10" },
{ "1.67:1", "5:3" },
{ "1.78:1", "16:9" },
{ NULL , NULL }
};
/*
===============
UI_ResolutionToAspect
===============
*/
static void UI_ResolutionToAspect( const char *resolution, char *aspect, size_t aspectLength ) {
int i, w, h;
char *x;
char str[8];
// calculate resolution's aspect ratio
x = strchr( resolution, 'x' ) + 1;
Q_strncpyz( str, resolution, MIN( x-resolution, sizeof( str ) ) );
w = atoi( str );
h = atoi( x );
Com_sprintf( aspect, aspectLength, "%.2f:1", (float)w / (float)h );
// rename common ratios ("1.33:1" -> "4:3")
for( i = 0; knownRatios[i][0]; i++ ) {
if( !Q_stricmp( aspect, knownRatios[i][0] ) ) {
Q_strncpyz( aspect, knownRatios[i][1], aspectLength );
break;
}
}
}
/*
===============
Item_ApplyHacks
@ -5261,6 +5338,89 @@ static void Item_ApplyHacks( itemDef_t *item ) {
}
}
// Replace mode list and use a temporary ui_videomode cvar for handling custom modes
if ( item->type == ITEM_TYPE_MULTI && item->cvar && !Q_stricmp( item->cvar, "r_mode" ) ) {
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
int i, oldCount;
char resbuf[MAX_STRING_CHARS];
char modeName[32], aspect[8];
item->cvar = "ui_videomode";
multiPtr->strDef = qtrue;
multiPtr->videoMode = qtrue;
oldCount = multiPtr->count;
multiPtr->count = 0;
DC->getCVarString( "r_availableModes", resbuf, sizeof( resbuf ) );
if ( *resbuf ) {
char *s = resbuf, *mode;
while ( s && multiPtr->count < MAX_MULTI_CVARS ) {
mode = s;
s = strchr(s, ' ');
if( s )
*s++ = '\0';
UI_ResolutionToAspect( mode, aspect, sizeof( aspect ) );
Com_sprintf( modeName, sizeof( modeName ), "%s (%s)", mode, aspect );
multiPtr->cvarList[multiPtr->count] = String_Alloc( modeName );
for ( i = 0; builtinResolutions[i]; i++ ) {
if( !Q_stricmp( builtinResolutions[i], mode ) ) {
multiPtr->cvarStr[multiPtr->count] = builtinResolutions[i];
multiPtr->cvarValue[multiPtr->count] = i;
break;
}
}
if ( builtinResolutions[i] == NULL ) {
multiPtr->cvarStr[multiPtr->count] = String_Alloc( mode );
multiPtr->cvarValue[multiPtr->count] = -1;
}
multiPtr->count++;
}
} else {
for ( i = 0; builtinResolutions[i] && multiPtr->count < MAX_MULTI_CVARS; i++ ) {
UI_ResolutionToAspect( builtinResolutions[i], aspect, sizeof( aspect ) );
Com_sprintf( modeName, sizeof( modeName ), "%s (%s)", builtinResolutions[i], aspect );
multiPtr->cvarList[multiPtr->count] = String_Alloc( modeName );
multiPtr->cvarStr[multiPtr->count] = builtinResolutions[i];
multiPtr->cvarValue[multiPtr->count] = i;
multiPtr->count++;
}
}
// Add custom resolution if not in mode list
if ( multiPtr->count < MAX_MULTI_CVARS ) {
char currentResolution[20];
Com_sprintf( currentResolution, sizeof ( currentResolution ), "%dx%d", DC->glconfig.vidWidth, DC->glconfig.vidHeight );
for ( i = 0; i < multiPtr->count; i++ ) {
if ( !Q_stricmp( multiPtr->cvarStr[i], currentResolution ) ) {
break;
}
}
if ( i == multiPtr->count ) {
UI_ResolutionToAspect( currentResolution, aspect, sizeof( aspect ) );
Com_sprintf( modeName, sizeof( modeName ), "%s (%s)", currentResolution, aspect );
multiPtr->cvarList[multiPtr->count] = String_Alloc( modeName );
multiPtr->cvarStr[multiPtr->count] = String_Alloc( currentResolution );
multiPtr->cvarValue[multiPtr->count] = -1;
multiPtr->count++;
}
}
Com_Printf( "Found video mode list with %d modes, replaced list with %d modes\n", oldCount, multiPtr->count );
}
}
/*

View file

@ -203,6 +203,7 @@ typedef struct multiDef_s {
float cvarValue[MAX_MULTI_CVARS];
int count;
qboolean strDef;
qboolean videoMode;
} multiDef_t;
typedef struct modelDef_s {

338
misc/msvc12/.gitignore vendored Normal file
View file

@ -0,0 +1,338 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
**/wwwroot/lib/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/

View file

@ -1,5 +1,5 @@
#!/bin/sh
rmdir --ignore-fail-on-non-empty demoq3 missionpack >& /dev/null
rmdir --ignore-fail-on-non-empty demoq3 missionpack >/dev/null 2>&1
if test -e "$SETUP_INSTALLPATH"/ioquake3.desktop.in; then
xdg_desktop_menu=`which xdg-desktop-menu 2>/dev/null`
if test "x$xdg_desktop_menu" = x; then

View file

@ -184,6 +184,11 @@ Cvars for advanced material usage:
1 - Use parallax occlusion mapping.
2 - Use relief mapping. (slower)
* `r_parallaxMapShadows` - Enable self-shadowing on parallax map
supported materials.
0 - No. (default)
1 - Yes.
* `r_baseSpecular` - Set the specular reflectance of materials
which don't include a specular map or
use the specularReflectance keyword.