Updating to ioq3 git dated 21 Jan 2014

This commit is contained in:
Richard Allen 2014-01-21 02:31:58 +00:00
parent 45e82a1618
commit 4b2fe84e40
81 changed files with 3737 additions and 4182 deletions

View file

@ -2677,6 +2677,10 @@ ifneq ($(BUILD_CLIENT),0)
ifneq ($(BUILD_RENDERER_OPENGL2),0)
$(INSTALL) $(STRIP_FLAG) -m 0755 $(BR)/renderer_opengl2_$(SHLIBNAME) $(COPYBINDIR)/renderer_opengl2_$(SHLIBNAME)
endif
else
ifneq ($(BUILD_RENDERER_OPENGL2),0)
$(INSTALL) $(STRIP_FLAG) -m 0755 $(BR)/$(CLIENTBIN)_opengl2$(FULLBINEXT) $(COPYBINDIR)/$(CLIENTBIN)_opengl2$(FULLBINEXT)
endif
endif
endif

View file

@ -39,7 +39,7 @@ renamed to id-readme.txt so as to prevent confusion. Please refer to the
web-site for updated status.
--------------------------------------------- Compilation and installation -----
# Compilation and installation
For *nix
1. Change to the directory containing this readme.
@ -73,6 +73,7 @@ x86_64.
The following variables may be set, either on the command line or in
Makefile.local:
```
CFLAGS - use this for custom CFLAGS
V - set to show cc command line when building
DEFAULT_BASEDIR - extra path to search for baseq3 and such
@ -108,13 +109,16 @@ Makefile.local:
DEBUG_CFLAGS - C compiler flags to use for building debug version
COPYDIR - the target installation directory
TEMPDIR - specify user defined directory for temp files
```
The defaults for these variables differ depending on the target platform.
------------------------------------------------------------------ Console -----
# Console
New cvars
## New cvars
```
cl_autoRecordDemo - record a new demo on each map change
cl_aviFrameRate - the framerate to use when capturing video
cl_aviMotionJpeg - use the mjpeg codec when capturing video
@ -271,8 +275,11 @@ New cvars
cl_aviMotionJpeg is enabled
r_mode -2 - This new video mode automatically uses the
desktop resolution.
```
New commands
## New commands
```
video [filename] - start video capture (use with demo command)
stopvideo - stop video capture
stopmusic - stop background music
@ -307,107 +314,125 @@ New commands
all bots even if someone is named "allbots")
tell <client num> <msg> - send message to a single client (new to server)
```
--------------------------------------------------------- README for Users -----
# README for Users
Using shared libraries instead of qvm
To force Q3 to use shared libraries instead of qvms run it with the following
parameters: +set sv_pure 0 +set vm_cgame 0 +set vm_game 0 +set vm_ui 0
## Using shared libraries instead of qvm
Using Demo Data Files
Copy demoq3/pak0.pk3 from the demo installer to your baseq3 directory. The
qvm files in this pak0.pk3 will not work, so you have to use the native
shared libraries or qvms from this project. To use the new qvms, they must be
put into a pk3 file. A pk3 file is just a zip file, so any compression tool
that can create such files will work. The shared libraries should already be
in the correct place. Use the instructions above to use them.
To force Q3 to use shared libraries instead of qvms run it with the following
parameters: `+set sv_pure 0 +set vm_cgame 0 +set vm_game 0 +set vm_ui 0`
Please bear in mind that you will not be able to play online using the demo
data, nor is it something that we like to spend much time maintaining or
supporting.
## Using Demo Data Files
Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps!
Ioquake3 now uses the select() system call to wait for the rendering of the
next frame when com_maxfps was hit. This will improve your CPU load
considerably in these cases. However, not all systems may support a
granularity for its timing functions that is required to perform this waiting
correctly. For instance, ioquake3 tells select() to wait 2 milliseconds, but
really it can only wait for a multiple of 5ms, i.e. 5, 10, 15, 20... ms.
In this case you can always revert back to the old behaviour by setting the
cvar com_busyWait to 1.
Copy demoq3/pak0.pk3 from the demo installer to your baseq3 directory. The
qvm files in this pak0.pk3 will not work, so you have to use the native
shared libraries or qvms from this project. To use the new qvms, they must be
put into a pk3 file. A pk3 file is just a zip file, so any compression tool
that can create such files will work. The shared libraries should already be
in the correct place. Use the instructions above to use them.
Using HTTP/FTP Download Support (Server)
You can enable redirected downloads on your server even if it's not
an ioquake3 server. You simply need to use the 'sets' command to put
the sv_dlURL cvar into your SERVERINFO string and ensure sv_allowDownloads
is set to 1
Please bear in mind that you will not be able to play online using the demo
data, nor is it something that we like to spend much time maintaining or
supporting.
sv_dlURL is the base of the URL that contains your custom .pk3 files
the client will append both fs_game and the filename to the end of
this value. For example, if you have sv_dlURL set to
"http://ioquake3.org", fs_game is "baseq3", and the client is
missing "test.pk3", it will attempt to download from the URL
"http://ioquake3.org/baseq3/test.pk3"
## Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps!
sv_allowDownload's value is now a bitmask made up of the following
flags:
1 - ENABLE
4 - do not use UDP downloads
8 - do not ask the client to disconnect when using HTTP/FTP
Ioquake3 now uses the select() system call to wait for the rendering of the
next frame when com_maxfps was hit. This will improve your CPU load
considerably in these cases. However, not all systems may support a
granularity for its timing functions that is required to perform this waiting
correctly. For instance, ioquake3 tells select() to wait 2 milliseconds, but
really it can only wait for a multiple of 5ms, i.e. 5, 10, 15, 20... ms.
In this case you can always revert back to the old behaviour by setting the
cvar com_busyWait to 1.
Server operators who are concerned about potential "leeching" from their
HTTP servers from other ioquake3 servers can make use of the HTTP_REFERER
that ioquake3 sets which is "ioQ3://{SERVER_IP}:{SERVER_PORT}". For,
example, Apache's mod_rewrite can restrict access based on HTTP_REFERER.
## Using HTTP/FTP Download Support (Server)
On a sidenote, downloading via UDP has been improved and yields higher data
rates now. You can configure the maximum bandwidth for UDP downloads via the
cvar sv_dlRate. Due to system-specific limits the download rate is capped
at about 1 Mbyte/s per client, so curl downloading may still be faster.
You can enable redirected downloads on your server even if it's not
an ioquake3 server. You simply need to use the 'sets' command to put
the sv_dlURL cvar into your SERVERINFO string and ensure sv_allowDownloads
is set to 1
Using HTTP/FTP Download Support (Client)
Simply setting cl_allowDownload to 1 will enable HTTP/FTP downloads
assuming ioquake3 was compiled with USE_CURL=1 (the default).
like sv_allowDownload, cl_allowDownload also uses a bitmask value
supporting the following flags:
1 - ENABLE
2 - do not use HTTP/FTP downloads
4 - do not use UDP downloads
sv_dlURL is the base of the URL that contains your custom .pk3 files
the client will append both fs_game and the filename to the end of
this value. For example, if you have sv_dlURL set to
`"http://ioquake3.org"`, fs_game is `"baseq3"`, and the client is
missing `"test.pk3"`, it will attempt to download from the URL
`"http://ioquake3.org/baseq3/test.pk3"`
When ioquake3 is built with USE_CURL_DLOPEN=1 (default on some platforms),
it will use the value of the cvar cl_cURLLib as the filename of the cURL
library to dynamically load.
sv_allowDownload's value is now a bitmask made up of the following
flags:
Multiuser Support on Windows systems
On Windows, all user specific files such as autogenerated configuration,
demos, videos, screenshots, and autodownloaded pk3s are now saved in a
directory specific to the user who is running ioquake3.
* 1 - ENABLE
* 4 - do not use UDP downloads
* 8 - do not ask the client to disconnect when using HTTP/FTP
On NT-based such as Windows XP, this is usually a directory named:
"C:\Documents and Settings\%USERNAME%\Application Data\Quake3\"
Server operators who are concerned about potential "leeching" from their
HTTP servers from other ioquake3 servers can make use of the HTTP_REFERER
that ioquake3 sets which is `"ioQ3://{SERVER_IP}:{SERVER_PORT}"`. For,
example, Apache's mod_rewrite can restrict access based on HTTP_REFERER.
Windows 95, Windows 98, and Windows ME will use a directory like:
"C:\Windows\Application Data\Quake3"
in single-user mode, or:
"C:\Windows\Profiles\%USERNAME%\Application Data\Quake3"
if multiple logins have been enabled.
On a sidenote, downloading via UDP has been improved and yields higher data
rates now. You can configure the maximum bandwidth for UDP downloads via the
cvar sv_dlRate. Due to system-specific limits the download rate is capped
at about 1 Mbyte/s per client, so curl downloading may still be faster.
In order to access this directory more easily, the installer may create a
Shortcut which has its target set to:
"%APPDATA%\Quake3\"
This Shortcut would work for all users on the system regardless of the
locale settings. Unfortunately, this environment variable is only
present on Windows NT based systems.
## Using HTTP/FTP Download Support (Client)
Simply setting cl_allowDownload to 1 will enable HTTP/FTP downloads
assuming ioquake3 was compiled with USE_CURL=1 (the default).
like sv_allowDownload, cl_allowDownload also uses a bitmask value
supporting the following flags:
* 1 - ENABLE
* 2 - do not use HTTP/FTP downloads
* 4 - do not use UDP downloads
When ioquake3 is built with USE_CURL_DLOPEN=1 (default on some platforms),
it will use the value of the cvar cl_cURLLib as the filename of the cURL
library to dynamically load.
## Multiuser Support on Windows systems
On Windows, all user specific files such as autogenerated configuration,
demos, videos, screenshots, and autodownloaded pk3s are now saved in a
directory specific to the user who is running ioquake3.
On NT-based such as Windows XP, this is usually a directory named:
C:\Documents and Settings\%USERNAME%\Application Data\Quake3\
Windows 95, Windows 98, and Windows ME will use a directory like:
C:\Windows\Application Data\Quake3
in single-user mode, or:
C:\Windows\Profiles\%USERNAME%\Application Data\Quake3
if multiple logins have been enabled.
In order to access this directory more easily, the installer may create a
Shortcut which has its target set to:
%APPDATA%\Quake3\
This Shortcut would work for all users on the system regardless of the
locale settings. Unfortunately, this environment variable is only
present on Windows NT based systems.
You can revert to the old single-user behaviour by setting the fs_homepath
cvar to the directory where ioquake3 is installed. For example:
You can revert to the old single-user behaviour by setting the fs_homepath
cvar to the directory where ioquake3 is installed. For example:
ioquake3.exe +set fs_homepath "c:\ioquake3"
Note that this cvar MUST be set as a command line parameter.
SDL Keyboard Differences
ioquake3 clients have different keyboard behaviour compared to the original
Quake3 clients.
Note that this cvar MUST be set as a command line parameter.
## SDL Keyboard Differences
ioquake3 clients have different keyboard behaviour compared to the original
Quake3 clients.
* "Caps Lock" and "Num Lock" can not be used as normal binds since they
do not send a KEYUP event until the key is pressed again.
@ -422,17 +447,17 @@ SDL Keyboard Differences
For non-US keyboards, all of the so called "World" keys are now supported
as well as F13, F14, F15, and the country-specific mode/meta keys.
On many international layouts the default console toggle keys are also dead
keys, meaning that dropping the console potentially results in
unintentionally initiating the keying of a dead key. Furthermore SDL 1.2's
dead key support is broken by design and Q3 doesn't support non-ASCII text
entry, so the chances are you won't get the correct character anyway.
On many international layouts the default console toggle keys are also dead
keys, meaning that dropping the console potentially results in
unintentionally initiating the keying of a dead key. Furthermore SDL 1.2's
dead key support is broken by design and Q3 doesn't support non-ASCII text
entry, so the chances are you won't get the correct character anyway.
If you use such a keyboard layout, you can set the cvar cl_consoleKeys. This
is a space delimited list of key names that will toggle the console. The key
names are the usual Q3 names e.g. "~", "`", "c", "BACKSPACE", "PAUSE",
"WINDOWS" etc. It's also possible to use ASCII characters, by hexadecimal
number. Some example values for cl_consoleKeys:
If you use such a keyboard layout, you can set the cvar cl_consoleKeys. This
is a space delimited list of key names that will toggle the console. The key
names are the usual Q3 names e.g. "~", "`", "c", "BACKSPACE", "PAUSE",
"WINDOWS" etc. It's also possible to use ASCII characters, by hexadecimal
number. Some example values for cl_consoleKeys:
"~ ` 0x7e 0x60" Toggle on ~ or ` (the default)
"WINDOWS" Toggle on the Windows key
@ -440,75 +465,79 @@ SDL Keyboard Differences
"0x43" Toggle on the C character (Shift-c)
"PAUSE F1 PGUP" Toggle on the Pause, F1 or Page Up keys
Note that when you elect a set of console keys or characters, they cannot
then be used for binding, nor will they generate characters when entering
text. Also, in addition to the nominated console keys, Shift-ESC is hard
coded to always toggle the console.
Note that when you elect a set of console keys or characters, they cannot
then be used for binding, nor will they generate characters when entering
text. Also, in addition to the nominated console keys, Shift-ESC is hard
coded to always toggle the console.
QuakeLive mouse acceleration (patch and this text written by TTimo from id)
I've been using an experimental mouse acceleration code for a while, and
decided to make it available to everyone. Don't be too worried if you don't
understand the explanations below, this is mostly intended for advanced
players:
To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior)
## QuakeLive mouse acceleration
(patch and this text written by TTimo from id)
New style is controlled with 3 cvars:
I've been using an experimental mouse acceleration code for a while, and
decided to make it available to everyone. Don't be too worried if you don't
understand the explanations below, this is mostly intended for advanced
players:
To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior)
sensitivity
cl_mouseAccel
cl_mouseAccelOffset
New style is controlled with 3 cvars:
The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if
you have a base sensitivity setup, as soon as you set a non zero acceleration
your base sensitivity at low speeds will change as well. The other problem
with style 0 is that you are stuck on a square (power of two) acceleration
curve.
sensitivity
cl_mouseAccel
cl_mouseAccelOffset
The new code tries to solve both problems:
The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if
you have a base sensitivity setup, as soon as you set a non zero acceleration
your base sensitivity at low speeds will change as well. The other problem
with style 0 is that you are stuck on a square (power of two) acceleration
curve.
Once you setup your sensitivity to feel comfortable and accurate enough for
low mouse deltas with no acceleration (cl_mouseAccel 0), you can start
increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the
amplification you want for high deltas with little effect on low mouse deltas.
The new code tries to solve both problems:
cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve
as style 0. The higher the value, the faster the amplification grows with the
mouse delta.
Once you setup your sensitivity to feel comfortable and accurate enough for
low mouse deltas with no acceleration (cl_mouseAccel 0), you can start
increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the
amplification you want for high deltas with little effect on low mouse deltas.
cl_mouseAccelOffset sets how much base mouse delta will be doubled by
acceleration. The closer to zero you bring it, the more acceleration will
happen at low speeds. This is also very useful if you are changing to a new
mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your
cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely
gain in precision when you do that, but that is not related to mouse
acceleration).
cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve
as style 0. The higher the value, the faster the amplification grows with the
mouse delta.
Mouse acceleration is tricky to configure, and when you do you'll have to
re-learn your aiming. But you will find that it's very much forth it in the
long run.
cl_mouseAccelOffset sets how much base mouse delta will be doubled by
acceleration. The closer to zero you bring it, the more acceleration will
happen at low speeds. This is also very useful if you are changing to a new
mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your
cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely
gain in precision when you do that, but that is not related to mouse
acceleration).
If you try the new acceleration code and start using it, I'd be very
interested by your feedback.
Mouse acceleration is tricky to configure, and when you do you'll have to
re-learn your aiming. But you will find that it's very much forth it in the
long run.
If you try the new acceleration code and start using it, I'd be very
interested by your feedback.
---------------------------------------------------- README for Developers -----
# README for Developers
pk3dir
ioquake3 has a useful new feature for mappers. Paths in a game directory with
the extension ".pk3dir" are treated like pk3 files. This means you can keep
all files specific to your map in one directory tree and easily zip this
folder for distribution.
## pk3dir
64bit mods
If you wish to compile external mods as shared libraries on a 64bit platform,
and the mod source is derived from the id Q3 SDK, you will need to modify the
interface code a little. Open the files ending in _syscalls.c and change
every instance of int to intptr_t in the declaration of the syscall function
pointer and the dllEntry function. Also find the vmMain function for each
module (usually in cg_main.c g_main.c etc.) and similarly replace the return
value in the prototype with intptr_t (arg0, arg1, ...stay int).
ioquake3 has a useful new feature for mappers. Paths in a game directory with
the extension ".pk3dir" are treated like pk3 files. This means you can keep
all files specific to your map in one directory tree and easily zip this
folder for distribution.
Add the following code snippet to q_shared.h:
## 64bit mods
If you wish to compile external mods as shared libraries on a 64bit platform,
and the mod source is derived from the id Q3 SDK, you will need to modify the
interface code a little. Open the files ending in _syscalls.c and change
every instance of int to intptr_t in the declaration of the syscall function
pointer and the dllEntry function. Also find the vmMain function for each
module (usually in cg_main.c g_main.c etc.) and similarly replace the return
value in the prototype with intptr_t (arg0, arg1, ...stay int).
Add the following code snippet to q_shared.h:
#ifdef Q3_VM
typedef int intptr_t;
@ -516,165 +545,173 @@ pk3dir
#include <stdint.h>
#endif
Note if you simply wish to run mods on a 64bit platform you do not need to
recompile anything since by default Q3 uses a virtual machine system.
Note if you simply wish to run mods on a 64bit platform you do not need to
recompile anything since by default Q3 uses a virtual machine system.
Creating mods compatible with Q3 1.32b
If you're using this package to create mods for the last official release of
Q3, it is necessary to pass the commandline option '-vq3' to your invocation
of q3asm. This is because by default q3asm outputs an updated qvm format that
is necessary to fix a bug involving the optimizing pass of the x86 vm JIT
compiler.
## Creating mods compatible with Q3 1.32b
Creating standalone games
Have you finished the daunting task of removing all dependencies on the Q3
game data? You probably now want to give your users the opportunity to play
the game without owning a copy of Q3, which consequently means removing cd-key
and authentication server checks. In addition to being a straightforward Q3
client, ioquake3 also purports to be a reliable and stable code base on which
to base your game project.
If you're using this package to create mods for the last official release of
Q3, it is necessary to pass the commandline option '-vq3' to your invocation
of q3asm. This is because by default q3asm outputs an updated qvm format that
is necessary to fix a bug involving the optimizing pass of the x86 vm JIT
compiler.
However, before you start compiling your own version of ioquake3, you have to
ask yourself: Have we changed or will we need to change anything of importance
in the engine?
## Creating standalone games
If your answer to this question is "no", it probably makes no sense to build
your own binaries. Instead, you can just use the pre-built binaries on the
website. Just make sure the game is called with:
Have you finished the daunting task of removing all dependencies on the Q3
game data? You probably now want to give your users the opportunity to play
the game without owning a copy of Q3, which consequently means removing cd-key
and authentication server checks. In addition to being a straightforward Q3
client, ioquake3 also purports to be a reliable and stable code base on which
to base your game project.
However, before you start compiling your own version of ioquake3, you have to
ask yourself: Have we changed or will we need to change anything of importance
in the engine?
If your answer to this question is "no", it probably makes no sense to build
your own binaries. Instead, you can just use the pre-built binaries on the
website. Just make sure the game is called with:
+set com_basegame <yournewbase>
in any links/scripts you install for your users to start the game. The
binary must not detect any original quake3 game pak files. If this
condition is met, the game will set com_standalone to 1 and is then running
in stand alone mode.
in any links/scripts you install for your users to start the game. The
binary must not detect any original quake3 game pak files. If this
condition is met, the game will set com_standalone to 1 and is then running
in stand alone mode.
If you want the engine to use a different directory in your homepath than
e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup
by adding
If you want the engine to use a different directory in your homepath than
e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup
by adding
+set com_homepath <homedirname>
to the command line. You can also control which game name to use when talking
to the master server:
to the command line. You can also control which game name to use when talking
to the master server:
+set com_gamename <gamename>
So clients requesting a server list will only receive servers that have a
matching game name.
So clients requesting a server list will only receive servers that have a
matching game name.
Example line:
Example line:
+set com_basegame basefoo +set com_homepath .foo
+set com_gamename foo
If you really changed parts that would make vanilla ioquake3 incompatible with
your mod, we have included another way to conveniently build a stand-alone
binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit
the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with
information appropriate for your project.
If you really changed parts that would make vanilla ioquake3 incompatible with
your mod, we have included another way to conveniently build a stand-alone
binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit
the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with
information appropriate for your project.
## Standalone game licensing
While a lot of work has been put into ioquake3 that you can benefit from free
of charge, it does not mean that you have no obligations to fulfill. Please be
aware that as soon as you start distributing your game with an engine based on
our sources we expect you to fully comply with the requirements as stated in
the GPL. That includes making sources and modifications you made to the
ioquake3 engine as well as the game-code used to compile the .qvm files for
the game logic freely available to everyone. Furthermore, note that the "QIIIA
Game Source License" prohibits distribution of mods that are intended to
operate on a version of Q3 not sanctioned by id software:
While a lot of work has been put into ioquake3 that you can benefit from free
of charge, it does not mean that you have no obligations to fulfill. Please be
aware that as soon as you start distributing your game with an engine based on
our sources we expect you to fully comply with the requirements as stated in
the GPL. That includes making sources and modifications you made to the
ioquake3 engine as well as the game-code used to compile the .qvm files for
the game logic freely available to everyone. Furthermore, note that the "QIIIA
Game Source License" prohibits distribution of mods that are intended to
operate on a version of Q3 not sanctioned by id software:
"with this Agreement, ID grants to you the non-exclusive and limited right
to distribute copies of the Software ... for operation only with the full
version of the software game QUAKE III ARENA"
This means that if you're creating a standalone game, you cannot use said
license on any portion of the product. As the only other license this code has
been released under is the GPL, this is the only option.
This means that if you're creating a standalone game, you cannot use said
license on any portion of the product. As the only other license this code has
been released under is the GPL, this is the only option.
This does NOT mean that you cannot market this game commercially. The GPL does
not prohibit commercial exploitation and all assets (e.g. textures, sounds,
maps) created by yourself are your property and can be sold like every other
game you find in stores.
This does NOT mean that you cannot market this game commercially. The GPL does
not prohibit commercial exploitation and all assets (e.g. textures, sounds,
maps) created by yourself are your property and can be sold like every other
game you find in stores.
Network protocols
There are now two cvars that give you some degree of freedom over the reported
protocol versions between clients and servers: "com_protocol" and
"com_legacyprotocol".
The reason for this is that some standalone games increased the protocol
number even though nothing really changed in their protocol and the ioquake3
engine is still fully compatible.
## Network protocols
In order to harden the network protocol against UDP spoofing attacks a new
network protocol was introduced that defends against such attacks.
Unfortunately, this protocol will be incompatible to the original quake3 1.32c
which is the latest official release from id.
Luckily, ioquake3 has backwards compatibility, on the client as well as on the
server. This means ioquake3 players can play on old servers just as ioquake3
servers are able to service old clients.
There are now two cvars that give you some degree of freedom over the reported
protocol versions between clients and servers: "com_protocol" and
"com_legacyprotocol".
The reason for this is that some standalone games increased the protocol
number even though nothing really changed in their protocol and the ioquake3
engine is still fully compatible.
The cvar "com_protocol" denotes the protocol version for the new hardened
protocol, whereas the "com_legacyprotocol" cvar denotes the protocol version
for the legacy protocol.
If the value for "com_protocol" and "com_legacyprotocol" is identical, then
the legacy protocol is always used. If "com_legacyprotocol" is set to 0, then
support for the legacy protocol is disabled.
In order to harden the network protocol against UDP spoofing attacks a new
network protocol was introduced that defends against such attacks.
Unfortunately, this protocol will be incompatible to the original quake3 1.32c
which is the latest official release from id.
Luckily, ioquake3 has backwards compatibility, on the client as well as on the
server. This means ioquake3 players can play on old servers just as ioquake3
servers are able to service old clients.
Mods that use a standalone engine obviously do not require dual protocol
support, and it is turned off if the engine is compiled with STANDALONE per
default. If you desire backwards compatibility to older versions of your
game you can still enable it in q_shared.h by defining
LEGACY_PROTOCOL.
The cvar "com_protocol" denotes the protocol version for the new hardened
protocol, whereas the "com_legacyprotocol" cvar denotes the protocol version
for the legacy protocol.
If the value for "com_protocol" and "com_legacyprotocol" is identical, then
the legacy protocol is always used. If "com_legacyprotocol" is set to 0, then
support for the legacy protocol is disabled.
cl_guid Support
cl_guid is a cvar which is part of the client's USERINFO string. Its value
is a 32 character string made up of [a-f] and [0-9] characters. This
value is pseudo-unique for every player. Id's Quake 3 Arena client also
sets cl_guid, but only if Punkbuster is enabled on the client.
Mods that use a standalone engine obviously do not require dual protocol
support, and it is turned off if the engine is compiled with STANDALONE per
default. If you desire backwards compatibility to older versions of your
game you can still enable it in q_shared.h by defining
LEGACY_PROTOCOL.
If cl_guidServerUniq is non-zero (the default), then this value is also
pseudo-unique for each server a client connects to (based on IP:PORT of
the server).
## cl_guid Support
The purpose of cl_guid is to add an identifier for each player on
a server. This value can be reset by the client at any time so it's not
useful for blocking access. However, it can have at least two uses in
your mod's game code:
1) improve logging to allow statistical tools to index players by more
cl_guid is a cvar which is part of the client's USERINFO string. Its value
is a 32 character string made up of [a-f] and [0-9] characters. This
value is pseudo-unique for every player. Id's Quake 3 Arena client also
sets cl_guid, but only if Punkbuster is enabled on the client.
If cl_guidServerUniq is non-zero (the default), then this value is also
pseudo-unique for each server a client connects to (based on IP:PORT of
the server).
The purpose of cl_guid is to add an identifier for each player on
a server. This value can be reset by the client at any time so it's not
useful for blocking access. However, it can have at least two uses in
your mod's game code:
1. improve logging to allow statistical tools to index players by more
than just name
2) granting some weak admin rights to players without requiring passwords
2. granting some weak admin rights to players without requiring passwords
PNG support
ioquake3 supports the use of PNG (Portable Network Graphic) images as
textures. It should be noted that the use of such images in a map will
result in missing placeholder textures where the map is used with the id
Quake 3 client or earlier versions of ioquake3.
## PNG support
Recent versions of GtkRadiant and q3map2 support PNG images without
modification. However GtkRadiant is not aware that PNG textures are supported
by ioquake3. To change this behaviour open the file 'q3.game' in the 'games'
directory of the GtkRadiant base directory with an editor and change the
line:
ioquake3 supports the use of PNG (Portable Network Graphic) images as
textures. It should be noted that the use of such images in a map will
result in missing placeholder textures where the map is used with the id
Quake 3 client or earlier versions of ioquake3.
Recent versions of GtkRadiant and q3map2 support PNG images without
modification. However GtkRadiant is not aware that PNG textures are supported
by ioquake3. To change this behaviour open the file 'q3.game' in the 'games'
directory of the GtkRadiant base directory with an editor and change the
line:
texturetypes="tga jpg"
to
to
texturetypes="tga jpg png"
Restart GtkRadiant and PNG textures are now available.
Restart GtkRadiant and PNG textures are now available.
Building with MinGW for pre Windows XP
IPv6 support requires a header named "wspiapi.h" to abstract away from
differences in earlier versions of Windows' IPv6 stack. There is no MinGW
equivalent of this header and the Microsoft version is obviously not
redistributable, so in its absence we're forced to require Windows XP.
However if this header is acquired separately and placed in the qcommon/
directory, this restriction is lifted.
## Building with MinGW for pre Windows XP
IPv6 support requires a header named "wspiapi.h" to abstract away from
differences in earlier versions of Windows' IPv6 stack. There is no MinGW
equivalent of this header and the Microsoft version is obviously not
redistributable, so in its absence we're forced to require Windows XP.
However if this header is acquired separately and placed in the qcommon/
directory, this restriction is lifted.
------------------------------------------------------------- Contributing -----
# Contributing
Please send all patches to bugzilla (https://bugzilla.icculus.org), or join the
mailing list (http://lists.ioquake.org/listinfo.cgi/ioquake3-ioquake.org) and
@ -689,7 +726,7 @@ accepted as long as they are entirely optional, do not require new media and
are off by default.
--------------------------------------------- Building Official Installers -----
# Building Official Installers
We need help getting automated installers on all the platforms that ioquake3
supports. We don't necessarily care about all the installers being identical,
@ -722,22 +759,28 @@ but we have some general guidelines:
* Your installer will be mirrored to an "official" directory, thus making it
a done deal.
------------------------------------------------------------------ Credits -----
# Credits
Maintainers
James Canete <use.less01@gmail.com>
Ludwig Nussel <ludwig.nussel@suse.de>
Thilo Schulz <arny@ats.s.bawue.de>
Tim Angus <tim@ngus.net>
Tony J. White <tjw@tjw.org>
Zachary J. Slater <zachary@ioquake.org>
Zack Middleton <zturtleman@gmail.com>
* James Canete <use.less01@gmail.com>
* Ludwig Nussel <ludwig.nussel@suse.de>
* Thilo Schulz <arny@ats.s.bawue.de>
* Tim Angus <tim@ngus.net>
* Tony J. White <tjw@tjw.org>
* Zachary J. Slater <zachary@ioquake.org>
* Zack Middleton <zturtleman@gmail.com>
Significant contributions from
Ryan C. Gordon <icculus@icculus.org>
Andreas Kohn <andreas@syndrom23.de>
Joerg Dietrich <Dietrich_Joerg@t-online.de>
Stuart Dalton <badcdev@gmail.com>
Vincent S. Cojot <vincent at cojot dot name>
optical <alex@rigbo.se>
Aaron Gyes <floam@aaron.gy>
* Ryan C. Gordon <icculus@icculus.org>
* Andreas Kohn <andreas@syndrom23.de>
* Joerg Dietrich <Dietrich_Joerg@t-online.de>
* Stuart Dalton <badcdev@gmail.com>
* Vincent S. Cojot <vincent at cojot dot name>
* optical <alex@rigbo.se>
* Aaron Gyes <floam@aaron.gy>
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/6d196bd663b47049a25dcb8caef95949 "githalytics.com")](http://githalytics.com/ioquake/ioq3)

View file

@ -1472,7 +1472,9 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
Con_Close();
if (!cinTable[currentHandle].silent) {
s_rawend[0] = s_soundtime;
}
return currentHandle;
}

View file

@ -112,7 +112,6 @@ cvar_t *cl_conXOffset;
cvar_t *cl_inGameVideo;
cvar_t *cl_serverStatusResendTime;
cvar_t *cl_trn;
cvar_t *cl_lanForcePackets;
@ -671,7 +670,7 @@ void CL_StopRecord_f( void ) {
CL_DemoFilename
==================
*/
void CL_DemoFilename( int number, char *fileName ) {
void CL_DemoFilename( int number, char *fileName, int fileNameSize ) {
int a,b,c,d;
if(number < 0 || number > 9999)
@ -685,7 +684,7 @@ void CL_DemoFilename( int number, char *fileName ) {
number -= c*10;
d = number;
Com_sprintf( fileName, MAX_OSPATH, "demo%i%i%i%i"
Com_sprintf( fileName, fileNameSize, "demo%i%i%i%i"
, a, b, c, d );
}
@ -745,7 +744,7 @@ void CL_Record_f( void ) {
// scan for a free demo name
for ( number = 0 ; number <= 9999 ; number++ ) {
CL_DemoFilename( number, demoName );
CL_DemoFilename( number, demoName, sizeof( demoName ) );
#ifdef LEGACY_PROTOCOL
if(clc.compat)
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer);
@ -2429,6 +2428,9 @@ void CL_InitServerInfo( serverInfo_t *server, netadr_t *address ) {
server->game[0] = '\0';
server->gameType = 0;
server->netType = 0;
server->punkbuster = 0;
server->g_humanplayers = 0;
server->g_needpass = 0;
}
#define MAX_SERVERSPERPACKET 256
@ -2937,13 +2939,13 @@ void CL_Frame ( int msec ) {
if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) {
// save the current screen
if ( clc.state == CA_ACTIVE || cl_forceavidemo->integer) {
float fps = MIN(cl_aviFrameRate->value * com_timescale->value, 1000.0f);
float frameDuration = MAX(1000.0f / fps, 1.0f) + clc.aviVideoFrameRemainder;
CL_TakeVideoFrame( );
// fixed time for next frame'
msec = (int)ceil( (1000.0f / cl_aviFrameRate->value) * com_timescale->value );
if (msec == 0) {
msec = 1;
}
msec = (int)frameDuration;
clc.aviVideoFrameRemainder = frameDuration - msec;
}
}
@ -3836,20 +3838,7 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
// add this to the list
cls.numlocalservers = i+1;
cls.localServers[i].adr = from;
cls.localServers[i].clients = 0;
cls.localServers[i].hostName[0] = '\0';
cls.localServers[i].mapName[0] = '\0';
cls.localServers[i].maxClients = 0;
cls.localServers[i].maxPing = 0;
cls.localServers[i].minPing = 0;
cls.localServers[i].ping = -1;
cls.localServers[i].game[0] = '\0';
cls.localServers[i].gameType = 0;
cls.localServers[i].netType = from.type;
cls.localServers[i].punkbuster = 0;
cls.localServers[i].g_humanplayers = 0;
cls.localServers[i].g_needpass = 0;
CL_InitServerInfo( &cls.localServers[i], &from );
Q_strncpyz( info, MSG_ReadString( msg ), MAX_INFO_STRING );
if (strlen(info)) {

View file

@ -709,7 +709,7 @@ void CL_ParseVoip ( msg_t *msg ) {
const int packetsize = MSG_ReadShort(msg);
const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
char encoded[1024];
int seqdiff = sequence - clc.voipIncomingSequence[sender];
int seqdiff;
int written = 0;
int i;
@ -753,6 +753,8 @@ void CL_ParseVoip ( msg_t *msg ) {
Com_DPrintf("VoIP: packet accepted!\n");
seqdiff = sequence - clc.voipIncomingSequence[sender];
// This is a new "generation" ... a new recording started, reset the bits.
if (generation != clc.voipIncomingGeneration[sender]) {
Com_DPrintf("VoIP: new generation %d!\n", generation);

View file

@ -233,6 +233,9 @@ typedef struct {
int timeDemoMaxDuration; // maximum frame duration
unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations
float aviVideoFrameRemainder;
float aviSoundFrameRemainder;
#ifdef USE_VOIP
qboolean voipEnabled;
qboolean speexInitialized;

View file

@ -157,11 +157,8 @@ int S_OGG_Callback_seek(void *datasource, ogg_int64_t offset, int whence)
case SEEK_END :
{
// Quake 3 seems to have trouble with FS_SEEK_END
// so we use the file length and FS_SEEK_SET
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) stream->length + (long) offset, FS_SEEK_SET);
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
// something has gone wrong, so we return here
if(retVal < 0)

View file

@ -146,11 +146,8 @@ int S_OggOpus_Callback_seek(void *datasource, opus_int64 offset, int whence)
case SEEK_END :
{
// Quake 3 seems to have trouble with FS_SEEK_END
// so we use the file length and FS_SEEK_SET
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) stream->length + (long) offset, FS_SEEK_SET);
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
// something has gone wrong, so we return here
if(retVal < 0)

View file

@ -271,6 +271,11 @@ static sfx_t *S_FindName( const char *name ) {
return NULL;
}
if (name[0] == '*') {
Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", name );
return NULL;
}
hash = S_HashSFXName(name);
sfx = sfxHash[hash];
@ -977,29 +982,34 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
int i;
int src, dst;
float scale;
int intVolume;
int intVolumeLeft, intVolumeRight;
portable_samplepair_t *rawsamples;
if ( !s_soundStarted || s_soundMuted ) {
return;
}
if(entityNum >= 0)
{
// FIXME: support spatialized raw streams, e.g. for VoIP
return;
}
if ( (stream < 0) || (stream >= MAX_RAW_STREAMS) ) {
return;
}
rawsamples = s_rawsamples[stream];
if(s_muted->integer)
intVolume = 0;
else
intVolume = 256 * volume * s_volume->value;
if ( s_muted->integer ) {
intVolumeLeft = intVolumeRight = 0;
} else {
int leftvol, rightvol;
if ( entityNum >= 0 && entityNum < MAX_GENTITIES ) {
// support spatialized raw streams, e.g. for VoIP
S_SpatializeOrigin( loopSounds[ entityNum ].origin, 256, &leftvol, &rightvol );
} else {
leftvol = rightvol = 256;
}
intVolumeLeft = leftvol * volume * s_volume->value;
intVolumeRight = rightvol * volume * s_volume->value;
}
if ( s_rawend[stream] < s_soundtime ) {
Com_DPrintf( "S_Base_RawSamples: resetting minimum: %i < %i\n", s_rawend[stream], s_soundtime );
@ -1017,8 +1027,8 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
{
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
s_rawend[stream]++;
rawsamples[dst].left = ((short *)data)[i*2] * intVolume;
rawsamples[dst].right = ((short *)data)[i*2+1] * intVolume;
rawsamples[dst].left = ((short *)data)[i*2] * intVolumeLeft;
rawsamples[dst].right = ((short *)data)[i*2+1] * intVolumeRight;
}
}
else
@ -1030,8 +1040,8 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
break;
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
s_rawend[stream]++;
rawsamples[dst].left = ((short *)data)[src*2] * intVolume;
rawsamples[dst].right = ((short *)data)[src*2+1] * intVolume;
rawsamples[dst].left = ((short *)data)[src*2] * intVolumeLeft;
rawsamples[dst].right = ((short *)data)[src*2+1] * intVolumeRight;
}
}
}
@ -1044,13 +1054,14 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
break;
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
s_rawend[stream]++;
rawsamples[dst].left = ((short *)data)[src] * intVolume;
rawsamples[dst].right = ((short *)data)[src] * intVolume;
rawsamples[dst].left = ((short *)data)[src] * intVolumeLeft;
rawsamples[dst].right = ((short *)data)[src] * intVolumeRight;
}
}
else if (s_channels == 2 && width == 1)
{
intVolume *= 256;
intVolumeLeft *= 256;
intVolumeRight *= 256;
for (i=0 ; ; i++)
{
@ -1059,13 +1070,14 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
break;
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
s_rawend[stream]++;
rawsamples[dst].left = ((char *)data)[src*2] * intVolume;
rawsamples[dst].right = ((char *)data)[src*2+1] * intVolume;
rawsamples[dst].left = ((char *)data)[src*2] * intVolumeLeft;
rawsamples[dst].right = ((char *)data)[src*2+1] * intVolumeRight;
}
}
else if (s_channels == 1 && width == 1)
{
intVolume *= 256;
intVolumeLeft *= 256;
intVolumeRight *= 256;
for (i=0 ; ; i++)
{
@ -1074,8 +1086,8 @@ void S_Base_RawSamples( int stream, int samples, int rate, int width, int s_chan
break;
dst = s_rawend[stream]&(MAX_RAW_SAMPLES-1);
s_rawend[stream]++;
rawsamples[dst].left = (((byte *)data)[src]-128) * intVolume;
rawsamples[dst].right = (((byte *)data)[src]-128) * intVolume;
rawsamples[dst].left = (((byte *)data)[src]-128) * intVolumeLeft;
rawsamples[dst].right = (((byte *)data)[src]-128) * intVolumeRight;
}
}
@ -1237,7 +1249,13 @@ void S_GetSoundtime(void)
if( CL_VideoRecording( ) )
{
s_soundtime += (int)ceil( dma.speed / cl_aviFrameRate->value );
float fps = MIN(cl_aviFrameRate->value, 1000.0f);
float frameDuration = MAX(dma.speed / fps, 1.0f) + clc.aviSoundFrameRemainder;
int msec = (int)frameDuration;
s_soundtime += msec;
clc.aviSoundFrameRemainder = frameDuration - msec;
return;
}
@ -1360,6 +1378,32 @@ void S_Base_StopBackgroundTrack( void ) {
s_rawend[0] = 0;
}
/*
======================
S_OpenBackgroundStream
======================
*/
static void S_OpenBackgroundStream( const char *filename ) {
// close the background track, but DON'T reset s_rawend
// if restarting the same back ground track
if(s_backgroundStream)
{
S_CodecCloseStream(s_backgroundStream);
s_backgroundStream = NULL;
}
// Open stream
s_backgroundStream = S_CodecOpenStream(filename);
if(!s_backgroundStream) {
Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", filename );
return;
}
if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) {
Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", filename );
}
}
/*
======================
S_StartBackgroundTrack
@ -1380,30 +1424,9 @@ void S_Base_StartBackgroundTrack( const char *intro, const char *loop ){
return;
}
if( !loop ) {
s_backgroundLoop[0] = 0;
} else {
Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) );
}
// close the background track, but DON'T reset s_rawend
// if restarting the same back ground track
if(s_backgroundStream)
{
S_CodecCloseStream(s_backgroundStream);
s_backgroundStream = NULL;
}
// Open stream
s_backgroundStream = S_CodecOpenStream(intro);
if(!s_backgroundStream) {
Com_Printf( S_COLOR_YELLOW "WARNING: couldn't open music file %s\n", intro );
return;
}
if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) {
Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", intro );
}
S_OpenBackgroundStream( intro );
}
/*
@ -1466,9 +1489,7 @@ void S_UpdateBackgroundTrack( void ) {
// loop
if(s_backgroundLoop[0])
{
S_CodecCloseStream(s_backgroundStream);
s_backgroundStream = NULL;
S_Base_StartBackgroundTrack( s_backgroundLoop, s_backgroundLoop );
S_OpenBackgroundStream( s_backgroundLoop );
if(!s_backgroundStream)
return;
}

View file

@ -56,6 +56,7 @@ typedef struct sfx_s {
qboolean soundCompressed; // not in Memory
int soundCompressionMethod;
int soundLength;
int soundChannels;
char soundName[MAX_QPATH];
int lastTimeUsed;
struct sfx_s *next;

View file

@ -113,34 +113,35 @@ ResampleSfx
resample / decimate to the current source rate
================
*/
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) {
static int ResampleSfx( sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, qboolean compressed ) {
int outcount;
int srcsample;
float stepscale;
int i;
int i, j;
int sample, samplefrac, fracstep;
int part;
sndBuffer *chunk;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
outcount = sfx->soundLength / stepscale;
sfx->soundLength = outcount;
outcount = samples / stepscale;
samplefrac = 0;
fracstep = stepscale * 256;
fracstep = stepscale * 256 * channels;
chunk = sfx->soundData;
for (i=0 ; i<outcount ; i++)
{
srcsample = samplefrac >> 8;
samplefrac += fracstep;
for (j=0 ; j<channels ; j++)
{
if( inwidth == 2 ) {
sample = ( ((short *)data)[srcsample] );
sample = ( ((short *)data)[srcsample+j] );
} else {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
}
part = (i&(SND_CHUNK_SIZE-1));
part = (i*channels+j)&(SND_CHUNK_SIZE-1);
if (part == 0) {
sndBuffer *newchunk;
newchunk = SND_malloc();
@ -154,6 +155,9 @@ static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboole
chunk->sndChunk[part] = sample;
}
}
return outcount;
}
/*
@ -163,11 +167,11 @@ ResampleSfx
resample / decimate to the current source rate
================
*/
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) {
static int ResampleSfxRaw( short *sfx, int channels, int inrate, int inwidth, int samples, byte *data ) {
int outcount;
int srcsample;
float stepscale;
int i;
int i, j;
int sample, samplefrac, fracstep;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
@ -175,18 +179,21 @@ static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byt
outcount = samples / stepscale;
samplefrac = 0;
fracstep = stepscale * 256;
fracstep = stepscale * 256 * channels;
for (i=0 ; i<outcount ; i++)
{
srcsample = samplefrac >> 8;
samplefrac += fracstep;
for (j=0 ; j<channels ; j++)
{
if( inwidth == 2 ) {
sample = LittleShort ( ((short *)data)[srcsample] );
sample = LittleShort ( ((short *)data)[srcsample+j] );
} else {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
}
sfx[i*channels+j] = sample;
}
sfx[i] = sample;
}
return outcount;
}
@ -208,11 +215,6 @@ qboolean S_LoadSound( sfx_t *sfx )
snd_info_t info;
// int size;
// player specific sounds are never directly loaded
if ( sfx->soundName[0] == '*') {
return qfalse;
}
// load it in
data = S_CodecLoad(sfx->soundName, &info);
if(!data)
@ -226,7 +228,7 @@ qboolean S_LoadSound( sfx_t *sfx )
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", sfx->soundName);
}
samples = Hunk_AllocateTempMemory(info.samples * sizeof(short) * 2);
samples = Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2);
sfx->lastTimeUsed = Com_Milliseconds()+1;
@ -236,30 +238,31 @@ qboolean S_LoadSound( sfx_t *sfx )
// manager to do the right thing for us and page
// sound in as needed
if( sfx->soundCompressed == qtrue) {
if( info.channels == 1 && sfx->soundCompressed == qtrue) {
sfx->soundCompressionMethod = 1;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, data + info.dataofs );
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, data + info.dataofs );
S_AdpcmEncodeSound(sfx, samples);
#if 0
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
sfx->soundCompressionMethod = 3;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeMuLaw( sfx, samples);
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
sfx->soundCompressionMethod = 2;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeWavelet( sfx, samples);
#endif
} else {
sfx->soundCompressionMethod = 0;
sfx->soundLength = info.samples;
sfx->soundData = NULL;
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse );
sfx->soundLength = ResampleSfx( sfx, info.channels, info.rate, info.width, info.samples, data + info.dataofs, qfalse );
}
sfx->soundChannels = info.channels;
Hunk_FreeTempMemory(samples);
Hunk_FreeTempMemory(data);

View file

@ -234,7 +234,7 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
portable_samplepair_t *samp;
sndBuffer *chunk;
short *samples;
float ooff, fdata, fdiv, fleftvol, frightvol;
float ooff, fdata[2], fdiv, fleftvol, frightvol;
samp = &paintbuffer[ bufferOffset ];
@ -242,6 +242,14 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
sampleOffset = sampleOffset*ch->oldDopplerScale;
}
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next;
@ -274,6 +282,10 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) {
@ -373,10 +385,10 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
for ( i=0 ; i<count ; i++ ) {
aoff = ooff;
ooff = ooff + ch->dopplerScale;
ooff = ooff + ch->dopplerScale * sc->soundChannels;
boff = ooff;
fdata = 0;
for (j=aoff; j<boff; j++) {
fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j += sc->soundChannels) {
if (j == SND_CHUNK_SIZE) {
chunk = chunk->next;
if (!chunk) {
@ -385,11 +397,17 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co
samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE;
}
fdata += samples[j&(SND_CHUNK_SIZE-1)];
if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
fdiv = 256 * (boff-aoff);
samp[i].left += (fdata * fleftvol)/fdiv;
samp[i].right += (fdata * frightvol)/fdiv;
}
fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata[1] * frightvol)/fdiv;
}
}
}
@ -402,7 +420,7 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
portable_samplepair_t *samp;
sndBuffer *chunk;
short *samples;
float ooff, fdata, fdiv, fleftvol, frightvol;
float ooff, fdata[2], fdiv, fleftvol, frightvol;
samp = &paintbuffer[ bufferOffset ];
@ -410,6 +428,14 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
sampleOffset = sampleOffset*ch->oldDopplerScale;
}
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next;
@ -426,6 +452,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
for ( i=0 ; i<count ; i++ ) {
data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) {
@ -447,10 +477,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
for ( i=0 ; i<count ; i++ ) {
aoff = ooff;
ooff = ooff + ch->dopplerScale;
ooff = ooff + ch->dopplerScale * sc->soundChannels;
boff = ooff;
fdata = 0;
for (j=aoff; j<boff; j++) {
fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j += sc->soundChannels) {
if (j == SND_CHUNK_SIZE) {
chunk = chunk->next;
if (!chunk) {
@ -459,11 +489,17 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE;
}
fdata += samples[j&(SND_CHUNK_SIZE-1)];
if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
fdiv = 256 * (boff-aoff);
samp[i].left += (fdata * fleftvol)/fdiv;
samp[i].right += (fdata * frightvol)/fdiv;
}
fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata[1] * frightvol)/fdiv;
}
}
}

View file

@ -318,6 +318,11 @@ static sfxHandle_t S_AL_BufferFind(const char *filename)
return 0;
}
if ( filename[0] == '*' ) {
Com_Printf( S_COLOR_YELLOW "WARNING: Tried to load player sound directly: %s\n", filename );
return 0;
}
for(i = 0; i < numSfx; i++)
{
if(!Q_stricmp(knownSfx[i].filename, filename))
@ -417,6 +422,44 @@ static qboolean S_AL_BufferEvict( void )
return qfalse;
}
/*
=================
S_AL_GenBuffers
=================
*/
static qboolean S_AL_GenBuffers(ALsizei numBuffers, ALuint *buffers, const char *name)
{
ALenum error;
S_AL_ClearError( qfalse );
qalGenBuffers( numBuffers, buffers );
error = qalGetError();
// If we ran out of buffers, start evicting the least recently used sounds
while( error == AL_INVALID_VALUE )
{
if( !S_AL_BufferEvict( ) )
{
Com_Printf( S_COLOR_RED "ERROR: Out of audio buffers\n");
return qfalse;
}
// Try again
S_AL_ClearError( qfalse );
qalGenBuffers( numBuffers, buffers );
error = qalGetError();
}
if( error != AL_NO_ERROR )
{
Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
name, S_AL_ErrorMsg(error));
return qfalse;
}
return qtrue;
}
/*
=================
S_AL_BufferLoad
@ -435,10 +478,6 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
if(curSfx->filename[0] == '\0')
return;
// Player SFX
if(curSfx->filename[0] == '*')
return;
// Already done?
if((curSfx->inMemory) || (curSfx->isDefault) || (!cache && curSfx->isDefaultChecked))
return;
@ -463,14 +502,10 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
format = S_AL_Format(info.width, info.channels);
// Create a buffer
S_AL_ClearError( qfalse );
qalGenBuffers(1, &curSfx->buffer);
if((error = qalGetError()) != AL_NO_ERROR)
if (!S_AL_GenBuffers(1, &curSfx->buffer, curSfx->filename))
{
S_AL_BufferUseDefault(sfx);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Can't create a sound buffer for %s - %s\n",
curSfx->filename, S_AL_ErrorMsg(error));
return;
}
@ -492,6 +527,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
{
if( !S_AL_BufferEvict( ) )
{
qalDeleteBuffers(1, &curSfx->buffer);
S_AL_BufferUseDefault(sfx);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Out of memory loading %s\n", curSfx->filename);
@ -506,6 +542,7 @@ static void S_AL_BufferLoad(sfxHandle_t sfx, qboolean cache)
// Some other error condition
if(error != AL_NO_ERROR)
{
qalDeleteBuffers(1, &curSfx->buffer);
S_AL_BufferUseDefault(sfx);
Hunk_FreeTempMemory(data);
Com_Printf( S_COLOR_RED "ERROR: Can't fill sound buffer for %s - %s\n",
@ -1091,7 +1128,7 @@ static void S_AL_SrcKill(srcHandle_t src)
curSource->isPlaying = qfalse;
}
// Remove the buffer
// Detach any buffers
qalSourcei(curSource->alSource, AL_BUFFER, 0);
curSource->sfx = 0;
@ -1621,6 +1658,10 @@ void S_AL_SrcUpdate( void )
if(!curSource->isPlaying)
{
qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
curSource->isPlaying = qtrue;
qalSourcePlay(curSource->alSource);
if(curSource->priority == SRCPRI_AMBIENT)
{
// If there are other ambient looping sources with the same sound,
@ -1678,10 +1719,6 @@ void S_AL_SrcUpdate( void )
}
curSfx->loopActiveCnt++;
qalSourcei(curSource->alSource, AL_LOOPING, AL_TRUE);
curSource->isPlaying = qtrue;
qalSourcePlay(curSource->alSource);
}
// Update locality
@ -1763,9 +1800,15 @@ ALuint S_AL_SrcGet(srcHandle_t src)
//===========================================================================
// Q3A cinematics use up to 12 buffers at once
#define MAX_STREAM_BUFFERS 20
static srcHandle_t streamSourceHandles[MAX_RAW_STREAMS];
static qboolean streamPlaying[MAX_RAW_STREAMS];
static ALuint streamSources[MAX_RAW_STREAMS];
static ALuint streamBuffers[MAX_RAW_STREAMS][MAX_STREAM_BUFFERS];
static int streamNumBuffers[MAX_RAW_STREAMS];
static int streamBufIndex[MAX_RAW_STREAMS];
/*
=================
@ -1823,6 +1866,9 @@ static void S_AL_AllocateStreamChannel(int stream, int entityNum)
streamSourceHandles[stream] = cursrc;
streamSources[stream] = alsrc;
streamNumBuffers[stream] = 0;
streamBufIndex[stream] = 0;
}
/*
@ -1835,6 +1881,15 @@ static void S_AL_FreeStreamChannel( int stream )
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
return;
// Detach any buffers
qalSourcei(streamSources[stream], AL_BUFFER, 0);
// Delete the buffers
if (streamNumBuffers[stream] > 0) {
qalDeleteBuffers(streamNumBuffers[stream], streamBuffers[stream]);
streamNumBuffers[stream] = 0;
}
// Release the output streamSource
S_AL_SrcUnlock(streamSourceHandles[stream]);
S_AL_SrcKill(streamSourceHandles[stream]);
@ -1850,6 +1905,7 @@ S_AL_RawSamples
static
void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum)
{
int numBuffers;
ALuint buffer;
ALuint format;
@ -1871,8 +1927,40 @@ void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels,
}
}
// Create a buffer, and stuff the data into it
qalGenBuffers(1, &buffer);
qalGetSourcei(streamSources[stream], AL_BUFFERS_QUEUED, &numBuffers);
if (numBuffers == MAX_STREAM_BUFFERS)
{
Com_DPrintf(S_COLOR_RED"WARNING: Steam dropping raw samples, reached MAX_STREAM_BUFFERS\n");
return;
}
// Allocate a new AL buffer if needed
if (numBuffers == streamNumBuffers[stream])
{
ALuint oldBuffers[MAX_STREAM_BUFFERS];
int i;
if (!S_AL_GenBuffers(1, &buffer, "stream"))
return;
Com_Memcpy(oldBuffers, &streamBuffers[stream], sizeof (oldBuffers));
// Reorder buffer array in order of oldest to newest
for ( i = 0; i < streamNumBuffers[stream]; ++i )
streamBuffers[stream][i] = oldBuffers[(streamBufIndex[stream] + i) % streamNumBuffers[stream]];
// Add the new buffer to end
streamBuffers[stream][streamNumBuffers[stream]] = buffer;
streamBufIndex[stream] = streamNumBuffers[stream];
streamNumBuffers[stream]++;
}
// Select next buffer in loop
buffer = streamBuffers[stream][ streamBufIndex[stream] ];
streamBufIndex[stream] = (streamBufIndex[stream] + 1) % streamNumBuffers[stream];
// Fill buffer
qalBufferData(buffer, format, (ALvoid *)data, (samples * width * channels), rate);
// Shove the data onto the streamSource
@ -1883,6 +1971,13 @@ void S_AL_RawSamples(int stream, int samples, int rate, int width, int channels,
// Volume
S_AL_Gain (streamSources[stream], volume * s_volume->value * s_alGain->value);
}
// Start stream
if(!streamPlaying[stream])
{
qalSourcePlay( streamSources[stream] );
streamPlaying[stream] = qtrue;
}
}
/*
@ -1902,13 +1997,12 @@ void S_AL_StreamUpdate( int stream )
if(streamSourceHandles[stream] == -1)
return;
// Un-queue any buffers, and delete them
// Un-queue any buffers
qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
while( numBuffers-- )
{
ALuint buffer;
qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
qalDeleteBuffers(1, &buffer);
}
// Start the streamSource playing if necessary
@ -1939,8 +2033,6 @@ S_AL_StreamDie
static
void S_AL_StreamDie( int stream )
{
int numBuffers;
if ((stream < 0) || (stream >= MAX_RAW_STREAMS))
return;
@ -1950,15 +2042,6 @@ void S_AL_StreamDie( int stream )
streamPlaying[stream] = qfalse;
qalSourceStop(streamSources[stream]);
// Un-queue any buffers, and delete them
qalGetSourcei( streamSources[stream], AL_BUFFERS_PROCESSED, &numBuffers );
while( numBuffers-- )
{
ALuint buffer;
qalSourceUnqueueBuffers(streamSources[stream], 1, &buffer);
qalDeleteBuffers(1, &buffer);
}
S_AL_FreeStreamChannel(stream);
}
@ -2050,22 +2133,17 @@ S_AL_StopBackgroundTrack
static
void S_AL_StopBackgroundTrack( void )
{
int numBuffers;
if(!musicPlaying)
return;
// Stop playing
qalSourceStop(musicSource);
// Un-queue any buffers, and delete them
qalGetSourcei( musicSource, AL_BUFFERS_PROCESSED, &numBuffers );
while( numBuffers-- )
{
ALuint buffer;
qalSourceUnqueueBuffers(musicSource, 1, &buffer);
qalDeleteBuffers(1, &buffer);
}
// Detach any buffers
qalSourcei(musicSource, AL_BUFFER, 0);
// Delete the buffers
qalDeleteBuffers(NUM_MUSIC_BUFFERS, musicBuffers);
// Free the musicSource
S_AL_MusicSourceFree();
@ -2198,7 +2276,8 @@ void S_AL_StartBackgroundTrack( const char *intro, const char *loop )
}
// Generate the musicBuffers
qalGenBuffers(NUM_MUSIC_BUFFERS, musicBuffers);
if (!S_AL_GenBuffers(NUM_MUSIC_BUFFERS, musicBuffers, "music"))
return;
// Queue the musicBuffers up
for(i = 0; i < NUM_MUSIC_BUFFERS; i++)
@ -3155,6 +3234,8 @@ qboolean S_AL_Init( soundInterface_t *si )
streamSourceHandles[i] = -1;
streamPlaying[i] = qfalse;
streamSources[i] = 0;
streamNumBuffers[i] = 0;
streamBufIndex[i] = 0;
}
// New console variables
@ -3328,12 +3409,15 @@ qboolean S_AL_Init( soundInterface_t *si )
defaultinputdevice = qalcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
// dump a list of available devices to a cvar for the user to see.
if (inputdevicelist)
{
while((curlen = strlen(inputdevicelist)))
{
Q_strcat(inputdevicenames, sizeof(inputdevicenames), inputdevicelist);
Q_strcat(inputdevicenames, sizeof(inputdevicenames), "\n");
inputdevicelist += curlen + 1;
}
}
s_alAvailableInputDevices = Cvar_Get("s_alAvailableInputDevices", inputdevicenames, CVAR_ROM | CVAR_NORESTART);
@ -3341,7 +3425,7 @@ qboolean S_AL_Init( soundInterface_t *si )
// !!! FIXME: should probably open the capture device after
// !!! FIXME: initializing Speex so we can change to wideband
// !!! FIXME: if we like.
Com_Printf("OpenAL default capture device is '%s'\n", defaultinputdevice);
Com_Printf("OpenAL default capture device is '%s'\n", defaultinputdevice ? defaultinputdevice : "none");
alCaptureDevice = qalcCaptureOpenDevice(inputdevice, 8000, AL_FORMAT_MONO16, 4096);
if( !alCaptureDevice && inputdevice )
{

View file

@ -275,9 +275,9 @@ typedef struct qfile_us {
typedef struct {
qfile_ut handleFiles;
qboolean handleSync;
int baseOffset;
int fileSize;
int zipFilePos;
int zipFileLen;
qboolean zipFile;
qboolean streamed;
char name[MAX_ZPATH];
@ -1262,6 +1262,7 @@ long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_
// open the file in the zip
unzOpenCurrentFile(fsh[*file].handleFiles.file.z);
fsh[*file].zipFilePos = pakFile->pos;
fsh[*file].zipFileLen = pakFile->len;
if(fs_debug->integer)
{
@ -1628,29 +1629,60 @@ int FS_Seek( fileHandle_t f, long offset, int origin ) {
}
if (fsh[f].streamed) {
int r;
fsh[f].streamed = qfalse;
FS_Seek( f, offset, origin );
r = FS_Seek( f, offset, origin );
fsh[f].streamed = qtrue;
return r;
}
if (fsh[f].zipFile == qtrue) {
//FIXME: this is incomplete and really, really
//crappy (but better than what was here before)
//FIXME: this is really, really crappy
//(but better than what was here before)
byte buffer[PK3_SEEK_BUFFER_SIZE];
int remainder = offset;
int remainder;
int currentPosition = FS_FTell( f );
if( offset < 0 || origin == FS_SEEK_END ) {
Com_Error( ERR_FATAL, "Negative offsets and FS_SEEK_END not implemented "
"for FS_Seek on pk3 file contents" );
return -1;
// change negative offsets into FS_SEEK_SET
if ( offset < 0 ) {
switch( origin ) {
case FS_SEEK_END:
remainder = fsh[f].zipFileLen + offset;
break;
case FS_SEEK_CUR:
remainder = currentPosition + offset;
break;
case FS_SEEK_SET:
default:
remainder = 0;
break;
}
if ( remainder < 0 ) {
remainder = 0;
}
origin = FS_SEEK_SET;
} else {
if ( origin == FS_SEEK_END ) {
remainder = fsh[f].zipFileLen - currentPosition + offset;
} else {
remainder = offset;
}
}
switch( origin ) {
case FS_SEEK_SET:
if ( remainder == currentPosition ) {
return offset;
}
unzSetOffset(fsh[f].handleFiles.file.z, fsh[f].zipFilePos);
unzOpenCurrentFile(fsh[f].handleFiles.file.z);
//fallthrough
case FS_SEEK_END:
case FS_SEEK_CUR:
while( remainder > PK3_SEEK_BUFFER_SIZE ) {
FS_Read( buffer, PK3_SEEK_BUFFER_SIZE, f );
@ -1658,12 +1690,10 @@ int FS_Seek( fileHandle_t f, long offset, int origin ) {
}
FS_Read( buffer, remainder, f );
return offset;
break;
default:
Com_Error( ERR_FATAL, "Bad origin in FS_Seek" );
return -1;
break;
}
} else {
FILE *file;
@ -4012,11 +4042,6 @@ int FS_FOpenFileByMode( const char *qpath, fileHandle_t *f, fsMode_t mode ) {
}
if ( *f ) {
if (fsh[*f].zipFile == qtrue) {
fsh[*f].baseOffset = unztell(fsh[*f].handleFiles.file.z);
} else {
fsh[*f].baseOffset = ftell(fsh[*f].handleFiles.file.o);
}
fsh[*f].fileSize = r;
fsh[*f].streamed = qfalse;

View file

@ -76,8 +76,12 @@ COM_StripExtension
void COM_StripExtension( const char *in, char *out, int destsize )
{
const char *dot = strrchr(in, '.'), *slash;
if (dot && (!(slash = strrchr(in, '/')) || slash < dot))
Q_strncpyz(out, in, (destsize < dot-in+1 ? destsize : dot-in+1));
destsize = (destsize < dot-in+1 ? destsize : dot-in+1);
if ( in == out && destsize > 1 )
out[destsize-1] = '\0';
else
Q_strncpyz(out, in, destsize);
}

View file

@ -694,7 +694,7 @@ int FS_FOpenFileByMode( const char *qpath, fileHandle_t *f, fsMode_t mode );
// opens a file for reading, writing, or appending depending on the value of mode
int FS_Seek( fileHandle_t f, long offset, int origin );
// seek on a file (doesn't work for zip files!!!!!!!!)
// seek on a file
qboolean FS_FilenameCompare( const char *s1, const char *s2 );
@ -1063,19 +1063,6 @@ void * QDECL Sys_LoadGameDll( const char *name, intptr_t (QDECL **entryPoint)(in
intptr_t (QDECL *systemcalls)(intptr_t, ...) );
void Sys_UnloadDll( void *dllHandle );
void Sys_UnloadGame( void );
void *Sys_GetGameAPI( void *parms );
void Sys_UnloadCGame( void );
void *Sys_GetCGameAPI( void );
void Sys_UnloadUI( void );
void *Sys_GetUIAPI( void );
//bot libraries
void Sys_UnloadBotLib( void );
void *Sys_GetBotLibAPI( void *parms );
char *Sys_GetCurrentUser( void );
void QDECL Sys_Error( const char *error, ...) __attribute__ ((noreturn, format (printf, 1, 2)));

View file

@ -179,94 +179,11 @@ typedef struct {
/*
==============================================================================
MD4 file format
MDR file format
==============================================================================
*/
#define MD4_IDENT (('4'<<24)+('P'<<16)+('D'<<8)+'I')
#define MD4_VERSION 1
#define MD4_MAX_BONES 128
typedef struct {
int boneIndex; // these are indexes into the boneReferences,
float boneWeight; // not the global per-frame bone list
vec3_t offset;
} md4Weight_t;
typedef struct {
vec3_t normal;
vec2_t texCoords;
int numWeights;
md4Weight_t weights[1]; // variable sized
} md4Vertex_t;
typedef struct {
int indexes[3];
} md4Triangle_t;
typedef struct {
int ident;
char name[MAX_QPATH]; // polyset name
char shader[MAX_QPATH];
int shaderIndex; // for in-game use
int ofsHeader; // this will be a negative number
int numVerts;
int ofsVerts;
int numTriangles;
int ofsTriangles;
// Bone references are a set of ints representing all the bones
// present in any vertex weights for this surface. This is
// needed because a model may have surfaces that need to be
// drawn at different sort times, and we don't want to have
// to re-interpolate all the bones for each surface.
int numBoneReferences;
int ofsBoneReferences;
int ofsEnd; // next surface follows
} md4Surface_t;
typedef struct {
float matrix[3][4];
} md4Bone_t;
typedef struct {
vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame
vec3_t localOrigin; // midpoint of bounds, used for sphere cull
float radius; // dist from localOrigin to corner
md4Bone_t bones[1]; // [numBones]
} md4Frame_t;
typedef struct {
int numSurfaces;
int ofsSurfaces; // first surface, others follow
int ofsEnd; // next lod follows
} md4LOD_t;
typedef struct {
int ident;
int version;
char name[MAX_QPATH]; // model name
// frames and bones are shared by all levels of detail
int numFrames;
int numBones;
int ofsBoneNames; // char name[ MAX_QPATH ]
int ofsFrames; // md4Frame_t[numFrames]
// each level of detail has completely separate sets of surfaces
int numLODs;
int ofsLODs;
int ofsEnd; // end of file
} md4Header_t;
/*
* Here are the definitions for Ravensoft's model format of md4. Raven stores their
* playermodels in .mdr files, in some games, which are pretty much like the md4

View file

@ -2274,7 +2274,7 @@ void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
{
case PNG_ColourType_Grey :
{
if(!ChunkHeaderLength == 2)
if(ChunkHeaderLength != 2)
{
CloseBufferedFile(ThePNG);
@ -2296,7 +2296,7 @@ void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
case PNG_ColourType_True :
{
if(!ChunkHeaderLength == 6)
if(ChunkHeaderLength != 6)
{
CloseBufferedFile(ThePNG);

View file

@ -33,140 +33,6 @@ frame.
*/
/*
==============
R_AddAnimSurfaces
==============
*/
void R_AddAnimSurfaces( trRefEntity_t *ent ) {
md4Header_t *header;
md4Surface_t *surface;
md4LOD_t *lod;
shader_t *shader;
int i;
header = (md4Header_t *) tr.currentModel->modelData;
lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
shader = R_GetShaderByHandle( surface->shaderIndex );
R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse );
surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd );
}
}
/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim( md4Surface_t *surface ) {
int i, j, k;
float frontlerp, backlerp;
int *triangles;
int indexes;
int baseIndex, baseVertex;
int numVerts;
md4Vertex_t *v;
md4Bone_t bones[MD4_MAX_BONES];
md4Bone_t *bonePtr, *bone;
md4Header_t *header;
md4Frame_t *frame;
md4Frame_t *oldFrame;
int frameSize;
if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
backlerp = 0;
frontlerp = 1;
} else {
backlerp = backEnd.currentEntity->e.backlerp;
frontlerp = 1.0f - backlerp;
}
header = (md4Header_t *)((byte *)surface + surface->ofsHeader);
frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] );
frame = (md4Frame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.frame * frameSize );
oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.oldframe * frameSize );
RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );
triangles = (int *) ((byte *)surface + surface->ofsTriangles);
indexes = surface->numTriangles * 3;
baseIndex = tess.numIndexes;
baseVertex = tess.numVertexes;
for (j = 0 ; j < indexes ; j++) {
tess.indexes[baseIndex + j] = baseIndex + triangles[j];
}
tess.numIndexes += indexes;
//
// lerp all the needed bones
//
if ( !backlerp ) {
// no lerping needed
bonePtr = frame->bones;
} else {
bonePtr = bones;
for ( i = 0 ; i < header->numBones*12 ; i++ ) {
((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i]
+ backlerp * ((float *)oldFrame->bones)[i];
}
}
//
// deform the vertexes by the lerped bones
//
numVerts = surface->numVerts;
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
for ( j = 0; j < numVerts; j++ ) {
vec3_t tempVert, tempNormal;
md4Weight_t *w;
VectorClear( tempVert );
VectorClear( tempNormal );
w = v->weights;
for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
bone = bonePtr + w->boneIndex;
tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
}
tess.xyz[baseVertex + j][0] = tempVert[0];
tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2];
tess.normal[baseVertex + j][0] = tempNormal[0];
tess.normal[baseVertex + j][1] = tempNormal[1];
tess.normal[baseVertex + j][2] = tempNormal[2];
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
v = (md4Vertex_t *)&v->weights[v->numWeights];
}
tess.numVertexes += surface->numVerts;
}
// copied and adapted from tr_mesh.c
@ -195,7 +61,7 @@ static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) {
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
// Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend
// we do. After all, the purpose of md4s are not that different, are they?
// we do. After all, the purpose of mdrs are not that different, are they?
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
@ -442,7 +308,7 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
RB_MDRSurfaceAnim
==============
*/
void RB_MDRSurfaceAnim( md4Surface_t *surface )
void RB_MDRSurfaceAnim( mdrSurface_t *surface )
{
int i, j, k;
float frontlerp, backlerp;
@ -454,7 +320,7 @@ void RB_MDRSurfaceAnim( md4Surface_t *surface )
mdrHeader_t *header;
mdrFrame_t *frame;
mdrFrame_t *oldFrame;
mdrBone_t bones[MD4_MAX_BONES], *bonePtr, *bone;
mdrBone_t bones[MDR_MAX_BONES], *bonePtr, *bone;
int frameSize;

View file

@ -737,6 +737,10 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
}
R_IssuePendingRenderCommands();
if ( tess.numIndexes ) {
RB_EndSurface();
}
// we definately want to sync every frame for the cinematics
qglFinish();

View file

@ -86,6 +86,19 @@ flare_t *r_activeFlares, *r_inactiveFlares;
int flareCoeff;
/*
==================
R_SetFlareCoeff
==================
*/
static void R_SetFlareCoeff( void ) {
if(r_flareCoeff->value == 0.0f)
flareCoeff = atof(FLARE_STDCOEFF);
else
flareCoeff = r_flareCoeff->value;
}
/*
==================
R_ClearFlares
@ -102,6 +115,8 @@ void R_ClearFlares( void ) {
r_flareStructs[i].next = r_inactiveFlares;
r_inactiveFlares = &r_flareStructs[i];
}
R_SetFlareCoeff();
}
@ -450,11 +465,7 @@ void RB_RenderFlares (void) {
if(r_flareCoeff->modified)
{
if(r_flareCoeff->value == 0.0f)
flareCoeff = atof(FLARE_STDCOEFF);
else
flareCoeff = r_flareCoeff->value;
R_SetFlareCoeff();
r_flareCoeff->modified = qfalse;
}

View file

@ -900,6 +900,8 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height,
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
// FIXME: this stops fog from setting border color?
glState.currenttextures[glState.currenttmu] = 0;
qglBindTexture( GL_TEXTURE_2D, 0 );
if ( image->TMU == 1 ) {

View file

@ -872,16 +872,6 @@ void GL_SetDefaultState( void )
qglEnable( GL_SCISSOR_TEST );
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
qglClearDepth( 1.0 );
qglDrawBuffer( GL_FRONT );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
qglDrawBuffer( GL_BACK );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
}
/*
@ -1039,7 +1029,7 @@ void R_Register( void )
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH );
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE);
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
r_customPixelAspect = ri.Cvar_Get( "r_customPixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );

View file

@ -41,10 +41,6 @@ typedef unsigned int glIndex_t;
#define SHADERNUM_BITS 14
#define MAX_SHADERS (1<<SHADERNUM_BITS)
//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32
typedef struct dlight_s {
@ -266,7 +262,6 @@ typedef struct {
int videoMapHandle;
qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap;
} textureBundle_t;
@ -370,27 +365,11 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to
float timeOffset; // current time offset for this shader
int numStates; // if non-zero this is a state shader
struct shader_s *currentShader; // current state if this is a state shader
struct shader_s *parentShader; // current state if this is a state shader
int currentState; // current state index for cycle purposes
long expireTime; // time in milliseconds this expires
struct shader_s *remappedShader; // current shader this one is remapped too
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next;
} shader_t;
typedef struct shaderState_s {
char shaderName[MAX_QPATH]; // name of shader this state belongs to
char name[MAX_STATE_NAME]; // name of this state
char stateShader[MAX_QPATH]; // shader this name invokes
int cycleTime; // time this cycle lasts, <= 0 is forever
shader_t *shader;
} shaderState_t;
// trRefdef_t holds everything that comes in refdef_t,
// as well as the locally generated scene information
@ -494,7 +473,6 @@ typedef enum {
SF_TRIANGLES,
SF_POLY,
SF_MD3,
SF_MD4,
SF_MDR,
SF_IQM,
SF_FLARE,
@ -610,6 +588,7 @@ typedef struct {
int num_frames;
int num_surfaces;
int num_joints;
int num_poses;
struct srfIQModel_s *surfaces;
float *positions;
@ -617,10 +596,18 @@ typedef struct {
float *normals;
float *tangents;
byte *blendIndexes;
byte *blendWeights;
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
int *triangles;
// 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 *jointParents;
float *jointMats;
float *poseMats;
@ -744,7 +731,6 @@ typedef enum {
MOD_BAD,
MOD_BRUSH,
MOD_MESH,
MOD_MD4,
MOD_MDR,
MOD_IQM
} modtype_t;
@ -757,7 +743,7 @@ typedef struct model_s {
int dataSize; // just for listing purposes
bmodel_t *bmodel; // only if type == MOD_BRUSH
md3Header_t *md3[MD3_MAX_LODS]; // only if type == MOD_MESH
void *modelData; // only if type == (MOD_MD4 | MOD_MDR | MOD_IQM)
void *modelData; // only if type == (MOD_MDR | MOD_IQM)
int numLods;
} model_t;
@ -1401,11 +1387,8 @@ ANIMATED MODELS
=============================================================
*/
// void R_MakeAnimModel( model_t *model ); haven't seen this one really, so not needed I guess.
void R_AddAnimSurfaces( trRefEntity_t *ent );
void RB_SurfaceAnim( md4Surface_t *surfType );
void R_MDRAddAnimSurfaces( trRefEntity_t *ent );
void RB_MDRSurfaceAnim( md4Surface_t *surface );
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 );

View file

@ -1242,9 +1242,6 @@ void R_AddEntitySurfaces (void) {
case MOD_MESH:
R_AddMD3Surfaces( ent );
break;
case MOD_MD4:
R_AddAnimSurfaces( ent );
break;
case MOD_MDR:
R_MDRAddAnimSurfaces( ent );
break;

View file

@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, const char *name );
static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name );
static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name );
/*
@ -72,15 +71,10 @@ qhandle_t R_RegisterMD3(const char *name, model_t *mod)
continue;
ident = LittleLong(* (unsigned *) buf.u);
if (ident == MD4_IDENT)
loaded = R_LoadMD4(mod, buf.u, name);
else
{
if (ident == MD3_IDENT)
loaded = R_LoadMD3(mod, lod, buf.u, name);
else
ri.Printf(PRINT_WARNING,"R_RegisterMD3: unknown fileid for %s\n", name);
}
ri.FS_FreeFile(buf.v);
@ -200,7 +194,6 @@ static modelExtToLoaderMap_t modelLoaders[ ] =
{
{ "iqm", R_RegisterIQM },
{ "mdr", R_RegisterMDR },
{ "md4", R_RegisterMD3 },
{ "md3", R_RegisterMD3 }
};
@ -576,7 +569,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
LL(pinmodel->ofsFrames);
// This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame
// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4.
// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target mdr.
if(pinmodel->ofsFrames < 0)
{
// mdrFrame_t is larger than mdrCompFrame_t:
@ -873,162 +866,6 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
return qtrue;
}
/*
=================
R_LoadMD4
=================
*/
static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
int i, j, k, lodindex;
md4Header_t *pinmodel, *md4;
md4Frame_t *frame;
md4LOD_t *lod;
md4Surface_t *surf;
md4Triangle_t *tri;
md4Vertex_t *v;
int version;
int size;
shader_t *sh;
int frameSize;
pinmodel = (md4Header_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != MD4_VERSION) {
ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n",
mod_name, version, MD4_VERSION);
return qfalse;
}
mod->type = MOD_MD4;
size = LittleLong(pinmodel->ofsEnd);
mod->dataSize += size;
mod->modelData = md4 = ri.Hunk_Alloc( size, h_low );
Com_Memcpy(md4, buffer, size);
LL(md4->ident);
LL(md4->version);
LL(md4->numFrames);
LL(md4->numBones);
LL(md4->numLODs);
LL(md4->ofsFrames);
LL(md4->ofsLODs);
md4->ofsEnd = size;
if ( md4->numFrames < 1 ) {
ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name );
return qfalse;
}
// we don't need to swap tags in the renderer, they aren't used
// swap all the frames
frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] );
for ( i = 0 ; i < md4->numFrames ; i++) {
frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize );
frame->radius = LittleFloat( frame->radius );
for ( j = 0 ; j < 3 ; j++ ) {
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
}
for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) {
((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] );
}
}
// swap all the LOD's
lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs );
for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) {
// swap all the surfaces
surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++) {
LL(surf->ident);
LL(surf->numTriangles);
LL(surf->ofsTriangles);
LL(surf->numVerts);
LL(surf->ofsVerts);
LL(surf->ofsEnd);
if ( surf->numVerts >= SHADER_MAX_VERTEXES ) {
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i verts on %s (%i).\n",
mod_name, SHADER_MAX_VERTEXES - 1, surf->name[0] ? surf->name : "a surface",
surf->numVerts );
return qfalse;
}
if ( surf->numTriangles*3 >= SHADER_MAX_INDEXES ) {
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i triangles on %s (%i).\n",
mod_name, ( SHADER_MAX_INDEXES / 3 ) - 1, surf->name[0] ? surf->name : "a surface",
surf->numTriangles );
return qfalse;
}
// change to surface identifier
surf->ident = SF_MD4;
// lowercase the surface name so skin compares are faster
Q_strlwr( surf->name );
// register the shaders
sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
if ( sh->defaultShader ) {
surf->shaderIndex = 0;
} else {
surf->shaderIndex = sh->index;
}
// swap all the triangles
tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
LL(tri->indexes[0]);
LL(tri->indexes[1]);
LL(tri->indexes[2]);
}
// swap all the vertexes
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12);
v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts);
for ( j = 0 ; j < surf->numVerts ; j++ ) {
v->normal[0] = LittleFloat( v->normal[0] );
v->normal[1] = LittleFloat( v->normal[1] );
v->normal[2] = LittleFloat( v->normal[2] );
v->texCoords[0] = LittleFloat( v->texCoords[0] );
v->texCoords[1] = LittleFloat( v->texCoords[1] );
v->numWeights = LittleLong( v->numWeights );
for ( k = 0 ; k < v->numWeights ; k++ ) {
v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
}
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]);
}
// find the next surface
surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd );
}
// find the next LOD
lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd );
}
return qtrue;
}
//=============================================================================
@ -1049,11 +886,6 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) {
RE_ClearScene();
tr.registered = qtrue;
// NOTE: this sucks, for some reason the first stretch pic is never drawn
// without this we'd see a white flash on a level load because the very
// first time the level shot would not be drawn
// RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0);
}
//=============================================================================
@ -1265,17 +1097,6 @@ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
} else if (model->type == MOD_MD4) {
md4Header_t *header;
md4Frame_t *frame;
header = (md4Header_t *)model->modelData;
frame = (md4Frame_t *) ((byte *)header + header->ofsFrames);
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
} else if (model->type == MOD_MDR) {
mdrHeader_t *header;

View file

@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
// 3x4 identity matrix
static float identityMatrix[12] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0
};
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
int count,int size ) {
// return true if the range specified by offset, count and size
@ -143,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData_t *iqmData;
srfIQModel_t *surface;
char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) {
return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse;
}
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
break;
case IQM_BLENDINDEXES:
case IQM_BLENDWEIGHTS:
if( vertexarray->format != IQM_UBYTE ||
if( (vertexarray->format != IQM_INT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break;
case IQM_COLOR:
if( vertexarray->format != IQM_UBYTE ||
@ -343,7 +362,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
}
if( header->num_poses != header->num_joints ) {
if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
mod_name, header->num_poses, header->num_joints );
return qfalse;
}
@ -379,7 +400,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
joint_names += strlen( (char *)header + header->ofs_text +
joint->name ) + 1;
}
}
if ( header->num_poses )
{
// check and swap poses
if( IQM_CheckRange( header, header->ofs_poses,
header->num_poses, sizeof(iqmPose_t) ) ) {
@ -438,7 +462,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size = sizeof(iqmData_t);
size += header->num_meshes * sizeof( srfIQModel_t );
size += header->num_joints * 12 * sizeof( float ); // joint mats
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats
size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
if(header->ofs_bounds)
size += header->num_frames * 6 * sizeof(float); // model bounds
size += header->num_vertexes * 3 * sizeof(float); // positions
@ -446,12 +470,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size += header->num_vertexes * 3 * sizeof(float); // normals
size += header->num_vertexes * 4 * sizeof(float); // tangents
size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes
size += header->num_vertexes * 4 * sizeof(byte); // blendWeights
size += header->num_vertexes * 4 * sizeof(byte); // colors
size += header->num_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles
size += joint_names; // joint names
// blendWeights
if (blendWeightsType == IQM_FLOAT) {
size += header->num_vertexes * 4 * sizeof(float);
} else {
size += header->num_vertexes * 4 * sizeof(byte);
}
mod->type = MOD_IQM;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
mod->modelData = iqmData;
@ -462,28 +492,40 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->num_frames = header->num_frames;
iqmData->num_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
if(header->ofs_bounds)
{
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
}
else
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes);
iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes;
if(blendWeightsType == IQM_FLOAT) {
iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes);
iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes);
} else {
iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes;
}
iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes);
iqmData->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
if ( header->num_joints == 0 )
iqmData->jointMats = iqmData->poseMats = NULL;
iqmData->jointMats = NULL;
if ( header->num_poses == 0 )
iqmData->poseMats = NULL;
// calculate joint matrices and their inverses
// joint inverses are needed only until the pose matrices are calculated
@ -620,14 +662,27 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
n * sizeof(float) );
break;
case IQM_BLENDINDEXES:
if( blendIndexesType == IQM_INT ) {
int *data = (int*)((byte*)header + vertexarray->offset);
for ( j = 0; j < n; j++ ) {
iqmData->blendIndexes[j] = (byte)data[j];
}
} else {
Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights,
if( blendWeightsType == IQM_FLOAT ) {
Com_Memcpy( iqmData->blendWeights.f,
(byte *)header + vertexarray->offset,
n * sizeof(float) );
} else {
Com_Memcpy( iqmData->blendWeights.b,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_COLOR:
Com_Memcpy( iqmData->colors,
@ -892,9 +947,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents;
int i;
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
if ( data->num_poses == 0 ) {
for( i = 0; i < data->num_joints; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
identityMatrix, mat + 12*i );
} else {
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
}
}
return;
}
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_poses * frame;
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i );
@ -903,10 +970,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
}
}
} else {
mat1 = data->poseMats + 12 * data->num_joints * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
mat1 = data->poseMats + 12 * data->num_poses * frame;
mat2 = data->poseMats + 12 * data->num_poses * oldframe;
for( i = 0; i < data->num_joints; i++, joint++ ) {
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) {
float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -974,7 +1041,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices
if ( data->num_joints > 0 ) {
if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
}
@ -985,28 +1052,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12];
float nrmMat[9];
int vtx = i + surf->first_vertex;
float blendWeights[4];
int numWeights;
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
// no blend joint, use identity matrix.
for( j = 0; j < 3; j++ ) {
for( k = 0; k < 4; k++ )
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
for ( numWeights = 0; numWeights < 4; numWeights++ ) {
if ( data->blendWeightsType == IQM_FLOAT )
blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
else
blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f;
if ( blendWeights[numWeights] <= 0 )
break;
}
if ( data->num_poses == 0 || numWeights == 0 ) {
// no blend joint, use identity matrix.
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else {
// compute the vertex matrix by blending the up to
// four blend weights
for( k = 0; k < 12; k++ )
vtxMat[k] = data->blendWeights[4*vtx]
* jointMats[12*data->blendIndexes[4*vtx] + k];
for( j = 1; j < 4; j++ ) {
if( data->blendWeights[4*vtx + j] <= 0 )
break;
for( k = 0; k < 12; k++ )
vtxMat[k] += data->blendWeights[4*vtx + j]
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
Com_Memset( vtxMat, 0, 12 * sizeof (float) );
for( j = 0; j < numWeights; j++ ) {
for( k = 0; k < 12; k++ ) {
vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k];
}
}
for( k = 0; k < 12; k++ )
vtxMat[k] *= 1.0f / 255.0f;
}
// compute the normal matrix as transpose of the adjoint

View file

@ -1145,11 +1145,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
// set state
//
if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
{
GL_Bind( tr.whiteImage );
}
else
R_BindAnimatedImage( &pStage->bundle[0] );
GL_State( pStage->stateBits );
@ -1160,7 +1155,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
R_DrawElements( input->numIndexes, input->indexes );
}
// allow skipping out to show just lightmaps during development
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
{
break;
}

View file

@ -1233,7 +1233,6 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
(void(*)(void*))RB_SurfacePolychain, // SF_POLY,
(void(*)(void*))RB_SurfaceMesh, // SF_MD3,
(void(*)(void*))RB_SurfaceAnim, // SF_MD4,
(void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
(void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM,
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
uniform mat4 u_ModelViewProjectionMatrix;
@ -8,6 +8,6 @@ varying vec2 var_TexCoords;
void main()
{
gl_Position = u_ModelViewProjectionMatrix * attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
var_TexCoords = attr_TexCoord0.st;
}

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
uniform mat4 u_ModelViewProjectionMatrix;
@ -8,6 +8,6 @@ varying vec2 var_TexCoords;
void main()
{
gl_Position = u_ModelViewProjectionMatrix * attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
var_TexCoords = attr_TexCoord0.st;
}

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
attribute vec3 attr_Normal;
@ -32,7 +32,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
if (u_DeformGen == DGEN_BULGE)
{
phase *= M_PI * 0.25 * st.x;
phase *= st.x;
}
else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
{
@ -48,7 +48,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
else if (u_DeformGen == DGEN_WAVE_SQUARE)
{
func = sign(sin(value * 2.0 * M_PI));
func = sign(0.5 - fract(value));
}
else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
{
@ -62,7 +62,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
{
func = (1.0 - fract(value));
}
else if (u_DeformGen == DGEN_BULGE)
else // if (u_DeformGen == DGEN_BULGE)
{
func = sin(value);
}
@ -73,16 +73,16 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
void main()
{
vec4 position = attr_Position;
vec3 normal = attr_Normal;
vec3 position = attr_Position;
vec3 normal = attr_Normal * 2.0 - vec3(1.0);
#if defined(USE_DEFORM_VERTEXES)
position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
position = DeformPosition(position, normal, attr_TexCoord0.st);
#endif
gl_Position = u_ModelViewProjectionMatrix * position;
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
vec3 dist = u_DlightInfo.xyz - position.xyz;
vec3 dist = u_DlightInfo.xyz - position;
var_Tex1 = dist.xy * u_DlightInfo.a + vec2(0.5);
float dlightmod = step(0.0, dot(dist, normal));

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
uniform mat4 u_ModelViewProjectionMatrix;
@ -8,6 +8,6 @@ varying vec2 var_TexCoords;
void main()
{
gl_Position = u_ModelViewProjectionMatrix * attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
var_TexCoords = attr_TexCoord0.st;
}

View file

@ -5,5 +5,5 @@ varying float var_Scale;
void main()
{
gl_FragColor = u_Color;
gl_FragColor.a *= sqrt(clamp(var_Scale, 0.0, 1.0));
gl_FragColor.a = sqrt(clamp(var_Scale, 0.0, 1.0));
}

View file

@ -1,27 +1,30 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec3 attr_Normal;
attribute vec4 attr_TexCoord0;
//#if defined(USE_VERTEX_ANIMATION)
attribute vec4 attr_Position2;
#if defined(USE_VERTEX_ANIMATION)
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
//#endif
#endif
uniform vec4 u_FogDistance;
uniform vec4 u_FogDepth;
uniform float u_FogEyeT;
//#if defined(USE_DEFORM_VERTEXES)
#if defined(USE_DEFORM_VERTEXES)
uniform int u_DeformGen;
uniform float u_DeformParams[5];
//#endif
#endif
uniform float u_Time;
uniform mat4 u_ModelViewProjectionMatrix;
//#if defined(USE_VERTEX_ANIMATION)
#if defined(USE_VERTEX_ANIMATION)
uniform float u_VertexLerp;
//#endif
#endif
uniform vec4 u_Color;
varying float var_Scale;
@ -41,7 +44,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
if (u_DeformGen == DGEN_BULGE)
{
phase *= M_PI * 0.25 * st.x;
phase *= st.x;
}
else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
{
@ -57,7 +60,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
else if (u_DeformGen == DGEN_WAVE_SQUARE)
{
func = sign(sin(value * 2.0 * M_PI));
func = sign(0.5 - fract(value));
}
else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
{
@ -71,7 +74,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
{
func = (1.0 - fract(value));
}
else if (u_DeformGen == DGEN_BULGE)
else // if (u_DeformGen == DGEN_BULGE)
{
func = sin(value);
}
@ -80,35 +83,36 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
#endif
float CalcFog(vec4 position)
float CalcFog(vec3 position)
{
float s = dot(position, u_FogDistance) * 8.0;
float t = dot(position, u_FogDepth);
float s = dot(vec4(position, 1.0), u_FogDistance) * 8.0;
float t = dot(vec4(position, 1.0), u_FogDepth);
bool eyeOutside = u_FogEyeT < 0.0;
float t2 = float(t >= float(eyeOutside));
float eyeOutside = float(u_FogEyeT < 0.0);
float fogged = float(t >= eyeOutside);
if (eyeOutside)
t2 *= t / (t - u_FogEyeT);
t += 1e-6;
t *= fogged / (t - u_FogEyeT * eyeOutside);
return s * t2;
return s * t;
}
void main()
{
#if defined(USE_VERTEX_ANIMATION)
vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
normal = normalize(normal - vec3(0.5));
#else
vec4 position = attr_Position;
vec3 normal = attr_Normal;
vec3 position = attr_Position;
vec3 normal = attr_Normal * 2.0 - vec3(1.0);
#endif
#if defined(USE_DEFORM_VERTEXES)
position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
#endif
gl_Position = u_ModelViewProjectionMatrix * position;
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
var_Scale = CalcFog(position);
var_Scale = CalcFog(position) * u_Color.a * u_Color.a;
}

View file

@ -37,6 +37,8 @@ void main()
{
color = color2;
}
//color = color * (u_Texture1Env.xxxx + color2 * u_Texture1Env.z) + color2 * u_Texture1Env.y;
#endif
gl_FragColor = color * var_Color;

View file

@ -1,8 +1,8 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec3 attr_Normal;
#if defined(USE_VERTEX_ANIMATION)
attribute vec4 attr_Position2;
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
#endif
@ -17,7 +17,7 @@ uniform vec4 u_DiffuseTexMatrix;
uniform vec4 u_DiffuseTexOffTurb;
#if defined(USE_TCGEN) || defined(USE_RGBAGEN)
uniform vec3 u_ViewOrigin;
uniform vec3 u_LocalViewOrigin;
#endif
#if defined(USE_TCGEN)
@ -48,7 +48,7 @@ uniform int u_ColorGen;
uniform int u_AlphaGen;
uniform vec3 u_AmbientLight;
uniform vec3 u_DirectedLight;
uniform vec4 u_LightOrigin;
uniform vec3 u_ModelLightDir;
uniform float u_PortalRange;
#endif
@ -73,7 +73,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
if (u_DeformGen == DGEN_BULGE)
{
phase *= M_PI * 0.25 * st.x;
phase *= st.x;
}
else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
{
@ -89,7 +89,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
else if (u_DeformGen == DGEN_WAVE_SQUARE)
{
func = sign(sin(value * 2.0 * M_PI));
func = sign(fract(0.5 - value));
}
else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
{
@ -103,7 +103,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
{
func = (1.0 - fract(value));
}
else if (u_DeformGen == DGEN_BULGE)
else // if (u_DeformGen == DGEN_BULGE)
{
func = sin(value);
}
@ -123,8 +123,10 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
}
else if (TCGen == TCGEN_ENVIRONMENT_MAPPED)
{
vec3 viewer = normalize(u_ViewOrigin - position);
tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
vec3 viewer = normalize(u_LocalViewOrigin - position);
vec2 ref = reflect(viewer, normal).yz;
tex.s = ref.x * -0.5 + 0.5;
tex.t = ref.y * 0.5 + 0.5;
}
else if (TCGen == TCGEN_VECTOR)
{
@ -139,13 +141,14 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
{
float amplitude = offTurb.z;
float phase = offTurb.w;
vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy;
float phase = offTurb.w * 2.0 * M_PI;
vec2 st2;
st2.x = st.x * texMatrix.x + (st.y * texMatrix.z + offTurb.x);
st2.y = st.x * texMatrix.y + (st.y * texMatrix.w + offTurb.y);
vec3 offsetPos = position / 1024.0;
offsetPos.x += offsetPos.z;
vec2 offsetPos = vec2(position.x + position.z, position.y);
vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);
vec2 texOffset = sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(phase));
return st2 + texOffset * amplitude;
}
@ -158,30 +161,25 @@ vec4 CalcColor(vec3 position, vec3 normal)
if (u_ColorGen == CGEN_LIGHTING_DIFFUSE)
{
float incoming = clamp(dot(normal, u_LightOrigin.xyz), 0.0, 1.0);
float incoming = clamp(dot(normal, u_ModelLightDir), 0.0, 1.0);
color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0);
}
vec3 toView = u_ViewOrigin - position;
vec3 viewer = normalize(u_ViewOrigin - position);
vec3 viewer = u_LocalViewOrigin - position;
if (u_AlphaGen == AGEN_LIGHTING_SPECULAR)
{
vec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz);
vec3 halfangle = normalize(lightDir + viewer);
vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - position);
vec3 reflected = -reflect(lightDir, normal);
color.a = pow(max(dot(normal, halfangle), 0.0), 8.0);
color.a = clamp(dot(reflected, normalize(viewer)), 0.0, 1.0);
color.a *= color.a;
color.a *= color.a;
}
else if (u_AlphaGen == AGEN_PORTAL)
{
float alpha = length(toView) / u_PortalRange;
color.a = clamp(alpha, 0.0, 1.0);
}
else if (u_AlphaGen == AGEN_FRESNEL)
{
color.a = 0.10 + 0.90 * pow(1.0 - dot(normal, viewer), 5);
color.a = clamp(length(viewer) / u_PortalRange, 0.0, 1.0);
}
return color;
@ -189,45 +187,46 @@ vec4 CalcColor(vec3 position, vec3 normal)
#endif
#if defined(USE_FOG)
float CalcFog(vec4 position)
float CalcFog(vec3 position)
{
float s = dot(position, u_FogDistance) * 8.0;
float t = dot(position, u_FogDepth);
float s = dot(vec4(position, 1.0), u_FogDistance) * 8.0;
float t = dot(vec4(position, 1.0), u_FogDepth);
bool eyeOutside = u_FogEyeT < 0.0;
float t2 = float(t >= float(eyeOutside));
float eyeOutside = float(u_FogEyeT < 0.0);
float fogged = float(t < eyeOutside);
if (eyeOutside)
t2 *= t / (t - u_FogEyeT);
t += 1e-6;
t *= fogged / (t - u_FogEyeT * eyeOutside);
return s * t2;
return s * t;
}
#endif
void main()
{
#if defined(USE_VERTEX_ANIMATION)
vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
normal = normalize(normal - vec3(0.5));
#else
vec4 position = attr_Position;
vec3 normal = attr_Normal;
vec3 position = attr_Position;
vec3 normal = attr_Normal * 2.0 - vec3(1.0);
#endif
#if defined(USE_DEFORM_VERTEXES)
position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
position = DeformPosition(position, normal, attr_TexCoord0.st);
#endif
gl_Position = u_ModelViewProjectionMatrix * position;
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
#if defined(USE_TCGEN)
vec2 tex = GenTexCoords(u_TCGen0, position.xyz, normal, u_TCGen0Vector0, u_TCGen0Vector1);
vec2 tex = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1);
#else
vec2 tex = attr_TexCoord0.st;
#endif
#if defined(USE_TCMOD)
var_DiffuseTex = ModTexCoords(tex, position.xyz, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
var_DiffuseTex = ModTexCoords(tex, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
#else
var_DiffuseTex = tex;
#endif
@ -237,7 +236,7 @@ void main()
#endif
#if defined(USE_RGBAGEN)
var_Color = CalcColor(position.xyz, normal);
var_Color = CalcColor(position, normal);
#else
var_Color = u_VertColor * attr_Color + u_BaseColor;
#endif

View file

@ -24,45 +24,49 @@ uniform sampler2D u_ShadowMap;
uniform samplerCube u_CubeMap;
#endif
#if defined(USE_LIGHT_VECTOR)
#if defined(USE_NORMALMAP) || defined(USE_DELUXEMAP) || defined(USE_SPECULARMAP) || defined(USE_CUBEMAP)
uniform vec4 u_EnableTextures; // x = normal, y = deluxe, z = specular, w = cube
#endif
#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight;
uniform float u_LightRadius;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec3 u_PrimaryLightColor;
uniform vec3 u_PrimaryLightAmbient;
uniform float u_PrimaryLightRadius;
#endif
#if defined(USE_LIGHT)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
uniform vec2 u_MaterialInfo;
#endif
varying vec2 var_DiffuseTex;
#if defined(USE_LIGHTMAP)
varying vec2 var_LightTex;
#endif
varying vec4 var_TexCoords;
varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
varying vec3 var_ViewDir;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
#if defined(USE_VERT_TANGENT_SPACE)
varying vec4 var_Normal;
varying vec4 var_Tangent;
varying vec4 var_Bitangent;
#else
varying vec3 var_Normal;
varying vec3 var_Tangent;
varying vec3 var_Bitangent;
varying vec3 var_ViewDir;
#endif
#endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor;
varying vec3 var_LightColor;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
varying vec4 var_LightDir;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir;
varying vec4 var_PrimaryLightDir;
#endif
@ -172,26 +176,49 @@ vec3 EnvironmentBRDF(float gloss, float NE, vec3 specular)
float CalcBlinn(float NH, float shininess)
{
#if defined(USE_BLINN) || defined(USE_BLINN_FRESNEL)
// Normalized Blinn-Phong
float norm = shininess * 0.125 + 1.0;
#elif defined(USE_MCAULEY)
// Cook-Torrance as done by Stephen McAuley
// http://blog.selfshadow.com/publications/s2012-shading-course/mcauley/s2012_pbs_farcry3_notes_v2.pdf
float norm = shininess * 0.25 + 0.125;
#elif defined(USE_GOTANDA)
// Neumann-Neumann as done by Yoshiharu Gotanda
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
float norm = shininess * 0.124858 + 0.269182;
#elif defined(USE_LAZAROV)
// Cook-Torrance as done by Dimitar Lazarov
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
float norm = shininess * 0.125 + 0.25;
#else
float norm = 1.0;
#endif
#if 0
// from http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
float a = shininess + 0.775;
return exp(a * NH - a);
return norm * exp(a * NH - a);
#else
return pow(NH, shininess);
return norm * pow(NH, shininess);
#endif
}
float CalcGGX(float NH, float shininess)
float CalcGGX(float NH, float gloss)
{
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf
float m_sq = 2.0 / shininess;
float d = ((NH * NH) * (m_sq - 1.0) + 1.0);
return m_sq / (d * d);
// from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
float a_sq = exp2(gloss * -13.0 + 1.0);
float d = ((NH * NH) * (a_sq - 1.0) + 1.0);
return a_sq / (d * d);
}
float CalcFresnel(float EH)
{
#if 1
// From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
// not accurate, but fast
return exp2(-10.0 * EH);
#elif 0
// From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/
return exp2((-5.55473 * EH - 6.98316) * EH);
#elif 0
@ -201,82 +228,70 @@ float CalcFresnel(float EH)
return blend;
#else
return pow(1.0 - NH, 5.0);
return pow(1.0 - EH, 5.0);
#endif
}
float CalcVisibility(float NH, float NL, float NE, float EH, float shininess)
float CalcVisibility(float NH, float NL, float NE, float EH, float gloss)
{
#if 0
float geo = 2.0 * NH * min(NE, NL);
geo /= max(EH, geo);
#if defined(USE_GOTANDA)
// Neumann-Neumann as done by Yoshiharu Gotanda
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
return 1.0 / max(max(NL, NE), EPSILON);
#elif defined(USE_LAZAROV)
// Cook-Torrance as done by Dimitar Lazarov
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
float k = min(1.0, gloss + 0.545);
return 1.0 / (k * (EH * EH - 1.0) + 1.0);
#elif defined(USE_GGX)
float roughness = exp2(gloss * -6.5);
return geo;
#else
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes.pdf
// Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
// NL, NE in numerator factored out from cook-torrance
#if defined(USE_GGX)
float roughness = sqrt(2.0 / (shininess + 2.0));
float k = (roughness + 1.0);
float k = roughness + 1.0;
k *= k * 0.125;
#else
float k = 2.0 / sqrt(3.1415926535 * (shininess + 2.0));
#endif
float k2 = 1.0 - k;
float invGeo1 = NL * k2 + k;
float invGeo2 = NE * k2 + k;
return 1.0 / (invGeo1 * invGeo2);
#endif
#else
return 1.0;
#endif
}
vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float shininess)
vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess)
{
float blinn = CalcBlinn(NH, shininess);
#if defined(USE_GGX)
float distrib = CalcGGX(NH, gloss);
#else
float distrib = CalcBlinn(NH, shininess);
#endif
#if defined(USE_BLINN)
vec3 fSpecular = specular;
#else
vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH));
float vis = CalcVisibility(NH, NL, NE, EH, shininess);
#endif
#if defined(USE_BLINN)
// Normalized Blinn-Phong
return specular * blinn * (shininess * 0.125 + 1.0);
#elif defined(USE_BLINN_FRESNEL)
// Normalized Blinn-Phong with Fresnel
return fSpecular * blinn * (shininess * 0.125 + 1.0);
#elif defined(USE_MCAULEY)
// Cook-Torrance as done by Stephen McAuley
// http://blog.selfshadow.com/publications/s2012-shading-course/mcauley/s2012_pbs_farcry3_notes_v2.pdf
return fSpecular * blinn * (shininess * 0.25 + 0.125);
#elif defined(USE_GOTANDA)
// Neumann-Neumann as done by Yoshiharu Gotanda
// http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
return fSpecular * blinn * (shininess * 0.124858 + 0.269182) / max(max(NL, NE), EPSILON);
#elif defined(USE_LAZAROV)
// Cook-Torrance as done by Dimitar Lazarov
// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
return fSpecular * blinn * (shininess * 0.125 + 0.25) * vis;
#endif
float vis = CalcVisibility(NH, NL, NE, EH, gloss);
return vec3(0.0);
return fSpecular * (distrib * vis);
}
float CalcLightAttenuation(vec3 dir, float sqrRadius)
float CalcLightAttenuation(float point, float normDist)
{
// point light at >0 radius, directional otherwise
float point = float(sqrRadius > 0.0);
// inverse square light
float attenuation = sqrRadius / dot(dir, dir);
// zero light at radius, approximating q3 style
// zero light at 1.0, approximating q3 style
// also don't attenuate directional light
attenuation = (0.5 * attenuation - 1.5) * point + 1.0;
float attenuation = (0.5 * normDist - 1.5) * point + 1.0;
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation *= float(attenuation > 0.0);
attenuation = max(attenuation, 0.0);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
@ -284,50 +299,66 @@ float CalcLightAttenuation(vec3 dir, float sqrRadius)
return attenuation;
}
// from http://www.thetenthplanet.de/archives/1180
mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv )
{
// get edge vectors of the pixel triangle
vec3 dp1 = dFdx( p );
vec3 dp2 = dFdy( p );
vec2 duv1 = dFdx( uv );
vec2 duv2 = dFdy( uv );
// solve the linear system
vec3 dp2perp = cross( dp2, N );
vec3 dp1perp = cross( N, dp1 );
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
// construct a scale-invariant frame
float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
return mat3( T * invmax, B * invmax, N );
}
void main()
{
vec3 L, N, E, H;
float NL, NH, NE, EH;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
mat3 tangentToWorld = mat3(var_Tangent, var_Bitangent, var_Normal);
#endif
#if defined(USE_DELUXEMAP)
L = (2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0));
#if defined(USE_TANGENT_SPACE_LIGHT)
L = L * tangentToWorld;
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_VERT_TANGENT_SPACE)
mat3 tangentToWorld = mat3(var_Tangent.xyz, var_Bitangent.xyz, var_Normal.xyz);
E = vec3(var_Normal.w, var_Tangent.w, var_Bitangent.w);
#else
mat3 tangentToWorld = cotangent_frame(var_Normal, -var_ViewDir, var_TexCoords.xy);
E = var_ViewDir;
#endif
#elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
L = var_LightDir.xyz;
#endif
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
E = normalize(var_ViewDir);
E = normalize(E);
L = var_LightDir.xyz;
#if defined(USE_DELUXEMAP)
L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y;
#endif
float sqrLightDist = dot(L, L);
#endif
#if defined(USE_LIGHTMAP)
vec4 lightSample = texture2D(u_LightMap, var_LightTex).rgba;
#if defined(RGBM_LIGHTMAP)
lightSample.rgb *= 32.0 * lightSample.a;
#endif
vec4 lightSample = texture2D(u_LightMap, var_TexCoords.zw);
vec3 lightColor = lightSample.rgb;
#if defined(RGBM_LIGHTMAP)
lightColor *= 32.0 * lightSample.a;
#endif
#elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
vec3 lightColor = u_DirectedLight * CalcLightAttenuation(L, u_LightRadius * u_LightRadius);
vec3 lightColor = u_DirectedLight * CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist);
vec3 ambientColor = u_AmbientLight;
#elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
vec3 lightColor = var_lightColor;
vec3 lightColor = var_LightColor;
#endif
vec2 texCoords = var_DiffuseTex;
vec2 texCoords = var_TexCoords.xy;
#if defined(USE_PARALLAXMAP)
#if defined(USE_TANGENT_SPACE_LIGHT)
vec3 offsetDir = E;
#else
vec3 offsetDir = E * tangentToWorld;
#endif
vec3 offsetDir = normalize(E * tangentToWorld);
offsetDir.xy *= -0.05 / offsetDir.z;
@ -335,41 +366,34 @@ void main()
#endif
vec4 diffuse = texture2D(u_DiffuseMap, texCoords);
#if defined(USE_GAMMA2_TEXTURES)
diffuse.rgb *= diffuse.rgb;
#endif
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_LINEAR_LIGHT)
diffuse.rgb *= diffuse.rgb;
#endif
#if defined(USE_NORMALMAP)
#if defined(SWIZZLE_NORMALMAP)
N.xy = 2.0 * texture2D(u_NormalMap, texCoords).ag - vec2(1.0);
N.xy = texture2D(u_NormalMap, texCoords).ag - vec2(0.5);
#else
N.xy = 2.0 * texture2D(u_NormalMap, texCoords).rg - vec2(1.0);
N.xy = texture2D(u_NormalMap, texCoords).rg - vec2(0.5);
#endif
N.z = sqrt(1.0 - clamp(dot(N.xy, N.xy), 0.0, 1.0));
#if !defined(USE_TANGENT_SPACE_LIGHT)
N = normalize(tangentToWorld * N);
#endif
#elif defined(USE_TANGENT_SPACE_LIGHT)
N = vec3(0.0, 0.0, 1.0);
N.xy *= u_EnableTextures.x;
N.z = sqrt((0.25 - N.x * N.x) - N.y * N.y);
N = tangentToWorld * N;
#else
N = normalize(var_Normal);
N = var_Normal.xyz;
#endif
L = normalize(L);
N = normalize(N);
L /= sqrt(sqrLightDist);
#if defined(USE_SHADOWMAP)
vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
float shadowValue = texture2D(u_ShadowMap, shadowTex).r;
// surfaces not facing the light are always shadowed
#if defined(USE_TANGENT_SPACE_LIGHT)
shadowValue *= float(var_PrimaryLightDir.z > 0.0);
#else
shadowValue *= float(dot(var_Normal, var_PrimaryLightDir) > 0.0);
#endif
shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0);
#if defined(SHADOWMAP_MODULATE)
//vec3 shadowColor = min(u_PrimaryLightAmbient, lightColor);
@ -377,7 +401,7 @@ void main()
#if 0
// Only shadow when the world light is parallel to the primary light
shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir), 0.0, 1.0);
shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0);
#endif
lightColor = mix(shadowColor, lightColor, shadowValue);
#endif
@ -385,12 +409,7 @@ void main()
#if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)
vec3 ambientColor = lightColor;
#if defined(USE_TANGENT_SPACE_LIGHT)
float surfNL = L.z;
#else
float surfNL = clamp(dot(var_Normal, L), 0.0, 1.0);
#endif
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
// Scale the incoming light to compensate for the baked-in light angle
// attenuation.
@ -406,40 +425,39 @@ void main()
NL = clamp(dot(N, L), 0.0, 1.0);
NE = clamp(dot(N, E), 0.0, 1.0);
vec4 specular = vec4(1.0);
#if defined(USE_SPECULARMAP)
vec4 specular = texture2D(u_SpecularMap, texCoords);
#if defined(USE_LINEAR_LIGHT)
specular += texture2D(u_SpecularMap, texCoords) * u_EnableTextures.z - u_EnableTextures.zzzz;
#if defined(USE_GAMMA2_TEXTURES)
specular.rgb *= specular.rgb;
#endif
#else
vec4 specular = vec4(1.0);
#endif
specular *= u_MaterialInfo.xxxy;
float gloss = specular.a;
float shininess = exp2(gloss * 13.0);
float localOcclusion = clamp((diffuse.r + diffuse.g + diffuse.b) * 16.0f, 0.0, 1.0);
#if defined(SPECULAR_IS_METALLIC)
// diffuse is actually base color, and red of specular is metallicness
float metallic = specular.r;
specular.rgb = vec3(0.04) + 0.96 * diffuse.rgb * metallic;
specular.rgb = (0.96 * metallic) * diffuse.rgb + vec3(0.04);
diffuse.rgb *= 1.0 - metallic;
#else
// adjust diffuse by specular reflectance, to maintain energy conservation
diffuse.rgb *= vec3(1.0) - specular.rgb;
#endif
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
#if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR)
float adjGloss = gloss;
float adjShininess = shininess;
#if !defined(USE_LIGHT_VECTOR)
adjShininess = exp2(gloss * r_deluxeSpecular * 13.0);
adjGloss *= r_deluxeSpecular;
adjShininess = exp2(adjGloss * 13.0);
#endif
H = normalize(L + E);
@ -448,9 +466,9 @@ void main()
NH = clamp(dot(N, H), 0.0, 1.0);
#if !defined(USE_LIGHT_VECTOR)
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * r_deluxeSpecular * localOcclusion;
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular;
#else
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjShininess) * localOcclusion;
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess);
#endif
#endif
@ -461,50 +479,50 @@ void main()
reflectance = EnvironmentBRDF(gloss, NE, specular.rgb);
vec3 R = reflect(E, N);
#if defined(USE_TANGENT_SPACE_LIGHT)
R = tangentToWorld * R;
#endif
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb;
#if defined(USE_LINEAR_LIGHT)
cubeLightColor *= cubeLightColor;
#endif
vec3 cubeLightColor = textureCubeLod(u_CubeMap, R, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w;
#if defined(USE_LIGHTMAP)
cubeLightColor *= lightSample.rgb;
#elif defined (USE_LIGHT_VERTEX)
cubeLightColor *= var_lightColor;
cubeLightColor *= var_LightColor;
#else
cubeLightColor *= lightColor * NL + ambientColor;
#endif
//gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb;
gl_FragColor.rgb += cubeLightColor * reflectance * localOcclusion;
//gl_FragColor.rgb += diffuse.rgb * textureCubeLod(u_CubeMap, N, 7.0).rgb * u_EnableTextures.w;
gl_FragColor.rgb += cubeLightColor * reflectance;
#endif
#if defined(USE_PRIMARY_LIGHT)
L = normalize(var_PrimaryLightDir);
NL = clamp(dot(N, L), 0.0, 1.0);
vec3 L2, H2;
float NL2, EH2, NH2;
H = normalize(L + E);
EH = clamp(dot(E, H), 0.0, 1.0);
NH = clamp(dot(N, H), 0.0, 1.0);
L2 = var_PrimaryLightDir.xyz;
reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess);
reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, shininess);
// enable when point lights are supported as primary lights
//sqrLightDist = dot(L2, L2);
//L2 /= sqrt(sqrLightDist);
lightColor = u_PrimaryLightColor; // * CalcLightAttenuation(L, u_PrimaryLightRadius * u_PrimaryLightRadius);
NL2 = clamp(dot(N, L2), 0.0, 1.0);
H2 = normalize(L2 + E);
EH2 = clamp(dot(E, H2), 0.0, 1.0);
NH2 = clamp(dot(N, H2), 0.0, 1.0);
reflectance = CalcDiffuse(diffuse.rgb, N, L2, E, NE, NL2, shininess);
reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, gloss, shininess);
lightColor = u_PrimaryLightColor;
// enable when point lights are supported as primary lights
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
#if defined(USE_SHADOWMAP)
lightColor *= shadowValue;
#endif
gl_FragColor.rgb += lightColor * reflectance * NL;
#endif
#if defined(USE_LINEAR_LIGHT)
gl_FragColor.rgb = sqrt(gl_FragColor.rgb);
gl_FragColor.rgb += lightColor * reflectance * NL2;
#endif
gl_FragColor.a = diffuse.a;

View file

@ -6,21 +6,27 @@ attribute vec4 attr_Color;
attribute vec3 attr_Position;
attribute vec3 attr_Normal;
attribute vec3 attr_Tangent;
attribute vec3 attr_Bitangent;
#if defined(USE_VERT_TANGENT_SPACE)
attribute vec4 attr_Tangent;
#endif
#if defined(USE_VERTEX_ANIMATION)
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
attribute vec3 attr_Tangent2;
attribute vec3 attr_Bitangent2;
#if defined(USE_VERT_TANGENT_SPACE)
attribute vec4 attr_Tangent2;
#endif
#endif
#if defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
attribute vec3 attr_LightDirection;
#endif
#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_DELUXEMAP)
uniform vec4 u_EnableTextures; // x = normal, y = deluxe, z = specular, w = cube
#endif
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
uniform vec3 u_ViewOrigin;
#endif
@ -28,6 +34,7 @@ uniform vec3 u_ViewOrigin;
uniform int u_TCGen0;
uniform vec3 u_TCGen0Vector0;
uniform vec3 u_TCGen0Vector1;
uniform vec3 u_LocalViewOrigin;
#endif
#if defined(USE_TCMOD)
@ -49,45 +56,43 @@ uniform float u_VertexLerp;
#if defined(USE_LIGHT_VECTOR)
uniform vec4 u_LightOrigin;
uniform float u_LightRadius;
#if defined(USE_FAST_LIGHT)
uniform vec3 u_DirectedLight;
uniform vec3 u_AmbientLight;
uniform float u_LightRadius;
#endif
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
uniform vec4 u_PrimaryLightOrigin;
uniform float u_PrimaryLightRadius;
#endif
varying vec2 var_DiffuseTex;
#if defined(USE_LIGHTMAP)
varying vec2 var_LightTex;
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
varying vec3 var_ViewDir;
#endif
varying vec4 var_TexCoords;
varying vec4 var_Color;
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_VERT_TANGENT_SPACE)
varying vec4 var_Normal;
varying vec4 var_Tangent;
varying vec4 var_Bitangent;
#else
varying vec3 var_Normal;
varying vec3 var_Tangent;
varying vec3 var_Bitangent;
varying vec3 var_ViewDir;
#endif
#endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
varying vec3 var_lightColor;
varying vec3 var_LightColor;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
varying vec4 var_LightDir;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
varying vec3 var_PrimaryLightDir;
varying vec4 var_PrimaryLightDir;
#endif
#if defined(USE_TCGEN)
@ -101,8 +106,10 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
}
else if (TCGen == TCGEN_ENVIRONMENT_MAPPED)
{
vec3 viewer = normalize(u_ViewOrigin - position);
tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
vec3 viewer = normalize(u_LocalViewOrigin - position);
vec2 ref = reflect(viewer, normal).yz;
tex.s = ref.x * -0.5 + 0.5;
tex.t = ref.y * 0.5 + 0.5;
}
else if (TCGen == TCGEN_VECTOR)
{
@ -117,34 +124,29 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3
vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
{
float amplitude = offTurb.z;
float phase = offTurb.w;
vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy;
float phase = offTurb.w * 2.0 * M_PI;
vec2 st2;
st2.x = st.x * texMatrix.x + (st.y * texMatrix.z + offTurb.x);
st2.y = st.x * texMatrix.y + (st.y * texMatrix.w + offTurb.y);
vec3 offsetPos = position * 0.0009765625;
offsetPos.x += offsetPos.z;
vec2 offsetPos = vec2(position.x + position.z, position.y);
vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);
vec2 texOffset = sin(offsetPos * (2.0 * M_PI / 1024.0) + vec2(phase));
return st2 + texOffset * amplitude;
}
#endif
float CalcLightAttenuation(vec3 dir, float sqrRadius)
float CalcLightAttenuation(float point, float normDist)
{
// point light at >0 radius, directional otherwise
float point = float(sqrRadius > 0.0);
// inverse square light
float attenuation = sqrRadius / dot(dir, dir);
// zero light at radius, approximating q3 style
// zero light at 1.0, approximating q3 style
// also don't attenuate directional light
attenuation = (0.5 * attenuation - 1.5) * point + 1.0;
float attenuation = (0.5 * normDist - 1.5) * point + 1.0;
// clamp attenuation
#if defined(NO_LIGHT_CLAMP)
attenuation *= float(attenuation > 0.0);
attenuation = max(attenuation, 0.0);
#else
attenuation = clamp(attenuation, 0.0, 1.0);
#endif
@ -157,14 +159,21 @@ void main()
{
#if defined(USE_VERTEX_ANIMATION)
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
vec3 tangent = normalize(mix(attr_Tangent, attr_Tangent2, u_VertexLerp));
vec3 bitangent = normalize(mix(attr_Bitangent, attr_Bitangent2, u_VertexLerp));
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 tangent = mix(attr_Tangent.xyz, attr_Tangent2.xyz, u_VertexLerp);
#endif
#else
vec3 position = attr_Position;
vec3 normal = attr_Normal;
vec3 tangent = attr_Tangent;
vec3 bitangent = attr_Bitangent;
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 tangent = attr_Tangent.xyz;
#endif
#endif
normal = normal * 2.0 - vec3(1.0);
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
tangent = tangent * 2.0 - vec3(1.0);
#endif
#if defined(USE_TCGEN)
@ -174,9 +183,9 @@ void main()
#endif
#if defined(USE_TCMOD)
var_DiffuseTex = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
var_TexCoords.xy = ModTexCoords(texCoords, position, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
#else
var_DiffuseTex = texCoords;
var_TexCoords.xy = texCoords;
#endif
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
@ -184,73 +193,68 @@ void main()
#if defined(USE_MODELMATRIX)
position = (u_ModelMatrix * vec4(position, 1.0)).xyz;
normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
tangent = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
bitangent = (u_ModelMatrix * vec4(bitangent, 0.0)).xyz;
#endif
#endif
#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 bitangent = cross(normal, tangent) * (attr_Tangent.w * 2.0 - 1.0);
#endif
#if defined(USE_LIGHT_VECTOR)
vec3 L = u_LightOrigin.xyz - (position * u_LightOrigin.w);
#elif defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
vec3 L = attr_LightDirection;
#elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 L = attr_LightDirection * 2.0 - vec3(1.0);
#if defined(USE_MODELMATRIX)
L = (u_ModelMatrix * vec4(L, 0.0)).xyz;
#endif
#endif
#if defined(USE_LIGHTMAP)
var_LightTex = attr_TexCoord1.st;
var_TexCoords.zw = attr_TexCoord1.st;
#endif
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
var_lightColor = u_VertColor.rgb * attr_Color.rgb;
var_Color.rgb = vec3(1.0);
var_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a;
#else
var_Color = u_VertColor * attr_Color + u_BaseColor;
#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
var_LightColor = var_Color.rgb;
var_Color.rgb = vec3(1.0);
#endif
#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
float attenuation = CalcLightAttenuation(L, u_LightRadius * u_LightRadius);
float NL = clamp(dot(normal, normalize(L)), 0.0, 1.0);
float sqrLightDist = dot(L, L);
float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist);
float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0);
var_Color.rgb *= u_DirectedLight * attenuation * NL + u_AmbientLight;
#endif
#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || defined(USE_PARALLAXMAP)
var_Normal = normal;
var_Tangent = tangent;
var_Bitangent = bitangent;
var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight;
#endif
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
var_PrimaryLightDir = (u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w));
var_PrimaryLightDir.xyz = u_PrimaryLightOrigin.xyz - (position * u_PrimaryLightOrigin.w);
var_PrimaryLightDir.w = u_PrimaryLightRadius * u_PrimaryLightRadius;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
#if defined(USE_LIGHT_VECTOR)
var_LightDir = vec4(L, u_LightOrigin.w);
var_LightDir = vec4(L, u_LightRadius * u_LightRadius);
#else
var_LightDir = vec4(L, 0.0);
#endif
#if defined(USE_DELUXEMAP)
var_LightDir -= u_EnableTextures.y * var_LightDir;
#endif
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
var_ViewDir = (u_ViewOrigin - position);
#endif
#if defined(USE_TANGENT_SPACE_LIGHT)
mat3 tangentToWorld = mat3(tangent, bitangent, normal);
#if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP)
var_PrimaryLightDir = var_PrimaryLightDir * tangentToWorld;
#endif
#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
var_LightDir.xyz = var_LightDir.xyz * tangentToWorld;
#endif
#if defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
var_ViewDir = var_ViewDir * tangentToWorld;
#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
vec3 viewDir = u_ViewOrigin - position;
#if defined(USE_VERT_TANGENT_SPACE)
// store view direction in tangent space to save on varyings
var_Normal = vec4(normal, viewDir.x);
var_Tangent = vec4(tangent, viewDir.y);
var_Bitangent = vec4(bitangent, viewDir.z);
#else
var_Normal = normal;
var_ViewDir = viewDir;
#endif
#endif
}

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec3 attr_Normal;
uniform mat4 u_ModelViewProjectionMatrix;
@ -8,10 +8,8 @@ varying vec3 var_Normal;
void main()
{
vec4 position = attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
gl_Position = u_ModelViewProjectionMatrix * position;
var_Position = position.xyz;
var_Normal = attr_Normal;
var_Position = attr_Position;
var_Normal = attr_Normal * 2.0 - vec3(1.0);
}

View file

@ -1,9 +1,9 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec3 attr_Normal;
attribute vec4 attr_TexCoord0;
//#if defined(USE_VERTEX_ANIMATION)
attribute vec4 attr_Position2;
attribute vec3 attr_Position2;
attribute vec3 attr_Normal2;
//#endif
@ -38,7 +38,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
if (u_DeformGen == DGEN_BULGE)
{
phase *= M_PI * 0.25 * st.x;
phase *= st.x;
}
else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
{
@ -54,7 +54,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
}
else if (u_DeformGen == DGEN_WAVE_SQUARE)
{
func = sign(sin(value * 2.0 * M_PI));
func = sign(0.5 - fract(value));
}
else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
{
@ -68,7 +68,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
{
func = (1.0 - fract(value));
}
else if (u_DeformGen == DGEN_BULGE)
else // if (u_DeformGen == DGEN_BULGE)
{
func = sin(value);
}
@ -78,12 +78,13 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
void main()
{
vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp);
vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp);
normal = normalize(normal - vec3(0.5));
position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
position = DeformPosition(position, normal, attr_TexCoord0.st);
gl_Position = u_ModelViewProjectionMatrix * position;
gl_Position = u_ModelViewProjectionMatrix * vec4(position, 1.0);
var_Position = (u_ModelMatrix * position).xyz;
var_Position = (u_ModelMatrix * vec4(position, 1.0)).xyz;
}

View file

@ -1,6 +1,6 @@
#version 120
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
uniform mat4 u_ModelViewProjectionMatrix;
@ -10,6 +10,6 @@ varying vec2 var_Tex1;
void main()
{
gl_Position = u_ModelViewProjectionMatrix * attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
var_Tex1 = attr_TexCoord0.st;
}

View file

@ -1,4 +1,4 @@
attribute vec4 attr_Position;
attribute vec3 attr_Position;
attribute vec4 attr_TexCoord0;
uniform mat4 u_ModelViewProjectionMatrix;
@ -8,6 +8,6 @@ varying vec2 var_TexCoords;
void main()
{
gl_Position = u_ModelViewProjectionMatrix * attr_Position;
gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0);
var_TexCoords = attr_TexCoord0.st;
}

View file

@ -33,143 +33,6 @@ frame.
*/
/*
==============
R_AddAnimSurfaces
==============
*/
void R_AddAnimSurfaces( trRefEntity_t *ent ) {
md4Header_t *header;
md4Surface_t *surface;
md4LOD_t *lod;
shader_t *shader;
int cubemapIndex;
int i;
header = (md4Header_t *) tr.currentModel->modelData;
lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
cubemapIndex = R_CubemapForPoint(ent->e.origin);
surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
shader = R_GetShaderByHandle( surface->shaderIndex );
R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse, qfalse, cubemapIndex );
surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd );
}
}
/*
==============
RB_SurfaceAnim
==============
*/
void RB_SurfaceAnim( md4Surface_t *surface ) {
int i, j, k;
float frontlerp, backlerp;
int *triangles;
int indexes;
int baseIndex, baseVertex;
int numVerts;
md4Vertex_t *v;
md4Bone_t bones[MD4_MAX_BONES];
md4Bone_t *bonePtr, *bone;
md4Header_t *header;
md4Frame_t *frame;
md4Frame_t *oldFrame;
int frameSize;
if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
backlerp = 0;
frontlerp = 1;
} else {
backlerp = backEnd.currentEntity->e.backlerp;
frontlerp = 1.0f - backlerp;
}
header = (md4Header_t *)((byte *)surface + surface->ofsHeader);
frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] );
frame = (md4Frame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.frame * frameSize );
oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames +
backEnd.currentEntity->e.oldframe * frameSize );
RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );
triangles = (int *) ((byte *)surface + surface->ofsTriangles);
indexes = surface->numTriangles * 3;
baseIndex = tess.numIndexes;
baseVertex = tess.numVertexes;
for (j = 0 ; j < indexes ; j++) {
tess.indexes[baseIndex + j] = baseIndex + triangles[j];
}
tess.numIndexes += indexes;
//
// lerp all the needed bones
//
if ( !backlerp ) {
// no lerping needed
bonePtr = frame->bones;
} else {
bonePtr = bones;
for ( i = 0 ; i < header->numBones*12 ; i++ ) {
((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i]
+ backlerp * ((float *)oldFrame->bones)[i];
}
}
//
// deform the vertexes by the lerped bones
//
numVerts = surface->numVerts;
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
for ( j = 0; j < numVerts; j++ ) {
vec3_t tempVert, tempNormal;
md4Weight_t *w;
VectorClear( tempVert );
VectorClear( tempNormal );
w = v->weights;
for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
bone = bonePtr + w->boneIndex;
tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
}
tess.xyz[baseVertex + j][0] = tempVert[0];
tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2];
tess.normal[baseVertex + j][0] = tempNormal[0];
tess.normal[baseVertex + j][1] = tempNormal[1];
tess.normal[baseVertex + j][2] = tempNormal[2];
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
v = (md4Vertex_t *)&v->weights[v->numWeights];
}
tess.numVertexes += surface->numVerts;
}
// copied and adapted from tr_mesh.c
@ -198,7 +61,7 @@ static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) {
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
// Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend
// we do. After all, the purpose of md4s are not that different, are they?
// we do. After all, the purpose of mdrs are not that different, are they?
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
@ -448,7 +311,7 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
RB_MDRSurfaceAnim
==============
*/
void RB_MDRSurfaceAnim( md4Surface_t *surface )
void RB_MDRSurfaceAnim( mdrSurface_t *surface )
{
int i, j, k;
float frontlerp, backlerp;
@ -460,7 +323,7 @@ void RB_MDRSurfaceAnim( md4Surface_t *surface )
mdrHeader_t *header;
mdrFrame_t *frame;
mdrFrame_t *oldFrame;
mdrBone_t bones[MD4_MAX_BONES], *bonePtr, *bone;
mdrBone_t bones[MDR_MAX_BONES], *bonePtr, *bone;
int frameSize;
@ -548,9 +411,7 @@ void RB_MDRSurfaceAnim( md4Surface_t *surface )
tess.xyz[baseVertex + j][1] = tempVert[1];
tess.xyz[baseVertex + j][2] = tempVert[2];
tess.normal[baseVertex + j][0] = tempNormal[0];
tess.normal[baseVertex + j][1] = tempNormal[1];
tess.normal[baseVertex + j][2] = tempNormal[2];
tess.normal[baseVertex + j] = R_VboPackNormal(tempNormal);
tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];

View file

@ -371,17 +371,17 @@ void GL_State( unsigned long stateBits )
}
void GL_SetProjectionMatrix(matrix_t matrix)
void GL_SetProjectionMatrix(mat4_t matrix)
{
Matrix16Copy(matrix, glState.projection);
Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
Mat4Copy(matrix, glState.projection);
Mat4Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
}
void GL_SetModelviewMatrix(matrix_t matrix)
void GL_SetModelviewMatrix(mat4_t matrix)
{
Matrix16Copy(matrix, glState.modelview);
Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
Mat4Copy(matrix, glState.modelview);
Mat4Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
}
@ -449,7 +449,7 @@ void RB_BeginDrawingView (void) {
{
if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
{
FBO_Bind(tr.screenScratchFbo);
FBO_Bind(NULL);
}
else
{
@ -461,7 +461,7 @@ void RB_BeginDrawingView (void) {
FBO_Bind(backEnd.viewParms.targetFbo);
// FIXME: hack for cubemap testing
if (backEnd.viewParms.targetFbo == tr.renderCubeFbo)
if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
{
//qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0);
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]->texnum, 0);
@ -501,7 +501,7 @@ void RB_BeginDrawingView (void) {
}
// clear to black for cube maps
if (backEnd.viewParms.targetFbo == tr.renderCubeFbo)
if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
{
clearBits |= GL_COLOR_BUFFER_BIT;
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
@ -765,7 +765,7 @@ RB_SetGL2D
================
*/
void RB_SetGL2D (void) {
matrix_t matrix;
mat4_t matrix;
int width, height;
if (backEnd.projection2D && backEnd.last2DFBO == glState.currentFBO)
@ -789,9 +789,9 @@ void RB_SetGL2D (void) {
qglViewport( 0, 0, width, height );
qglScissor( 0, 0, width, height );
Matrix16Ortho(0, width, height, 0, 0, 1, matrix);
Mat4Ortho(0, width, height, 0, 0, 1, matrix);
GL_SetProjectionMatrix(matrix);
Matrix16Identity(matrix);
Mat4Identity(matrix);
GL_SetModelviewMatrix(matrix);
GL_State( GLS_DEPTHTEST_DISABLE |
@ -830,6 +830,10 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
}
R_IssuePendingRenderCommands();
if ( tess.numIndexes ) {
RB_EndSurface();
}
// we definately want to sync every frame for the cinematics
qglFinish();
@ -859,7 +863,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
{
if (!tr.renderFbo || backEnd.framePostProcessed)
{
FBO_Bind(tr.screenScratchFbo);
FBO_Bind(NULL);
}
else
{
@ -881,7 +885,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
GLSL_BindProgram(&tr.textureColorShader);
GLSL_SetUniformMatrix16(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite);
RB_InstantQuad2(quadVerts, texCoords);
@ -946,7 +950,7 @@ const void *RB_StretchPic ( const void *data ) {
{
if (!tr.renderFbo || backEnd.framePostProcessed)
{
FBO_Bind(tr.screenScratchFbo);
FBO_Bind(NULL);
}
else
{
@ -1077,7 +1081,7 @@ const void *RB_DrawSurfs( const void *data ) {
FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0);
}
if (backEnd.viewParms.flags & VPF_USESUNLIGHT)
if (r_sunlightMode->integer && backEnd.viewParms.flags & VPF_USESUNLIGHT)
{
vec4_t quadVerts[4];
vec2_t texCoords[4];
@ -1122,9 +1126,9 @@ const void *RB_DrawSurfs( const void *data ) {
GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
GLSL_SetUniformMatrix16(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]);
GLSL_SetUniformMatrix16(&tr.shadowmaskShader, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
GLSL_SetUniformMatrix16(&tr.shadowmaskShader, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]);
GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg);
{
@ -1292,7 +1296,7 @@ const void *RB_DrawSurfs( const void *data ) {
RB_RenderFlares();
}
if (glRefConfig.framebufferObject && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo)
{
FBO_Bind(NULL);
GL_SelectTexture(TB_CUBEMAP);
@ -1443,7 +1447,7 @@ const void *RB_ClearDepth(const void *data)
{
if (!tr.renderFbo || backEnd.framePostProcessed)
{
FBO_Bind(tr.screenScratchFbo);
FBO_Bind(NULL);
}
else
{
@ -1512,32 +1516,13 @@ const void *RB_SwapBuffers( const void *data ) {
{
// Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first
FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
FBO_FastBlit(tr.msaaResolveFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
FBO_FastBlit(tr.msaaResolveFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else if (tr.renderFbo)
{
FBO_FastBlit(tr.renderFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
FBO_FastBlit(tr.renderFbo, NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
if (tr.screenScratchFbo)
{
vec4_t color;
color[0] =
color[1] =
color[2] = pow(2, tr.overbrightBits); //exp2(tr.overbrightBits);
color[3] = 1.0f;
// turn off colormask when copying final image
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
FBO_Blit(tr.screenScratchFbo, NULL, NULL, NULL, NULL, NULL, color, 0);
if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
}
}
if ( !glState.finishCalled ) {
@ -1572,16 +1557,22 @@ const void *RB_CapShadowMap(const void *data)
{
GL_SelectTexture(0);
if (cmd->cubeSide != -1)
{
if (tr.shadowCubemaps[cmd->map])
{
GL_Bind(tr.shadowCubemaps[cmd->map]);
qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
}
}
else
{
if (tr.pshadowMaps[cmd->map])
{
GL_Bind(tr.pshadowMaps[cmd->map]);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
}
}
}
return (const void *)(cmd + 1);
}
@ -1597,7 +1588,7 @@ const void *RB_PostProcess(const void *data)
{
const postProcessCommand_t *cmd = data;
FBO_t *srcFbo;
vec4i_t srcBox, dstBox;
ivec4_t srcBox, dstBox;
qboolean autoExposure;
// finish any 2D drawing if needed
@ -1654,11 +1645,11 @@ const void *RB_PostProcess(const void *data)
if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer))
{
autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer;
RB_ToneMap(srcFbo, srcBox, tr.screenScratchFbo, dstBox, autoExposure);
RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure);
}
else if (r_cameraExposure->value == 0.0f)
{
FBO_FastBlit(srcFbo, srcBox, tr.screenScratchFbo, dstBox, GL_COLOR_BUFFER_BIT, GL_NEAREST);
FBO_FastBlit(srcFbo, srcBox, NULL, dstBox, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
else
{
@ -1669,56 +1660,56 @@ const void *RB_PostProcess(const void *data)
color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
color[3] = 1.0f;
FBO_Blit(srcFbo, srcBox, NULL, tr.screenScratchFbo, dstBox, NULL, color, 0);
FBO_Blit(srcFbo, srcBox, NULL, NULL, dstBox, NULL, color, 0);
}
}
if (r_drawSunRays->integer)
RB_SunRays(tr.screenScratchFbo, srcBox, tr.screenScratchFbo, dstBox);
RB_SunRays(NULL, srcBox, NULL, dstBox);
if (1)
RB_BokehBlur(tr.screenScratchFbo, srcBox, tr.screenScratchFbo, dstBox, backEnd.refdef.blurFactor);
RB_BokehBlur(NULL, srcBox, NULL, dstBox, backEnd.refdef.blurFactor);
else
RB_GaussianBlur(backEnd.refdef.blurFactor);
if (0)
if (0 && r_sunlightMode->integer)
{
vec4i_t dstBox;
ivec4_t dstBox;
VectorSet4(dstBox, 0, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, NULL, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 128, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, NULL, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 256, 0, 128, 128);
FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, NULL, dstBox, NULL, NULL, 0);
}
if (0)
{
vec4i_t dstBox;
ivec4_t dstBox;
VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0);
VectorSet4(dstBox, 512, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0);
}
if (0)
{
vec4i_t dstBox;
ivec4_t dstBox;
VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0);
}
#if 0
if (r_cubeMapping->integer && tr.numCubemaps)
{
vec4i_t dstBox;
ivec4_t dstBox;
int cubemapIndex = R_CubemapForPoint( backEnd.viewParms.or.origin );
if (cubemapIndex)
{
VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256);
//FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, tr.screenScratchFbo, dstBox, &tr.testcubeShader, NULL, 0);
FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1], NULL, NULL, tr.screenScratchFbo, dstBox, &tr.testcubeShader, NULL, 0);
//FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1], NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0);
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -442,12 +442,6 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
qglClear(GL_COLOR_BUFFER_BIT);
}
if (tr.screenScratchFbo)
{
FBO_Bind(tr.screenScratchFbo);
qglClear(GL_COLOR_BUFFER_BIT);
}
FBO_Bind(NULL);
}

View file

@ -25,14 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/*
This file does all of the processing necessary to turn a raw grid of points
read from the map file into a srfGridMesh_t ready for rendering.
read from the map file into a srfBspSurface_t ready for rendering.
The level of detail solution is direction independent, based only on subdivided
distance from the true curve.
Only a single entry point:
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
*/
@ -213,13 +213,13 @@ static int neighbors[8][2] = {
}
#ifdef USE_VERT_TANGENT_SPACE
static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles,
srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2])
static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numIndexes,
glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
{
int i, j;
srfVert_t *dv[3];
static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
srfTriangle_t *tri;
glIndex_t *tri;
// FIXME: use more elegant way
for(i = 0; i < width; i++)
@ -231,53 +231,15 @@ static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRI
}
}
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
for(i = 0, tri = indexes; i < numIndexes; i += 3, tri += 3)
{
dv[0] = &ctrl2[tri->indexes[0]];
dv[1] = &ctrl2[tri->indexes[1]];
dv[2] = &ctrl2[tri->indexes[2]];
dv[0] = &ctrl2[tri[0]];
dv[1] = &ctrl2[tri[1]];
dv[2] = &ctrl2[tri[2]];
R_CalcTangentVectors(dv);
}
#if 0
for(i = 0; i < (width * height); i++)
{
dv0 = &ctrl2[i];
VectorNormalize(dv0->normal);
#if 0
VectorNormalize(dv0->tangent);
VectorNormalize(dv0->bitangent);
#else
d = DotProduct(dv0->tangent, dv0->normal);
VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent);
VectorNormalize(dv0->tangent);
d = DotProduct(dv0->bitangent, dv0->normal);
VectorMA(dv0->bitangent, -d, dv0->normal, dv0->bitangent);
VectorNormalize(dv0->bitangent);
#endif
}
#endif
#if 0
// do another extra smoothing for normals to avoid flat shading
for(i = 0; i < (width * height); i++)
{
for(j = 0; j < (width * height); j++)
{
if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse))
{
VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal);
}
}
VectorNormalize(ctrl2[i].normal);
}
#endif
for(i = 0; i < width; i++)
{
for(j = 0; j < height; j++)
@ -285,26 +247,25 @@ static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRI
dv[0] = &ctrl2[j * width + i];
dv[1] = &ctrl[j][i];
VectorCopy(dv[0]->tangent, dv[1]->tangent);
VectorCopy(dv[0]->bitangent, dv[1]->bitangent);
VectorCopy4(dv[0]->tangent, dv[1]->tangent);
}
}
}
#endif
static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2])
static int MakeMeshIndexes(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
{
int i, j;
int numTriangles;
int numIndexes;
int w, h;
srfVert_t *dv;
static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
h = height - 1;
w = width - 1;
numTriangles = 0;
numIndexes = 0;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
@ -317,20 +278,16 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE
v3 = v2 + width;
v4 = v3 + 1;
triangles[numTriangles].indexes[0] = v2;
triangles[numTriangles].indexes[1] = v3;
triangles[numTriangles].indexes[2] = v1;
numTriangles++;
indexes[numIndexes++] = v2;
indexes[numIndexes++] = v3;
indexes[numIndexes++] = v1;
triangles[numTriangles].indexes[0] = v1;
triangles[numTriangles].indexes[1] = v3;
triangles[numTriangles].indexes[2] = v4;
numTriangles++;
indexes[numIndexes++] = v1;
indexes[numIndexes++] = v3;
indexes[numIndexes++] = v4;
}
}
R_CalcSurfaceTriangleNeighbors(numTriangles, triangles);
// FIXME: use more elegant way
for(i = 0; i < width; i++)
{
@ -341,9 +298,7 @@ static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE
}
}
R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2);
return numTriangles;
return numIndexes;
}
@ -420,13 +375,13 @@ static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
R_CreateSurfaceGridMesh
=================
*/
srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height,
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) {
int numIndexes, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3]) {
int i, j, size;
srfVert_t *vert;
vec3_t tmpVec;
srfGridMesh_t *grid;
srfBspSurface_t *grid;
// copy the results out to a grid
size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid );
@ -441,9 +396,9 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 );
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
grid->numTriangles = numTriangles;
grid->triangles = ri.Malloc(grid->numTriangles * sizeof(srfTriangle_t));
Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
grid->numIndexes = numIndexes;
grid->indexes = ri.Malloc(grid->numIndexes * sizeof(glIndex_t));
Com_Memcpy(grid->indexes, indexes, numIndexes * sizeof(glIndex_t));
grid->numVerts = (width * height);
grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t));
@ -457,9 +412,9 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->heightLodError = ri.Hunk_Alloc( height * 4 );
Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
grid->numTriangles = numTriangles;
grid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
grid->numIndexes = numIndexes;
grid->indexes = ri.Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t), h_low);
Com_Memcpy(grid->indexes, indexes, numIndexes * sizeof(glIndex_t));
grid->numVerts = (width * height);
grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
@ -468,23 +423,23 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
grid->width = width;
grid->height = height;
grid->surfaceType = SF_GRID;
ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
ClearBounds( grid->cullBounds[0], grid->cullBounds[1] );
for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) {
vert = &grid->verts[j*width+i];
*vert = ctrl[j][i];
AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
AddPointToBounds( vert->xyz, grid->cullBounds[0], grid->cullBounds[1] );
}
}
// compute local origin and bounds
VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
grid->meshRadius = VectorLength( tmpVec );
VectorAdd( grid->cullBounds[0], grid->cullBounds[1], grid->cullOrigin );
VectorScale( grid->cullOrigin, 0.5f, grid->cullOrigin );
VectorSubtract( grid->cullBounds[0], grid->cullOrigin, tmpVec );
grid->cullRadius = VectorLength( tmpVec );
VectorCopy( grid->localOrigin, grid->lodOrigin );
grid->lodRadius = grid->meshRadius;
VectorCopy( grid->cullOrigin, grid->lodOrigin );
grid->lodRadius = grid->cullRadius;
//
return grid;
}
@ -494,10 +449,10 @@ srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
R_FreeSurfaceGridMesh
=================
*/
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
void R_FreeSurfaceGridMesh( srfBspSurface_t *grid ) {
ri.Free(grid->widthLodError);
ri.Free(grid->heightLodError);
ri.Free(grid->triangles);
ri.Free(grid->indexes);
ri.Free(grid->verts);
ri.Free(grid);
}
@ -507,7 +462,7 @@ void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
R_SubdividePatchToGrid
=================
*/
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
int i, j, k, l;
srfVert_t_cleared( prev );
@ -518,8 +473,8 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
int t;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
int numTriangles;
static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
int numIndexes;
static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
int consecutiveComplete;
for ( i = 0 ; i < width ; i++ ) {
@ -673,16 +628,16 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
}
#endif
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate indexes
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
// calculate normals
MakeMeshNormals( width, height, ctrl );
#ifdef USE_VERT_TANGENT_SPACE
MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
#endif
return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
}
/*
@ -690,15 +645,15 @@ srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
R_GridInsertColumn
===============
*/
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) {
int i, j;
int width, height, oldwidth;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
int numTriangles;
static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
int numIndexes;
static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
oldwidth = 0;
width = grid->width + 1;
@ -728,8 +683,8 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
// put all the aproximating points on the curve
//PutPointsOnCurve( ctrl, width, height );
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate indexes
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
// calculate normals
MakeMeshNormals( width, height, ctrl );
@ -739,7 +694,7 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
// free the old grid
R_FreeSurfaceGridMesh(grid);
// create a new grid
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
grid->lodRadius = lodRadius;
VectorCopy(lodOrigin, grid->lodOrigin);
return grid;
@ -750,15 +705,15 @@ srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec
R_GridInsertRow
===============
*/
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) {
int i, j;
int width, height, oldheight;
srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
float lodRadius;
vec3_t lodOrigin;
int numTriangles;
static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
int numIndexes;
static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
oldheight = 0;
width = grid->width;
@ -788,8 +743,8 @@ srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t
// put all the aproximating points on the curve
//PutPointsOnCurve( ctrl, width, height );
// calculate triangles
numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
// calculate indexes
numIndexes = MakeMeshIndexes(width, height, ctrl, indexes);
// calculate normals
MakeMeshNormals( width, height, ctrl );
@ -799,7 +754,7 @@ srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t
// free the old grid
R_FreeSurfaceGridMesh(grid);
// create a new grid
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numIndexes, indexes);
grid->lodRadius = lodRadius;
VectorCopy(lodOrigin, grid->lodOrigin);
return grid;

View file

@ -701,8 +701,25 @@ void GLimp_InitExtraExtensions()
glRefConfig.seamlessCubeMap = qfalse;
if( GLimp_HaveExtension( extension ) )
{
if (r_arb_seamless_cube_map->integer)
glRefConfig.seamlessCubeMap = qtrue;
ri.Printf(PRINT_ALL, result[1], extension);
ri.Printf(PRINT_ALL, result[glRefConfig.seamlessCubeMap], extension);
}
else
{
ri.Printf(PRINT_ALL, result[2], extension);
}
// GL_ARB_vertex_type_2_10_10_10_rev
extension = "GL_ARB_vertex_type_2_10_10_10_rev";
glRefConfig.packedNormalDataType = GL_UNSIGNED_BYTE;
if( GLimp_HaveExtension( extension ) )
{
if (r_arb_vertex_type_2_10_10_10_rev->integer)
glRefConfig.packedNormalDataType = GL_UNSIGNED_INT_2_10_10_10_REV;
ri.Printf(PRINT_ALL, result[r_arb_vertex_type_2_10_10_10_rev->integer ? 1 : 0], extension);
}
else
{

View file

@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// Some matrix helper functions
// FIXME: do these already exist in ioq3 and I don't know about them?
void Matrix16Zero( matrix_t out )
void Mat4Zero( mat4_t out )
{
out[ 0] = 0.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
out[ 1] = 0.0f; out[ 5] = 0.0f; out[ 9] = 0.0f; out[13] = 0.0f;
@ -34,7 +34,7 @@ void Matrix16Zero( matrix_t out )
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 0.0f;
}
void Matrix16Identity( matrix_t out )
void Mat4Identity( mat4_t out )
{
out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = 0.0f;
@ -42,7 +42,7 @@ void Matrix16Identity( matrix_t out )
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void Matrix16Copy( const matrix_t in, matrix_t out )
void Mat4Copy( const mat4_t in, mat4_t out )
{
out[ 0] = in[ 0]; out[ 4] = in[ 4]; out[ 8] = in[ 8]; out[12] = in[12];
out[ 1] = in[ 1]; out[ 5] = in[ 5]; out[ 9] = in[ 9]; out[13] = in[13];
@ -50,7 +50,7 @@ void Matrix16Copy( const matrix_t in, matrix_t out )
out[ 3] = in[ 3]; out[ 7] = in[ 7]; out[11] = in[11]; out[15] = in[15];
}
void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out )
void Mat4Multiply( const mat4_t in1, const mat4_t in2, mat4_t out )
{
out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
@ -73,7 +73,7 @@ void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out )
out[15] = in1[ 3] * in2[12] + in1[ 7] * in2[13] + in1[11] * in2[14] + in1[15] * in2[15];
}
void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out )
void Mat4Transform( const mat4_t in1, const vec4_t in2, vec4_t out )
{
out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
@ -81,7 +81,7 @@ void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out )
out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3];
}
qboolean Matrix16Compare( const matrix_t a, const matrix_t b )
qboolean Mat4Compare( const mat4_t a, const mat4_t b )
{
return !(a[ 0] != b[ 0] || a[ 4] != b[ 4] || a[ 8] != b[ 8] || a[12] != b[12] ||
a[ 1] != b[ 1] || a[ 5] != b[ 5] || a[ 9] != b[ 9] || a[13] != b[13] ||
@ -89,7 +89,7 @@ qboolean Matrix16Compare( const matrix_t a, const matrix_t b )
a[ 3] != b[ 3] || a[ 7] != b[ 7] || a[11] != b[11] || a[15] != b[15]);
}
void Matrix16Dump( const matrix_t in )
void Mat4Dump( const mat4_t in )
{
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 0], in[ 4], in[ 8], in[12]);
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 1], in[ 5], in[ 9], in[13]);
@ -97,7 +97,7 @@ void Matrix16Dump( const matrix_t in )
ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 3], in[ 7], in[11], in[15]);
}
void Matrix16Translation( vec3_t vec, matrix_t out )
void Mat4Translation( vec3_t vec, mat4_t out )
{
out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = vec[0];
out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = vec[1];
@ -105,7 +105,7 @@ void Matrix16Translation( vec3_t vec, matrix_t out )
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out )
void Mat4Ortho( float left, float right, float bottom, float top, float znear, float zfar, mat4_t out )
{
out[ 0] = 2.0f / (right - left); out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = -(right + left) / (right - left);
out[ 1] = 0.0f; out[ 5] = 2.0f / (top - bottom); out[ 9] = 0.0f; out[13] = -(top + bottom) / (top - bottom);
@ -113,7 +113,7 @@ void Matrix16Ortho( float left, float right, float bottom, float top, float znea
out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
}
void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out)
void Mat4View(vec3_t axes[3], vec3_t origin, mat4_t out)
{
out[0] = axes[0][0];
out[1] = axes[1][0];
@ -136,7 +136,7 @@ void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out)
out[15] = 1;
}
void Matrix16SimpleInverse( const matrix_t in, matrix_t out)
void Mat4SimpleInverse( const mat4_t in, mat4_t out)
{
vec3_t v;
float invSqrLen;

View file

@ -24,22 +24,22 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef __TR_EXTRAMATH_H__
#define __TR_EXTRAMATH_H__
typedef vec_t matrix_t[16];
typedef int vec2i_t[2];
typedef int vec3i_t[3];
typedef int vec4i_t[4];
typedef vec_t mat4_t[16];
typedef int ivec2_t[2];
typedef int ivec3_t[3];
typedef int ivec4_t[4];
void Matrix16Zero( matrix_t out );
void Matrix16Identity( matrix_t out );
void Matrix16Copy( const matrix_t in, matrix_t out );
void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out );
void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out );
qboolean Matrix16Compare(const matrix_t a, const matrix_t b);
void Matrix16Dump( const matrix_t in );
void Matrix16Translation( vec3_t vec, matrix_t out );
void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out );
void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out);
void Matrix16SimpleInverse( const matrix_t in, matrix_t out);
void Mat4Zero( mat4_t out );
void Mat4Identity( mat4_t out );
void Mat4Copy( const mat4_t in, mat4_t out );
void Mat4Multiply( const mat4_t in1, const mat4_t in2, mat4_t out );
void Mat4Transform( const mat4_t in1, const vec4_t in2, vec4_t out );
qboolean Mat4Compare(const mat4_t a, const mat4_t b);
void Mat4Dump( const mat4_t in );
void Mat4Translation( vec3_t vec, mat4_t out );
void Mat4Ortho( float left, float right, float bottom, float top, float znear, float zfar, mat4_t out );
void Mat4View(vec3_t axes[3], vec3_t origin, mat4_t out);
void Mat4SimpleInverse( const mat4_t in, mat4_t out);
#define VectorCopy2(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
#define VectorSet2(v,x,y) ((v)[0]=(x),(v)[1]=(y));
@ -52,7 +52,7 @@ void Matrix16SimpleInverse( const matrix_t in, matrix_t out);
#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])
#define OffsetByteToFloat(a) ((float)(a) * 1.0f/127.5f - 1.0f)
#define FloatToOffsetByte(a) (byte)(((a) + 1.0f) * 127.5f)
#define FloatToOffsetByte(a) (byte)((a) * 127.5f + 128.0f)
#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f)
#define FloatToByte(a) (byte)((a) * 255.0f)

View file

@ -386,7 +386,7 @@ void FBO_Init(void)
hdrFormat = GL_RGBA8;
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
{
hdrFormat = GL_RGB16F_ARB;
hdrFormat = GL_RGBA16F_ARB;
}
qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
@ -465,6 +465,8 @@ void FBO_Init(void)
}
// FIXME: Don't use separate color/depth buffers for a shadow buffer
if (MAX_DRAWN_PSHADOWS && tr.pshadowMaps[0])
{
for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
{
tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
@ -478,7 +480,10 @@ void FBO_Init(void)
R_CheckFBO(tr.pshadowFbos[i]);
}
}
if (tr.sunShadowDepthImage[0])
{
for ( i = 0; i < 3; i++)
{
tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
@ -493,6 +498,15 @@ void FBO_Init(void)
R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
R_CheckFBO(tr.sunShadowFbo[i]);
}
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
FBO_Bind(tr.screenShadowFbo);
FBO_AttachTextureImage(tr.screenShadowImage, 0);
R_CheckFBO(tr.screenShadowFbo);
}
for (i = 0; i < 2; i++)
@ -526,22 +540,6 @@ void FBO_Init(void)
R_CheckFBO(tr.targetLevelsFbo);
}
if (r_softOverbright->integer)
{
//tr.screenScratchFbo = FBO_Create("_screenscratch", width, height);
tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height);
FBO_Bind(tr.screenScratchFbo);
//FBO_CreateBuffer(tr.screenScratchFbo, format, 0, 0);
FBO_AttachTextureImage(tr.screenScratchImage, 0);
// FIXME: hack: share zbuffer between render fbo and pre-screen fbo
//FBO_CreateBuffer(tr.screenScratchFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
R_CheckFBO(tr.screenScratchFbo);
}
for (i = 0; i < 2; i++)
{
tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
@ -553,15 +551,6 @@ void FBO_Init(void)
R_CheckFBO(tr.quarterFbo[i]);
}
{
tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
FBO_Bind(tr.screenShadowFbo);
FBO_AttachTextureImage(tr.screenShadowImage, 0);
R_CheckFBO(tr.screenShadowFbo);
}
if (r_ssao->integer)
{
tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
@ -579,6 +568,7 @@ void FBO_Init(void)
R_CheckFBO(tr.screenSsaoFbo);
}
if (tr.renderCubeImage)
{
tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height);
FBO_Bind(tr.renderCubeFbo);
@ -667,16 +657,16 @@ void R_FBOList_f(void)
// FIXME
extern void RB_SetGL2D (void);
void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, vec4i_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
{
vec4i_t dstBox, srcBox;
ivec4_t dstBox, srcBox;
vec2_t srcTexScale;
vec4_t color;
vec4_t quadVerts[4];
vec2_t texCoords[4];
vec2_t invTexRes;
FBO_t *oldFbo = glState.currentFBO;
matrix_t projection;
mat4_t projection;
int width, height;
if (!src)
@ -757,7 +747,7 @@ void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexS
qglViewport( 0, 0, width, height );
qglScissor( 0, 0, width, height );
Matrix16Ortho(0, width, height, 0, 0, 1, projection);
Mat4Ortho(0, width, height, 0, 0, 1, projection);
qglDisable( GL_CULL_FACE );
@ -780,7 +770,7 @@ void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexS
GLSL_BindProgram(shaderProgram);
GLSL_SetUniformMatrix16(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection);
GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection);
GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color);
GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes);
GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
@ -791,9 +781,9 @@ void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexS
FBO_Bind(oldFbo);
}
void FBO_Blit(FBO_t *src, vec4i_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
{
vec4i_t srcBox;
ivec4_t srcBox;
if (!src)
{
@ -817,9 +807,9 @@ void FBO_Blit(FBO_t *src, vec4i_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, vec4
FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE);
}
void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter)
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter)
{
vec4i_t srcBoxFinal, dstBoxFinal;
ivec4_t srcBoxFinal, dstBoxFinal;
GLuint srcFb, dstFb;
if (!glRefConfig.framebufferBlit)

View file

@ -56,9 +56,9 @@ void FBO_Bind(FBO_t *fbo);
void FBO_Init(void);
void FBO_Shutdown(void);
void FBO_BlitFromTexture(struct image_s *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_Blit(FBO_t *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter);
void FBO_BlitFromTexture(struct image_s *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_Blit(FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter);
#endif

View file

@ -86,6 +86,19 @@ flare_t *r_activeFlares, *r_inactiveFlares;
int flareCoeff;
/*
==================
R_SetFlareCoeff
==================
*/
static void R_SetFlareCoeff( void ) {
if(r_flareCoeff->value == 0.0f)
flareCoeff = atof(FLARE_STDCOEFF);
else
flareCoeff = r_flareCoeff->value;
}
/*
==================
R_ClearFlares
@ -102,6 +115,8 @@ void R_ClearFlares( void ) {
r_flareStructs[i].next = r_inactiveFlares;
r_inactiveFlares = &r_flareStructs[i];
}
R_SetFlareCoeff();
}
@ -262,6 +277,7 @@ void RB_TestFlare( flare_t *f ) {
qboolean visible;
float fade;
float screenZ;
FBO_t *oldFbo;
backEnd.pc.c_flareTests++;
@ -269,9 +285,22 @@ void RB_TestFlare( flare_t *f ) {
// don't bother with another sync
glState.finishCalled = qfalse;
// if we're doing multisample rendering, read from the correct FBO
oldFbo = glState.currentFBO;
if (tr.msaaResolveFbo)
{
FBO_Bind(tr.msaaResolveFbo);
}
// read back the z buffer contents
qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
// if we're doing multisample rendering, switch to the old FBO
if (tr.msaaResolveFbo)
{
FBO_Bind(oldFbo);
}
screenZ = backEnd.viewParms.projectionMatrix[14] /
( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
@ -443,7 +472,7 @@ void RB_RenderFlares (void) {
flare_t *f;
flare_t **prev;
qboolean draw;
matrix_t oldmodelview, oldprojection, matrix;
mat4_t oldmodelview, oldprojection, matrix;
if ( !r_flares->integer ) {
return;
@ -451,11 +480,7 @@ void RB_RenderFlares (void) {
if(r_flareCoeff->modified)
{
if(r_flareCoeff->value == 0.0f)
flareCoeff = atof(FLARE_STDCOEFF);
else
flareCoeff = r_flareCoeff->value;
R_SetFlareCoeff();
r_flareCoeff->modified = qfalse;
}
@ -505,11 +530,11 @@ void RB_RenderFlares (void) {
qglDisable (GL_CLIP_PLANE0);
}
Matrix16Copy(glState.projection, oldprojection);
Matrix16Copy(glState.modelview, oldmodelview);
Matrix16Identity(matrix);
Mat4Copy(glState.projection, oldprojection);
Mat4Copy(glState.modelview, oldmodelview);
Mat4Identity(matrix);
GL_SetModelviewMatrix(matrix);
Matrix16Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
Mat4Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
-99999, 99999, matrix );
GL_SetProjectionMatrix(matrix);

View file

@ -84,6 +84,8 @@ static uniformInfo_t uniformsInfo[] =
{ "u_ShadowMvp2", GLSL_MAT16 },
{ "u_ShadowMvp3", GLSL_MAT16 },
{ "u_EnableTextures", GLSL_VEC4 },
{ "u_DiffuseTexMatrix", GLSL_VEC4 },
{ "u_DiffuseTexOffTurb", GLSL_VEC4 },
{ "u_Texture1Env", GLSL_INT },
@ -106,6 +108,7 @@ static uniformInfo_t uniformsInfo[] =
{ "u_LightUp", GLSL_VEC3 },
{ "u_LightRight", GLSL_VEC3 },
{ "u_LightOrigin", GLSL_VEC4 },
{ "u_ModelLightDir", GLSL_VEC3 },
{ "u_LightRadius", GLSL_FLOAT },
{ "u_AmbientLight", GLSL_VEC3 },
{ "u_DirectedLight", GLSL_VEC3 },
@ -126,6 +129,7 @@ static uniformInfo_t uniformsInfo[] =
{ "u_ViewInfo", GLSL_VEC4 },
{ "u_ViewOrigin", GLSL_VEC3 },
{ "u_LocalViewOrigin", GLSL_VEC3 },
{ "u_ViewForward", GLSL_VEC3 },
{ "u_ViewLeft", GLSL_VEC3 },
{ "u_ViewUp", GLSL_VEC3 },
@ -294,11 +298,9 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha
"#define alphaGen_t\n"
"#define AGEN_LIGHTING_SPECULAR %i\n"
"#define AGEN_PORTAL %i\n"
"#define AGEN_FRESNEL %i\n"
"#endif\n",
AGEN_LIGHTING_SPECULAR,
AGEN_PORTAL,
AGEN_FRESNEL));
AGEN_PORTAL));
Q_strcat(dest, size,
va("#ifndef texenv_t\n"
@ -526,9 +528,6 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int
#ifdef USE_VERT_TANGENT_SPACE
if(attribs & ATTR_TANGENT)
qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent");
if(attribs & ATTR_BITANGENT)
qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT, "attr_Bitangent");
#endif
if(attribs & ATTR_NORMAL)
@ -552,9 +551,6 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int
#ifdef USE_VERT_TANGENT_SPACE
if(attribs & ATTR_TANGENT2)
qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT2, "attr_Tangent2");
if(attribs & ATTR_BITANGENT2)
qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT2, "attr_Bitangent2");
#endif
GLSL_LinkProgram(program->program);
@ -813,7 +809,7 @@ void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_
qglUniform1fvARB(uniforms[uniformNum], 5, v);
}
void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix)
void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix)
{
GLint *uniforms = program->uniforms;
vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
@ -823,16 +819,16 @@ void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const mat
if (uniformsInfo[uniformNum].type != GLSL_MAT16)
{
ri.Printf( PRINT_WARNING, "GLSL_SetUniformMatrix16: wrong type for uniform %i in program %s\n", uniformNum, program->name);
ri.Printf( PRINT_WARNING, "GLSL_SetUniformMat4: wrong type for uniform %i in program %s\n", uniformNum, program->name);
return;
}
if (Matrix16Compare(matrix, compare))
if (Mat4Compare(matrix, compare))
{
return;
}
Matrix16Copy(matrix, compare);
Mat4Copy(matrix, compare);
qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
}
@ -907,7 +903,7 @@ void GLSL_InitGPUShaders(void)
if (i & GENERICDEF_USE_LIGHTMAP)
Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer))
Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n");
if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp))
@ -997,27 +993,19 @@ void GLSL_InitGPUShaders(void)
for (i = 0; i < LIGHTDEF_COUNT; i++)
{
int lightType = i & LIGHTDEF_LIGHTTYPE_MASK;
qboolean fastLight = !(r_normalMapping->integer || r_specularMapping->integer);
// skip impossible combos
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer)
continue;
if ((i & LIGHTDEF_USE_DELUXEMAP) && !r_deluxeMapping->integer)
if (!lightType && (i & LIGHTDEF_USE_PARALLAXMAP))
continue;
if ((i & LIGHTDEF_USE_CUBEMAP) && !r_cubeMapping->integer)
if (!lightType && (i & LIGHTDEF_USE_SHADOWMAP))
continue;
if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_USE_DELUXEMAP))
continue;
if (!(i & LIGHTDEF_LIGHTTYPE_MASK))
{
if (i & LIGHTDEF_USE_SHADOWMAP)
continue;
if (i & LIGHTDEF_USE_CUBEMAP)
continue;
}
attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL;
extradefines[0] = '\0';
@ -1026,30 +1014,30 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value));
if (r_specularIsMetallic->value)
Q_strcat(extradefines, 1024, va("#define SPECULAR_IS_METALLIC\n"));
Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n");
if (r_dlightMode->integer >= 2)
Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
if (1)
{
Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
}
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer))
Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n");
if (i & LIGHTDEF_LIGHTTYPE_MASK)
if (lightType)
{
Q_strcat(extradefines, 1024, "#define USE_LIGHT\n");
if (r_normalMapping->integer == 0 && r_specularMapping->integer == 0)
if (fastLight)
Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n");
switch (i & LIGHTDEF_LIGHTTYPE_MASK)
switch (lightType)
{
case LIGHTDEF_USE_LIGHTMAP:
Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
if (r_deluxeMapping->integer && !fastLight)
Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n");
attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION;
break;
case LIGHTDEF_USE_LIGHT_VECTOR:
@ -1062,7 +1050,6 @@ void GLSL_InitGPUShaders(void)
default:
break;
}
}
if (r_normalMapping->integer)
{
@ -1076,8 +1063,11 @@ void GLSL_InitGPUShaders(void)
#ifdef USE_VERT_TANGENT_SPACE
Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n");
attribs |= ATTR_TANGENT | ATTR_BITANGENT;
attribs |= ATTR_TANGENT;
#endif
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
}
if (r_specularMapping->integer)
@ -1109,14 +1099,9 @@ void GLSL_InitGPUShaders(void)
}
}
if ((i & LIGHTDEF_USE_DELUXEMAP) && r_deluxeMapping->integer)
Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n");
if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
if ((i & LIGHTDEF_USE_CUBEMAP))
if (r_cubeMapping->integer)
Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n");
}
if (i & LIGHTDEF_USE_SHADOWMAP)
{
@ -1142,7 +1127,7 @@ void GLSL_InitGPUShaders(void)
#ifdef USE_VERT_TANGENT_SPACE
if (r_normalMapping->integer)
{
attribs |= ATTR_TANGENT2 | ATTR_BITANGENT2;
attribs |= ATTR_TANGENT2;
}
#endif
}
@ -1409,12 +1394,10 @@ void GLSL_ShutdownGPUShaders(void)
qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
#ifdef USE_VERT_TANGENT_SPACE
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
#endif
qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
#ifdef USE_VERT_TANGENT_SPACE
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
#endif
qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
@ -1574,20 +1557,6 @@ void GLSL_VertexAttribsState(uint32_t stateBits)
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
}
}
if(diff & ATTR_BITANGENT)
{
if(stateBits & ATTR_BITANGENT)
{
GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
}
else
{
GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
}
}
#endif
if(diff & ATTR_COLOR)
@ -1660,20 +1629,6 @@ void GLSL_VertexAttribsState(uint32_t stateBits)
qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
}
}
if(diff & ATTR_BITANGENT2)
{
if(stateBits & ATTR_BITANGENT2)
{
GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
}
else
{
GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
}
}
#endif
glState.vertexAttribsState = stateBits;
@ -1683,26 +1638,30 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
qboolean animated;
int newFrame, oldFrame;
VBO_t *vbo = glState.currentVBO;
if(!glState.currentVBO)
if(!vbo)
{
ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound");
return;
}
// don't just call LogComment, or we will get a call to va() every frame!
GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", glState.currentVBO->name));
if(r_logFile->integer)
{
GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", vbo->name));
}
// position/normal/tangent/bitangent are always set in case of animation
// position/normal/tangent are always set in case of animation
oldFrame = glState.vertexAttribsOldFrame;
newFrame = glState.vertexAttribsNewFrame;
animated = (oldFrame != newFrame) && (glState.vertexAttribsInterpolation > 0.0f);
animated = glState.vertexAnimation;
if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n");
qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + newFrame * glState.currentVBO->size_xyz));
qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + newFrame * vbo->size_xyz));
glState.vertexAttribPointersSet |= ATTR_POSITION;
}
@ -1710,7 +1669,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n");
qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st));
qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, vbo->stride_st, BUFFER_OFFSET(vbo->ofs_st));
glState.vertexAttribPointersSet |= ATTR_TEXCOORD;
}
@ -1718,7 +1677,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n");
qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, glState.currentVBO->stride_lightmap, BUFFER_OFFSET(glState.currentVBO->ofs_lightmap));
qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, vbo->stride_lightmap, BUFFER_OFFSET(vbo->ofs_lightmap));
glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD;
}
@ -1726,7 +1685,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n");
qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + newFrame * glState.currentVBO->size_normal));
qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + newFrame * vbo->size_normal));
glState.vertexAttribPointersSet |= ATTR_NORMAL;
}
@ -1735,24 +1694,16 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n");
qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + newFrame * glState.currentVBO->size_normal)); // FIXME
qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + newFrame * vbo->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_TANGENT;
}
if((attribBits & ATTR_BITANGENT) && (!(glState.vertexAttribPointersSet & ATTR_BITANGENT) || animated))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT )\n");
qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + newFrame * glState.currentVBO->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_BITANGENT;
}
#endif
if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n");
qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, glState.currentVBO->stride_vertexcolor, BUFFER_OFFSET(glState.currentVBO->ofs_vertexcolor));
qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, vbo->stride_vertexcolor, BUFFER_OFFSET(vbo->ofs_vertexcolor));
glState.vertexAttribPointersSet |= ATTR_COLOR;
}
@ -1760,7 +1711,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n");
qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 3, GL_FLOAT, 0, glState.currentVBO->stride_lightdir, BUFFER_OFFSET(glState.currentVBO->ofs_lightdir));
qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_lightdir, BUFFER_OFFSET(vbo->ofs_lightdir));
glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION;
}
@ -1768,7 +1719,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n");
qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + oldFrame * glState.currentVBO->size_xyz));
qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + oldFrame * vbo->size_xyz));
glState.vertexAttribPointersSet |= ATTR_POSITION2;
}
@ -1776,7 +1727,7 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n");
qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + oldFrame * glState.currentVBO->size_normal));
qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + oldFrame * vbo->size_normal));
glState.vertexAttribPointersSet |= ATTR_NORMAL2;
}
@ -1785,17 +1736,9 @@ void GLSL_VertexAttribPointers(uint32_t attribBits)
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n");
qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + oldFrame * glState.currentVBO->size_normal)); // FIXME
qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + oldFrame * vbo->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_TANGENT2;
}
if((attribBits & ATTR_BITANGENT2) && (!(glState.vertexAttribPointersSet & ATTR_BITANGENT2) || animated))
{
GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT2 )\n");
qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + oldFrame * glState.currentVBO->size_normal)); // FIXME
glState.vertexAttribPointersSet |= ATTR_BITANGENT2;
}
#endif
}
@ -1829,7 +1772,6 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL:
case AGEN_FRESNEL:
shaderAttribs |= GENERICDEF_USE_RGBAGEN;
break;
default:
@ -1846,7 +1788,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
}
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
if (glState.vertexAnimation)
{
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
}

View file

@ -2303,6 +2303,9 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT
qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
if (image->flags & IMGFLAG_MIPMAP)
qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
image->uploadWidth = width;
image->uploadHeight = height;
}
@ -2872,9 +2875,6 @@ void R_CreateBuiltinImages( void ) {
Com_Memset( data, 255, sizeof( data ) );
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, 0);
Com_Memset( data, 128, sizeof( data ) );
tr.greyImage = R_CreateImage("*grey", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, GL_RGBA8);
if (r_dlightMode->integer >= 2)
{
for( x = 0; x < MAX_DLIGHTS; x++)
@ -2922,7 +2922,7 @@ void R_CreateBuiltinImages( void ) {
hdrFormat = GL_RGBA8;
if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
hdrFormat = GL_RGB16F_ARB;
hdrFormat = GL_RGBA16F_ARB;
rgbFormat = GL_RGBA8;
@ -2931,9 +2931,6 @@ void R_CreateBuiltinImages( void ) {
if (r_drawSunRays->integer)
tr.sunRaysImage = R_CreateImage("*sunRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, rgbFormat);
if (r_softOverbright->integer)
tr.screenScratchImage = R_CreateImage("*screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, rgbFormat);
if (glRefConfig.framebufferObject)
{
tr.renderDepthImage = R_CreateImage("*renderdepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
@ -2944,7 +2941,7 @@ void R_CreateBuiltinImages( void ) {
unsigned short sdata[4];
void *p;
if (hdrFormat == GL_RGB16F_ARB)
if (hdrFormat == GL_RGBA16F_ARB)
{
sdata[0] = FloatToHalf(0.0f);
sdata[1] = FloatToHalf(0.45f);
@ -2975,26 +2972,35 @@ void R_CreateBuiltinImages( void ) {
tr.quarterImage[x] = R_CreateImage(va("*quarter%d", x), NULL, width / 2, height / 2, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
}
tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
if (r_ssao->integer)
{
tr.screenSsaoImage = R_CreateImage("*screenSsao", NULL, width / 2, height / 2, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
tr.hdrDepthImage = R_CreateImage("*hdrDepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_INTENSITY32F_ARB);
}
if (r_shadows->integer == 4)
{
for( x = 0; x < MAX_DRAWN_PSHADOWS; x++)
{
tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
}
}
if (r_sunlightMode->integer)
{
for ( x = 0; x < 3; x++)
{
tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
}
tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
}
if (r_cubeMapping->integer)
{
tr.renderCubeImage = R_CreateImage("*renderCube", NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat);
}
}
}

View file

@ -100,6 +100,8 @@ cvar_t *r_ext_framebuffer_object;
cvar_t *r_ext_texture_float;
cvar_t *r_arb_half_float_pixel;
cvar_t *r_ext_framebuffer_multisample;
cvar_t *r_arb_seamless_cube_map;
cvar_t *r_arb_vertex_type_2_10_10_10_rev;
cvar_t *r_mergeMultidraws;
cvar_t *r_mergeLeafSurfaces;
@ -109,6 +111,7 @@ cvar_t *r_cameraExposure;
cvar_t *r_softOverbright;
cvar_t *r_hdr;
cvar_t *r_floatLightmap;
cvar_t *r_postProcess;
cvar_t *r_toneMap;
@ -156,6 +159,7 @@ cvar_t *r_shadowMapSize;
cvar_t *r_shadowCascadeZNear;
cvar_t *r_shadowCascadeZFar;
cvar_t *r_shadowCascadeZBias;
cvar_t *r_ignoreDstAlpha;
cvar_t *r_ignoreGLErrors;
cvar_t *r_logFile;
@ -950,16 +954,6 @@ void GL_SetDefaultState( void )
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
qglClearDepth( 1.0 );
qglDrawBuffer( GL_FRONT );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
qglDrawBuffer( GL_BACK );
qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
if (glRefConfig.seamlessCubeMap)
qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
@ -1133,6 +1127,8 @@ void R_Register( void )
r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
"0", CVAR_ARCHIVE | CVAR_LATCH );
@ -1153,7 +1149,7 @@ void R_Register( void )
r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH );
r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE);
r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH );
r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH );
r_customPixelAspect = ri.Cvar_Get( "r_customPixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
@ -1168,6 +1164,7 @@ void R_Register( void )
r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );
@ -1219,6 +1216,7 @@ void R_Register( void )
r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", CVAR_ARCHIVE | CVAR_LATCH );
r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", CVAR_ARCHIVE | CVAR_LATCH );
r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", CVAR_ARCHIVE | CVAR_LATCH );
r_ignoreDstAlpha = ri.Cvar_Get( "r_ignoreDstAlpha", "1", CVAR_ARCHIVE | CVAR_LATCH );
//
// temporary latched variables that can only change over a restart

View file

@ -94,12 +94,17 @@ void R_DlightBmodel( bmodel_t *bmodel ) {
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
surf = tr.world->surfaces + bmodel->firstSurface + i;
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->dlightBits = mask;
switch(*surf->data)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
case SF_VBO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = mask;
break;
default:
break;
}
}
}
@ -403,8 +408,11 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
((byte *)&ent->ambientLightInt)[3] = 0xff;
// transform the direction to local space
// no need to do this if using lightentity glsl shader
VectorNormalize( lightDir );
ent->modelLightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
ent->modelLightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
ent->modelLightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
VectorCopy(lightDir, ent->lightDir);
}

View file

@ -47,10 +47,6 @@ typedef unsigned int glIndex_t;
#define SHADERNUM_BITS 14
#define MAX_SHADERS (1<<SHADERNUM_BITS)
//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32
#define MAX_FBOS 64
#define MAX_VISCOUNTS 5
#define MAX_VBOS 4096
@ -84,7 +80,8 @@ typedef struct {
qboolean needDlights; // true for bmodels that touch a dlight
qboolean lightingCalculated;
qboolean mirrored; // mirrored matrix, needs reversed culling
vec3_t lightDir; // normalized direction towards light
vec3_t lightDir; // normalized direction towards light, in world space
vec3_t modelLightDir; // normalized direction towards light, in model space
vec3_t ambientLight; // color normalized to 0-255
int ambientLightInt; // 32 bit rgba packed
vec3_t directedLight;
@ -119,7 +116,6 @@ typedef struct VBO_s
uint32_t ofs_lightdir;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t ofs_tangent;
uint32_t ofs_bitangent;
#endif
uint32_t stride_xyz;
uint32_t stride_normal;
@ -129,7 +125,6 @@ typedef struct VBO_s
uint32_t stride_lightdir;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t stride_tangent;
uint32_t stride_bitangent;
#endif
uint32_t size_xyz;
uint32_t size_normal;
@ -241,7 +236,6 @@ typedef enum {
AGEN_WAVEFORM,
AGEN_PORTAL,
AGEN_CONST,
AGEN_FRESNEL
} alphaGen_t;
typedef enum {
@ -354,7 +348,6 @@ typedef struct {
int videoMapHandle;
qboolean isLightmap;
qboolean vertexLightmap;
qboolean isVideoMap;
} textureBundle_t;
@ -486,16 +479,8 @@ typedef struct shader_s {
float clampTime; // time this shader is clamped to
float timeOffset; // current time offset for this shader
int numStates; // if non-zero this is a state shader
struct shader_s *currentShader; // current state if this is a state shader
struct shader_s *parentShader; // current state if this is a state shader
int currentState; // current state index for cycle purposes
long expireTime; // time in milliseconds this expires
struct shader_s *remappedShader; // current shader this one is remapped too
int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
struct shader_s *next;
} shader_t;
@ -522,110 +507,23 @@ static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader)
return qfalse;
}
typedef struct shaderState_s {
char shaderName[MAX_QPATH]; // name of shader this state belongs to
char name[MAX_STATE_NAME]; // name of this state
char stateShader[MAX_QPATH]; // shader this name invokes
int cycleTime; // time this cycle lasts, <= 0 is forever
shader_t *shader;
} shaderState_t;
enum
{
ATTR_INDEX_POSITION = 0,
ATTR_INDEX_TEXCOORD0 = 1,
ATTR_INDEX_TEXCOORD1 = 2,
ATTR_INDEX_TANGENT = 3,
ATTR_INDEX_BITANGENT = 4,
ATTR_INDEX_NORMAL = 5,
ATTR_INDEX_COLOR = 6,
ATTR_INDEX_PAINTCOLOR = 7,
ATTR_INDEX_LIGHTDIRECTION = 8,
ATTR_INDEX_BONE_INDEXES = 9,
ATTR_INDEX_BONE_WEIGHTS = 10,
ATTR_INDEX_NORMAL = 4,
ATTR_INDEX_COLOR = 5,
ATTR_INDEX_PAINTCOLOR = 6,
ATTR_INDEX_LIGHTDIRECTION = 7,
ATTR_INDEX_BONE_INDEXES = 8,
ATTR_INDEX_BONE_WEIGHTS = 9,
// GPU vertex animations
ATTR_INDEX_POSITION2 = 11,
ATTR_INDEX_TANGENT2 = 12,
ATTR_INDEX_BITANGENT2 = 13,
ATTR_INDEX_NORMAL2 = 14
};
enum
{
GLS_SRCBLEND_ZERO = (1 << 0),
GLS_SRCBLEND_ONE = (1 << 1),
GLS_SRCBLEND_DST_COLOR = (1 << 2),
GLS_SRCBLEND_ONE_MINUS_DST_COLOR = (1 << 3),
GLS_SRCBLEND_SRC_ALPHA = (1 << 4),
GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA = (1 << 5),
GLS_SRCBLEND_DST_ALPHA = (1 << 6),
GLS_SRCBLEND_ONE_MINUS_DST_ALPHA = (1 << 7),
GLS_SRCBLEND_ALPHA_SATURATE = (1 << 8),
GLS_SRCBLEND_BITS = GLS_SRCBLEND_ZERO
| GLS_SRCBLEND_ONE
| GLS_SRCBLEND_DST_COLOR
| GLS_SRCBLEND_ONE_MINUS_DST_COLOR
| GLS_SRCBLEND_SRC_ALPHA
| GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA
| GLS_SRCBLEND_DST_ALPHA
| GLS_SRCBLEND_ONE_MINUS_DST_ALPHA
| GLS_SRCBLEND_ALPHA_SATURATE,
GLS_DSTBLEND_ZERO = (1 << 9),
GLS_DSTBLEND_ONE = (1 << 10),
GLS_DSTBLEND_SRC_COLOR = (1 << 11),
GLS_DSTBLEND_ONE_MINUS_SRC_COLOR = (1 << 12),
GLS_DSTBLEND_SRC_ALPHA = (1 << 13),
GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA = (1 << 14),
GLS_DSTBLEND_DST_ALPHA = (1 << 15),
GLS_DSTBLEND_ONE_MINUS_DST_ALPHA = (1 << 16),
GLS_DSTBLEND_BITS = GLS_DSTBLEND_ZERO
| GLS_DSTBLEND_ONE
| GLS_DSTBLEND_SRC_COLOR
| GLS_DSTBLEND_ONE_MINUS_SRC_COLOR
| GLS_DSTBLEND_SRC_ALPHA
| GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA
| GLS_DSTBLEND_DST_ALPHA
| GLS_DSTBLEND_ONE_MINUS_DST_ALPHA,
GLS_DEPTHMASK_TRUE = (1 << 17),
GLS_POLYMODE_LINE = (1 << 18),
GLS_DEPTHTEST_DISABLE = (1 << 19),
GLS_DEPTHFUNC_LESS = (1 << 20),
GLS_DEPTHFUNC_EQUAL = (1 << 21),
GLS_DEPTHFUNC_BITS = GLS_DEPTHFUNC_LESS
| GLS_DEPTHFUNC_EQUAL,
GLS_ATEST_GT_0 = (1 << 22),
GLS_ATEST_LT_128 = (1 << 23),
GLS_ATEST_GE_128 = (1 << 24),
// GLS_ATEST_GE_CUSTOM = (1 << 25),
GLS_ATEST_BITS = GLS_ATEST_GT_0
| GLS_ATEST_LT_128
| GLS_ATEST_GE_128,
// | GLS_ATEST_GT_CUSTOM,
GLS_REDMASK_FALSE = (1 << 26),
GLS_GREENMASK_FALSE = (1 << 27),
GLS_BLUEMASK_FALSE = (1 << 28),
GLS_ALPHAMASK_FALSE = (1 << 29),
GLS_COLORMASK_BITS = GLS_REDMASK_FALSE
| GLS_GREENMASK_FALSE
| GLS_BLUEMASK_FALSE
| GLS_ALPHAMASK_FALSE,
GLS_STENCILTEST_ENABLE = (1 << 30),
GLS_DEFAULT = GLS_DEPTHMASK_TRUE
ATTR_INDEX_POSITION2 = 10,
ATTR_INDEX_TANGENT2 = 11,
ATTR_INDEX_NORMAL2 = 12
};
enum
@ -634,26 +532,23 @@ enum
ATTR_TEXCOORD = 0x0002,
ATTR_LIGHTCOORD = 0x0004,
ATTR_TANGENT = 0x0008,
ATTR_BITANGENT = 0x0010,
ATTR_NORMAL = 0x0020,
ATTR_COLOR = 0x0040,
ATTR_PAINTCOLOR = 0x0080,
ATTR_LIGHTDIRECTION = 0x0100,
ATTR_BONE_INDEXES = 0x0200,
ATTR_BONE_WEIGHTS = 0x0400,
ATTR_NORMAL = 0x0010,
ATTR_COLOR = 0x0020,
ATTR_PAINTCOLOR = 0x0040,
ATTR_LIGHTDIRECTION = 0x0080,
ATTR_BONE_INDEXES = 0x0100,
ATTR_BONE_WEIGHTS = 0x0200,
// for .md3 interpolation
ATTR_POSITION2 = 0x0800,
ATTR_TANGENT2 = 0x1000,
ATTR_BITANGENT2 = 0x2000,
ATTR_NORMAL2 = 0x4000,
ATTR_POSITION2 = 0x0400,
ATTR_TANGENT2 = 0x0800,
ATTR_NORMAL2 = 0x1000,
ATTR_DEFAULT = ATTR_POSITION,
ATTR_BITS = ATTR_POSITION |
ATTR_TEXCOORD |
ATTR_LIGHTCOORD |
ATTR_TANGENT |
ATTR_BITANGENT |
ATTR_NORMAL |
ATTR_COLOR |
ATTR_PAINTCOLOR |
@ -662,7 +557,6 @@ enum
ATTR_BONE_WEIGHTS |
ATTR_POSITION2 |
ATTR_TANGENT2 |
ATTR_BITANGENT2 |
ATTR_NORMAL2
};
@ -701,12 +595,10 @@ enum
LIGHTDEF_LIGHTTYPE_MASK = 0x0003,
LIGHTDEF_ENTITY = 0x0004,
LIGHTDEF_USE_TCGEN_AND_TCMOD = 0x0008,
LIGHTDEF_USE_DELUXEMAP = 0x0010,
LIGHTDEF_USE_PARALLAXMAP = 0x0020,
LIGHTDEF_USE_SHADOWMAP = 0x0040,
LIGHTDEF_USE_CUBEMAP = 0x0080,
LIGHTDEF_ALL = 0x00FF,
LIGHTDEF_COUNT = 0x0100
LIGHTDEF_USE_PARALLAXMAP = 0x0010,
LIGHTDEF_USE_SHADOWMAP = 0x0020,
LIGHTDEF_ALL = 0x003F,
LIGHTDEF_COUNT = 0x0040
};
enum
@ -743,6 +635,8 @@ typedef enum
UNIFORM_SHADOWMVP2,
UNIFORM_SHADOWMVP3,
UNIFORM_ENABLETEXTURES,
UNIFORM_DIFFUSETEXMATRIX,
UNIFORM_DIFFUSETEXOFFTURB,
UNIFORM_TEXTURE1ENV,
@ -765,6 +659,7 @@ typedef enum
UNIFORM_LIGHTUP,
UNIFORM_LIGHTRIGHT,
UNIFORM_LIGHTORIGIN,
UNIFORM_MODELLIGHTDIR,
UNIFORM_LIGHTRADIUS,
UNIFORM_AMBIENTLIGHT,
UNIFORM_DIRECTEDLIGHT,
@ -785,6 +680,7 @@ typedef enum
UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
UNIFORM_VIEWORIGIN,
UNIFORM_LOCALVIEWORIGIN,
UNIFORM_VIEWFORWARD,
UNIFORM_VIEWLEFT,
UNIFORM_VIEWUP,
@ -951,7 +847,6 @@ typedef enum {
SF_TRIANGLES,
SF_POLY,
SF_MDV,
SF_MD4,
SF_MDR,
SF_IQM,
SF_FLARE,
@ -1005,8 +900,7 @@ typedef struct
vec2_t lightmap;
vec3_t normal;
#ifdef USE_VERT_TANGENT_SPACE
vec3_t tangent;
vec3_t bitangent;
vec4_t tangent;
#endif
vec3_t lightdir;
vec4_t vertexColors;
@ -1017,22 +911,13 @@ typedef struct
} srfVert_t;
#ifdef USE_VERT_TANGENT_SPACE
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#else
#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
#endif
typedef struct
{
int indexes[3];
int neighbors[3];
vec4_t plane;
qboolean facingLight;
qboolean degenerated;
} srfTriangle_t;
typedef struct srfGridMesh_s
// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH
typedef struct srfBspSurface_s
{
surfaceType_t surfaceType;
@ -1041,9 +926,30 @@ typedef struct srfGridMesh_s
int pshadowBits;
// culling information
vec3_t meshBounds[2];
vec3_t localOrigin;
float meshRadius;
vec3_t cullBounds[2];
vec3_t cullOrigin;
float cullRadius;
cplane_t cullPlane;
// indexes
int numIndexes;
glIndex_t *indexes;
// vertexes
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo;
IBO_t *ibo;
// SF_GRID specific variables after here
// lod information, which may be different
// than the culling information to allow for
@ -1057,85 +963,7 @@ typedef struct srfGridMesh_s
int width, height;
float *widthLodError;
float *heightLodError;
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfGridMesh_t;
typedef struct
{
surfaceType_t surfaceType;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
cplane_t plane;
// vec3_t bounds[2];
// triangle definitions
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfSurfaceFace_t;
// misc_models in maps are turned into direct geometry by xmap
typedef struct
{
surfaceType_t surfaceType;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
// vec3_t bounds[2];
// triangle definitions
int numTriangles;
srfTriangle_t *triangles;
int numVerts;
srfVert_t *verts;
// BSP VBO offsets
int firstVert;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo; // points to bsp model VBO
IBO_t *ibo;
} srfTriangles_t;
} srfBspSurface_t;
// inter-quake-model
typedef struct {
@ -1144,6 +972,7 @@ typedef struct {
int num_frames;
int num_surfaces;
int num_joints;
int num_poses;
struct srfIQModel_s *surfaces;
float *positions;
@ -1151,10 +980,18 @@ typedef struct {
float *normals;
float *tangents;
byte *blendIndexes;
byte *blendWeights;
union {
float *f;
byte *b;
} blendWeights;
byte *colors;
int *triangles;
// 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 *jointParents;
float *jointMats;
float *poseMats;
@ -1172,33 +1009,6 @@ typedef struct srfIQModel_s {
int first_triangle, num_triangles;
} srfIQModel_t;
typedef struct srfVBOMesh_s
{
surfaceType_t surfaceType;
struct shader_s *shader; // FIXME move this to somewhere else
int fogIndex;
int cubemapIndex;
// dynamic lighting information
int dlightBits;
int pshadowBits;
// culling information
vec3_t bounds[2];
// backEnd stats
int numIndexes;
int numVerts;
int firstIndex;
glIndex_t minIndex;
glIndex_t maxIndex;
// static render data
VBO_t *vbo;
IBO_t *ibo;
} srfVBOMesh_t;
typedef struct srfVBOMDVMesh_s
{
surfaceType_t surfaceType;
@ -1332,9 +1142,6 @@ typedef struct {
int numDecisionNodes;
mnode_t *nodes;
VBO_t *vbo;
IBO_t *ibo;
int numWorldSurfaces;
int numsurfaces;
@ -1426,8 +1233,8 @@ typedef struct mdvSurface_s
mdvVertex_t *verts;
mdvSt_t *st;
int numTriangles;
srfTriangle_t *triangles;
int numIndexes;
glIndex_t *indexes;
struct mdvModel_s *model;
} mdvSurface_t;
@ -1457,7 +1264,6 @@ typedef enum {
MOD_BAD,
MOD_BRUSH,
MOD_MESH,
MOD_MD4,
MOD_MDR,
MOD_IQM
} modtype_t;
@ -1470,7 +1276,7 @@ typedef struct model_s {
int dataSize; // just for listing purposes
bmodel_t *bmodel; // only if type == MOD_BRUSH
mdvModel_t *mdv[MD3_MAX_LODS]; // only if type == MOD_MESH
void *modelData; // only if type == (MOD_MD4 | MOD_MDR | MOD_IQM)
void *modelData; // only if type == (MOD_MDR | MOD_IQM)
int numLods;
} model_t;
@ -1564,13 +1370,14 @@ typedef struct {
uint32_t vertexAttribsNewFrame;
uint32_t vertexAttribsOldFrame;
float vertexAttribsInterpolation;
qboolean vertexAnimation;
shaderProgram_t *currentProgram;
FBO_t *currentFBO;
VBO_t *currentVBO;
IBO_t *currentIBO;
matrix_t modelview;
matrix_t projection;
matrix_t modelviewProjection;
mat4_t modelview;
mat4_t projection;
mat4_t modelviewProjection;
} glstate_t;
typedef enum {
@ -1616,6 +1423,8 @@ typedef struct {
qboolean depthClamp;
qboolean seamlessCubeMap;
GLenum packedNormalDataType;
} glRefConfig_t;
@ -1708,7 +1517,6 @@ typedef struct {
image_t *fogImage;
image_t *dlightImage; // inverse-quare highlight for projective adding
image_t *flareImage;
image_t *greyImage; // full of 0x80
image_t *whiteImage; // full of 0xff
image_t *identityLightImage; // full of tr.identityLightByte
@ -1720,7 +1528,6 @@ typedef struct {
image_t *renderDepthImage;
image_t *pshadowMaps[MAX_DRAWN_PSHADOWS];
image_t *textureScratchImage[2];
image_t *screenScratchImage;
image_t *quarterImage[2];
image_t *calcLevelsImage;
image_t *targetLevelsImage;
@ -1739,7 +1546,6 @@ typedef struct {
FBO_t *depthFbo;
FBO_t *pshadowFbos[MAX_DRAWN_PSHADOWS];
FBO_t *textureScratchFbo[2];
FBO_t *screenScratchFbo;
FBO_t *quarterFbo[2];
FBO_t *calcLevelsFbo;
FBO_t *targetLevelsFbo;
@ -1915,6 +1721,8 @@ extern cvar_t *r_ext_framebuffer_object;
extern cvar_t *r_ext_texture_float;
extern cvar_t *r_arb_half_float_pixel;
extern cvar_t *r_ext_framebuffer_multisample;
extern cvar_t *r_arb_seamless_cube_map;
extern cvar_t *r_arb_vertex_type_2_10_10_10_rev;
extern cvar_t *r_nobind; // turns off binding to appropriate textures
extern cvar_t *r_singleShader; // make most world faces use default shader
@ -1958,6 +1766,7 @@ extern cvar_t *r_mergeLeafSurfaces;
extern cvar_t *r_softOverbright;
extern cvar_t *r_hdr;
extern cvar_t *r_floatLightmap;
extern cvar_t *r_postProcess;
extern cvar_t *r_toneMap;
@ -2007,6 +1816,7 @@ extern cvar_t *r_shadowMapSize;
extern cvar_t *r_shadowCascadeZNear;
extern cvar_t *r_shadowCascadeZFar;
extern cvar_t *r_shadowCascadeZBias;
extern cvar_t *r_ignoreDstAlpha;
extern cvar_t *r_greyscale;
@ -2052,8 +1862,6 @@ void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2);
qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles);
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts);
#define CULL_IN 0 // completely unclipped
#define CULL_CLIP 1 // clipped by one or more planes
@ -2080,8 +1888,8 @@ void GL_TextureMode( const char *string );
void GL_CheckErrs( char *file, int line );
#define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__)
void GL_State( unsigned long stateVector );
void GL_SetProjectionMatrix(matrix_t matrix);
void GL_SetModelviewMatrix(matrix_t matrix);
void GL_SetProjectionMatrix(mat4_t matrix);
void GL_SetModelviewMatrix(mat4_t matrix);
void GL_TexEnv( int env );
void GL_Cull( int cullType );
@ -2202,14 +2010,13 @@ typedef struct shaderCommands_s
{
glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16);
vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16);
uint32_t normal[SHADER_MAX_VERTEXES] QALIGN(16);
#ifdef USE_VERT_TANGENT_SPACE
vec4_t tangent[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t bitangent[SHADER_MAX_VERTEXES] QALIGN(16);
uint32_t tangent[SHADER_MAX_VERTEXES] QALIGN(16);
#endif
vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16);
vec4_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16);
vec4_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16);
uint32_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16);
//int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);
VBO_t *vbo;
@ -2348,11 +2155,11 @@ CURVE TESSELATION
#define PATCH_STITCHING
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] );
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror );
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror );
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid );
srfBspSurface_t *R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror );
srfBspSurface_t *R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror );
void R_FreeSurfaceGridMesh( srfBspSurface_t *grid );
/*
============================================================
@ -2373,11 +2180,17 @@ VERTEX BUFFER OBJECTS
============================================================
*/
uint32_t R_VboPackTangent(vec4_t v);
uint32_t R_VboPackNormal(vec3_t v);
void R_VboUnpackTangent(vec4_t v, uint32_t b);
void R_VboUnpackNormal(vec3_t v, uint32_t b);
VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage);
VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes, uint32_t stateBits, vboUsage_t usage);
IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage);
IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage);
IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes, vboUsage_t usage);
void R_BindVBO(VBO_t * vbo);
void R_BindNullVBO(void);
@ -2413,7 +2226,7 @@ void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_
void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v);
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_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix);
void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix);
shaderProgram_t *GLSL_GetGenericShaderProgram(int stage);
@ -2463,11 +2276,8 @@ ANIMATED MODELS
=============================================================
*/
// void R_MakeAnimModel( model_t *model ); haven't seen this one really, so not needed I guess.
void R_AddAnimSurfaces( trRefEntity_t *ent );
void RB_SurfaceAnim( md4Surface_t *surfType );
void R_MDRAddAnimSurfaces( trRefEntity_t *ent );
void RB_MDRSurfaceAnim( md4Surface_t *surface );
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 );
@ -2499,35 +2309,18 @@ void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t
void RB_DeformTessGeometry( void );
void RB_CalcEnvironmentTexCoords( float *dstTexCoords );
void RB_CalcFogTexCoords( float *dstTexCoords );
void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords );
void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords );
void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords );
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords );
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords );
void RB_CalcScaleTexMatrix( const float scale[2], float *matrix );
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix );
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix );
void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix );
void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now );
void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix );
void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix );
void RB_CalcModulateColorsByFog( unsigned char *dstColors );
void RB_CalcModulateAlphasByFog( unsigned char *dstColors );
void RB_CalcModulateRGBAsByFog( unsigned char *dstColors );
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors );
float RB_CalcWaveAlphaSingle( const waveForm_t *wf );
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors );
float RB_CalcWaveColorSingle( const waveForm_t *wf );
void RB_CalcAlphaFromEntity( unsigned char *dstColors );
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords );
void RB_CalcColorFromEntity( unsigned char *dstColors );
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors );
void RB_CalcSpecularAlpha( unsigned char *alphas );
void RB_CalcDiffuseColor( unsigned char *colors );
/*
=============================================================

View file

@ -454,6 +454,8 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
/* do each vertex */
for(i = 0; i < 3; i++)
{
vec3_t bitangent, nxt;
// calculate s tangent vector
s = dv[i]->st[0] + 10.0f;
t = dv[i]->st[1];
@ -475,12 +477,16 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
dv[i]->bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
dv[i]->bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
dv[i]->bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
VectorSubtract(dv[i]->bitangent, dv[i]->xyz, dv[i]->bitangent);
VectorNormalize(dv[i]->bitangent);
VectorSubtract(bitangent, dv[i]->xyz, bitangent);
VectorNormalize(bitangent);
// store bitangent handedness
CrossProduct(dv[i]->normal, dv[i]->tangent, nxt);
dv[i]->tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
// debug code
//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
@ -492,99 +498,6 @@ qboolean R_CalcTangentVectors(srfVert_t * dv[3])
#endif
/*
=================
R_FindSurfaceTriangleWithEdge
Recoded from Q2E
=================
*/
static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore)
{
srfTriangle_t *tri;
int count, match;
int i;
count = 0;
match = -1;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
if((tri->indexes[0] == start && tri->indexes[1] == end) ||
(tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end))
{
if(i != ignore)
{
match = i;
}
count++;
}
else if((tri->indexes[1] == start && tri->indexes[0] == end) ||
(tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end))
{
count++;
}
}
// detect edges shared by three triangles and make them seams
if(count > 2)
{
match = -1;
}
return match;
}
/*
=================
R_CalcSurfaceTriangleNeighbors
Recoded from Q2E
=================
*/
void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i);
tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i);
tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i);
}
}
/*
=================
R_CalcSurfaceTrianglePlanes
=================
*/
void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts)
{
int i;
srfTriangle_t *tri;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
{
float *v1, *v2, *v3;
vec3_t d1, d2;
v1 = verts[tri->indexes[0]].xyz;
v2 = verts[tri->indexes[1]].xyz;
v3 = verts[tri->indexes[2]].xyz;
VectorSubtract(v2, v1, d1);
VectorSubtract(v3, v1, d2);
CrossProduct(d2, d1, tri->plane);
tri->plane[3] = DotProduct(tri->plane, v1);
}
}
/*
=================
R_CullLocalBox
@ -927,7 +840,7 @@ void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms,
glMatrix[11] = 0;
glMatrix[15] = 1;
Matrix16Copy(glMatrix, or->transformMatrix);
Mat4Copy(glMatrix, or->transformMatrix);
myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix );
// calculate the viewer origin in the model's space
@ -1365,7 +1278,7 @@ R_PlaneForSurface
=============
*/
void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
srfTriangles_t *tri;
srfBspSurface_t *tri;
srfPoly_t *poly;
srfVert_t *v1, *v2, *v3;
vec4_t plane4;
@ -1377,13 +1290,13 @@ void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
}
switch (*surfType) {
case SF_FACE:
*plane = ((srfSurfaceFace_t *)surfType)->plane;
*plane = ((srfBspSurface_t *)surfType)->cullPlane;
return;
case SF_TRIANGLES:
tri = (srfTriangles_t *)surfType;
v1 = tri->verts + tri->triangles[0].indexes[0];
v2 = tri->verts + tri->triangles[0].indexes[1];
v3 = tri->verts + tri->triangles[0].indexes[2];
tri = (srfBspSurface_t *)surfType;
v1 = tri->verts + tri->indexes[0];
v2 = tri->verts + tri->indexes[1];
v3 = tri->verts + tri->indexes[2];
PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz );
VectorCopy( plane4, plane->normal );
plane->dist = plane4[3];
@ -1649,7 +1562,8 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
for ( i = 0; i < tess.numIndexes; i += 3 )
{
vec3_t normal;
vec3_t normal, tNormal;
float len;
VectorSubtract( tess.xyz[tess.indexes[i]], tr.viewParms.or.origin, normal );
@ -1660,7 +1574,9 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
shortest = len;
}
if ( DotProduct( normal, tess.normal[tess.indexes[i]] ) >= 0 )
R_VboUnpackNormal(tNormal, tess.normal[tess.indexes[i]]);
if ( DotProduct( normal, tNormal ) >= 0 )
{
numTriangles--;
}
@ -1997,9 +1913,6 @@ static void R_AddEntitySurface (int entityNum)
case MOD_MESH:
R_AddMD3Surfaces( ent );
break;
case MOD_MD4:
R_AddAnimSurfaces( ent );
break;
case MOD_MDR:
R_MDRAddAnimSurfaces( ent );
break;
@ -2286,12 +2199,6 @@ void R_RenderPshadowMaps(const refdef_t *fd)
}
break;
case MOD_MD4:
{
// FIXME: actually calculate the radius and bounds, this is a horrible hack
radius = r_pshadowDist->value / 2.0f;
}
break;
case MOD_MDR:
{
// FIXME: never actually tested this
@ -2716,7 +2623,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
// Create bounds for light projection using slice of view projection
{
matrix_t lightViewMatrix;
mat4_t lightViewMatrix;
vec4_t point, base, lightViewPoint;
float lx, ly;
@ -2724,7 +2631,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
point[3] = 1;
lightViewPoint[3] = 1;
Matrix16View(lightViewAxis, lightOrigin, lightViewMatrix);
Mat4View(lightViewAxis, lightOrigin, lightViewMatrix);
ClearBounds(lightviewBounds[0], lightviewBounds[1]);
@ -2735,22 +2642,22 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
@ -2761,22 +2668,22 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
VectorMA(base, -lx, fd->viewaxis[1], point);
VectorMA(point, -ly, fd->viewaxis[2], point);
Matrix16Transform(lightViewMatrix, point, lightViewPoint);
Mat4Transform(lightViewMatrix, point, lightViewPoint);
AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
if (!glRefConfig.depthClamp)
@ -2874,7 +2781,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level)
R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
}
Matrix16Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]);
Mat4Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]);
}
}
@ -2944,7 +2851,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
// FIXME: sun shadows aren't rendered correctly in cubemaps
// fix involves changing r_FBufScale to fit smaller cubemap image size, or rendering cubemap to framebuffer first
if(0) //(glRefConfig.framebufferObject && (r_forceSun->integer || tr.sunShadows))
if(0) //(glRefConfig.framebufferObject && r_sunlightMode->integer && (r_forceSun->integer || tr.sunShadows))
{
R_RenderSunShadowMaps(&refdef, 0);
R_RenderSunShadowMaps(&refdef, 1);

View file

@ -268,8 +268,8 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
int numClipPoints;
float *v;
srfGridMesh_t *cv;
srfTriangle_t *tri;
srfBspSurface_t *cv;
glIndex_t *tri;
srfVert_t *dv;
vec3_t normal;
vec3_t projectionDir;
@ -327,7 +327,7 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
if (*surfaces[i] == SF_GRID) {
cv = (srfGridMesh_t *) surfaces[i];
cv = (srfBspSurface_t *) surfaces[i];
for ( m = 0 ; m < cv->height - 1 ; m++ ) {
for ( n = 0 ; n < cv->width - 1 ; n++ ) {
// We triangulate the grid and chop all triangles within
@ -407,19 +407,19 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
}
else if (*surfaces[i] == SF_FACE) {
srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i];
srfBspSurface_t *surf = ( srfBspSurface_t * ) surfaces[i];
// check the normal of this face
if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
if (DotProduct(surf->cullPlane.normal, projectionDir) > -0.5) {
continue;
}
for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
for(k = 0, tri = surf->indexes; k < surf->numIndexes; k += 3, tri += 3)
{
for(j = 0; j < 3; j++)
{
v = surf->verts[tri->indexes[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
v = surf->verts[tri[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->cullPlane.normal, clipPoints[0][j]);
}
// add the fragments of this face
@ -435,14 +435,14 @@ int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projectio
}
else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) {
srfTriangles_t *surf = (srfTriangles_t *) surfaces[i];
srfBspSurface_t *surf = (srfBspSurface_t *) surfaces[i];
for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
for(k = 0, tri = surf->indexes; k < surf->numIndexes; k += 3, tri += 3)
{
for(j = 0; j < 3; j++)
{
v = surf->verts[tri->indexes[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->verts[tri->indexes[j]].normal, clipPoints[0][j]);
v = surf->verts[tri[j]].xyz;
VectorMA(v, MARKER_OFFSET, surf->verts[tri[j]].normal, clipPoints[0][j]);
}
// add the fragments of this face

View file

@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName);
static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name );
static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name );
/*
@ -73,15 +72,10 @@ qhandle_t R_RegisterMD3(const char *name, model_t *mod)
continue;
ident = LittleLong(* (unsigned *) buf.u);
if (ident == MD4_IDENT)
loaded = R_LoadMD4(mod, buf.u, name);
else
{
if (ident == MD3_IDENT)
loaded = R_LoadMD3(mod, lod, buf.u, size, name);
else
ri.Printf(PRINT_WARNING,"R_RegisterMD3: unknown fileid for %s\n", name);
}
ri.FS_FreeFile(buf.v);
@ -201,7 +195,6 @@ static modelExtToLoaderMap_t modelLoaders[ ] =
{
{ "iqm", R_RegisterIQM },
{ "mdr", R_RegisterMDR },
{ "md4", R_RegisterMD3 },
{ "md3", R_RegisterMD3 }
};
@ -394,7 +387,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
mdvFrame_t *frame;
mdvSurface_t *surf;//, *surface;
int *shaderIndex;
srfTriangle_t *tri;
glIndex_t *tri;
mdvVertex_t *v;
mdvSt_t *st;
mdvTag_t *tag;
@ -551,19 +544,17 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
}
// swap all the triangles
surf->numTriangles = md3Surf->numTriangles;
surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * md3Surf->numTriangles, h_low);
surf->numIndexes = md3Surf->numTriangles * 3;
surf->indexes = tri = ri.Hunk_Alloc(sizeof(*tri) * 3 * md3Surf->numTriangles, h_low);
md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles);
for(j = 0; j < md3Surf->numTriangles; j++, tri++, md3Tri++)
for(j = 0; j < md3Surf->numTriangles; j++, tri += 3, md3Tri++)
{
tri->indexes[0] = LittleLong(md3Tri->indexes[0]);
tri->indexes[1] = LittleLong(md3Tri->indexes[1]);
tri->indexes[2] = LittleLong(md3Tri->indexes[2]);
tri[0] = LittleLong(md3Tri->indexes[0]);
tri[1] = LittleLong(md3Tri->indexes[1]);
tri[2] = LittleLong(md3Tri->indexes[2]);
}
R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);
// swap all the XyzNormals
surf->numVerts = md3Surf->numVerts;
surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low);
@ -625,15 +616,15 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
for(f = 0; f < mdvModel->numFrames; f++)
{
for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++)
for(j = 0, tri = surf->indexes; j < surf->numIndexes; j += 3, tri += 3)
{
v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz;
v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz;
v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz;
v0 = surf->verts[surf->numVerts * f + tri[0]].xyz;
v1 = surf->verts[surf->numVerts * f + tri[1]].xyz;
v2 = surf->verts[surf->numVerts * f + tri[2]].xyz;
t0 = surf->st[tri->indexes[0]].st;
t1 = surf->st[tri->indexes[1]].st;
t2 = surf->st[tri->indexes[2]].st;
t0 = surf->st[tri[0]].st;
t1 = surf->st[tri[1]].st;
t2 = surf->st[tri[2]].st;
if (!r_recalcMD3Normals->integer)
VectorCopy(v->normal, normal);
@ -651,15 +642,15 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
{
float *v;
v = surf->verts[surf->numVerts * f + tri->indexes[k]].tangent;
v = surf->verts[surf->numVerts * f + tri[k]].tangent;
VectorAdd(v, tangent, v);
v = surf->verts[surf->numVerts * f + tri->indexes[k]].bitangent;
v = surf->verts[surf->numVerts * f + tri[k]].bitangent;
VectorAdd(v, bitangent, v);
if (r_recalcMD3Normals->integer)
{
v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal;
v = surf->verts[surf->numVerts * f + tri[k]].normal;
VectorAdd(v, normal, v);
}
}
@ -691,11 +682,10 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++)
{
vec3_t *verts;
vec3_t *normals;
vec2_t *texcoords;
uint32_t *normals;
#ifdef USE_VERT_TANGENT_SPACE
vec3_t *tangents;
vec3_t *bitangents;
uint32_t *tangents;
#endif
byte *data;
@ -703,7 +693,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
int ofs_xyz, ofs_normal, ofs_st;
#ifdef USE_VERT_TANGENT_SPACE
int ofs_tangent, ofs_bitangent;
int ofs_tangent;
#endif
dataSize = 0;
@ -717,9 +707,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
#ifdef USE_VERT_TANGENT_SPACE
ofs_tangent = dataSize;
dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*tangents);
ofs_bitangent = dataSize;
dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*bitangents);
#endif
ofs_st = dataSize;
@ -731,18 +718,24 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
normals = (void *)(data + ofs_normal);
#ifdef USE_VERT_TANGENT_SPACE
tangents = (void *)(data + ofs_tangent);
bitangents = (void *)(data + ofs_bitangent);
#endif
texcoords = (void *)(data + ofs_st);
v = surf->verts;
for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
{
vec3_t nxt;
vec4_t tangent;
VectorCopy(v->xyz, verts[j]);
VectorCopy(v->normal, normals[j]);
normals[j] = R_VboPackNormal(v->normal);
#ifdef USE_VERT_TANGENT_SPACE
VectorCopy(v->tangent, tangents[j]);
VectorCopy(v->bitangent, bitangents[j]);
CrossProduct(v->normal, v->tangent, nxt);
VectorCopy(v->tangent, tangent);
tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f;
tangents[j] = R_VboPackTangent(tangent);
#endif
}
@ -755,7 +748,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
vboSurf->surfaceType = SF_VBO_MDVMESH;
vboSurf->mdvModel = mdvModel;
vboSurf->mdvSurface = surf;
vboSurf->numIndexes = surf->numTriangles * 3;
vboSurf->numIndexes = surf->numIndexes;
vboSurf->numVerts = surf->numVerts;
vboSurf->minIndex = 0;
@ -767,7 +760,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
vboSurf->vbo->ofs_normal = ofs_normal;
#ifdef USE_VERT_TANGENT_SPACE
vboSurf->vbo->ofs_tangent = ofs_tangent;
vboSurf->vbo->ofs_bitangent = ofs_bitangent;
#endif
vboSurf->vbo->ofs_st = ofs_st;
@ -775,7 +767,6 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
vboSurf->vbo->stride_normal = sizeof(*normals);
#ifdef USE_VERT_TANGENT_SPACE
vboSurf->vbo->stride_tangent = sizeof(*tangents);
vboSurf->vbo->stride_bitangent = sizeof(*bitangents);
#endif
vboSurf->vbo->stride_st = sizeof(*st);
@ -784,7 +775,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize,
ri.Free(data);
vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC);
vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numIndexes, surf->indexes, VBO_USAGE_STATIC);
}
}
@ -836,7 +827,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
LL(pinmodel->ofsFrames);
// This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame
// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4.
// over and over again, we'll uncompress it in this function already, so we must adjust the size of the target mdr.
if(pinmodel->ofsFrames < 0)
{
// mdrFrame_t is larger than mdrCompFrame_t:
@ -1133,162 +1124,6 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char
return qtrue;
}
/*
=================
R_LoadMD4
=================
*/
static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
int i, j, k, lodindex;
md4Header_t *pinmodel, *md4;
md4Frame_t *frame;
md4LOD_t *lod;
md4Surface_t *surf;
md4Triangle_t *tri;
md4Vertex_t *v;
int version;
int size;
shader_t *sh;
int frameSize;
pinmodel = (md4Header_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != MD4_VERSION) {
ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n",
mod_name, version, MD4_VERSION);
return qfalse;
}
mod->type = MOD_MD4;
size = LittleLong(pinmodel->ofsEnd);
mod->dataSize += size;
mod->modelData = md4 = ri.Hunk_Alloc( size, h_low );
Com_Memcpy(md4, buffer, size);
LL(md4->ident);
LL(md4->version);
LL(md4->numFrames);
LL(md4->numBones);
LL(md4->numLODs);
LL(md4->ofsFrames);
LL(md4->ofsLODs);
md4->ofsEnd = size;
if ( md4->numFrames < 1 ) {
ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name );
return qfalse;
}
// we don't need to swap tags in the renderer, they aren't used
// swap all the frames
frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] );
for ( i = 0 ; i < md4->numFrames ; i++) {
frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize );
frame->radius = LittleFloat( frame->radius );
for ( j = 0 ; j < 3 ; j++ ) {
frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
}
for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) {
((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] );
}
}
// swap all the LOD's
lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs );
for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) {
// swap all the surfaces
surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces );
for ( i = 0 ; i < lod->numSurfaces ; i++) {
LL(surf->ident);
LL(surf->numTriangles);
LL(surf->ofsTriangles);
LL(surf->numVerts);
LL(surf->ofsVerts);
LL(surf->ofsEnd);
if ( surf->numVerts >= SHADER_MAX_VERTEXES ) {
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i verts on %s (%i).\n",
mod_name, SHADER_MAX_VERTEXES - 1, surf->name[0] ? surf->name : "a surface",
surf->numVerts );
return qfalse;
}
if ( surf->numTriangles*3 >= SHADER_MAX_INDEXES ) {
ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i triangles on %s (%i).\n",
mod_name, ( SHADER_MAX_INDEXES / 3 ) - 1, surf->name[0] ? surf->name : "a surface",
surf->numTriangles );
return qfalse;
}
// change to surface identifier
surf->ident = SF_MD4;
// lowercase the surface name so skin compares are faster
Q_strlwr( surf->name );
// register the shaders
sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
if ( sh->defaultShader ) {
surf->shaderIndex = 0;
} else {
surf->shaderIndex = sh->index;
}
// swap all the triangles
tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
LL(tri->indexes[0]);
LL(tri->indexes[1]);
LL(tri->indexes[2]);
}
// swap all the vertexes
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12);
v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts);
for ( j = 0 ; j < surf->numVerts ; j++ ) {
v->normal[0] = LittleFloat( v->normal[0] );
v->normal[1] = LittleFloat( v->normal[1] );
v->normal[2] = LittleFloat( v->normal[2] );
v->texCoords[0] = LittleFloat( v->texCoords[0] );
v->texCoords[1] = LittleFloat( v->texCoords[1] );
v->numWeights = LittleLong( v->numWeights );
for ( k = 0 ; k < v->numWeights ; k++ ) {
v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
}
// FIXME
// This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
// in for reference.
//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]);
}
// find the next surface
surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd );
}
// find the next LOD
lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd );
}
return qtrue;
}
//=============================================================================
@ -1311,11 +1146,6 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) {
RE_ClearScene();
tr.registered = qtrue;
// NOTE: this sucks, for some reason the first stretch pic is never drawn
// without this we'd see a white flash on a level load because the very
// first time the level shot would not be drawn
// RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0);
}
//=============================================================================
@ -1528,17 +1358,6 @@ void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
} else if (model->type == MOD_MD4) {
md4Header_t *header;
md4Frame_t *frame;
header = (md4Header_t *)model->modelData;
frame = (md4Frame_t *) ((byte *)header + header->ofsFrames);
VectorCopy( frame->bounds[0], mins );
VectorCopy( frame->bounds[1], maxs );
return;
} else if (model->type == MOD_MDR) {
mdrHeader_t *header;

View file

@ -25,6 +25,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define LL(x) x=LittleLong(x)
// 3x4 identity matrix
static float identityMatrix[12] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0
};
static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
int count,int size ) {
// return true if the range specified by offset, count and size
@ -143,6 +150,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData_t *iqmData;
srfIQModel_t *surface;
char meshName[MAX_QPATH];
byte blendIndexesType, blendWeightsType;
if( filesize < sizeof(iqmHeader_t) ) {
return qfalse;
@ -198,6 +206,8 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
return qfalse;
}
blendIndexesType = blendWeightsType = IQM_UBYTE;
// check and swap vertex arrays
if( IQM_CheckRange( header, header->ofs_vertexarrays,
header->num_vertexarrays,
@ -264,11 +274,20 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
break;
case IQM_BLENDINDEXES:
case IQM_BLENDWEIGHTS:
if( vertexarray->format != IQM_UBYTE ||
if( (vertexarray->format != IQM_INT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendIndexesType = vertexarray->format;
break;
case IQM_BLENDWEIGHTS:
if( (vertexarray->format != IQM_FLOAT &&
vertexarray->format != IQM_UBYTE) ||
vertexarray->size != 4 ) {
return qfalse;
}
blendWeightsType = vertexarray->format;
break;
case IQM_COLOR:
if( vertexarray->format != IQM_UBYTE ||
@ -343,7 +362,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
}
}
if( header->num_poses != header->num_joints ) {
if( header->num_poses != header->num_joints && header->num_poses != 0 ) {
ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has %d poses and %d joints, must have the same number or 0 poses\n",
mod_name, header->num_poses, header->num_joints );
return qfalse;
}
@ -379,7 +400,10 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
joint_names += strlen( (char *)header + header->ofs_text +
joint->name ) + 1;
}
}
if ( header->num_poses )
{
// check and swap poses
if( IQM_CheckRange( header, header->ofs_poses,
header->num_poses, sizeof(iqmPose_t) ) ) {
@ -438,7 +462,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size = sizeof(iqmData_t);
size += header->num_meshes * sizeof( srfIQModel_t );
size += header->num_joints * 12 * sizeof( float ); // joint mats
size += header->num_joints * header->num_frames * 12 * sizeof( float ); // pose mats
size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats
if(header->ofs_bounds)
size += header->num_frames * 6 * sizeof(float); // model bounds
size += header->num_vertexes * 3 * sizeof(float); // positions
@ -446,12 +470,18 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
size += header->num_vertexes * 3 * sizeof(float); // normals
size += header->num_vertexes * 4 * sizeof(float); // tangents
size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes
size += header->num_vertexes * 4 * sizeof(byte); // blendWeights
size += header->num_vertexes * 4 * sizeof(byte); // colors
size += header->num_joints * sizeof(int); // parents
size += header->num_triangles * 3 * sizeof(int); // triangles
size += joint_names; // joint names
// blendWeights
if (blendWeightsType == IQM_FLOAT) {
size += header->num_vertexes * 4 * sizeof(float);
} else {
size += header->num_vertexes * 4 * sizeof(byte);
}
mod->type = MOD_IQM;
iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
mod->modelData = iqmData;
@ -462,28 +492,40 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->num_frames = header->num_frames;
iqmData->num_surfaces = header->num_meshes;
iqmData->num_joints = header->num_joints;
iqmData->num_poses = header->num_poses;
iqmData->blendWeightsType = blendWeightsType;
iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
iqmData->jointMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
iqmData->poseMats = iqmData->jointMats + 12 * header->num_joints;
if(header->ofs_bounds)
{
iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
iqmData->bounds = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->positions = iqmData->bounds + 6 * header->num_frames;
}
else
iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
iqmData->positions = iqmData->poseMats + 12 * header->num_poses * header->num_frames;
iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes);
iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes;
if(blendWeightsType == IQM_FLOAT) {
iqmData->blendWeights.f = (float *)(iqmData->blendIndexes + 4 * header->num_vertexes);
iqmData->colors = (byte *)(iqmData->blendWeights.f + 4 * header->num_vertexes);
} else {
iqmData->blendWeights.b = iqmData->blendIndexes + 4 * header->num_vertexes;
iqmData->colors = iqmData->blendWeights.b + 4 * header->num_vertexes;
}
iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes);
iqmData->triangles = iqmData->jointParents + header->num_joints;
iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
if ( header->num_joints == 0 )
iqmData->jointMats = iqmData->poseMats = NULL;
iqmData->jointMats = NULL;
if ( header->num_poses == 0 )
iqmData->poseMats = NULL;
// calculate joint matrices and their inverses
// joint inverses are needed only until the pose matrices are calculated
@ -620,14 +662,27 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
n * sizeof(float) );
break;
case IQM_BLENDINDEXES:
if( blendIndexesType == IQM_INT ) {
int *data = (int*)((byte*)header + vertexarray->offset);
for ( j = 0; j < n; j++ ) {
iqmData->blendIndexes[j] = (byte)data[j];
}
} else {
Com_Memcpy( iqmData->blendIndexes,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_BLENDWEIGHTS:
Com_Memcpy( iqmData->blendWeights,
if( blendWeightsType == IQM_FLOAT ) {
Com_Memcpy( iqmData->blendWeights.f,
(byte *)header + vertexarray->offset,
n * sizeof(float) );
} else {
Com_Memcpy( iqmData->blendWeights.b,
(byte *)header + vertexarray->offset,
n * sizeof(byte) );
}
break;
case IQM_COLOR:
Com_Memcpy( iqmData->colors,
@ -895,9 +950,21 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
int *joint = data->jointParents;
int i;
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_joints * frame;
if ( data->num_poses == 0 ) {
for( i = 0; i < data->num_joints; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
identityMatrix, mat + 12*i );
} else {
Com_Memcpy( mat + 12*i, identityMatrix, 12 * sizeof(float) );
}
}
return;
}
if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_poses * frame;
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) {
Matrix34Multiply( mat + 12 * *joint,
mat1 + 12*i, mat + 12*i );
@ -906,10 +973,10 @@ static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
}
}
} else {
mat1 = data->poseMats + 12 * data->num_joints * frame;
mat2 = data->poseMats + 12 * data->num_joints * oldframe;
mat1 = data->poseMats + 12 * data->num_poses * frame;
mat2 = data->poseMats + 12 * data->num_poses * oldframe;
for( i = 0; i < data->num_joints; i++, joint++ ) {
for( i = 0; i < data->num_poses; i++, joint++ ) {
if( *joint >= 0 ) {
float tmpMat[12];
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
@ -957,7 +1024,10 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
int i;
vec4_t *outXYZ;
vec4_t *outNormal;
uint32_t *outNormal;
#ifdef USE_VERT_TANGENT_SPACE
uint32_t *outTangent;
#endif
vec2_t (*outTexCoord)[2];
vec4_t *outColor;
@ -973,11 +1043,14 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
outXYZ = &tess.xyz[tess.numVertexes];
outNormal = &tess.normal[tess.numVertexes];
#ifdef USE_VERT_TANGENT_SPACE
outTangent = &tess.tangent[tess.numVertexes];
#endif
outTexCoord = &tess.texCoords[tess.numVertexes];
outColor = &tess.vertexColors[tess.numVertexes];
// compute interpolated joint matrices
if ( data->num_joints > 0 ) {
if ( data->num_poses > 0 ) {
ComputePoseMats( data, frame, oldframe, backlerp, jointMats );
}
@ -988,28 +1061,31 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float vtxMat[12];
float nrmMat[9];
int vtx = i + surf->first_vertex;
float blendWeights[4];
int numWeights;
if ( data->num_joints == 0 || data->blendWeights[4*vtx] <= 0 ) {
// no blend joint, use identity matrix.
for( j = 0; j < 3; j++ ) {
for( k = 0; k < 4; k++ )
vtxMat[4*j+k] = ( k == j ) ? 1 : 0;
for ( numWeights = 0; numWeights < 4; numWeights++ ) {
if ( data->blendWeightsType == IQM_FLOAT )
blendWeights[numWeights] = data->blendWeights.f[4*vtx + numWeights];
else
blendWeights[numWeights] = (float)data->blendWeights.b[4*vtx + numWeights] / 255.0f;
if ( blendWeights[numWeights] <= 0 )
break;
}
if ( data->num_poses == 0 || numWeights == 0 ) {
// no blend joint, use identity matrix.
Com_Memcpy( vtxMat, identityMatrix, 12 * sizeof (float) );
} else {
// compute the vertex matrix by blending the up to
// four blend weights
for( k = 0; k < 12; k++ )
vtxMat[k] = data->blendWeights[4*vtx]
* jointMats[12*data->blendIndexes[4*vtx] + k];
for( j = 1; j < 4; j++ ) {
if( data->blendWeights[4*vtx + j] <= 0 )
break;
for( k = 0; k < 12; k++ )
vtxMat[k] += data->blendWeights[4*vtx + j]
* jointMats[12*data->blendIndexes[4*vtx + j] + k];
Com_Memset( vtxMat, 0, 12 * sizeof (float) );
for( j = 0; j < numWeights; j++ ) {
for( k = 0; k < 12; k++ ) {
vtxMat[k] += blendWeights[j] * jointMats[12*data->blendIndexes[4*vtx + j] + k];
}
}
for( k = 0; k < 12; k++ )
vtxMat[k] *= 1.0f / 255.0f;
}
// compute the normal matrix as transpose of the adjoint
@ -1046,19 +1122,25 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
vtxMat[11];
(*outXYZ)[3] = 1.0f;
(*outNormal)[0] =
nrmMat[ 0] * data->normals[3*vtx+0] +
nrmMat[ 1] * data->normals[3*vtx+1] +
nrmMat[ 2] * data->normals[3*vtx+2];
(*outNormal)[1] =
nrmMat[ 3] * data->normals[3*vtx+0] +
nrmMat[ 4] * data->normals[3*vtx+1] +
nrmMat[ 5] * data->normals[3*vtx+2];
(*outNormal)[2] =
nrmMat[ 6] * data->normals[3*vtx+0] +
nrmMat[ 7] * data->normals[3*vtx+1] +
nrmMat[ 8] * data->normals[3*vtx+2];
(*outNormal)[3] = 0.0f;
{
vec3_t normal;
vec4_t tangent;
normal[0] = DotProduct(&nrmMat[0], &data->normals[3*vtx]);
normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]);
normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]);
*outNormal = R_VboPackNormal(normal);
#ifdef USE_VERT_TANGENT_SPACE
tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]);
tangent[1] = DotProduct(&nrmMat[3], &data->tangents[4*vtx]);
tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]);
tangent[3] = data->tangents[4*vtx+3];
*outTangent++ = R_VboPackTangent(tangent);
#endif
}
(*outColor)[0] = data->colors[4*vtx+0] / 255.0f;
(*outColor)[1] = data->colors[4*vtx+1] / 255.0f;

View file

@ -22,9 +22,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_local.h"
void RB_ToneMap(FBO_t *hdrFbo, vec4i_t hdrBox, FBO_t *ldrFbo, vec4i_t ldrBox, int autoExposure)
void RB_ToneMap(FBO_t *hdrFbo, ivec4_t hdrBox, FBO_t *ldrFbo, ivec4_t ldrBox, int autoExposure)
{
vec4i_t srcBox, dstBox;
ivec4_t srcBox, dstBox;
vec4_t color;
static int lastFrameCount = 0;
@ -103,9 +103,9 @@ Blurs a part of one framebuffer to another.
Framebuffers can be identical.
=============
*/
void RB_BokehBlur(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, float blur)
void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float blur)
{
// vec4i_t srcBox, dstBox;
// ivec4_t srcBox, dstBox;
vec4_t color;
blur *= 10.0f;
@ -118,7 +118,7 @@ void RB_BokehBlur(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, float
// bokeh blur
if (blur > 0.0f)
{
vec4i_t quarterBox;
ivec4_t quarterBox;
quarterBox[0] = 0;
quarterBox[1] = tr.quarterFbo[0]->height;
@ -226,7 +226,7 @@ void RB_BokehBlur(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, float
static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha)
{
vec4i_t srcBox, dstBox;
ivec4_t srcBox, dstBox;
vec4_t color;
const float inc = 1.f / passes;
const float mul = powf(stretch, inc);
@ -255,10 +255,20 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretc
float s1 = iscale + s0;
float t1 = iscale + t0;
if (srcFbo)
{
srcBox[0] = s0 * srcFbo->width;
srcBox[1] = t0 * srcFbo->height;
srcBox[2] = (s1 - s0) * srcFbo->width;
srcBox[3] = (t1 - t0) * srcFbo->height;
}
else
{
srcBox[0] = s0 * glConfig.vidWidth;
srcBox[1] = t0 * glConfig.vidHeight;
srcBox[2] = (s1 - s0) * glConfig.vidWidth;
srcBox[3] = (t1 - t0) * glConfig.vidHeight;
}
FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
@ -298,7 +308,7 @@ static qboolean RB_UpdateSunFlareVis(void)
return sampleCount > 0;
}
void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox)
void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox)
{
vec4_t color;
float dot;
@ -306,7 +316,7 @@ void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox)
qboolean colorize = qtrue;
// float w, h, w2, h2;
matrix_t mvp;
mat4_t mvp;
vec4_t pos, hpos;
dot = DotProduct(tr.sunDirection, backEnd.viewParms.or.axis[0]);
@ -319,11 +329,11 @@ void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox)
// From RB_DrawSun()
{
float dist;
matrix_t trans, model, mvp;
mat4_t trans, model, mvp;
Matrix16Translation( backEnd.viewParms.or.origin, trans );
Matrix16Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
Matrix16Multiply(backEnd.viewParms.projectionMatrix, model, mvp);
Mat4Translation( backEnd.viewParms.or.origin, trans );
Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
Mat4Multiply(backEnd.viewParms.projectionMatrix, model, mvp);
dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
@ -331,8 +341,8 @@ void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox)
}
// project sun point
//Matrix16Multiply(backEnd.viewParms.projectionMatrix, backEnd.viewParms.world.modelMatrix, mvp);
Matrix16Transform(mvp, pos, hpos);
//Mat4Multiply(backEnd.viewParms.projectionMatrix, backEnd.viewParms.world.modelMatrix, mvp);
Mat4Transform(mvp, pos, hpos);
// transform to UV coords
hpos[3] = 0.5f / hpos[3];
@ -344,17 +354,27 @@ void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox)
{
float mul = 1.f;
vec2_t texScale;
vec4i_t rayBox, quarterBox;
ivec4_t rayBox, quarterBox;
texScale[0] =
texScale[1] = 1.0f;
VectorSet4(color, mul, mul, mul, 1);
if (srcFbo)
{
rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / srcFbo->width;
rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / srcFbo->height;
rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / srcFbo->width;
rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / srcFbo->height;
}
else
{
rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / glConfig.vidWidth;
rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / glConfig.vidHeight;
rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / glConfig.vidWidth;
rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / glConfig.vidHeight;
}
quarterBox[0] = 0;
quarterBox[1] = tr.quarterFbo[0]->height;
@ -421,7 +441,7 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean h
ymul *= strength;
{
vec4i_t srcBox, dstBox;
ivec4_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;
@ -470,7 +490,7 @@ void RB_GaussianBlur(float blur)
return;
{
vec4i_t srcBox, dstBox;
ivec4_t srcBox, dstBox;
vec4_t color;
vec2_t texScale;
@ -480,7 +500,7 @@ void RB_GaussianBlur(float blur)
VectorSet4(color, 1, 1, 1, 1);
// first, downsample the framebuffer
FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
// set the alpha channel
@ -498,6 +518,6 @@ void RB_GaussianBlur(float blur)
VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
color[3] = factor;
FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, NULL, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
}
}

View file

@ -25,9 +25,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tr_fbo.h"
void RB_ToneMap(FBO_t *hdrFbo, vec4i_t hdrBox, FBO_t *ldrFbo, vec4i_t ldrBox, int autoExposure);
void RB_BokehBlur(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, float blur);
void RB_SunRays(FBO_t *srcFbo, vec4i_t srcBox, FBO_t *dstFbo, vec4i_t dstBox);
void RB_ToneMap(FBO_t *hdrFbo, ivec4_t hdrBox, FBO_t *ldrFbo, ivec4_t ldrBox, int autoExposure);
void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float blur);
void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox);
void RB_GaussianBlur(float blur);
#endif

View file

@ -496,7 +496,7 @@ void RE_RenderScene( const refdef_t *fd ) {
}
// playing with even more shadows
if(glRefConfig.framebufferObject && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
{
R_RenderSunShadowMaps(fd, 0);
R_RenderSunShadowMaps(fd, 1);

View file

@ -44,9 +44,9 @@ R_DrawElements
void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex )
{
if (glRefConfig.drawRangeElements)
qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
else
qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)));
}
@ -148,7 +148,7 @@ static void DrawTris (shaderCommands_t *input) {
GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
VectorSet4(color, 1, 1, 1, 1);
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color);
@ -221,14 +221,22 @@ extern float EvalWaveForm( const waveForm_t *wf );
extern float EvalWaveFormClamped( const waveForm_t *wf );
static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outmatrix)
static void ComputeTexMods( shaderStage_t *pStage, int bundleNum, float *outMatrix, float *outOffTurb)
{
int tm;
float matrix[16], currentmatrix[16];
float matrix[6], currentmatrix[6];
textureBundle_t *bundle = &pStage->bundle[bundleNum];
Matrix16Identity(outmatrix);
Matrix16Identity(currentmatrix);
matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = 0.0f;
matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = 0.0f;
currentmatrix[0] = 1.0f; currentmatrix[2] = 0.0f; currentmatrix[4] = 0.0f;
currentmatrix[1] = 0.0f; currentmatrix[3] = 1.0f; currentmatrix[5] = 0.0f;
outMatrix[0] = 1.0f; outMatrix[2] = 0.0f;
outMatrix[1] = 0.0f; outMatrix[3] = 1.0f;
outOffTurb[0] = 0.0f; outOffTurb[1] = 0.0f; outOffTurb[2] = 0.0f; outOffTurb[3] = 0.0f;
for ( tm = 0; tm < bundle->numTexMods ; tm++ ) {
switch ( bundle->texMods[tm].type )
@ -239,59 +247,73 @@ static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outma
break;
case TMOD_TURBULENT:
RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave,
matrix );
outmatrix[12] = matrix[12];
outmatrix[13] = matrix[13];
Matrix16Copy(outmatrix, currentmatrix);
RB_CalcTurbulentFactors(&bundle->texMods[tm].wave, &outOffTurb[2], &outOffTurb[3]);
break;
case TMOD_ENTITY_TRANSLATE:
RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, matrix );
break;
case TMOD_SCROLL:
RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_SCALE:
RB_CalcScaleTexMatrix( bundle->texMods[tm].scale,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_STRETCH:
RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_TRANSFORM:
RB_CalcTransformTexMatrix( &bundle->texMods[tm],
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
case TMOD_ROTATE:
RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed,
matrix );
Matrix16Multiply(matrix, currentmatrix, outmatrix);
Matrix16Copy(outmatrix, currentmatrix);
break;
default:
ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name );
break;
}
switch ( bundle->texMods[tm].type )
{
case TMOD_NONE:
case TMOD_TURBULENT:
default:
break;
case TMOD_ENTITY_TRANSLATE:
case TMOD_SCROLL:
case TMOD_SCALE:
case TMOD_STRETCH:
case TMOD_TRANSFORM:
case TMOD_ROTATE:
outMatrix[0] = matrix[0] * currentmatrix[0] + matrix[2] * currentmatrix[1];
outMatrix[1] = matrix[1] * currentmatrix[0] + matrix[3] * currentmatrix[1];
outMatrix[2] = matrix[0] * currentmatrix[2] + matrix[2] * currentmatrix[3];
outMatrix[3] = matrix[1] * currentmatrix[2] + matrix[3] * currentmatrix[3];
outOffTurb[0] = matrix[0] * currentmatrix[4] + matrix[2] * currentmatrix[5] + matrix[4];
outOffTurb[1] = matrix[1] * currentmatrix[4] + matrix[3] * currentmatrix[5] + matrix[5];
currentmatrix[0] = outMatrix[0];
currentmatrix[1] = outMatrix[1];
currentmatrix[2] = outMatrix[2];
currentmatrix[3] = outMatrix[3];
currentmatrix[4] = outOffTurb[0];
currentmatrix[5] = outOffTurb[1];
break;
}
}
}
@ -370,7 +392,7 @@ static void ProjectDlightTexture( void ) {
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -421,46 +443,29 @@ static void ProjectDlightTexture( void ) {
}
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor )
static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend )
{
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
//
// rgbGen
//
switch ( pStage->rgbGen )
{
case CGEN_IDENTITY:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_IDENTITY_LIGHTING:
baseColor[0] =
baseColor[1] =
baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_EXACT_VERTEX:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 0.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 1.0f;
break;
case CGEN_EXACT_VERTEX_LIT:
baseColor[0] =
baseColor[1] =
@ -477,11 +482,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[1] = pStage->constantColor[1] / 255.0f;
baseColor[2] = pStage->constantColor[2] / 255.0f;
baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_VERTEX:
baseColor[0] =
@ -509,12 +509,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[0] =
baseColor[1] =
baseColor[2] = tr.identityLight;
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] = -tr.identityLight;
vertColor[3] = 0.0f;
break;
case CGEN_FOG:
{
@ -527,22 +525,11 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_WAVEFORM:
baseColor[0] =
baseColor[1] =
baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_ENTITY:
if (backEnd.currentEntity)
@ -552,11 +539,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_ONE_MINUS_ENTITY:
if (backEnd.currentEntity)
@ -566,23 +548,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
}
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
case CGEN_IDENTITY:
case CGEN_LIGHTING_DIFFUSE:
case CGEN_BAD:
baseColor[0] =
baseColor[1] =
baseColor[2] =
baseColor[3] = 1.0f;
vertColor[0] =
vertColor[1] =
vertColor[2] =
vertColor[3] = 0.0f;
break;
}
@ -593,10 +562,6 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
{
case AGEN_SKIP:
break;
case AGEN_IDENTITY:
baseColor[3] = 1.0f;
vertColor[3] = 0.0f;
break;
case AGEN_CONST:
baseColor[3] = pStage->constantColor[3] / 255.0f;
vertColor[3] = 0.0f;
@ -627,15 +592,32 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t
baseColor[3] = 1.0f;
vertColor[3] = -1.0f;
break;
case AGEN_IDENTITY:
case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL:
case AGEN_FRESNEL:
// Done entirely in vertex program
baseColor[3] = 1.0f;
vertColor[3] = 0.0f;
break;
}
// multiply color by overbrightbits if this isn't a blend
if (r_softOverbright->integer && tr.overbrightBits
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR)
&& !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR)
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR)
&& !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR))
{
float scale = 1 << tr.overbrightBits;
baseColor[0] *= scale;
baseColor[1] *= scale;
baseColor[2] *= scale;
vertColor[0] *= scale;
vertColor[1] *= scale;
vertColor[2] *= scale;
}
// FIXME: find some way to implement this.
#if 0
// if in greyscale rendering mode turn all color values into greyscale.
@ -749,7 +731,8 @@ static void ForwardDlight( void ) {
dlight_t *dl;
shaderProgram_t *sp;
vec4_t vector;
matrix_t matrix;
vec4_t texMatrix;
vec4_t texOffTurb;
if ( !( tess.dlightBits & ( 1 << l ) ) ) {
continue; // this surface definately doesn't have any of this light
@ -764,7 +747,7 @@ static void ForwardDlight( void ) {
{
int index = pStage->glslShaderIndex;
index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP);
index &= ~LIGHTDEF_LIGHTTYPE_MASK;
index |= LIGHTDEF_USE_LIGHT_VECTOR;
sp = &tr.lightallShader[index];
@ -774,8 +757,9 @@ static void ForwardDlight( void ) {
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -802,7 +786,7 @@ static void ForwardDlight( void ) {
vec4_t baseColor;
vec4_t vertColor;
ComputeShaderColors(pStage, baseColor, vertColor);
ComputeShaderColors(pStage, baseColor, vertColor, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor);
GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor);
@ -833,7 +817,7 @@ static void ForwardDlight( void ) {
// where they aren't rendered
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
if (pStage->bundle[TB_DIFFUSEMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP);
@ -851,13 +835,9 @@ static void ForwardDlight( void ) {
GL_SelectTexture(0);
}
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector);
VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
@ -914,7 +894,7 @@ static void ProjectPshadowVBOGLSL( void ) {
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
VectorCopy(origin, vector);
vector[3] = 1.0f;
@ -982,7 +962,7 @@ static void RB_FogPass( void ) {
if (deformGen != DGEN_NONE)
index |= FOGDEF_USE_DEFORM_VERTEXES;
if (glState.vertexAttribsInterpolation)
if (glState.vertexAnimation)
index |= FOGDEF_USE_VERTEX_ANIMATION;
sp = &tr.fogShader[index];
@ -994,7 +974,7 @@ static void RB_FogPass( void ) {
fog = tr.world->fogs + tess.fogNum;
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -1039,7 +1019,7 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
{
unsigned int vertexAttribs = input->shader->vertexAttribs;
if(glState.vertexAttribsInterpolation > 0.0f)
if(glState.vertexAnimation)
{
vertexAttribs |= ATTR_POSITION2;
if (vertexAttribs & ATTR_NORMAL)
@ -1047,7 +1027,6 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
vertexAttribs |= ATTR_NORMAL2;
#ifdef USE_VERT_TANGENT_SPACE
vertexAttribs |= ATTR_TANGENT2;
vertexAttribs |= ATTR_BITANGENT2;
#endif
}
}
@ -1058,7 +1037,6 @@ static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
int stage;
matrix_t matrix;
vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
float eyeT = 0;
@ -1074,6 +1052,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
{
shaderStage_t *pStage = input->xstages[stage];
shaderProgram_t *sp;
vec4_t texMatrix;
vec4_t texOffTurb;
if ( !pStage )
{
@ -1082,7 +1062,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
if (backEnd.depthFill)
{
if (pStage->glslShaderGroup)
if (pStage->glslShaderGroup == tr.lightallShader)
{
int index = 0;
@ -1107,7 +1087,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
}
if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
if (glState.vertexAnimation)
{
shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
}
@ -1120,7 +1100,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &tr.genericShader[shaderAttribs];
}
}
else if (pStage->glslShaderGroup)
else if (pStage->glslShaderGroup == tr.lightallShader)
{
int index = pStage->glslShaderIndex;
@ -1134,11 +1114,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
index |= LIGHTDEF_USE_SHADOWMAP;
}
if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && (index & LIGHTDEF_LIGHTTYPE_MASK) && input->cubemapIndex)
{
index |= LIGHTDEF_USE_CUBEMAP;
}
if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP)
{
index = LIGHTDEF_USE_LIGHTMAP;
@ -1146,11 +1121,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
sp = &pStage->glslShaderGroup[index];
if (pStage->glslShaderGroup == tr.lightallShader)
{
backEnd.pc.c_lightallDraws++;
}
}
else
{
sp = GLSL_GetGenericShaderProgram(stage);
@ -1160,8 +1132,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -1184,7 +1157,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
vec4_t baseColor;
vec4_t vertColor;
ComputeShaderColors(pStage, baseColor, vertColor);
ComputeShaderColors(pStage, baseColor, vertColor, pStage->stateBits);
if ((backEnd.refdef.colorScale != 1.0f) && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
{
@ -1210,6 +1183,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
VectorCopy(backEnd.currentEntity->lightDir, vec);
vec[3] = 0.0f;
GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec);
GLSL_SetUniformVec3(sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir);
GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f);
}
@ -1231,16 +1205,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask);
}
ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
{
vec4_t vector;
VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector);
VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector);
}
ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb );
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix);
GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb);
GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
if (pStage->bundle[0].tcGen == TCGEN_VECTOR)
@ -1253,7 +1220,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec);
}
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo);
@ -1269,11 +1236,12 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
}
else if ( pStage->glslShaderGroup )
else if ( pStage->glslShaderGroup == tr.lightallShader )
{
int i;
vec4_t enableTextures;
if ((backEnd.viewParms.flags & VPF_USESUNLIGHT) && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK))
if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK))
{
GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol);
@ -1281,18 +1249,15 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir);
}
VectorSet4(enableTextures, 0, 0, 0, 0);
if ((r_lightmap->integer == 1 || r_lightmap->integer == 2) && pStage->bundle[TB_LIGHTMAP].image[0])
{
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if (i == TB_LIGHTMAP)
{
R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
}
else if (pStage->bundle[i].image[0])
{
GL_BindToTMU( tr.whiteImage, i);
}
R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i);
else
GL_BindToTMU( tr.whiteImage, i );
}
}
else if (r_lightmap->integer == 3 && pStage->bundle[TB_DELUXEMAP].image[0])
@ -1300,25 +1265,62 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
{
if (i == TB_LIGHTMAP)
{
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
}
else if (pStage->bundle[i].image[0])
{
GL_BindToTMU( tr.whiteImage, i);
}
else
GL_BindToTMU( tr.whiteImage, i );
}
}
else
{
for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
qboolean light = (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) != 0;
qboolean fastLight = !(r_normalMapping->integer || r_specularMapping->integer);
if (pStage->bundle[TB_DIFFUSEMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP);
if (pStage->bundle[TB_LIGHTMAP].image[0])
R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], TB_LIGHTMAP);
// bind textures that are sampled and used in the glsl shader, and
// bind whiteImage to textures that are sampled but zeroed in the glsl shader
//
// alternatives:
// - use the last bound texture
// -> costs more to sample a higher res texture then throw out the result
// - disable texture sampling in glsl shader with #ifdefs, as before
// -> increases the number of shaders that must be compiled
//
if (light && !fastLight)
{
if (pStage->bundle[i].image[0])
if (pStage->bundle[TB_NORMALMAP].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP);
enableTextures[0] = 1.0f;
}
else if (r_normalMapping->integer)
GL_BindToTMU( tr.whiteImage, TB_NORMALMAP );
if (pStage->bundle[TB_DELUXEMAP].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], TB_DELUXEMAP);
enableTextures[1] = 1.0f;
}
else if (r_deluxeMapping->integer)
GL_BindToTMU( tr.whiteImage, TB_DELUXEMAP );
if (pStage->bundle[TB_SPECULARMAP].image[0])
{
R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP);
enableTextures[2] = 1.0f;
}
else if (r_specularMapping->integer)
GL_BindToTMU( tr.whiteImage, TB_SPECULARMAP );
}
enableTextures[3] = (r_cubeMapping->integer && !(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex) ? 1.0f : 0.0f;
}
GLSL_SetUniformVec4(sp, UNIFORM_ENABLETEXTURES, enableTextures);
}
else if ( pStage->bundle[1].image[0] != 0 )
{
@ -1340,11 +1342,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
//
// set state
//
if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
{
GL_BindToTMU( tr.whiteImage, 0 );
}
else
R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 );
GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0);
@ -1369,7 +1366,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
}
// allow skipping out to show just lightmaps during development
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )
{
break;
}
@ -1394,9 +1391,9 @@ static void RB_RenderShadowmap( shaderCommands_t *input )
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
@ -1555,8 +1552,8 @@ void RB_StageIteratorGeneric( void )
//
// pshadows!
//
if (glRefConfig.framebufferObject && tess.pshadowBits && tess.shader->sort <= SS_OPAQUE
&& !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
if (glRefConfig.framebufferObject && r_shadows->integer == 4 && tess.pshadowBits
&& tess.shader->sort <= SS_OPAQUE && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
ProjectPshadowVBOGLSL();
}

View file

@ -84,42 +84,16 @@ static float EvalWaveFormClamped( const waveForm_t *wf )
}
/*
** RB_CalcStretchTexCoords
** RB_CalcStretchTexMatrix
*/
void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
{
float p;
texModInfo_t tmi;
p = 1.0f / EvalWaveForm( wf );
tmi.matrix[0][0] = p;
tmi.matrix[1][0] = 0;
tmi.translate[0] = 0.5f - 0.5f * p;
tmi.matrix[0][1] = 0;
tmi.matrix[1][1] = p;
tmi.translate[1] = 0.5f - 0.5f * p;
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix )
{
float p;
texModInfo_t tmi;
p = 1.0f / EvalWaveForm( wf );
tmi.matrix[0][0] = p;
tmi.matrix[1][0] = 0;
tmi.translate[0] = 0.5f - 0.5f * p;
tmi.matrix[0][1] = 0;
tmi.matrix[1][1] = p;
tmi.translate[1] = 0.5f - 0.5f * p;
RB_CalcTransformTexMatrix( &tmi, matrix );
matrix[0] = p; matrix[2] = 0; matrix[4] = 0.5f - 0.5f * p;
matrix[1] = 0; matrix[3] = p; matrix[5] = 0.5f - 0.5f * p;
}
/*
@ -142,27 +116,27 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
vec3_t offset;
float scale;
float *xyz = ( float * ) tess.xyz;
float *normal = ( float * ) tess.normal;
uint32_t *normal = tess.normal;
float *table;
if ( ds->deformationWave.frequency == 0 )
{
scale = EvalWaveForm( &ds->deformationWave );
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
{
VectorScale( normal, scale, offset );
R_VboUnpackNormal(offset, *normal);
xyz[0] += offset[0];
xyz[1] += offset[1];
xyz[2] += offset[2];
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
xyz[2] += offset[2] * scale;
}
}
else
{
table = TableForFunc( ds->deformationWave.func );
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ )
{
float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
@ -171,11 +145,11 @@ void RB_CalcDeformVertexes( deformStage_t *ds )
ds->deformationWave.phase + off,
ds->deformationWave.frequency );
VectorScale( normal, scale, offset );
R_VboUnpackNormal(offset, *normal);
xyz[0] += offset[0];
xyz[1] += offset[1];
xyz[2] += offset[2];
xyz[0] += offset[0] * scale;
xyz[1] += offset[1] * scale;
xyz[2] += offset[2] * scale;
}
}
}
@ -191,25 +165,31 @@ void RB_CalcDeformNormals( deformStage_t *ds ) {
int i;
float scale;
float *xyz = ( float * ) tess.xyz;
float *normal = ( float * ) tess.normal;
uint32_t *normal = tess.normal;
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) {
vec3_t fNormal;
R_VboUnpackNormal(fNormal, *normal);
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
scale = 0.98f;
scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
tess.shaderTime * ds->deformationWave.frequency );
normal[ 0 ] += ds->deformationWave.amplitude * scale;
fNormal[ 0 ] += ds->deformationWave.amplitude * scale;
scale = 0.98f;
scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
tess.shaderTime * ds->deformationWave.frequency );
normal[ 1 ] += ds->deformationWave.amplitude * scale;
fNormal[ 1 ] += ds->deformationWave.amplitude * scale;
scale = 0.98f;
scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
tess.shaderTime * ds->deformationWave.frequency );
normal[ 2 ] += ds->deformationWave.amplitude * scale;
fNormal[ 2 ] += ds->deformationWave.amplitude * scale;
VectorNormalizeFast( normal );
VectorNormalizeFast( fNormal );
*normal = R_VboPackNormal(fNormal);
}
}
@ -223,22 +203,25 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) {
int i;
const float *st = ( const float * ) tess.texCoords[0];
float *xyz = ( float * ) tess.xyz;
float *normal = ( float * ) tess.normal;
uint32_t *normal = tess.normal;
float now;
now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) {
for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal++ ) {
int off;
float scale;
vec3_t fNormal;
R_VboUnpackNormal(fNormal, *normal);
off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight;
xyz[0] += normal[0] * scale;
xyz[1] += normal[1] * scale;
xyz[2] += normal[2] * scale;
xyz[0] += fNormal[0] * scale;
xyz[1] += fNormal[1] * scale;
xyz[2] += fNormal[2] * scale;
}
}
@ -288,11 +271,14 @@ void DeformText( const char *text ) {
float color[4];
float bottom, top;
vec3_t mid;
vec3_t fNormal;
height[0] = 0;
height[1] = 0;
height[2] = -1;
CrossProduct( tess.normal[0], height, width );
R_VboUnpackNormal(fNormal, tess.normal[0]);
CrossProduct( fNormal, height, width );
// find the midpoint of the box
VectorClear( mid );
@ -618,88 +604,6 @@ COLORS
*/
/*
** RB_CalcColorFromEntity
*/
void RB_CalcColorFromEntity( unsigned char *dstColors )
{
int i;
int *pColors = ( int * ) dstColors;
int c;
if ( !backEnd.currentEntity )
return;
c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = c;
}
}
/*
** RB_CalcColorFromOneMinusEntity
*/
void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
{
int i;
int *pColors = ( int * ) dstColors;
unsigned char invModulate[4];
int c;
if ( !backEnd.currentEntity )
return;
invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it
c = * ( int * ) invModulate;
for ( i = 0; i < tess.numVertexes; i++, pColors++ )
{
*pColors = c;
}
}
/*
** RB_CalcAlphaFromEntity
*/
void RB_CalcAlphaFromEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = backEnd.currentEntity->e.shaderRGBA[3];
}
}
/*
** RB_CalcAlphaFromOneMinusEntity
*/
void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
{
int i;
if ( !backEnd.currentEntity )
return;
dstColors += 3;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
*dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
}
}
/*
** RB_CalcWaveColorSingle
*/
@ -723,29 +627,6 @@ float RB_CalcWaveColorSingle( const waveForm_t *wf )
return glow;
}
/*
** RB_CalcWaveColor
*/
void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
int *colors = ( int * ) dstColors;
byte color[4];
glow = RB_CalcWaveColorSingle( wf );
v = ri.ftol(255 * glow);
color[0] = color[1] = color[2] = v;
color[3] = 255;
v = *(int *)color;
for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
*colors = v;
}
}
/*
** RB_CalcWaveAlphaSingle
*/
@ -754,25 +635,6 @@ float RB_CalcWaveAlphaSingle( const waveForm_t *wf )
return EvalWaveFormClamped( wf );
}
/*
** RB_CalcWaveAlpha
*/
void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
{
int i;
int v;
float glow;
glow = EvalWaveFormClamped( wf );
v = 255 * glow;
for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
{
dstColors[3] = v;
}
}
/*
** RB_CalcModulateColorsByFog
*/
@ -793,45 +655,6 @@ void RB_CalcModulateColorsByFog( unsigned char *colors ) {
}
}
/*
** RB_CalcModulateAlphasByFog
*/
void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[3] *= f;
}
}
/*
** RB_CalcModulateRGBAsByFog
*/
void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
int i;
float texCoords[SHADER_MAX_VERTEXES][2];
// calculate texcoords so we can derive density
// this is not wasted, because it would only have
// been previously called if the surface was opaque
RB_CalcFogTexCoords( texCoords[0] );
for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
colors[0] *= f;
colors[1] *= f;
colors[2] *= f;
colors[3] *= f;
}
}
/*
====================================================================
@ -928,118 +751,27 @@ void RB_CalcFogTexCoords( float *st ) {
}
}
/*
** RB_CalcEnvironmentTexCoords
** RB_CalcTurbulentFactors
*/
void RB_CalcEnvironmentTexCoords( float *st )
void RB_CalcTurbulentFactors( const waveForm_t *wf, float *amplitude, float *now )
{
int i;
float *v, *normal;
vec3_t viewer, reflected;
float d;
v = tess.xyz[0];
normal = tess.normal[0];
for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
{
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
VectorNormalizeFast (viewer);
d = DotProduct (normal, viewer);
reflected[0] = normal[0]*2*d - viewer[0];
reflected[1] = normal[1]*2*d - viewer[1];
reflected[2] = normal[2]*2*d - viewer[2];
st[0] = 0.5 + reflected[1] * 0.5;
st[1] = 0.5 - reflected[2] * 0.5;
}
*now = wf->phase + tess.shaderTime * wf->frequency;
*amplitude = wf->amplitude;
}
/*
** RB_CalcTurbulentTexCoords
** RB_CalcScaleTexMatrix
*/
void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
{
int i;
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
}
}
void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix )
{
float now;
now = ( wf->phase + tess.shaderTime * wf->frequency );
// bit of a hack here, hide amplitude and now in the matrix
// the vertex program will extract them and perform a turbulent pass last if it's nonzero
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
}
/*
** RB_CalcScaleTexCoords
*/
void RB_CalcScaleTexCoords( const float scale[2], float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] *= scale[0];
st[1] *= scale[1];
}
}
void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
{
matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
matrix[0] = scale[0]; matrix[2] = 0.0f; matrix[4] = 0.0f;
matrix[1] = 0.0f; matrix[3] = scale[1]; matrix[5] = 0.0f;
}
/*
** RB_CalcScrollTexCoords
** RB_CalcScrollTexMatrix
*/
void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
{
int i;
float timeScale = tess.shaderTime;
float adjustedScrollS, adjustedScrollT;
adjustedScrollS = scrollSpeed[0] * timeScale;
adjustedScrollT = scrollSpeed[1] * timeScale;
// clamp so coordinates don't continuously get larger, causing problems
// with hardware limits
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
st[0] += adjustedScrollS;
st[1] += adjustedScrollT;
}
}
void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
{
float timeScale = tess.shaderTime;
@ -1053,73 +785,28 @@ void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f;
matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = adjustedScrollS;
matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = adjustedScrollT;
}
/*
** RB_CalcTransformTexCoords
** RB_CalcTransformTexMatrix
*/
void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st )
{
int i;
for ( i = 0; i < tess.numVertexes; i++, st += 2 )
{
float s = st[0];
float t = st[1];
st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
}
}
void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix )
{
matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f;
matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f;
matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
matrix[0] = tmi->matrix[0][0]; matrix[2] = tmi->matrix[1][0]; matrix[4] = tmi->translate[0];
matrix[1] = tmi->matrix[0][1]; matrix[3] = tmi->matrix[1][1]; matrix[5] = tmi->translate[1];
}
/*
** RB_CalcRotateTexCoords
** RB_CalcRotateTexMatrix
*/
void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue;
tmi.matrix[1][0] = -sinValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexCoords( &tmi, st );
}
void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
{
float timeScale = tess.shaderTime;
float degs;
int index;
float sinValue, cosValue;
texModInfo_t tmi;
degs = -degsPerSecond * timeScale;
index = degs * ( FUNCTABLE_SIZE / 360.0f );
@ -1127,213 +814,6 @@ void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
tmi.matrix[0][0] = cosValue;
tmi.matrix[1][0] = -sinValue;
tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
tmi.matrix[0][1] = sinValue;
tmi.matrix[1][1] = cosValue;
tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
RB_CalcTransformTexMatrix( &tmi, matrix );
matrix[0] = cosValue; matrix[2] = -sinValue; matrix[4] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
matrix[1] = sinValue; matrix[3] = cosValue; matrix[5] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
}
/*
** RB_CalcSpecularAlpha
**
** Calculates specular coefficient and places it in the alpha channel
*/
vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically
void RB_CalcSpecularAlpha( unsigned char *alphas ) {
int i;
float *v, *normal;
vec3_t viewer, reflected;
float l, d;
int b;
vec3_t lightDir;
int numVertexes;
v = tess.xyz[0];
normal = tess.normal[0];
alphas += 3;
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
float ilength;
VectorSubtract( lightOrigin, v, lightDir );
// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
VectorNormalizeFast( lightDir );
// calculate the specular color
d = DotProduct (normal, lightDir);
// d *= ilength;
// we don't optimize for the d < 0 case since this tends to
// cause visual artifacts such as faceted "snapping"
reflected[0] = normal[0]*2*d - lightDir[0];
reflected[1] = normal[1]*2*d - lightDir[1];
reflected[2] = normal[2]*2*d - lightDir[2];
VectorSubtract (backEnd.or.viewOrigin, v, viewer);
ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
l = DotProduct (reflected, viewer);
l *= ilength;
if (l < 0) {
b = 0;
} else {
l = l*l;
l = l*l;
b = l * 255;
if (b > 255) {
b = 255;
}
}
*alphas = b;
}
}
/*
** RB_CalcDiffuseColor
**
** The basic vertex lighting calc
*/
#if idppc_altivec
static void RB_CalcDiffuseColor_altivec( unsigned char *colors )
{
int i;
float *v, *normal;
trRefEntity_t *ent;
int ambientLightInt;
vec3_t lightDir;
int numVertexes;
vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff);
vector float ambientLightVec;
vector float directedLightVec;
vector float lightDirVec;
vector float normalVec0, normalVec1;
vector float incomingVec0, incomingVec1, incomingVec2;
vector float zero, jVec;
vector signed int jVecInt;
vector signed short jVecShort;
vector unsigned char jVecChar, normalPerm;
ent = backEnd.currentEntity;
ambientLightInt = ent->ambientLightInt;
// A lot of this could be simplified if we made sure
// entities light info was 16-byte aligned.
jVecChar = vec_lvsl(0, ent->ambientLight);
ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
jVec = vec_ld(11, (vector float *)ent->ambientLight);
ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->directedLight);
directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
jVec = vec_ld(11,(vector float *)ent->directedLight);
directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
jVecChar = vec_lvsl(0, ent->lightDir);
lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
jVec = vec_ld(11,(vector float *)ent->lightDir);
lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
zero = (vector float)vec_splat_s8(0);
VectorCopy( ent->lightDir, lightDir );
v = tess.xyz[0];
normal = tess.normal[0];
normalPerm = vec_lvsl(0,normal);
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
normalVec0 = vec_ld(0,(vector float *)normal);
normalVec1 = vec_ld(11,(vector float *)normal);
normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
incomingVec2 = vec_add(incomingVec0,incomingVec1);
incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
incomingVec2 = vec_add(incomingVec2,incomingVec1);
incomingVec0 = vec_splat(incomingVec2,0);
incomingVec0 = vec_max(incomingVec0,zero);
normalPerm = vec_lvsl(12,normal);
jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
jVecInt = vec_cts(jVec,0); // RGBx
jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx
jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color
}
}
#endif
static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
{
int i, j;
float *v, *normal;
float incoming;
trRefEntity_t *ent;
int ambientLightInt;
vec3_t ambientLight;
vec3_t lightDir;
vec3_t directedLight;
int numVertexes;
ent = backEnd.currentEntity;
ambientLightInt = ent->ambientLightInt;
VectorCopy( ent->ambientLight, ambientLight );
VectorCopy( ent->directedLight, directedLight );
VectorCopy( ent->lightDir, lightDir );
v = tess.xyz[0];
normal = tess.normal[0];
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
incoming = DotProduct (normal, lightDir);
if ( incoming <= 0 ) {
*(int *)&colors[i*4] = ambientLightInt;
continue;
}
j = ri.ftol(ambientLight[0] + incoming * directedLight[0]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+0] = j;
j = ri.ftol(ambientLight[1] + incoming * directedLight[1]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+1] = j;
j = ri.ftol(ambientLight[2] + incoming * directedLight[2]);
if ( j > 255 ) {
j = 255;
}
colors[i*4+2] = j;
colors[i*4+3] = 255;
}
}
void RB_CalcDiffuseColor( unsigned char *colors )
{
#if idppc_altivec
if (com_altivec->integer) {
// must be in a seperate function or G3 systems will crash.
RB_CalcDiffuseColor_altivec( colors );
return;
}
#endif
RB_CalcDiffuseColor_scalar( colors );
}

View file

@ -203,10 +203,16 @@ static int NameToSrcBlendMode( const char *name )
}
else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
{
if (r_ignoreDstAlpha->integer)
return GLS_SRCBLEND_ONE;
return GLS_SRCBLEND_DST_ALPHA;
}
else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
{
if (r_ignoreDstAlpha->integer)
return GLS_SRCBLEND_ZERO;
return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
}
else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) )
@ -243,10 +249,16 @@ static int NameToDstBlendMode( const char *name )
}
else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
{
if (r_ignoreDstAlpha->integer)
return GLS_DSTBLEND_ONE;
return GLS_DSTBLEND_DST_ALPHA;
}
else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
{
if (r_ignoreDstAlpha->integer)
return GLS_DSTBLEND_ZERO;
return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
}
else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) )
@ -1109,10 +1121,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text )
shader.portalRange = atof( token );
}
}
else if ( !Q_stricmp( token, "fresnel" ) )
{
stage->alphaGen = AGEN_FRESNEL;
}
else
{
ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
@ -1951,7 +1959,7 @@ static void ComputeVertexAttribs(void)
#ifdef USE_VERT_TANGENT_SPACE
if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && !(r_normalMapping->integer == 0 && r_specularMapping->integer == 0))
{
shader.vertexAttribs |= ATTR_BITANGENT | ATTR_TANGENT;
shader.vertexAttribs |= ATTR_TANGENT;
}
#endif
@ -2011,7 +2019,6 @@ static void ComputeVertexAttribs(void)
switch(pStage->alphaGen)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_FRESNEL:
shader.vertexAttribs |= ATTR_NORMAL;
break;
@ -2213,7 +2220,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
//ri.Printf(PRINT_ALL, ", deluxemap");
diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex];
defs |= LIGHTDEF_USE_DELUXEMAP;
}
if (r_normalMapping->integer)
@ -2247,15 +2253,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
defs |= LIGHTDEF_USE_PARALLAXMAP;
}
}
if (!diffuse->bundle[TB_NORMALMAP].image[0])
{
// use 0x80 image, shader will interpret as (0,0,1)
diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0];
diffuse->bundle[TB_NORMALMAP].numImageAnimations = 0;
diffuse->bundle[TB_NORMALMAP].image[0] = tr.greyImage;
//ri.Printf(PRINT_ALL, ", normalmap %s", diffuse->bundle[TB_NORMALMAP].image[0]->imgName);
}
}
if (r_specularMapping->integer)
@ -2267,18 +2264,6 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse,
diffuse->materialInfo[0] = specular->materialInfo[0];
diffuse->materialInfo[1] = specular->materialInfo[1];
}
else if (lightmap || useLightVector || useLightVertex)
{
// use a white image, materialinfo will do the rest
diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0];
diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0;
diffuse->bundle[TB_SPECULARMAP].image[0] = tr.whiteImage;
if (!diffuse->materialInfo[0])
diffuse->materialInfo[0] = r_baseSpecular->value;
if (!diffuse->materialInfo[1])
diffuse->materialInfo[1] = r_baseGloss->value;
//ri.Printf(PRINT_ALL, ", specularmap %s", diffuse->bundle[TB_SPECULARMAP].image[0]->imgName);
}
}
if (tcgen || diffuse->bundle[0].numTexMods)
@ -2308,7 +2293,7 @@ static qboolean CollapseStagesToGLSL(void)
{
// if 2+ stages and first stage is lightmap, switch them
// this makes it easier for the later bits to process
if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active)
if (stages[0].active && stages[0].bundle[0].tcGen == TCGEN_LIGHTMAP && stages[1].active)
{
int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2345,7 +2330,7 @@ static qboolean CollapseStagesToGLSL(void)
break;
}
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
@ -2362,6 +2347,7 @@ static qboolean CollapseStagesToGLSL(void)
case TCGEN_TEXTURE:
case TCGEN_LIGHTMAP:
case TCGEN_ENVIRONMENT_MAPPED:
case TCGEN_VECTOR:
break;
default:
skip = qtrue;
@ -2372,7 +2358,6 @@ static qboolean CollapseStagesToGLSL(void)
{
case AGEN_LIGHTING_SPECULAR:
case AGEN_PORTAL:
case AGEN_FRESNEL:
skip = qtrue;
break;
default:
@ -2397,7 +2382,7 @@ static qboolean CollapseStagesToGLSL(void)
continue;
// skip lightmaps
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
continue;
diffuse = pStage;
@ -2439,7 +2424,7 @@ static qboolean CollapseStagesToGLSL(void)
break;
case ST_COLORMAP:
if (pStage2->bundle[0].isLightmap)
if (pStage2->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
lightmap = pStage2;
}
@ -2481,7 +2466,7 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active)
continue;
if (pStage->bundle[0].isLightmap)
if (pStage->bundle[0].tcGen == TCGEN_LIGHTMAP)
{
pStage->active = qfalse;
}
@ -2547,15 +2532,14 @@ static qboolean CollapseStagesToGLSL(void)
if (pStage->adjustColorsForFog)
continue;
if (pStage->bundle[TB_DIFFUSEMAP].isLightmap)
if (pStage->bundle[TB_DIFFUSEMAP].tcGen == TCGEN_LIGHTMAP)
{
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHTMAP;
if (r_deluxeMapping->integer && tr.worldDeluxeMapping)
pStage->glslShaderIndex |= LIGHTDEF_USE_DELUXEMAP;
pStage->bundle[TB_LIGHTMAP] = pStage->bundle[TB_DIFFUSEMAP];
pStage->bundle[TB_DIFFUSEMAP].image[0] = tr.whiteImage;
pStage->bundle[TB_DIFFUSEMAP].isLightmap = qfalse;
pStage->bundle[TB_DIFFUSEMAP].tcGen = TCGEN_TEXTURE;
}
}
}
@ -2577,11 +2561,14 @@ static qboolean CollapseStagesToGLSL(void)
{
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
if (pStage->bundle[0].tcGen != TCGEN_TEXTURE || pStage->bundle[0].numTexMods != 0)
pStage->glslShaderIndex |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
}
}
}
// convert any remaining lightingdiffuse stages to a lighting pass
// insert default material info if needed
for (i = 0; i < MAX_SHADER_STAGES; i++)
{
shaderStage_t *pStage = &stages[i];
@ -2589,13 +2576,20 @@ static qboolean CollapseStagesToGLSL(void)
if (!pStage->active)
continue;
if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE)
{
pStage->glslShaderGroup = tr.lightallShader;
pStage->glslShaderIndex = LIGHTDEF_USE_LIGHT_VECTOR;
}
}
if (pStage->glslShaderGroup != tr.lightallShader)
continue;
if ((pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) == 0)
continue;
if (!pStage->bundle[TB_SPECULARMAP].image[0] && r_specularMapping->integer)
{
if (!pStage->materialInfo[0])
pStage->materialInfo[0] = r_baseSpecular->value;
if (!pStage->materialInfo[1])
pStage->materialInfo[1] = r_baseGloss->value;
}
}
return numStages;
}

View file

@ -429,7 +429,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
color[0] =
color[1] =
@ -445,11 +445,11 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
color[0] =
color[1] =
color[2] = tr.identityLight * backEnd.refdef.colorScale;
color[2] = (r_softOverbright->integer ? 1.0 : tr.identityLight) * backEnd.refdef.colorScale;
color[3] = 1.0f;
GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, color);
@ -468,7 +468,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
R_DrawElementsVBO(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex);
//qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(GL_INDEX_TYPE)));
//qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t)));
//R_BindNullVBO();
//R_BindNullIBO();
@ -806,10 +806,10 @@ void RB_DrawSun( float scale, shader_t *shader ) {
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
{
// FIXME: this could be a lot cleaner
matrix_t translation, modelview;
mat4_t translation, modelview;
Matrix16Translation( backEnd.viewParms.or.origin, translation );
Matrix16Multiply( backEnd.viewParms.world.modelMatrix, translation, modelview );
Mat4Translation( backEnd.viewParms.or.origin, translation );
Mat4Multiply( backEnd.viewParms.world.modelMatrix, translation, modelview );
GL_SetModelviewMatrix( modelview );
}
@ -869,18 +869,18 @@ void RB_StageIteratorSky( void ) {
// draw the outer skybox
if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
matrix_t oldmodelview;
mat4_t oldmodelview;
GL_State( 0 );
//qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
{
// FIXME: this could be a lot cleaner
matrix_t trans, product;
mat4_t trans, product;
Matrix16Copy( glState.modelview, oldmodelview );
Matrix16Translation( backEnd.viewParms.or.origin, trans );
Matrix16Multiply( glState.modelview, trans, product );
Mat4Copy( glState.modelview, oldmodelview );
Mat4Translation( backEnd.viewParms.or.origin, trans );
Mat4Multiply( glState.modelview, trans, product );
GL_SetModelviewMatrix( product );
}

View file

@ -124,10 +124,10 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4],
// constant normal all the way around
VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
VectorCopy(normal, tess.normal[ndx]);
VectorCopy(normal, tess.normal[ndx+1]);
VectorCopy(normal, tess.normal[ndx+2]);
VectorCopy(normal, tess.normal[ndx+3]);
tess.normal[ndx] =
tess.normal[ndx+1] =
tess.normal[ndx+2] =
tess.normal[ndx+3] = R_VboPackNormal(normal);
// standard square texture coordinates
VectorSet2(tess.texCoords[ndx ][0], s1, t1);
@ -228,7 +228,7 @@ void RB_InstantQuad(vec4_t quadVerts[4])
GLSL_BindProgram(&tr.textureColorShader);
GLSL_SetUniformMatrix16(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite);
RB_InstantQuad2(quadVerts, texCoords);
@ -311,30 +311,30 @@ static void RB_SurfacePolychain( srfPoly_t *p ) {
tess.numVertexes = numv;
}
static void RB_SurfaceVertsAndTris( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits, int pshadowBits)
static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIndexes, glIndex_t *indexes, int dlightBits, int pshadowBits)
{
int i;
srfTriangle_t *tri;
glIndex_t *inIndex;
srfVert_t *dv;
float *xyz, *normal, *texCoords, *lightCoords, *lightdir;
float *xyz, *texCoords, *lightCoords;
uint32_t *lightdir;
uint32_t *normal;
#ifdef USE_VERT_TANGENT_SPACE
float *tangent, *bitangent;
uint32_t *tangent;
#endif
glIndex_t *index;
glIndex_t *outIndex;
float *color;
RB_CheckVBOandIBO(tess.vbo, tess.ibo);
RB_CHECKOVERFLOW( numVerts, numTriangles * 3 );
RB_CHECKOVERFLOW( numVerts, numIndexes );
tri = triangles;
index = &tess.indexes[ tess.numIndexes ];
for ( i = 0 ; i < numTriangles ; i++, tri++ ) {
*index++ = tess.numVertexes + tri->indexes[0];
*index++ = tess.numVertexes + tri->indexes[1];
*index++ = tess.numVertexes + tri->indexes[2];
inIndex = indexes;
outIndex = &tess.indexes[ tess.numIndexes ];
for ( i = 0 ; i < numIndexes ; i++ ) {
*outIndex++ = tess.numVertexes + *inIndex++;
}
tess.numIndexes += numTriangles * 3;
tess.numIndexes += numIndexes;
if ( tess.shader->vertexAttribs & ATTR_POSITION )
{
@ -347,26 +347,18 @@ static void RB_SurfaceVertsAndTris( int numVerts, srfVert_t *verts, int numTrian
if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{
dv = verts;
normal = tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 )
VectorCopy(dv->normal, normal);
normal = &tess.normal[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, normal++ )
*normal = R_VboPackNormal(dv->normal);
}
#ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{
dv = verts;
tangent = tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 )
VectorCopy(dv->tangent, tangent);
}
if ( tess.shader->vertexAttribs & ATTR_BITANGENT )
{
dv = verts;
bitangent = tess.bitangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, bitangent+=4 )
VectorCopy(dv->bitangent, bitangent);
tangent = &tess.tangent[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ )
*tangent = R_VboPackTangent(dv->tangent);
}
#endif
@ -397,9 +389,9 @@ static void RB_SurfaceVertsAndTris( int numVerts, srfVert_t *verts, int numTrian
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{
dv = verts;
lightdir = tess.lightdir[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 )
VectorCopy(dv->lightdir, lightdir);
lightdir = &tess.lightdir[ tess.numVertexes ];
for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ )
*lightdir = R_VboPackNormal(dv->lightdir);
}
#if 0 // nothing even uses vertex dlightbits
@ -437,8 +429,8 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
// merge this into any existing multidraw primitives
mergeForward = -1;
mergeBack = -1;
firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE));
lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(GL_INDEX_TYPE));
firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(glIndex_t));
lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(glIndex_t));
if (r_mergeMultidraws->integer)
{
@ -522,15 +514,15 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex
RB_SurfaceTriangles
=============
*/
static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
static void RB_SurfaceTriangles( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{
return;
}
RB_SurfaceVertsAndTris(srf->numVerts, srf->verts, srf->numTriangles,
srf->triangles, srf->dlightBits, srf->pshadowBits);
RB_SurfaceVertsAndIndexes(srf->numVerts, srf->verts, srf->numIndexes,
srf->indexes, srf->dlightBits, srf->pshadowBits);
}
@ -614,7 +606,7 @@ static void RB_SurfaceBeam( void )
GLSL_VertexAttribsState(ATTR_POSITION);
GLSL_BindProgram(sp);
GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed);
@ -840,6 +832,7 @@ static void RB_SurfaceLightningBolt( void ) {
}
}
#if 0
/*
** VectorArrayNormalize
*
@ -895,12 +888,14 @@ static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
#endif
}
#endif
/*
** LerpMeshVertexes
*/
#if 0
#if idppc_altivec
static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
{
@ -1030,6 +1025,7 @@ static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
}
}
#endif
#endif
static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
{
@ -1129,14 +1125,15 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
}
#endif
float *outXyz, *outNormal;
float *outXyz;
uint32_t *outNormal;
mdvVertex_t *newVerts;
int vertNum;
newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;
outXyz = tess.xyz[tess.numVertexes];
outNormal = tess.normal[tess.numVertexes];
outNormal = &tess.normal[tess.numVertexes];
if (backlerp == 0)
{
@ -1146,11 +1143,16 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
vec3_t normal;
VectorCopy(newVerts->xyz, outXyz);
VectorCopy(newVerts->normal, outNormal);
VectorCopy(newVerts->normal, normal);
*outNormal = R_VboPackNormal(normal);
newVerts++;
outXyz += 4;
outNormal += 4;
outNormal++;
}
}
else
@ -1165,15 +1167,19 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
{
vec3_t normal;
VectorLerp(newVerts->xyz, oldVerts->xyz, backlerp, outXyz);
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, outNormal);
//VectorNormalize(outNormal);
VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal);
VectorNormalize(normal);
*outNormal = R_VboPackNormal(normal);
newVerts++;
oldVerts++;
outXyz += 4;
outNormal += 4;
outNormal++;
}
VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], surf->numVerts);
}
}
@ -1201,9 +1207,7 @@ RB_SurfaceMesh
static void RB_SurfaceMesh(mdvSurface_t *surface) {
int j;
float backlerp;
srfTriangle_t *triangles;
mdvSt_t *texCoords;
int indexes;
int Bob, Doug;
int numVerts;
@ -1213,20 +1217,16 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) {
backlerp = backEnd.currentEntity->e.backlerp;
}
RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 );
RB_CHECKOVERFLOW( surface->numVerts, surface->numIndexes );
LerpMeshVertexes (surface, backlerp);
triangles = surface->triangles;
indexes = surface->numTriangles * 3;
Bob = tess.numIndexes;
Doug = tess.numVertexes;
for (j = 0 ; j < surface->numTriangles ; j++) {
tess.indexes[Bob + j*3 + 0] = Doug + triangles[j].indexes[0];
tess.indexes[Bob + j*3 + 1] = Doug + triangles[j].indexes[1];
tess.indexes[Bob + j*3 + 2] = Doug + triangles[j].indexes[2];
for (j = 0 ; j < surface->numIndexes ; j++) {
tess.indexes[Bob + j] = Doug + surface->indexes[j];
}
tess.numIndexes += indexes;
tess.numIndexes += surface->numIndexes;
texCoords = surface->st;
@ -1247,15 +1247,15 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) {
RB_SurfaceFace
==============
*/
static void RB_SurfaceFace( srfSurfaceFace_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
static void RB_SurfaceFace( srfBspSurface_t *srf ) {
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{
return;
}
RB_SurfaceVertsAndTris(srf->numVerts, srf->verts, srf->numTriangles,
srf->triangles, srf->dlightBits, srf->pshadowBits);
RB_SurfaceVertsAndIndexes(srf->numVerts, srf->verts, srf->numIndexes,
srf->indexes, srf->dlightBits, srf->pshadowBits);
}
@ -1296,15 +1296,16 @@ RB_SurfaceGrid
Just copy the grid of points and triangulate
=============
*/
static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
static void RB_SurfaceGrid( srfBspSurface_t *srf ) {
int i, j;
float *xyz;
float *texCoords, *lightCoords;
float *normal;
uint32_t *normal;
#ifdef USE_VERT_TANGENT_SPACE
float *tangent, *bitangent;
uint32_t *tangent;
#endif
float *color, *lightdir;
float *color;
uint32_t *lightdir;
srfVert_t *dv;
int rows, irows, vrows;
int used;
@ -1317,7 +1318,7 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
int pshadowBits;
//int *vDlightBits;
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes,
srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
{
return;
@ -1387,15 +1388,14 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
numVertexes = tess.numVertexes;
xyz = tess.xyz[numVertexes];
normal = tess.normal[numVertexes];
normal = &tess.normal[numVertexes];
#ifdef USE_VERT_TANGENT_SPACE
tangent = tess.tangent[numVertexes];
bitangent = tess.bitangent[numVertexes];
tangent = &tess.tangent[numVertexes];
#endif
texCoords = tess.texCoords[numVertexes][0];
lightCoords = tess.texCoords[numVertexes][1];
color = tess.vertexColors[numVertexes];
lightdir = tess.lightdir[numVertexes];
lightdir = &tess.lightdir[numVertexes];
//vDlightBits = &tess.vertexDlightBits[numVertexes];
for ( i = 0 ; i < rows ; i++ ) {
@ -1411,21 +1411,13 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_NORMAL )
{
VectorCopy(dv->normal, normal);
normal += 4;
*normal++ = R_VboPackNormal(dv->normal);
}
#ifdef USE_VERT_TANGENT_SPACE
if ( tess.shader->vertexAttribs & ATTR_TANGENT )
{
VectorCopy(dv->tangent, tangent);
tangent += 4;
}
if ( tess.shader->vertexAttribs & ATTR_BITANGENT )
{
VectorCopy(dv->bitangent, bitangent);
bitangent += 4;
*tangent++ = R_VboPackTangent(dv->tangent);
}
#endif
if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
@ -1448,8 +1440,7 @@ static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
{
VectorCopy(dv->lightdir, lightdir);
lightdir += 4;
*lightdir++ = R_VboPackNormal(dv->lightdir);
}
//*vDlightBits++ = dlightBits;
@ -1574,7 +1565,7 @@ static void RB_SurfaceFlare(srfFlare_t *surf)
RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
}
static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf)
static void RB_SurfaceVBOMesh(srfBspSurface_t * srf)
{
RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex,
srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse );
@ -1621,11 +1612,12 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
glState.vertexAttribsOldFrame = refEnt->oldframe;
glState.vertexAttribsNewFrame = refEnt->frame;
glState.vertexAnimation = qtrue;
RB_EndSurface();
// So we don't lerp surfaces that shouldn't be lerped
glState.vertexAttribsInterpolation = 0;
glState.vertexAnimation = qfalse;
}
static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {
@ -1646,7 +1638,6 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
(void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
(void(*)(void*))RB_SurfacePolychain, // SF_POLY,
(void(*)(void*))RB_SurfaceMesh, // SF_MDV,
(void(*)(void*))RB_SurfaceAnim, // SF_MD4,
(void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
(void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM,
(void(*)(void*))RB_SurfaceFlare, // SF_FLARE,

View file

@ -22,6 +22,75 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// tr_vbo.c
#include "tr_local.h"
uint32_t R_VboPackTangent(vec4_t v)
{
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{
return (((uint32_t)(v[3] * 1.5f + 2.0f )) << 30)
| (((uint32_t)(v[2] * 511.5f + 512.0f)) << 20)
| (((uint32_t)(v[1] * 511.5f + 512.0f)) << 10)
| (((uint32_t)(v[0] * 511.5f + 512.0f)));
}
else
{
return (((uint32_t)(v[3] * 127.5f + 128.0f)) << 24)
| (((uint32_t)(v[2] * 127.5f + 128.0f)) << 16)
| (((uint32_t)(v[1] * 127.5f + 128.0f)) << 8)
| (((uint32_t)(v[0] * 127.5f + 128.0f)));
}
}
uint32_t R_VboPackNormal(vec3_t v)
{
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{
return (((uint32_t)(v[2] * 511.5f + 512.0f)) << 20)
| (((uint32_t)(v[1] * 511.5f + 512.0f)) << 10)
| (((uint32_t)(v[0] * 511.5f + 512.0f)));
}
else
{
return (((uint32_t)(v[2] * 127.5f + 128.0f)) << 16)
| (((uint32_t)(v[1] * 127.5f + 128.0f)) << 8)
| (((uint32_t)(v[0] * 127.5f + 128.0f)));
}
}
void R_VboUnpackTangent(vec4_t v, uint32_t b)
{
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{
v[0] = ((b) & 0x3ff) * 1.0f/511.5f - 1.0f;
v[1] = ((b >> 10) & 0x3ff) * 1.0f/511.5f - 1.0f;
v[2] = ((b >> 20) & 0x3ff) * 1.0f/511.5f - 1.0f;
v[3] = ((b >> 30) & 0x3) * 1.0f/1.5f - 1.0f;
}
else
{
v[0] = ((b) & 0xff) * 1.0f/127.5f - 1.0f;
v[1] = ((b >> 8) & 0xff) * 1.0f/127.5f - 1.0f;
v[2] = ((b >> 16) & 0xff) * 1.0f/127.5f - 1.0f;
v[3] = ((b >> 24) & 0xff) * 1.0f/127.5f - 1.0f;
}
}
void R_VboUnpackNormal(vec3_t v, uint32_t b)
{
if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV)
{
v[0] = ((b) & 0x3ff) * 1.0f/511.5f - 1.0f;
v[1] = ((b >> 10) & 0x3ff) * 1.0f/511.5f - 1.0f;
v[2] = ((b >> 20) & 0x3ff) * 1.0f/511.5f - 1.0f;
}
else
{
v[0] = ((b) & 0xff) * 1.0f/127.5f - 1.0f;
v[1] = ((b >> 8) & 0xff) * 1.0f/127.5f - 1.0f;
v[2] = ((b >> 16) & 0xff) * 1.0f/127.5f - 1.0f;
}
}
/*
============
R_CreateVBO
@ -142,20 +211,14 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
if(stateBits & ATTR_NORMAL)
{
vbo->ofs_normal = dataSize;
dataSize += sizeof(verts[0].normal);
dataSize += sizeof(uint32_t);
}
#ifdef USE_VERT_TANGENT_SPACE
if(stateBits & ATTR_TANGENT)
{
vbo->ofs_tangent = dataSize;
dataSize += sizeof(verts[0].tangent);
}
if(stateBits & ATTR_BITANGENT)
{
vbo->ofs_bitangent = dataSize;
dataSize += sizeof(verts[0].bitangent);
dataSize += sizeof(uint32_t);
}
#endif
@ -180,14 +243,13 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
if(stateBits & ATTR_LIGHTDIRECTION)
{
vbo->ofs_lightdir = dataSize;
dataSize += sizeof(verts[0].lightdir);
dataSize += sizeof(uint32_t);
}
vbo->stride_xyz = dataSize;
vbo->stride_normal = dataSize;
#ifdef USE_VERT_TANGENT_SPACE
vbo->stride_tangent = dataSize;
vbo->stride_bitangent = dataSize;
#endif
vbo->stride_st = dataSize;
vbo->stride_lightmap = dataSize;
@ -211,23 +273,22 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// normal
if(stateBits & ATTR_NORMAL)
{
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
dataOfs += sizeof(verts[i].normal);
uint32_t *p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].normal);
dataOfs += sizeof(uint32_t);
}
#ifdef USE_VERT_TANGENT_SPACE
// tangent
if(stateBits & ATTR_TANGENT)
{
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
dataOfs += sizeof(verts[i].tangent);
}
uint32_t *p = (uint32_t *)(data + dataOfs);
// bitangent
if(stateBits & ATTR_BITANGENT)
{
memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
dataOfs += sizeof(verts[i].bitangent);
*p = R_VboPackTangent(verts[i].tangent);
dataOfs += sizeof(uint32_t);
}
#endif
@ -255,8 +316,11 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
// feed vertex light directions
if(stateBits & ATTR_LIGHTDIRECTION)
{
memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
dataOfs += sizeof(verts[i].lightdir);
uint32_t *p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].lightdir);
dataOfs += sizeof(uint32_t);
}
}
}
@ -267,18 +331,13 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
if(stateBits & ATTR_NORMAL)
{
dataSize += sizeof(verts[0].normal);
dataSize += sizeof(uint32_t);
}
#ifdef USE_VERT_TANGENT_SPACE
if(stateBits & ATTR_TANGENT)
{
dataSize += sizeof(verts[0].tangent);
}
if(stateBits & ATTR_BITANGENT)
{
dataSize += sizeof(verts[0].bitangent);
dataSize += sizeof(uint32_t);
}
#endif
@ -299,7 +358,7 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
if(stateBits & ATTR_LIGHTDIRECTION)
{
dataSize += sizeof(verts[0].lightdir);
dataSize += sizeof(uint32_t);
}
// create VBO
@ -311,7 +370,6 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_normal = 0;
#ifdef USE_VERT_TANGENT_SPACE
vbo->ofs_tangent = 0;
vbo->ofs_bitangent = 0;
#endif
vbo->ofs_st = 0;
vbo->ofs_lightmap = 0;
@ -319,15 +377,14 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_lightdir = 0;
vbo->stride_xyz = sizeof(verts[0].xyz);
vbo->stride_normal = sizeof(verts[0].normal);
vbo->stride_normal = sizeof(uint32_t);
#ifdef USE_VERT_TANGENT_SPACE
vbo->stride_tangent = sizeof(verts[0].tangent);
vbo->stride_bitangent = sizeof(verts[0].bitangent);
vbo->stride_tangent = sizeof(uint32_t);
#endif
vbo->stride_vertexcolor = sizeof(verts[0].vertexColors);
vbo->stride_st = sizeof(verts[0].st);
vbo->stride_lightmap = sizeof(verts[0].lightmap);
vbo->stride_lightdir = sizeof(verts[0].lightdir);
vbo->stride_lightdir = sizeof(uint32_t);
//ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
//vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);
@ -345,8 +402,11 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_normal = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
dataOfs += sizeof(verts[i].normal);
uint32_t *p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].normal);
dataOfs += sizeof(uint32_t);
}
}
@ -357,19 +417,11 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_tangent = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
dataOfs += sizeof(verts[i].tangent);
}
}
uint32_t *p = (uint32_t *)(data + dataOfs);
// bitangent
if(stateBits & ATTR_BITANGENT)
{
vbo->ofs_bitangent = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
dataOfs += sizeof(verts[i].bitangent);
*p = R_VboPackTangent(verts[i].tangent);
dataOfs += sizeof(uint32_t);
}
}
#endif
@ -413,8 +465,11 @@ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vert
vbo->ofs_lightdir = dataOfs;
for (i = 0; i < numVertexes; i++)
{
memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
dataOfs += sizeof(verts[i].lightdir);
uint32_t *p = (uint32_t *)(data + dataOfs);
*p = R_VboPackNormal(verts[i].lightdir);
dataOfs += sizeof(uint32_t);
}
}
}
@ -501,17 +556,14 @@ IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, v
R_CreateIBO2
============
*/
IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage)
IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes, vboUsage_t usage)
{
IBO_t *ibo;
int i, j;
int i;
byte *indexes;
glIndex_t *indexes;
int indexesSize;
int indexesOfs;
srfTriangle_t *tri;
glIndex_t index;
int glUsage;
switch (usage)
@ -529,7 +581,7 @@ IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t *
return NULL;
}
if(!numTriangles)
if(!numIndexes)
return NULL;
if(strlen(name) >= MAX_QPATH)
@ -548,18 +600,12 @@ IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t *
Q_strncpyz(ibo->name, name, sizeof(ibo->name));
indexesSize = numTriangles * 3 * sizeof(int);
indexesSize = numIndexes * sizeof(glIndex_t);
indexes = ri.Hunk_AllocateTempMemory(indexesSize);
indexesOfs = 0;
for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
for(i = 0; i < numIndexes; i++)
{
for(j = 0; j < 3; j++)
{
index = tri->indexes[j];
memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t));
indexesOfs += sizeof(glIndex_t);
}
indexes[i] = inIndexes[i];
}
ibo->indexesSize = indexesSize;
@ -608,6 +654,7 @@ void R_BindVBO(VBO_t * vbo)
glState.vertexAttribsInterpolation = 0;
glState.vertexAttribsOldFrame = 0;
glState.vertexAttribsNewFrame = 0;
glState.vertexAnimation = qfalse;
qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
@ -699,7 +746,6 @@ void R_InitVBOs(void)
dataSize += sizeof(tess.normal[0]);
#ifdef USE_VERT_TANGENT_SPACE
dataSize += sizeof(tess.tangent[0]);
dataSize += sizeof(tess.bitangent[0]);
#endif
dataSize += sizeof(tess.vertexColors[0]);
dataSize += sizeof(tess.texCoords[0][0]) * 2;
@ -714,7 +760,6 @@ void R_InitVBOs(void)
tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
#ifdef USE_VERT_TANGENT_SPACE
tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
tess.vbo->ofs_bitangent = offset; offset += sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES;
#endif
// these next two are actually interleaved
tess.vbo->ofs_st = offset;
@ -728,7 +773,6 @@ void R_InitVBOs(void)
tess.vbo->stride_normal = sizeof(tess.normal[0]);
#ifdef USE_VERT_TANGENT_SPACE
tess.vbo->stride_tangent = sizeof(tess.tangent[0]);
tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]);
#endif
tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]);
tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2;
@ -856,6 +900,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{
R_BindVBO(tess.vbo);
// orphan old buffer so we don't stall on it
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
if(attribBits & ATTR_BITS)
{
if(attribBits & ATTR_POSITION)
@ -883,12 +930,6 @@ void RB_UpdateVBOs(unsigned int attribBits)
//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]));
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
}
if(attribBits & ATTR_BITANGENT)
{
//ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]));
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
}
#endif
if(attribBits & ATTR_COLOR)
@ -910,7 +951,6 @@ void RB_UpdateVBOs(unsigned int attribBits)
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
#ifdef USE_VERT_TANGENT_SPACE
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
#endif
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir);
@ -923,6 +963,9 @@ void RB_UpdateVBOs(unsigned int attribBits)
{
R_BindIBO(tess.ibo);
// orphan old buffer so we don't stall on it
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB);
qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
}
}

View file

@ -208,16 +208,18 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
}
}
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits = dlightBits;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->dlightBits = dlightBits;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->dlightBits = dlightBits;
} else if ( *surf->data == SF_VBO_MESH ) {
((srfVBOMesh_t *)surf->data)->dlightBits = dlightBits;
} else {
switch(*surf->data)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
case SF_VBO_MESH:
((srfBspSurface_t *)surf->data)->dlightBits = dlightBits;
break;
default:
dlightBits = 0;
break;
}
if ( dlightBits ) {
@ -292,16 +294,18 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
}
}
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->pshadowBits = pshadowBits;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->pshadowBits = pshadowBits;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->pshadowBits = pshadowBits;
} else if ( *surf->data == SF_VBO_MESH ) {
((srfVBOMesh_t *)surf->data)->pshadowBits = pshadowBits;
} else {
switch(*surf->data)
{
case SF_FACE:
case SF_GRID:
case SF_TRIANGLES:
case SF_VBO_MESH:
((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits;
break;
default:
pshadowBits = 0;
break;
}
if ( pshadowBits ) {

View file

@ -698,8 +698,8 @@ void GLimp_Init( void )
{
r_allowSoftwareGL = ri.Cvar_Get( "r_allowSoftwareGL", "0", CVAR_LATCH );
r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM );
r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE );
r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE );
r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE | CVAR_LATCH );
if( ri.Cvar_VariableIntegerValue( "com_abnormalExit" ) )
{

View file

@ -194,7 +194,7 @@ typedef struct client_s {
#endif
int oldServerTime;
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
qboolean csUpdated[MAX_CONFIGSTRINGS];
#ifdef LEGACY_PROTOCOL
qboolean compat;

View file

@ -82,7 +82,7 @@ void SV_UpdateConfigstrings(client_t *client)
{
int index;
for( index = 0; index <= MAX_CONFIGSTRINGS; index++ ) {
for( index = 0; index < MAX_CONFIGSTRINGS; index++ ) {
// if the CS hasn't changed since we went to CS_PRIMED, ignore
if(!client->csUpdated[index])
continue;

View file

@ -429,6 +429,7 @@ qboolean UI_ConsoleCommand(int realTime)
if (Q_stricmp(cmd, "ui_test") == 0) {
UI_ShowPostGame(qtrue);
return qtrue;
}
if (Q_stricmp(cmd, "ui_report") == 0) {

View file

@ -1918,7 +1918,7 @@ void UI_ParseMenu(const char *menuFile)
int handle;
pc_token_t token;
Com_Printf("Parsing menu file:%s\n", menuFile);
Com_Printf("Parsing menu file: %s\n", menuFile);
handle = trap_PC_LoadSource(menuFile);
if (!handle) {

View file

@ -221,13 +221,13 @@ for ARCH in $SEARCH_ARCHS; do
IOQ3_UI_ARCHS="${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_UI} ${IOQ3_UI_ARCHS}"
fi
# missionpack
if [ -e ${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_MP_CGAME} ]; then
if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_CGAME} ]; then
IOQ3_MP_CGAME_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_CGAME} ${IOQ3_MP_CGAME_ARCHS}"
fi
if [ -e ${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_MP_GAME} ]; then
if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_GAME} ]; then
IOQ3_MP_GAME_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_GAME} ${IOQ3_MP_GAME_ARCHS}"
fi
if [ -e ${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_MP_UI} ]; then
if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_UI} ]; then
IOQ3_MP_UI_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_UI} ${IOQ3_MP_UI_ARCHS}"
fi

932
misc/msvc/opengl1.vcproj Normal file
View file

@ -0,0 +1,932 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="opengl1"
ProjectGUID="{CD289B03-887C-4602-BDCE-AB6785A7489E}"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release TA|Win32"
OutputDirectory="..\..\build\opengl1_release_ta"
IntermediateDirectory="..\..\build\opengl1_release_ta"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName="$(IntDir)\opengl1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;&quot;..\..\code\jpeg-8c&quot;"
PreprocessorDefinitions="_WIN32;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;HAVE_CONFIG_H;MISSIONPACK;USE_INTERNAL_JPEG;USE_RENDERER_DLOPEN"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile="$(IntDir)\opengl1.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="4"
SuppressStartupBanner="true"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="user32.lib advapi32.lib winmm.lib wsock32.lib ws2_32.lib SDL.lib OpenGL32.lib msvcrt.lib psapi.lib"
OutputFile="$(OutDir)\renderer_opengl1_x86.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\code\libs\win32"
GenerateDebugInformation="false"
ProgramDatabaseFile="$(IntDir)\opengl1.pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)\opengl1.map"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Post build processing.."
CommandLine="rem bash -c &quot;perl ./unix/cons -- release-TA&quot;"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\..\build\opengl1_debug"
IntermediateDirectory="..\..\build\opengl1_debug"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName="$(IntDir)\opengl1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;&quot;..\..\code\jpeg-8c&quot;"
PreprocessorDefinitions="_WIN32;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;HAVE_CONFIG_H;USE_INTERNAL_JPEG;USE_RENDERER_DLOPEN"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
PrecompiledHeaderFile="$(IntDir)\opengl1.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
BrowseInformation="1"
BrowseInformationFile="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
ResourceOutputFileName="..\winquake.res"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="user32.lib advapi32.lib winmm.lib wsock32.lib ws2_32.lib SDL.lib OpenGL32.lib msvcrt.lib psapi.lib"
OutputFile="$(OutDir)\renderer_opengl1_x86.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\code\libs\win32"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)\opengl1.pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)\opengl1.map"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Post build processing.."
CommandLine="rem bash -c &quot;perl ./unix/cons -- debug&quot;"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\..\build\opengl1_release"
IntermediateDirectory="..\..\build\opengl1_release"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName="$(IntDir)\opengl1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="2"
AdditionalIncludeDirectories="..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;&quot;..\..\code\jpeg-8c&quot;"
PreprocessorDefinitions="_WIN32;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;HAVE_CONFIG_H;USE_INTERNAL_JPEG;USE_RENDERER_DLOPEN"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
PrecompiledHeaderFile="$(IntDir)\opengl1.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
WarningLevel="4"
SuppressStartupBanner="true"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="user32.lib advapi32.lib winmm.lib wsock32.lib ws2_32.lib SDL.lib OpenGL32.lib msvcrt.lib psapi.lib"
OutputFile="$(OutDir)\renderer_opengl1_x86.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\code\libs\win32"
GenerateDebugInformation="false"
ProgramDatabaseFile="$(IntDir)\opengl1.pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)\opengl1.map"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug TA|Win32"
OutputDirectory="..\..\build\opengl1_debug_ta"
IntermediateDirectory="..\..\build\opengl1_debug_ta"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName="$(IntDir)\opengl1.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;&quot;..\..\code\jpeg-8c&quot;"
PreprocessorDefinitions="_WIN32;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;HAVE_CONFIG_H;MISSIONPACK;USE_INTERNAL_JPEG;USE_RENDERER_DLOPEN"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
PrecompiledHeaderFile="$(IntDir)\opengl1.pch"
AssemblerListingLocation="$(IntDir)\"
ObjectFile="$(IntDir)\"
ProgramDataBaseFileName="$(IntDir)\"
BrowseInformation="1"
BrowseInformationFile="$(IntDir)\"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
ResourceOutputFileName="..\winquake.res"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="user32.lib advapi32.lib winmm.lib wsock32.lib ws2_32.lib SDL.lib OpenGL32.lib msvcrt.lib psapi.lib"
OutputFile="$(OutDir)\renderer_opengl1_x86.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\..\code\libs\win32"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(IntDir)\opengl1.pdb"
GenerateMapFile="true"
MapFileName="$(IntDir)\opengl1.map"
SubSystem="2"
StackReserveSize="8388608"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Post build processing.."
CommandLine="rem bash -c &quot;perl ./unix/cons -- debug-TA&quot;"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
>
<File
RelativePath="..\..\code\qcommon\puff.c"
>
</File>
<File
RelativePath="..\..\code\.\qcommon\q_math.c"
>
</File>
<File
RelativePath="..\..\code\.\qcommon\q_shared.c"
>
</File>
<File
RelativePath="..\..\code\sdl\sdl_gamma.c"
>
</File>
<File
RelativePath="..\..\code\sdl\sdl_glimp.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_animation.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_backend.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_bsp.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_cmds.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_curve.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_flares.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_font.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_image.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_image_bmp.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_image_jpg.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_image_pcx.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_image_png.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_image_tga.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_init.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_light.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_main.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_marks.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_mesh.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_model.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_model_iqm.c"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_noise.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_scene.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_shade.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_shade_calc.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_shader.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_shadows.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_sky.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_subs.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_surface.c"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_world.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;fi;fd"
>
<File
RelativePath="..\..\code\qcommon\puff.h"
>
</File>
<File
RelativePath="..\..\code\.\qcommon\q_shared.h"
>
</File>
<File
RelativePath="..\..\code\qcommon\qcommon.h"
>
</File>
<File
RelativePath="..\..\code\qcommon\qfiles.h"
>
</File>
<File
RelativePath="..\..\code\renderercommon\qgl.h"
>
</File>
<File
RelativePath="..\..\code\win32\resource.h"
>
</File>
<File
RelativePath="..\..\code\server\server.h"
>
</File>
<File
RelativePath="..\..\code\client\snd_local.h"
>
</File>
<File
RelativePath="..\..\code\client\snd_public.h"
>
</File>
<File
RelativePath="..\..\code\.\qcommon\surfaceflags.h"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_extramath.h"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_extratypes.h"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_fbo.h"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_local.h"
>
</File>
<File
RelativePath="..\..\code\renderergl1\tr_postprocess.h"
>
</File>
<File
RelativePath="..\..\code\renderercommon\tr_public.h"
>
</File>
<File
RelativePath="..\..\code\cgame\tr_types.h"
>
</File>
<File
RelativePath="..\..\code\ui\ui_public.h"
>
</File>
<File
RelativePath="..\..\code\qcommon\unzip.h"
>
</File>
<File
RelativePath="..\..\code\qcommon\vm_local.h"
>
</File>
<File
RelativePath="..\..\code\win32\win_local.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
>
</Filter>
<Filter
Name="jpeg"
>
<Filter
Name="Source Files"
>
<File
RelativePath="..\..\code\jpeg-8c\jaricom.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcapimin.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcapistd.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcarith.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jccoefct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jccolor.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcdctmgr.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jchuff.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcinit.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcmainct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcmarker.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcmaster.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcomapi.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcparam.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcprepct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jcsample.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jctrans.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdapimin.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdapistd.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdarith.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdatadst.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdatasrc.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdcoefct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdcolor.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jddctmgr.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdhuff.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdinput.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdmainct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdmarker.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdmaster.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdmerge.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdpostct.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdsample.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jdtrans.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jerror.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jfdctflt.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jfdctfst.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jfdctint.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jidctflt.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jidctfst.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jidctint.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jmemmgr.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jmemnobs.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jquant1.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jquant2.c"
>
</File>
<File
RelativePath="..\..\code\jpeg-8c\jutils.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
>
<File
RelativePath="..\..\code\jpeg-6b\jchuff.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jconfig.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jdct.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jdhuff.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jerror.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jinclude.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jmemsys.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jmorecfg.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jpegint.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jpeglib.h"
>
</File>
<File
RelativePath="..\..\code\jpeg-6b\jversion.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="zlib"
>
<File
RelativePath="..\..\code\zlib\adler32.c"
>
</File>
<File
RelativePath="..\..\code\zlib\crc32.c"
>
</File>
<File
RelativePath="..\..\code\zlib\inffast.c"
>
</File>
<File
RelativePath="..\..\code\zlib\inflate.c"
>
</File>
<File
RelativePath="..\..\code\zlib\inftrees.c"
>
</File>
<File
RelativePath="..\..\code\zlib\zutil.c"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>