centerprints with links now show cursors.

q2 temp entity tweaks. still more work to be done.
support sRGB (mostly)properly in gl+vk+d3d9+d3d11.
vulkan tweaks - multisample works under certain conditions. additional other changes to comply... cvars to enable some other device extensions.
removed r_viewleaf. now using clusters for q1 too.
improved compat with quakespasm's sky command.
Added vid_winthread cvar, to handle window messages on a separate thread. When set this allows the game to keep redrawing when the user is resizing the window etc.
Finally added renderers option to menusys.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5130 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-07-28 01:49:25 +00:00
parent d66db9930d
commit db2c378fa0
67 changed files with 6083 additions and 2281 deletions

View File

@ -1,417 +1,417 @@
#!/bin/bash #!/bin/bash
#sets up dependancies for debian-jessie (8.7) #sets up dependancies for debian-jessie (8.7)
#this script must be run twice. first time as root, which installs system packages #this script must be run twice. first time as root, which installs system packages
#second time as a regular user (probably not your normal one), which installs 3rd-party stuff #second time as a regular user (probably not your normal one), which installs 3rd-party stuff
SVNROOT=$(cd "$(dirname "$BASH_SOURCE")" && pwd) SVNROOT=$(cd "$(dirname "$BASH_SOURCE")" && pwd)
FTEROOT=$(realpath $SVNROOT/..) FTEROOT=$(realpath $SVNROOT/..)
FTEROOT=${FTEROOT:-~} FTEROOT=${FTEROOT:-~}
FTECONFIG=$SVNROOT/build.cfg FTECONFIG=$SVNROOT/build.cfg
BUILDFOLDER=`echo ~`/htdocs BUILDFOLDER=`echo ~`/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs BUILDLOGFOLDER=$BUILDFOLDER/build_logs
#mac defaults #mac defaults
OSXCROSSROOT=$FTEROOT/osxcross OSXCROSSROOT=$FTEROOT/osxcross
#emscripten defaults #emscripten defaults
EMSCRIPTENROOT=$FTEROOT/emsdk-portable EMSCRIPTENROOT=$FTEROOT/emsdk-portable
#nacl defaults #nacl defaults
NACLROOT=$FTEROOT/nacl_sdk NACLROOT=$FTEROOT/nacl_sdk
NACLSDKVERSION=pepper_49 NACLSDKVERSION=pepper_49
#android defaults #android defaults
ANDROIDROOT=$FTEROOT/android ANDROIDROOT=$FTEROOT/android
if [ ! -z "$(uname -o 2>&1 | grep Cygwin)" ]; then if [ ! -z "$(uname -o 2>&1 | grep Cygwin)" ]; then
ANDROID_HOSTSYSTEM=windows-x86_64 ANDROID_HOSTSYSTEM=windows-x86_64
else else
ANDROID_HOSTSYSTEM=linux-$(uname -m) ANDROID_HOSTSYSTEM=linux-$(uname -m)
fi fi
ANDROIDBUILDTOOLS=25.0.0 ANDROIDBUILDTOOLS=25.0.0
ANDROID_ZIPALIGN=$ANDROIDROOT/build-tools/$ANDROIDBUILDTOOLS/zipalign #relative to ndk tools ANDROID_ZIPALIGN=$ANDROIDROOT/build-tools/$ANDROIDBUILDTOOLS/zipalign #relative to ndk tools
THREADS="-j 4" THREADS="-j 4"
#windows is always cross compiled, so we don't have issues with non-native ffmpeg #windows is always cross compiled, so we don't have issues with non-native ffmpeg
PLUGINS_LINUXx86="ode qi ezhud xmpp irc" PLUGINS_LINUXx86="ode qi ezhud xmpp irc"
PLUGINS_LINUXx64="ode qi ezhud xmpp irc" PLUGINS_LINUXx64="ode qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc" PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_LINUXarmhf="qi ezhud xmpp irc" PLUGINS_LINUXarmhf="qi ezhud xmpp irc"
if [ "$(uname -m)" != "x86_64" ]; then if [ "$(uname -m)" != "x86_64" ]; then
PLUGINS_LINUXx86="ffmpeg ode qi ezhud xmpp irc" PLUGINS_LINUXx86="ffmpeg ode qi ezhud xmpp irc"
fi fi
if [ "$(uname -m)" == "x86_64" ]; then if [ "$(uname -m)" == "x86_64" ]; then
PLUGINS_LINUX64="ffmpeg ode qi ezhud xmpp irc" PLUGINS_LINUX64="ffmpeg ode qi ezhud xmpp irc"
fi fi
#windows doesn't cross compile, so no system dependancy issues #windows doesn't cross compile, so no system dependancy issues
#skip some dependancies if we're running on cygwin, ode is buggy. #skip some dependancies if we're running on cygwin, ode is buggy.
if [ "$(uname -s)" == "Linux" ]; then if [ "$(uname -s)" == "Linux" ]; then
PLUGINS_WINDOWS="ffmpeg ode qi ezhud xmpp irc" PLUGINS_WINDOWS="ffmpeg ode qi ezhud xmpp irc"
else else
PLUGINS_WINDOWS="qi ezhud xmpp irc" PLUGINS_WINDOWS="qi ezhud xmpp irc"
fi fi
echo echo
echo "This is Spike's script to set up various cross compilers and dependancies." echo "This is Spike's script to set up various cross compilers and dependancies."
echo "This script will check dependancies. If something isn't installed you can either rerun the script as root (which will ONLY install system packages), or manually apt-get or whatever. You can then re-run the script as a regular user to finish configuring 3rd party dependancies." echo "This script will check dependancies. If something isn't installed you can either rerun the script as root (which will ONLY install system packages), or manually apt-get or whatever. You can then re-run the script as a regular user to finish configuring 3rd party dependancies."
echo echo
echo "You can change your choices later by just re-running this script" echo "You can change your choices later by just re-running this script"
echo "(Your settings will be autosaved in $FTECONFIG)" echo "(Your settings will be autosaved in $FTECONFIG)"
echo echo
echo "If you just want to compile a native build, just use the following command:" echo "If you just want to compile a native build, just use the following command:"
echo "cd $SVNROOT/engine && make gl-rel" echo "cd $SVNROOT/engine && make gl-rel"
echo "(if you're in cygwin, add FTE_TARGET=win32 to compile for native windows)" echo "(if you're in cygwin, add FTE_TARGET=win32 to compile for native windows)"
echo "(add plugins-rel qcc-rel qccgui-rel sv-rel vk-rel etc for additional targets)" echo "(add plugins-rel qcc-rel qccgui-rel sv-rel vk-rel etc for additional targets)"
echo "(or use -dbg if you want debug builds for whatever reason)" echo "(or use -dbg if you want debug builds for whatever reason)"
echo echo
#always execute it if it exists, so that we preserve custom paths etc that are not prompted for here #always execute it if it exists, so that we preserve custom paths etc that are not prompted for here
if [ -e $FTECONFIG ]; then if [ -e $FTECONFIG ]; then
. $FTECONFIG . $FTECONFIG
if [ $UID -eq 0 ]; then if [ $UID -eq 0 ]; then
REUSE_CONFIG=y #root shouldn't be writing/owning the config file. REUSE_CONFIG=y #root shouldn't be writing/owning the config file.
else else
read -n 1 -p "Reuse previous build config? [y/N] " REUSE_CONFIG && echo read -n 1 -p "Reuse previous build config? [y/N] " REUSE_CONFIG && echo
REUSE_CONFIG=${REUSE_CONFIG:-n} REUSE_CONFIG=${REUSE_CONFIG:-n}
fi fi
else else
if [ $UID -eq 0 ]; then if [ $UID -eq 0 ]; then
exit #root can't create the output, as that would take ownership. exit #root can't create the output, as that would take ownership.
else else
REUSE_CONFIG=n REUSE_CONFIG=n
fi fi
fi fi
if [ "$REUSE_CONFIG" != "y" ]; then if [ "$REUSE_CONFIG" != "y" ]; then
#linux compiles are native-only, so don't bug out on cygwin which lacks a cross compiler. #linux compiles are native-only, so don't bug out on cygwin which lacks a cross compiler.
BUILD_LINUXx86=n BUILD_LINUXx86=n
BUILD_LINUXx64=n BUILD_LINUXx64=n
BUILD_LINUXx32=n BUILD_LINUXx32=n
BUILD_LINUXarmhf=n BUILD_LINUXarmhf=n
if [ "$(uname -s)" == "Linux" ]; then if [ "$(uname -s)" == "Linux" ]; then
read -n 1 -p "Build for Linux x86? [Y/n] " BUILD_LINUXx86 && echo read -n 1 -p "Build for Linux x86? [Y/n] " BUILD_LINUXx86 && echo
read -n 1 -p "Build for Linux x86_64? [Y/n] " BUILD_LINUXx64 && echo read -n 1 -p "Build for Linux x86_64? [Y/n] " BUILD_LINUXx64 && echo
read -n 1 -p "Build for Linux x32? [y/N] " BUILD_LINUXx32 && echo read -n 1 -p "Build for Linux x32? [y/N] " BUILD_LINUXx32 && echo
#ubuntu's gcc-multilib-arm-foo package conflicts with gcc-multilib... #ubuntu's gcc-multilib-arm-foo package conflicts with gcc-multilib...
#the whole point of multilib was to avoid conflicts... someone fucked up. #the whole point of multilib was to avoid conflicts... someone fucked up.
#read -n 1 -p "Build for Linux armhf [y/N] " BUILD_LINUXarmhf && echo #read -n 1 -p "Build for Linux armhf [y/N] " BUILD_LINUXarmhf && echo
else else
echo "Skipping Linux options." echo "Skipping Linux options."
fi fi
BUILD_CYGWIN=n BUILD_CYGWIN=n
BUILD_MSVC=n BUILD_MSVC=n
if [ "$(uname -o)" == "Cygwin" ]; then if [ "$(uname -o)" == "Cygwin" ]; then
read -n 1 -p "Build for Cygwin? [y/N] " BUILD_CYGWIN && echo read -n 1 -p "Build for Cygwin? [y/N] " BUILD_CYGWIN && echo
read -n 1 -p "Build with MSVC? (requires windows7 sdk) [y/N] " BUILD_MSVC && echo read -n 1 -p "Build with MSVC? (requires windows7 sdk) [y/N] " BUILD_MSVC && echo
else else
echo "Skipping Cygwin options." echo "Skipping Cygwin options."
fi fi
read -n 1 -p "Build for Windows? [Y/n] " BUILD_WINDOWS && echo read -n 1 -p "Build for Windows? [Y/n] " BUILD_WINDOWS && echo
read -n 1 -p "Build for Dos? [y/N] " BUILD_WINDOWS && echo read -n 1 -p "Build for Dos? [y/N] " BUILD_WINDOWS && echo
read -n 1 -p "Build for SDL? [y/N] " BUILD_SDL && echo read -n 1 -p "Build for SDL? [y/N] " BUILD_SDL && echo
read -n 1 -p "Build for Android? [y/N] " BUILD_ANDROID && echo read -n 1 -p "Build for Android? [y/N] " BUILD_ANDROID && echo
read -n 1 -p "Build for Emscripten? [y/N] " BUILD_WEB && echo read -n 1 -p "Build for Emscripten? [y/N] " BUILD_WEB && echo
if [ 0 -ne 0 ]; then if [ 0 -ne 0 ]; then
read -n 1 -p "Build for MacOSX? [y/N] " BUILD_MAC && echo read -n 1 -p "Build for MacOSX? [y/N] " BUILD_MAC && echo
else else
echo "Skipping mac option." echo "Skipping mac option."
fi fi
read -n 1 -p "Build for NaCL? [y/N] " BUILD_NACL && echo read -n 1 -p "Build for NaCL? [y/N] " BUILD_NACL && echo
fi fi
BUILD_LINUXx86=${BUILD_LINUXx86:-y} BUILD_LINUXx86=${BUILD_LINUXx86:-y}
BUILD_LINUXx64=${BUILD_LINUXx64:-y} BUILD_LINUXx64=${BUILD_LINUXx64:-y}
BUILD_LINUXx32=${BUILD_LINUXx32:-n} BUILD_LINUXx32=${BUILD_LINUXx32:-n}
BUILD_LINUXarmhf=${BUILD_LINUXarmhf:-n} BUILD_LINUXarmhf=${BUILD_LINUXarmhf:-n}
BUILD_CYGWIN=${BUILD_CYGWIN:-n} BUILD_CYGWIN=${BUILD_CYGWIN:-n}
BUILD_WINDOWS=${BUILD_WINDOWS:-y} BUILD_WINDOWS=${BUILD_WINDOWS:-y}
BUILD_DOS=${BUILD_DOS:-n} BUILD_DOS=${BUILD_DOS:-n}
BUILD_MSVC=${BUILD_MSVC:-n} BUILD_MSVC=${BUILD_MSVC:-n}
BUILD_SDL=${BUILD_SDL:-n} BUILD_SDL=${BUILD_SDL:-n}
BUILD_ANDROID=${BUILD_ANDROID:-n} BUILD_ANDROID=${BUILD_ANDROID:-n}
BUILD_WEB=${BUILD_WEB:-n} BUILD_WEB=${BUILD_WEB:-n}
BUILD_MAC=${BUILD_MAC:-n} BUILD_MAC=${BUILD_MAC:-n}
BUILD_NACL=${BUILD_NACL:-n} BUILD_NACL=${BUILD_NACL:-n}
if [ "$UID" != "0" ]; then if [ "$UID" != "0" ]; then
echo "#path config for fte build scripts" >$FTECONFIG echo "#path config for fte build scripts" >$FTECONFIG
echo "THREADS=\"$THREADS\"" >>$FTECONFIG echo "THREADS=\"$THREADS\"" >>$FTECONFIG
echo "BUILDFOLDER=\"$BUILDFOLDER\"" >>$FTECONFIG echo "BUILDFOLDER=\"$BUILDFOLDER\"" >>$FTECONFIG
echo "BUILDLOGFOLDER=\"$BUILDLOGFOLDER\"" >>$FTECONFIG echo "BUILDLOGFOLDER=\"$BUILDLOGFOLDER\"" >>$FTECONFIG
echo "SVNROOT=\"$SVNROOT\"" >>$FTECONFIG echo "SVNROOT=\"$SVNROOT\"" >>$FTECONFIG
echo "ANDROIDROOT=\"$ANDROIDROOT\"" >>$FTECONFIG echo "ANDROIDROOT=\"$ANDROIDROOT\"" >>$FTECONFIG
echo "export ANDROID_HOSTSYSTEM=\"ANDROID_HOSTSYSTEM\"" >>$FTECONFIG echo "export ANDROID_HOSTSYSTEM=\"ANDROID_HOSTSYSTEM\"" >>$FTECONFIG
echo "export ANDROID_ZIPALIGN=\"ANDROID_ZIPALIGN\"" >>$FTECONFIG echo "export ANDROID_ZIPALIGN=\"ANDROID_ZIPALIGN\"" >>$FTECONFIG
echo "EMSCRIPTENROOT=\"$EMSCRIPTENROOT\"" >>$FTECONFIG echo "EMSCRIPTENROOT=\"$EMSCRIPTENROOT\"" >>$FTECONFIG
echo "OSXCROSSROOT=\"$OSXCROSSROOT\"" >>$FTECONFIG echo "OSXCROSSROOT=\"$OSXCROSSROOT\"" >>$FTECONFIG
echo "NACLROOT=\"$NACLROOT\"" >>$FTECONFIG echo "NACLROOT=\"$NACLROOT\"" >>$FTECONFIG
echo "NACL_SDK_ROOT=\"$NACLROOT/nacl_sdk/$NACLSDKVERSION\"" >>$FTECONFIG echo "NACL_SDK_ROOT=\"$NACLROOT/nacl_sdk/$NACLSDKVERSION\"" >>$FTECONFIG
echo "NACLSDKVERSION=\"$NACLSDKVERSION\"" >>$FTECONFIG echo "NACLSDKVERSION=\"$NACLSDKVERSION\"" >>$FTECONFIG
echo "BUILD_LINUXx86=\"$BUILD_LINUXx86\"" >>$FTECONFIG echo "BUILD_LINUXx86=\"$BUILD_LINUXx86\"" >>$FTECONFIG
echo "BUILD_LINUXx64=\"$BUILD_LINUXx64\"" >>$FTECONFIG echo "BUILD_LINUXx64=\"$BUILD_LINUXx64\"" >>$FTECONFIG
echo "BUILD_LINUXx32=\"$BUILD_LINUXx32\"" >>$FTECONFIG echo "BUILD_LINUXx32=\"$BUILD_LINUXx32\"" >>$FTECONFIG
echo "BUILD_LINUXarmhf=\"$BUILD_LINUXarmhf\"" >>$FTECONFIG echo "BUILD_LINUXarmhf=\"$BUILD_LINUXarmhf\"" >>$FTECONFIG
echo "BUILD_CYGWIN=\"$BUILD_CYGWIN\"" >>$FTECONFIG echo "BUILD_CYGWIN=\"$BUILD_CYGWIN\"" >>$FTECONFIG
echo "BUILD_WINDOWS=\"$BUILD_WINDOWS\"" >>$FTECONFIG echo "BUILD_WINDOWS=\"$BUILD_WINDOWS\"" >>$FTECONFIG
echo "BUILD_DOS=\"$BUILD_DOS\"" >>$FTECONFIG echo "BUILD_DOS=\"$BUILD_DOS\"" >>$FTECONFIG
echo "BUILD_MSVC=\"$BUILD_MSVC\"" >>$FTECONFIG echo "BUILD_MSVC=\"$BUILD_MSVC\"" >>$FTECONFIG
echo "BUILD_ANDROID=\"$BUILD_ANDROID\"" >>$FTECONFIG echo "BUILD_ANDROID=\"$BUILD_ANDROID\"" >>$FTECONFIG
echo "BUILD_SDL=\"$BUILD_SDL\"" >>$FTECONFIG echo "BUILD_SDL=\"$BUILD_SDL\"" >>$FTECONFIG
echo "BUILD_WEB=\"$BUILD_WEB\"" >>$FTECONFIG echo "BUILD_WEB=\"$BUILD_WEB\"" >>$FTECONFIG
echo "BUILD_MAC=\"$BUILD_MAC\"" >>$FTECONFIG echo "BUILD_MAC=\"$BUILD_MAC\"" >>$FTECONFIG
echo "BUILD_NACL=\"$BUILD_NACL\"" >>$FTECONFIG echo "BUILD_NACL=\"$BUILD_NACL\"" >>$FTECONFIG
echo "PLUGINS_WINDOWS=\"$PLUGINS_WINDOWS\"" >>$FTECONFIG echo "PLUGINS_WINDOWS=\"$PLUGINS_WINDOWS\"" >>$FTECONFIG
echo "PLUGINS_LINUXx86=\"$PLUGINS_LINUXx86\"" >>$FTECONFIG echo "PLUGINS_LINUXx86=\"$PLUGINS_LINUXx86\"" >>$FTECONFIG
echo "PLUGINS_LINUXx64=\"$PLUGINS_LINUXx64\"" >>$FTECONFIG echo "PLUGINS_LINUXx64=\"$PLUGINS_LINUXx64\"" >>$FTECONFIG
echo "PLUGINS_LINUXx32=\"$PLUGINS_LINUXx32\"" >>$FTECONFIG echo "PLUGINS_LINUXx32=\"$PLUGINS_LINUXx32\"" >>$FTECONFIG
echo "PLUGINS_LINUXarmhf=\"$PLUGINS_LINUXarmhf\"" >>$FTECONFIG echo "PLUGINS_LINUXarmhf=\"$PLUGINS_LINUXarmhf\"" >>$FTECONFIG
fi fi
true true
true=$? true=$?
false false
false=$? false=$?
if [ "$(uname -s)" == "Linux" ]; then if [ "$(uname -s)" == "Linux" ]; then
. /etc/os-release . /etc/os-release
fi fi
function debianpackages { function debianpackages {
#make sure apt-get is installed #make sure apt-get is installed
if [ -z `which apt-get 2>>/dev/null` ]; then if [ -z `which apt-get 2>>/dev/null` ]; then
return $false return $false
fi fi
local ret=$true local ret=$true
for i in "$@" for i in "$@"
do do
dpkg -s $i 2>&1 >> /dev/null dpkg -s $i 2>&1 >> /dev/null
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
ret=$false ret=$false
fi fi
done done
if [ $ret == $false ]; then if [ $ret == $false ]; then
if [ $UID -eq 0 ]; then if [ $UID -eq 0 ]; then
apt-get install --no-install-recommends $@ apt-get install --no-install-recommends $@
ret=$true ret=$true
else else
echo "Packages not installed. Run as root to easily install dependancies." echo "Packages not installed. Run as root to easily install dependancies."
fi fi
fi fi
return $ret return $ret
} }
function jessiepackages { function jessiepackages {
if [ "$PRETTY_NAME" != "Debian GNU/Linux 8 (jessie)" ]; then if [ "$PRETTY_NAME" != "Debian GNU/Linux 8 (jessie)" ]; then
return $false return $false
fi fi
debianpackages $@ debianpackages $@
return $? return $?
} }
#we don't really know what system we're on. assume they have any system dependancies. #we don't really know what system we're on. assume they have any system dependancies.
#fixme: args are programs findable with which #fixme: args are programs findable with which
function otherpackages { function otherpackages {
if [ -z "$PRETTY_NAME" ]; then if [ -z "$PRETTY_NAME" ]; then
return $true return $true
fi fi
return $false return $false
} }
#Note: only the native linux-sdl target can be compiled, as libSDL[2]-dev doesn't support multiarch properly, and we depend upon it instead of building from source (thus ensuring it has whatever distro stuff needed... though frankly that should be inside the .so instead of the headers). #Note: only the native linux-sdl target can be compiled, as libSDL[2]-dev doesn't support multiarch properly, and we depend upon it instead of building from source (thus ensuring it has whatever distro stuff needed... though frankly that should be inside the .so instead of the headers).
if [ $UID -eq 0 ] && [ ! -z `which apt-get` ]; then if [ $UID -eq 0 ] && [ ! -z `which apt-get` ]; then
#because multiarch requires separate packages for some things, we'll need to set that up now (in case noone did that yet) #because multiarch requires separate packages for some things, we'll need to set that up now (in case noone did that yet)
dpkg --add-architecture i386 dpkg --add-architecture i386
apt-get update apt-get update
fi fi
#generic crap. much of this is needed to set up and decompress dependancies and stuff. #generic crap. much of this is needed to set up and decompress dependancies and stuff.
debianpackages subversion make automake libtool p7zip-full zip || otherpackages z7 make svn || exit debianpackages subversion make automake libtool p7zip-full zip || otherpackages z7 make svn || exit
if [ "$BUILD_LINUXx86" == "y" ]; then if [ "$BUILD_LINUXx86" == "y" ]; then
#for building linux targets #for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev libvorbis-dev || otherpackages gcc || exit debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev libvorbis-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx86" =~ "ffmpeg" ]]; then if [[ "$PLUGINS_LINUXx86" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi fi
fi fi
if [ "$BUILD_LINUXx64" == "y" ]; then if [ "$BUILD_LINUXx64" == "y" ]; then
#for building linux targets #for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx64" =~ "ffmpeg" ]]; then if [[ "$PLUGINS_LINUXx64" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi fi
fi fi
if [ "$BUILD_LINUXx32" == "y" ]; then if [ "$BUILD_LINUXx32" == "y" ]; then
#for building linux targets #for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then if [ "$BUILD_LINUXarmhf" == "y" ]; then
#for building linux targets #for building linux targets
debianpackages gcc-multilib-arm-linux-gnueabihf g++-multilib-arm-linux-gnueabihf mesa-common-dev libasound2-dev || otherpackages gcc || exit debianpackages gcc-multilib-arm-linux-gnueabihf g++-multilib-arm-linux-gnueabihf mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi fi
if [ "$BUILD_SDL" == "y" ]; then if [ "$BUILD_SDL" == "y" ]; then
#for building SDL targets #for building SDL targets
debianpackages libSDL1.2-dev libSDL2-dev libspeex-dev libspeexdsp-dev || otherpackages || exit debianpackages libSDL1.2-dev libSDL2-dev libspeex-dev libspeexdsp-dev || otherpackages || exit
fi fi
if [ "$BUILD_WINDOWS" == "y" ]; then if [ "$BUILD_WINDOWS" == "y" ]; then
#for building windows targets #for building windows targets
debianpackages mingw-w64 || otherpackages x86_64-w64-mingw32-gcc || exit debianpackages mingw-w64 || otherpackages x86_64-w64-mingw32-gcc || exit
fi fi
if [ "$BUILD_ANDROID" == "y" ]; then if [ "$BUILD_ANDROID" == "y" ]; then
( (jessiepackages openjdk-8-jdk-headless || debianpackages openjdk-8-jdk-headless ) && debianpackages ant) || otherpackages || exit ( (jessiepackages openjdk-8-jdk-headless || debianpackages openjdk-8-jdk-headless ) && debianpackages ant) || otherpackages || exit
fi fi
if [ "$BUILD_WEB" == "y" ]; then if [ "$BUILD_WEB" == "y" ]; then
( (jessiepackages cmake || debianpackages cmake) && debianpackages git build-essential) || exit ( (jessiepackages cmake || debianpackages cmake) && debianpackages git build-essential) || exit
fi fi
if [ "$BUILD_MAC" == "y" ]; then if [ "$BUILD_MAC" == "y" ]; then
debianpackages git cmake libxml2-dev fuse || otherpackages || exit debianpackages git cmake libxml2-dev fuse || otherpackages || exit
fi fi
debianpackages subversion make build-essential || otherpackages svn make || exit debianpackages subversion make build-essential || otherpackages svn make || exit
echo "System Package checks complete." echo "System Package checks complete."
if [ "$UID" == "0" ]; then if [ "$UID" == "0" ]; then
#avoid root taking ownership of anything. #avoid root taking ownership of anything.
echo "Refusing to update/rebuild toolchains as root." echo "Refusing to update/rebuild toolchains as root."
echo "Please continue running this script as a regular user." echo "Please continue running this script as a regular user."
exit exit
fi fi
echo echo
echo "(Any new toolchains will be installed to $FTEROOT)" echo "(Any new toolchains will be installed to $FTEROOT)"
echo "(Say no if you're certain you already set up everything)" echo "(Say no if you're certain you already set up everything)"
read -n 1 -p "Rebuild/update any toolchains now? [y/N] " REBUILD_TOOLCHAINS && echo read -n 1 -p "Rebuild/update any toolchains now? [y/N] " REBUILD_TOOLCHAINS && echo
REBUILD_TOOLCHAINS=${REBUILD_TOOLCHAINS:-n} REBUILD_TOOLCHAINS=${REBUILD_TOOLCHAINS:-n}
mkdir -p $FTEROOT mkdir -p $FTEROOT
#dos shit #dos shit
if [ "$BUILD_DOS" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ "$BUILD_DOS" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "You'll need to manually install djgpp for DOS builds." echo "You'll need to manually install djgpp for DOS builds."
fi fi
#android shit. WARNING: should come first as it spits out some EULAs that need confirming. #android shit. WARNING: should come first as it spits out some EULAs that need confirming.
if [ "$BUILD_ANDROID" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ "$BUILD_ANDROID" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $ANDROIDROOT mkdir -p $ANDROIDROOT
cd $ANDROIDROOT cd $ANDROIDROOT
wget -N https://dl.google.com/android/repository/tools_r25.2.3-linux.zip wget -N https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
unzip -qn tools_r25.2.3-linux.zip unzip -qn tools_r25.2.3-linux.zip
cd tools/bin cd tools/bin
#yes, android-8 is fucking old now. newer versions won't work on older devices. #yes, android-8 is fucking old now. newer versions won't work on older devices.
echo "downloading android build tools" echo "downloading android build tools"
./sdkmanager "build-tools;$ANDROID_BUILDTOOLS" ./sdkmanager "build-tools;$ANDROID_BUILDTOOLS"
echo "downloading android platform tools" echo "downloading android platform tools"
./sdkmanager "platform-tools" ./sdkmanager "platform-tools"
echo "downloading android-9" echo "downloading android-9"
./sdkmanager "platforms;android-9" ./sdkmanager "platforms;android-9"
echo "downloading android ndk" echo "downloading android ndk"
./sdkmanager "ndk-bundle" ./sdkmanager "ndk-bundle"
cd ~ cd ~
fi fi
#emscripten/web shit #emscripten/web shit
if [ "$BUILD_WEB" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ "$BUILD_WEB" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $EMSCRIPTENROOT mkdir -p $EMSCRIPTENROOT
cd $EMSCRIPTENROOT/.. cd $EMSCRIPTENROOT/..
wget -N https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz wget -N https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
cd $EMSCRIPTENROOT cd $EMSCRIPTENROOT
tar xzf ../emsdk-portable.tar.gz --strip-components=1 tar xzf ../emsdk-portable.tar.gz --strip-components=1
./emsdk install latest ./emsdk install latest
./emsdk activate latest ./emsdk activate latest
cd ~ cd ~
fi fi
#osxcross, for mac crap #osxcross, for mac crap
if [ "$BUILD_MAC" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ "$BUILD_MAC" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up OSXCross... THIS IS TOTALLY UNTESTED" echo "Setting up OSXCross... THIS IS TOTALLY UNTESTED"
read -p "You need to download xcode first. Where did you download the .dmg file to?" XCODE read -p "You need to download xcode first. Where did you download the .dmg file to?" XCODE
git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSSROOT git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSSROOT
cd $OSXCROSSROOT cd $OSXCROSSROOT
tools/gen_sdk_package_darling_dmg.sh $XCODE tools/gen_sdk_package_darling_dmg.sh $XCODE
cp *.tar.xz cp *.tar.xz
SDK_VERSION=10.10 UNATTENDED=0 ./build.sh SDK_VERSION=10.10 UNATTENDED=0 ./build.sh
cd ~ cd ~
fi fi
if [ "$BUILD_NACL" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ "$BUILD_NACL" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up NaCL..." echo "Setting up NaCL..."
mkdir -p $NACLROOT mkdir -p $NACLROOT
cd $NACLROOT/.. cd $NACLROOT/..
wget -N https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip wget -N https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip
unzip -qn nacl_sdk.zip unzip -qn nacl_sdk.zip
cd $NACLROOT cd $NACLROOT
./naclsdk update $NACLSDKVERSION ./naclsdk update $NACLSDKVERSION
fi fi
#initial checkout of fte's svn #initial checkout of fte's svn
if [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then if [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
if [ ! -d $SVNROOT ]; then if [ ! -d $SVNROOT ]; then
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
else else
cd $SVNROOT cd $SVNROOT
svn up svn up
fi fi
#FIXME: there may be race conditions when compiling. #FIXME: there may be race conditions when compiling.
#so make sure we've pre-built certain targets without using -j #so make sure we've pre-built certain targets without using -j
#linux distros vary too much with various dependancies and versions and such, so we might as well pre-build our own copies of certain libraries. this really only needs to be done once, but its safe to retry anyway. #linux distros vary too much with various dependancies and versions and such, so we might as well pre-build our own copies of certain libraries. this really only needs to be done once, but its safe to retry anyway.
cd $SVNROOT/engine cd $SVNROOT/engine
if [ "$BUILD_LINUXx86" == "y" ]; then if [ "$BUILD_LINUXx86" == "y" ]; then
echo "Making libraries (x86)..." echo "Making libraries (x86)..."
make FTE_TARGET=linux32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linux32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_LINUXx64" == "y" ]; then if [ "$BUILD_LINUXx64" == "y" ]; then
echo "Making libraries (linux x86_64)..." echo "Making libraries (linux x86_64)..."
make FTE_TARGET=linux64 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linux64 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_LINUXx32" == "y" ]; then if [ "$BUILD_LINUXx32" == "y" ]; then
echo "Making libraries (linux x32)..." echo "Making libraries (linux x32)..."
make FTE_TARGET=linuxx32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linuxx32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then if [ "$BUILD_LINUXarmhf" == "y" ]; then
echo "Making libraries (linux armhf)..." echo "Making libraries (linux armhf)..."
make FTE_TARGET=linuxarmhf makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linuxarmhf makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_WINDOWS" == "y" ] && [[ "$PLUGINS_WINDOWS" =~ "ode" ]]; then if [ "$BUILD_WINDOWS" == "y" ] && [[ "$PLUGINS_WINDOWS" =~ "ode" ]]; then
echo "Prebuilding ODE library (win32)..." echo "Prebuilding ODE library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
echo "Prebuilding ODE library (win64)..." echo "Prebuilding ODE library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
fi fi
if [ "$BUILD_LINUXx86" == "y" ] && [[ "$PLUGINS_LINUXx86" =~ "ode" ]]; then if [ "$BUILD_LINUXx86" == "y" ] && [[ "$PLUGINS_LINUXx86" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86)..." echo "Prebuilding ODE library (linux x86)..."
make FTE_TARGET=linux32 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linux32 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_LINUXx64" == "y" ] && [[ "$PLUGINS_LINUXx64" =~ "ode" ]]; then if [ "$BUILD_LINUXx64" == "y" ] && [[ "$PLUGINS_LINUXx64" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86_64)..." echo "Prebuilding ODE library (linux x86_64)..."
make FTE_TARGET=linux64 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null make FTE_TARGET=linux64 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi fi
if [ "$BUILD_WINDOWS" == "y" ]; then if [ "$BUILD_WINDOWS" == "y" ]; then
echo "Obtaining ffmpeg library (win32)..." echo "Obtaining ffmpeg library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
echo "Obtaining ffmpeg library (win64)..." echo "Obtaining ffmpeg library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
fi fi
cd ~ cd ~
fi fi
echo "Setup script complete." echo "Setup script complete."
echo "When you run build_wip.sh output will be written to $BUILDFOLDER/*" echo "When you run build_wip.sh output will be written to $BUILDFOLDER/*"

View File

@ -1,329 +1,329 @@
#!/bin/bash #!/bin/bash
START=$(date +%s) START=$(date +%s)
SVNROOT=$(cd "$(dirname "$(readlink "$BASH_SOURCE")")" && pwd) SVNROOT=$(cd "$(dirname "$(readlink "$BASH_SOURCE")")" && pwd)
FTECONFIG=$SVNROOT/build.cfg FTECONFIG=$SVNROOT/build.cfg
HOME=`echo ~` HOME=`echo ~`
BASE=$SVNROOT/.. BASE=$SVNROOT/..
#set this if you want non-default branding, for customised builds. #set this if you want non-default branding, for customised builds.
#export BRANDING=wastes #export BRANDING=wastes
#defaults, if we're not set up properly. #defaults, if we're not set up properly.
#should be overriden in build.cfg #should be overriden in build.cfg
BUILDFOLDER=$HOME/htdocs BUILDFOLDER=$HOME/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs BUILDLOGFOLDER=$BUILDFOLDER/build_logs
SVNROOT=$BASE/fteqw-code SVNROOT=$BASE/fteqw-code
BUILD_LINUXx86=y BUILD_LINUXx86=y
BUILD_LINUXx64=y BUILD_LINUXx64=y
BUILD_WINDOWS=y BUILD_WINDOWS=y
BUILD_ANDROID=y BUILD_ANDROID=y
BUILD_WEB=y BUILD_WEB=y
PLUGINS_LINUXx86="qi ezhud xmpp irc" PLUGINS_LINUXx86="qi ezhud xmpp irc"
PLUGINS_LINUXx64="qi ezhud xmpp irc" PLUGINS_LINUXx64="qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc" PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_WINDOWS="avplug ode qi ezhud xmpp irc" PLUGINS_WINDOWS="avplug ode qi ezhud xmpp irc"
THREADS="-j 4" THREADS="-j 4"
########### NaCL stuff ########### NaCL stuff
NACL_SDK_ROOT=/opt/nacl_sdk/pepper_31/ NACL_SDK_ROOT=/opt/nacl_sdk/pepper_31/
if [ -e $FTECONFIG ]; then if [ -e $FTECONFIG ]; then
. $FTECONFIG . $FTECONFIG
else else
echo "WARNING: $FTECONFIG does not exist yet." echo "WARNING: $FTECONFIG does not exist yet."
fi fi
export NACL_SDK_ROOT export NACL_SDK_ROOT
########### Emscripten / Web Stuff ########### Emscripten / Web Stuff
export EMSDK=$EMSCRIPTENROOT export EMSDK=$EMSCRIPTENROOT
#export WEB_PREJS="--pre-js $HOME/prejs.js" #export WEB_PREJS="--pre-js $HOME/prejs.js"
########### Android Stuff. so messy... ########### Android Stuff. so messy...
#This is some android password that you should keep private. You should keep the keystore file private too, of course. Frankly, that part is more important than this small random number. #This is some android password that you should keep private. You should keep the keystore file private too, of course. Frankly, that part is more important than this small random number.
KEYPASSFILE=$BASE/.fte_keypass KEYPASSFILE=$BASE/.fte_keypass
if [ ! -e $KEYPASSFILE ]; then if [ ! -e $KEYPASSFILE ]; then
dd if=/dev/urandom count=9 bs=1 2>/dev/null | base64 > $KEYPASSFILE dd if=/dev/urandom count=9 bs=1 2>/dev/null | base64 > $KEYPASSFILE
chmod 400 $KEYPASSFILE chmod 400 $KEYPASSFILE
fi fi
KEYPASS=`cat $KEYPASSFILE` KEYPASS=`cat $KEYPASSFILE`
export JAVA_HOME=/usr export JAVA_HOME=/usr
if [ ! -z "$ANDROIDROOT" ]; then if [ ! -z "$ANDROIDROOT" ]; then
export ANDROID_HOME=$ANDROIDROOT export ANDROID_HOME=$ANDROIDROOT
fi fi
if [ ! -z "$ANDROIDNDKROOT" ]; then if [ ! -z "$ANDROIDNDKROOT" ]; then
export ANDROID_NDK_ROOT=$ANDROIDNDKROOT export ANDROID_NDK_ROOT=$ANDROIDNDKROOT
else else
export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk-bundle export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk-bundle
fi fi
export KEYTOOLARGS="-keypass $KEYPASS -storepass $KEYPASS -dname \"CN=fteqw.com, OU=ID, O=FTE, L=Unknown, S=Unknown, C=GB\"" export KEYTOOLARGS="-keypass $KEYPASS -storepass $KEYPASS -dname \"CN=fteqw.com, OU=ID, O=FTE, L=Unknown, S=Unknown, C=GB\""
export JARSIGNARGS="-storepass $KEYPASS" export JARSIGNARGS="-storepass $KEYPASS"
########### Various Output etc Paths ########### Various Output etc Paths
QCCBUILDFOLDER=$BUILDFOLDER/fteqcc QCCBUILDFOLDER=$BUILDFOLDER/fteqcc
SVNFOLDER=$SVNROOT/engine/release SVNFOLDER=$SVNROOT/engine/release
ARCHIVEFOLDER=$BUILDFOLDER/archive ARCHIVEFOLDER=$BUILDFOLDER/archive
SVNDBGFOLDER=$SVNROOT/engine/debug SVNDBGFOLDER=$SVNROOT/engine/debug
WARNINGLEVEL="-w" WARNINGLEVEL="-w"
FILELOCK=$BASE/.fte_buildlock FILELOCK=$BASE/.fte_buildlock
#./ccache-alias.sh #./ccache-alias.sh
exec 9>$FILELOCK exec 9>$FILELOCK
if ! flock -n 9 ; then if ! flock -n 9 ; then
echo "Build script is already running!"; echo "Build script is already running!";
exit 1 exit 1
fi fi
mkdir -p $BUILDLOGFOLDER mkdir -p $BUILDLOGFOLDER
if [ ! -d $SVNROOT ]; then if [ ! -d $SVNROOT ]; then
#just in case... #just in case...
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
fi fi
cd $SVNROOT/ cd $SVNROOT/
echo "SVN Update" echo "SVN Update"
svn update svn update
cd engine cd engine
date > $BUILDLOGFOLDER/buildlog.txt date > $BUILDLOGFOLDER/buildlog.txt
echo "Starting build" >> $BUILDLOGFOLDER/buildlog.txt echo "Starting build" >> $BUILDLOGFOLDER/buildlog.txt
function build { function build {
BUILDSTART=$(date +%s) BUILDSTART=$(date +%s)
NAME=$1 NAME=$1
DEST=$2 DEST=$2
shift; shift shift; shift
make clean >> /dev/null make clean >> /dev/null
echo -n "Making $NAME... " echo -n "Making $NAME... "
date > $BUILDLOGFOLDER/$DEST.txt date > $BUILDLOGFOLDER/$DEST.txt
echo make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1 echo make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1 make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
BUILDEND=$(date +%s) BUILDEND=$(date +%s)
BUILDTIME=$(( $BUILDEND - $BUILDSTART )) BUILDTIME=$(( $BUILDEND - $BUILDSTART ))
echo "$BUILDTIME seconds" echo "$BUILDTIME seconds"
echo "$NAME done, took $BUILDTIME seconds" >> $BUILDLOGFOLDER/buildlog.txt echo "$NAME done, took $BUILDTIME seconds" >> $BUILDLOGFOLDER/buildlog.txt
rm -rf $BUILDFOLDER/$DEST >> /dev/null 2>&1 rm -rf $BUILDFOLDER/$DEST >> /dev/null 2>&1
mkdir $BUILDFOLDER/$DEST 2>> /dev/null mkdir $BUILDFOLDER/$DEST 2>> /dev/null
mkdir $BUILDFOLDER/$DEST/debug 2>> /dev/null mkdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
cp $SVNFOLDER/* $BUILDFOLDER/$DEST >> /dev/null 2>> /dev/null cp $SVNFOLDER/* $BUILDFOLDER/$DEST >> /dev/null 2>> /dev/null
cp $SVNDBGFOLDER/* $BUILDFOLDER/$DEST/debug >> /dev/null 2>> /dev/null cp $SVNDBGFOLDER/* $BUILDFOLDER/$DEST/debug >> /dev/null 2>> /dev/null
rm -rf $BUILDFOLDER/$DEST/*.a >> /dev/null 2>&1 rm -rf $BUILDFOLDER/$DEST/*.a >> /dev/null 2>&1
rm -rf $BUILDFOLDER/$DEST/debug/*.a >> /dev/null 2>&1 rm -rf $BUILDFOLDER/$DEST/debug/*.a >> /dev/null 2>&1
rmdir $BUILDFOLDER/$DEST/debug 2>> /dev/null rmdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
else else
echo "$NAME failed" >> $BUILDLOGFOLDER/buildlog.txt echo "$NAME failed" >> $BUILDLOGFOLDER/buildlog.txt
echo "failed" echo "failed"
fi fi
} }
function build_fteqcc { function build_fteqcc {
echo "--- no code ---" echo "--- no code ---"
} }
echo "--- Engine builds ---" echo "--- Engine builds ---"
#the -fno-finite-math-only is to avoid a glibc dependancy #the -fno-finite-math-only is to avoid a glibc dependancy
if [ "$BUILD_LINUXx86" != "n" ]; then if [ "$BUILD_LINUXx86" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx86" build "Linux 32-bit" linux_x86 FTE_TARGET=linux32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg NATIVE_PLUGINS="$PLUGINS_LINUXx86" build "Linux 32-bit" linux_x86 FTE_TARGET=linux32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi fi
if [ "$BUILD_LINUXx64" != "n" ]; then if [ "$BUILD_LINUXx64" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx64" build "Linux 64-bit" linux_amd64 FTE_TARGET=linux64 LDFLAGS="-Llibs/64" CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg NATIVE_PLUGINS="$PLUGINS_LINUXx64" build "Linux 64-bit" linux_amd64 FTE_TARGET=linux64 LDFLAGS="-Llibs/64" CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi fi
if [ "$BUILD_LINUXx32" != "n" ]; then if [ "$BUILD_LINUXx32" != "n" ]; then
# CFLAGS="-DNO_JPEG" # CFLAGS="-DNO_JPEG"
NATIVE_PLUGINS="$PLUGINS_LINUXx32" build "Linux x32" linux_x32 FTE_TARGET=linuxx32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg plugins-rel plugins-dbg NATIVE_PLUGINS="$PLUGINS_LINUXx32" build "Linux x32" linux_x32 FTE_TARGET=linuxx32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg plugins-rel plugins-dbg
fi fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then if [ "$BUILD_LINUXarmhf" != "n" ]; then
#debian/ubuntu's armhf targets armv7. we instead target armv6, because that means we work on rpi too (but still with hard-float). It should be compatible although we likely need more ops. #debian/ubuntu's armhf targets armv7. we instead target armv6, because that means we work on rpi too (but still with hard-float). It should be compatible although we likely need more ops.
NATIVE_PLUGINS="$PLUGINS_LINUXarmhf" build "Linux ARMhf" linux_armhf FTE_TARGET=linuxarmhf CPUOPTIMIZATIONS=-fno-finite-math-only rel dbg qcc-rel plugins-rel plugins-dbg NATIVE_PLUGINS="$PLUGINS_LINUXarmhf" build "Linux ARMhf" linux_armhf FTE_TARGET=linuxarmhf CPUOPTIMIZATIONS=-fno-finite-math-only rel dbg qcc-rel plugins-rel plugins-dbg
fi fi
if [ "$BUILD_CYGWIN" != "n" ]; then if [ "$BUILD_CYGWIN" != "n" ]; then
NATIVE_PLUGINS="qi ezhud" build "Cygwin" cygwin qcc-rel rel dbg plugins-rel plugins-dbg NATIVE_PLUGINS="qi ezhud" build "Cygwin" cygwin qcc-rel rel dbg plugins-rel plugins-dbg
fi fi
if [ "$BUILD_WINDOWS" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 32-bit" win32 FTE_TARGET=win32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS" NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 32-bit" win32 FTE_TARGET=win32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS"
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 64-bit" win64 FTE_TARGET=win64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 64-bit" win64 FTE_TARGET=win64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi fi
if [ "$BUILD_MSVC" != "n" ]; then if [ "$BUILD_MSVC" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 32-bit" msvc FTE_TARGET=vc BITS=32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 32-bit" msvc FTE_TARGET=vc BITS=32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 64-bit" msvc FTE_TARGET=vc BITS=64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 64-bit" msvc FTE_TARGET=vc BITS=64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi fi
export NATIVE_PLUGINS="qi ezhud xmpp irc" export NATIVE_PLUGINS="qi ezhud xmpp irc"
if [ "$BUILD_ANDROID" != "n" ]; then if [ "$BUILD_ANDROID" != "n" ]; then
build "Android" android droid-rel build "Android" android droid-rel
fi fi
if [ "$BUILD_WINDOWS" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ]; then
build "NPFTE" npfte npfte-rel build "NPFTE" npfte npfte-rel
fi fi
if [ "$BUILD_DOS" == "y" ]; then if [ "$BUILD_DOS" == "y" ]; then
#no networking makes dedicated servers useless. and only a crappy sw renderer is implemented right now. #no networking makes dedicated servers useless. and only a crappy sw renderer is implemented right now.
#the qcc might be useful to someone though! #the qcc might be useful to someone though!
build "DOS" dos m-rel qcc-rel build "DOS" dos m-rel qcc-rel
fi fi
if [ "$BUILD_WEB" != "n" ]; then if [ "$BUILD_WEB" != "n" ]; then
source $EMSDK/emsdk_env.sh >> /dev/null source $EMSDK/emsdk_env.sh >> /dev/null
build "Emscripten" web FTE_TARGET=web gl-rel CC=emcc build "Emscripten" web FTE_TARGET=web gl-rel CC=emcc
fi fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" != "x86_64" ]; then if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" != "x86_64" ]; then
build "Linux 32-bit (SDL)" linux_x86_sdl FTE_TARGET=SDL BITS=32 LTO=1 build "Linux 32-bit (SDL)" linux_x86_sdl FTE_TARGET=SDL BITS=32 LTO=1
fi fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" == "x86_64" ]; then if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" == "x86_64" ]; then
build "Linux 64-bit (SDL)" linux_amd64_sdl FTE_TARGET=SDL BITS=64 LDFLAGS="-Llibs/64" LTO=1 build "Linux 64-bit (SDL)" linux_amd64_sdl FTE_TARGET=SDL BITS=64 LDFLAGS="-Llibs/64" LTO=1
fi fi
if [ "$BUILD_WINDOWS" != "n" ] && [ "$BUILD_SDL" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ] && [ "$BUILD_SDL" != "n" ]; then
build "Windows 32-bit (SDL)" win32_sdl FTE_TARGET=win32_SDL gl-rel mingl-rel build "Windows 32-bit (SDL)" win32_sdl FTE_TARGET=win32_SDL gl-rel mingl-rel
build "Windows 64-bit (SDL)" win64_sdl FTE_TARGET=win64_SDL LDFLAGS="-L./libs/mingw64-libs/" gl-rel mingl-rel build "Windows 64-bit (SDL)" win64_sdl FTE_TARGET=win64_SDL LDFLAGS="-L./libs/mingw64-libs/" gl-rel mingl-rel
CFLAGS="$WARNINGLEVEL -DNOLEGACY -DOMIT_QCC" build "Windows 32-bit nocompat" nocompat FTE_TARGET=win32 LTO=1 NOCOMPAT=1 BOTLIB_CFLAGS="" BOTLIB_OBJS="" gl-rel m-rel -k CFLAGS="$WARNINGLEVEL -DNOLEGACY -DOMIT_QCC" build "Windows 32-bit nocompat" nocompat FTE_TARGET=win32 LTO=1 NOCOMPAT=1 BOTLIB_CFLAGS="" BOTLIB_OBJS="" gl-rel m-rel -k
fi fi
if [ "$BUILD_NACL" != "n" ]; then if [ "$BUILD_NACL" != "n" ]; then
#non-pnacl is supported ONLY in chrome's store crap, but pnacl works anywhere. #non-pnacl is supported ONLY in chrome's store crap, but pnacl works anywhere.
# build "Native Client 64-bit" nacl_amd64 FTE_TARGET=nacl NARCH=x86_64 gl-rel # build "Native Client 64-bit" nacl_amd64 FTE_TARGET=nacl NARCH=x86_64 gl-rel
# build "Native Client 32-bit" nacl_x86 FTE_TARGET=nacl NARCH=x86_32 gl-rel # build "Native Client 32-bit" nacl_x86 FTE_TARGET=nacl NARCH=x86_32 gl-rel
#internal compiler error build "Native Client ARM" nacl_arm FTE_TARGET=nacl NARCH=arm gl-rel #internal compiler error build "Native Client ARM" nacl_arm FTE_TARGET=nacl NARCH=arm gl-rel
build "Native Client Portable" nacl_portable FTE_TARGET=nacl NARCH=pnacl gl-rel build "Native Client Portable" nacl_portable FTE_TARGET=nacl NARCH=pnacl gl-rel
fi fi
####build "MorphOS" morphos CFLAGS="-I$BASE/morphos/os-include/ -I$BASE/morphos/lib/ -L$BASE/morphos/lib/ -I$BASE/zlib/zlib-1.2.5 -L$BASE/zlib/zlib-1.2.5 -I./libs $WARNINGLEVEL" gl-rel mingl-rel sv-rel qcc-rel ####build "MorphOS" morphos CFLAGS="-I$BASE/morphos/os-include/ -I$BASE/morphos/lib/ -L$BASE/morphos/lib/ -I$BASE/zlib/zlib-1.2.5 -L$BASE/zlib/zlib-1.2.5 -I./libs $WARNINGLEVEL" gl-rel mingl-rel sv-rel qcc-rel
if [ "$BUILD_MAC" != "n" ]; then if [ "$BUILD_MAC" != "n" ]; then
#build "MacOSX" macosx_tiger CFLAGS="-I$BASE/mac/x86/include/ -L$BASE/mac/x86/lib -I./libs" FTE_TARGET=macosx_x86 sv-rel gl-rel mingl-rel qcc-rel #build "MacOSX" macosx_tiger CFLAGS="-I$BASE/mac/x86/include/ -L$BASE/mac/x86/lib -I./libs" FTE_TARGET=macosx_x86 sv-rel gl-rel mingl-rel qcc-rel
#FIXME: figure out how to do universal binaries or whatever they're called #FIXME: figure out how to do universal binaries or whatever they're called
build "MacOSX 32-bit" osx32 CC=o32-clang CXX=o32-clang++ FTE_TARGET=osx_x86 BITS=32 sv-rel gl-rel mingl-rel qcc-rel build "MacOSX 32-bit" osx32 CC=o32-clang CXX=o32-clang++ FTE_TARGET=osx_x86 BITS=32 sv-rel gl-rel mingl-rel qcc-rel
build "MacOSX 64-bit" osx64 CC=o64-clang CXX=o64-clang++ FTE_TARGET=osx_x86_64 BITS=64 sv-rel gl-rel mingl-rel qcc-rel build "MacOSX 64-bit" osx64 CC=o64-clang CXX=o64-clang++ FTE_TARGET=osx_x86_64 BITS=64 sv-rel gl-rel mingl-rel qcc-rel
fi fi
#third party stuff / misc crap #third party stuff / misc crap
if [ "$BUILD_WEB" != "n" ]; then if [ "$BUILD_WEB" != "n" ]; then
cp $BASE/3rdparty/web/* $BUILDFOLDER/web/ cp $BASE/3rdparty/web/* $BUILDFOLDER/web/
fi fi
if [ "$BUILD_WINDOWS" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BASE/3rdparty/win32/3rdparty.zip $BUILDFOLDER/win32/3rdparty.zip cp $BASE/3rdparty/win32/3rdparty.zip $BUILDFOLDER/win32/3rdparty.zip
cp $BASE/3rdparty/win64/3rdparty.zip $BUILDFOLDER/win64/3rdparty.zip cp $BASE/3rdparty/win64/3rdparty.zip $BUILDFOLDER/win64/3rdparty.zip
if [ "$BUILD_SDL" != "n" ]; then if [ "$BUILD_SDL" != "n" ]; then
cp $SVNROOT/engine/libs/SDL2-2.0.1/i686-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win32_sdl cp $SVNROOT/engine/libs/SDL2-2.0.1/i686-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win32_sdl
cp $SVNROOT/engine/libs/SDL2-2.0.1/x86_64-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win64_sdl cp $SVNROOT/engine/libs/SDL2-2.0.1/x86_64-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win64_sdl
fi fi
cp $HOME/nocompat_readme.html $BUILDFOLDER/nocompat/README.html cp $HOME/nocompat_readme.html $BUILDFOLDER/nocompat/README.html
fi fi
echo "--- QC builds ---" echo "--- QC builds ---"
rm -rf $QCCBUILDFOLDER 2>&1 rm -rf $QCCBUILDFOLDER 2>&1
mkdir -p $QCCBUILDFOLDER mkdir -p $QCCBUILDFOLDER
if [ -e "$BUILDFOLDER/linux_x86/fteqw-gl32" ] if [ -e "$BUILDFOLDER/linux_x86/fteqw-gl32" ]
then then
echo "Making fteextensions.qc" echo "Making fteextensions.qc"
mkdir -p ~/.fte/fte mkdir -p ~/.fte/fte
echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg
$BUILDFOLDER/linux_x86/fteqw-gl32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null $BUILDFOLDER/linux_x86/fteqw-gl32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null
mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER
else else
echo "Skipping FTE Extensions, no Linux gl32 build located" echo "Skipping FTE Extensions, no Linux gl32 build located"
fi fi
if [ -e $BUILDFOLDER/linux_x86/fteqcc32 ]; then if [ -e $BUILDFOLDER/linux_x86/fteqcc32 ]; then
echo "Making csaddon + qcmenu" echo "Making csaddon + qcmenu"
mkdir -p $BUILDFOLDER/csaddon/ mkdir -p $BUILDFOLDER/csaddon/
cd $SVNROOT/quakec cd $SVNROOT/quakec
cd csaddon/src cd csaddon/src
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt $BUILDFOLDER/linux_x86/fteqcc32 -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt
mv ../csaddon.dat $BUILDFOLDER/csaddon/ mv ../csaddon.dat $BUILDFOLDER/csaddon/
cd ../../menusys cd ../../menusys
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile menu.src > $BUILDLOGFOLDER/menu.txt $BUILDFOLDER/linux_x86/fteqcc32 -srcfile menu.src > $BUILDLOGFOLDER/menu.txt
rm fteqcc.log rm fteqcc.log
zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip . zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip .
mv ../menu.dat $BUILDFOLDER/csaddon/ mv ../menu.dat $BUILDFOLDER/csaddon/
else else
echo "Skiping csaddon + qcmenu, no compiler build" echo "Skiping csaddon + qcmenu, no compiler build"
fi fi
cd $SVNROOT/engine/ cd $SVNROOT/engine/
svn info > $BUILDFOLDER/version.txt svn info > $BUILDFOLDER/version.txt
if [ "$BUILD_LINUXx86" != "n" ]; then if [ "$BUILD_LINUXx86" != "n" ]; then
cp $BUILDFOLDER/linux_x86/fteqcc32 $QCCBUILDFOLDER/linux32-fteqcc cp $BUILDFOLDER/linux_x86/fteqcc32 $QCCBUILDFOLDER/linux32-fteqcc
fi fi
if [ "$BUILD_LINUXx64" != "n" ]; then if [ "$BUILD_LINUXx64" != "n" ]; then
cp $BUILDFOLDER/linux_amd64/fteqcc64 $QCCBUILDFOLDER/linux64-fteqcc cp $BUILDFOLDER/linux_amd64/fteqcc64 $QCCBUILDFOLDER/linux64-fteqcc
fi fi
if [ "$BUILD_LINUXx32" != "n" ]; then if [ "$BUILD_LINUXx32" != "n" ]; then
cp $BUILDFOLDER/linux_x32/fteqccx32 $QCCBUILDFOLDER/linuxx32-fteqcc cp $BUILDFOLDER/linux_x32/fteqccx32 $QCCBUILDFOLDER/linuxx32-fteqcc
fi fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then if [ "$BUILD_LINUXarmhf" != "n" ]; then
cp $BUILDFOLDER/linux_armhf/fteqccarmhf $QCCBUILDFOLDER/linuxarmhf-fteqcc cp $BUILDFOLDER/linux_armhf/fteqccarmhf $QCCBUILDFOLDER/linuxarmhf-fteqcc
fi fi
if [ "$BUILD_WINDOWS" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BUILDFOLDER/win32/fteqcc.exe $QCCBUILDFOLDER/win32-fteqcc.exe cp $BUILDFOLDER/win32/fteqcc.exe $QCCBUILDFOLDER/win32-fteqcc.exe
cp $BUILDFOLDER/win32/fteqccgui.exe $QCCBUILDFOLDER/win32-fteqccgui.exe cp $BUILDFOLDER/win32/fteqccgui.exe $QCCBUILDFOLDER/win32-fteqccgui.exe
cp $BUILDFOLDER/win64/fteqcc64.exe $QCCBUILDFOLDER/win64-fteqcc.exe cp $BUILDFOLDER/win64/fteqcc64.exe $QCCBUILDFOLDER/win64-fteqcc.exe
cp $BUILDFOLDER/win64/fteqccgui64.exe $QCCBUILDFOLDER/win64-fteqccgui.exe cp $BUILDFOLDER/win64/fteqccgui64.exe $QCCBUILDFOLDER/win64-fteqccgui.exe
fi fi
#cp $BUILDFOLDER/morphos/fteqcc $QCCBUILDFOLDER/morphos-fteqcc #cp $BUILDFOLDER/morphos/fteqcc $QCCBUILDFOLDER/morphos-fteqcc
#cp $BUILDFOLDER/macosx_tiger/fteqcc $QCCBUILDFOLDER/macosx_tiger-fteqcc #cp $BUILDFOLDER/macosx_tiger/fteqcc $QCCBUILDFOLDER/macosx_tiger-fteqcc
cp $BUILDFOLDER/version.txt $QCCBUILDFOLDER/version.txt cp $BUILDFOLDER/version.txt $QCCBUILDFOLDER/version.txt
if [ "$BUILD_NACL" != "n" ]; then if [ "$BUILD_NACL" != "n" ]; then
mkdir -p $BUILDFOLDER/nacl mkdir -p $BUILDFOLDER/nacl
NACL=$BUILDFOLDER/nacl/fteqw.nmf NACL=$BUILDFOLDER/nacl/fteqw.nmf
echo "{ \"program\":{" > $NACL echo "{ \"program\":{" > $NACL
if [ -e "$BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe" ]; then if [ -e "$BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe" ]; then
mv $BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe $BUILDFOLDER/nacl/fteqw-x86_64.nexe mv $BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe $BUILDFOLDER/nacl/fteqw-x86_64.nexe
echo " \"x86-64\":{\"url\":\"fteqw-x86_64.nexe\"}," >> $NACL echo " \"x86-64\":{\"url\":\"fteqw-x86_64.nexe\"}," >> $NACL
fi fi
if [ -e "$BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe" ]; then if [ -e "$BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe" ]; then
mv $BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe $BUILDFOLDER/nacl/fteqw-x86_32.nexe mv $BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe $BUILDFOLDER/nacl/fteqw-x86_32.nexe
echo " \"x86-32\":{\"url\":\"fteqw-x86_32.nexe\"}," >> $NACL echo " \"x86-32\":{\"url\":\"fteqw-x86_32.nexe\"}," >> $NACL
fi fi
if [ -e "$BUILDFOLDER/nacl_arm/fteqw-arm.nexe" ]; then if [ -e "$BUILDFOLDER/nacl_arm/fteqw-arm.nexe" ]; then
mv $BUILDFOLDER/nacl_arm/fteqw-arm.nexe $BUILDFOLDER/nacl/fteqw-arm.nexe mv $BUILDFOLDER/nacl_arm/fteqw-arm.nexe $BUILDFOLDER/nacl/fteqw-arm.nexe
echo " \"arm\":{\"url\":\"fteqw-arm.nexe\"}" >> $NACL echo " \"arm\":{\"url\":\"fteqw-arm.nexe\"}" >> $NACL
fi fi
$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-finalize -o $BUILDFOLDER/nacl/fteqw.pexe $BUILDFOLDER/nacl_portable/fteqw.pexe $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-finalize -o $BUILDFOLDER/nacl/fteqw.pexe $BUILDFOLDER/nacl_portable/fteqw.pexe
echo " \"portable\":{\"pnacl-translate\":{\"url\":\"fteqw.pexe\"}}" >> $NACL echo " \"portable\":{\"pnacl-translate\":{\"url\":\"fteqw.pexe\"}}" >> $NACL
echo "} }" >> $NACL echo "} }" >> $NACL
rm -rf "$BUILDFOLDER/nacl_amd64" rm -rf "$BUILDFOLDER/nacl_amd64"
rm -rf "$BUILDFOLDER/nacl_x86" rm -rf "$BUILDFOLDER/nacl_x86"
rm -rf "$BUILDFOLDER/nacl_arm" rm -rf "$BUILDFOLDER/nacl_arm"
rm -rf "$BUILDFOLDER/nacl_portable" rm -rf "$BUILDFOLDER/nacl_portable"
fi fi
if [ "$BUILD_WINDOWS" != "n" ]; then if [ "$BUILD_WINDOWS" != "n" ]; then
echo Archiving output echo Archiving output
SVNVER=$(svnversion $SVNROOT) SVNVER=$(svnversion $SVNROOT)
cd $BUILDFOLDER/ cd $BUILDFOLDER/
zip -q -9 $ARCHIVEFOLDER/win_fteqw_$SVNVER.zip win32/fteglqw.exe win32/fteqwsv.exe win32/fteqccgui.exe win32/debug/fteglqw.exe win64/fteqw.exe win64/debug/fteglqw.exe zip -q -9 $ARCHIVEFOLDER/win_fteqw_$SVNVER.zip win32/fteglqw.exe win32/fteqwsv.exe win32/fteqccgui.exe win32/debug/fteglqw.exe win64/fteqw.exe win64/debug/fteglqw.exe
cd $BUILDFOLDER/win32/ cd $BUILDFOLDER/win32/
zip -q -j -9 $BUILDFOLDER/fteqw_for_windows.zip fteglqw.exe fteqwsv.exe fteqccgui.exe fteplug_qi_x86.dll fteplug_xmpp_x86.dll fteplug_irc_x86.dll fteplug_ezhud_x86.dll zip -q -j -9 $BUILDFOLDER/fteqw_for_windows.zip fteglqw.exe fteqwsv.exe fteqccgui.exe fteplug_qi_x86.dll fteplug_xmpp_x86.dll fteplug_irc_x86.dll fteplug_ezhud_x86.dll
cd $HOME/3rdparty_win32/ cd $HOME/3rdparty_win32/
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip ogg.dll vorbis.dll vorbisfile.dll freetype6.dll zlib1.dll zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip ogg.dll vorbis.dll vorbisfile.dll freetype6.dll zlib1.dll
mkdir -p $BASE/tmp/fte mkdir -p $BASE/tmp/fte
cd $BASE/tmp/ cd $BASE/tmp/
cp $BUILDFOLDER/csaddon/menu.dat fte cp $BUILDFOLDER/csaddon/menu.dat fte
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip fte/menu.dat zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip fte/menu.dat
#~/afterquake/updatemini.sh #~/afterquake/updatemini.sh
fi fi
echo "All done" echo "All done"
END=$(date +%s) END=$(date +%s)
DIFF=$(( $END - $START )) DIFF=$(( $END - $START ))
MINS=$(( $DIFF / 60 )) MINS=$(( $DIFF / 60 ))
echo "Total Compile Time: $MINS minutes" >> $BUILDLOGFOLDER/buildlog.txt echo "Total Compile Time: $MINS minutes" >> $BUILDLOGFOLDER/buildlog.txt
echo "Total Compile Time: $MINS minutes" echo "Total Compile Time: $MINS minutes"
cd $HOME cd $HOME
#./errorlog.sh #./errorlog.sh
#cd $HOME #cd $HOME
#rm .bitchxrc #rm .bitchxrc
#cp ./fteqw/.bitchxrc ./ #cp ./fteqw/.bitchxrc ./
#./BitchX -a irc.quakenet.org -A -c "#fte" -n A_Gorilla #./BitchX -a irc.quakenet.org -A -c "#fte" -n A_Gorilla

View File

@ -4235,7 +4235,7 @@ void CL_LinkPacketEntities (void)
{ {
if (trailef == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, trailef, ent->keynum, ent->axis, &(le->trailstate))) if (trailef == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, trailef, ent->keynum, ent->axis, &(le->trailstate)))
if (model->traildefaultindex >= 0) if (model->traildefaultindex >= 0)
pe->ParticleTrailIndex(old_origin, ent->origin, trailidx, 0, &(le->trailstate)); pe->ParticleTrailIndex(old_origin, ent->origin, P_INVALID, trailidx, 0, &(le->trailstate));
//dlights are not so customisable. //dlights are not so customisable.
if (r_rocketlight.value && (modelflags & MF_ROCKET) && !(state->lightpflags & (PFLAGS_FULLDYNAMIC|PFLAGS_CORONA))) if (r_rocketlight.value && (modelflags & MF_ROCKET) && !(state->lightpflags & (PFLAGS_FULLDYNAMIC|PFLAGS_CORONA)))

View File

@ -1540,7 +1540,7 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
i = cls.netchan.outgoing_sequence & UPDATE_MASK; i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.outframes[i].cmd[seat]; cmd = &cl.outframes[i].cmd[seat];
*cmd = independantphysics[seat]; *cmd = independantphysics[seat];
cmd->lightlevel = (lightlev>255)?255:lightlev; cmd->lightlevel = (lightlev>255)?255:lightlev;
cl.outframes[i].senttime = realtime; cl.outframes[i].senttime = realtime;

View File

@ -8083,10 +8083,8 @@ void CLNQ_ParseServerMessage (void)
break; break;
case svcfitz_skybox: case svcfitz_skybox:
{ Q_strncpyz(cl.skyname, MSG_ReadString(), sizeof(cl.skyname));
extern cvar_t r_skyboxname; R_SetSky(cl.skyname);
Cvar_Set(&r_skyboxname, MSG_ReadString());
}
break; break;
case svcfitz_bf: case svcfitz_bf:
Cmd_ExecuteString("bf", RESTRICT_SERVER); Cmd_ExecuteString("bf", RESTRICT_SERVER);

View File

@ -830,7 +830,7 @@ void CL_PredictEntityMovement(entity_state_t *estate, float age)
{ {
VectorClear(startstate.velocity); VectorClear(startstate.velocity);
startstate.onground = false; startstate.onground = false;
startstate.jump_held = false; startstate.jump_held = false;
CL_EntStateToPlayerState(&startstate, estate); CL_EntStateToPlayerState(&startstate, estate);
CL_EntStateToPlayerCommand(&cmd, estate, age); CL_EntStateToPlayerCommand(&cmd, estate, age);

View File

@ -63,7 +63,7 @@ void RSpeedShow(void)
RSpNames[RSPEED_STENCILSHADOWS] = "Stencil Shadows"; RSpNames[RSPEED_STENCILSHADOWS] = "Stencil Shadows";
RSpNames[RSPEED_FULLBRIGHTS] = "World fullbrights"; RSpNames[RSPEED_FULLBRIGHTS] = "World fullbrights";
RSpNames[RSPEED_SETUP] = "Setup"; RSpNames[RSPEED_SETUP] = "Setup/Acquire";
RSpNames[RSPEED_SUBMIT] = "submit/finish"; RSpNames[RSPEED_SUBMIT] = "submit/finish";
RSpNames[RSPEED_PRESENT] = "present"; RSpNames[RSPEED_PRESENT] = "present";
@ -296,9 +296,10 @@ typedef struct {
unsigned int flags; unsigned int flags;
conchar_t *string; conchar_t *string;
conchar_t *cursorchar; //pointer into string
size_t stringbytes; size_t stringbytes;
size_t charcount;
char titleimage[MAX_QPATH]; char titleimage[MAX_QPATH];
unsigned int charcount;
float time_start; // for slow victory printing float time_start; // for slow victory printing
float time_off; float time_off;
int erase_lines; int erase_lines;
@ -379,6 +380,7 @@ for a few moments
*/ */
void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
{ {
size_t i;
cprint_t *p; cprint_t *p;
if (!str) if (!str)
{ {
@ -411,6 +413,7 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p = &scr_centerprint[pnum]; p = &scr_centerprint[pnum];
p->flags = 0; p->flags = 0;
p->titleimage[0] = 0; p->titleimage[0] = 0;
p->cursorchar = NULL;
if (*str != '/') if (*str != '/')
{ {
@ -435,6 +438,8 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p->flags |= CPRINT_PERSIST | CPRINT_BACKGROUND; p->flags |= CPRINT_PERSIST | CPRINT_BACKGROUND;
p->flags &= ~CPRINT_TALIGN; p->flags &= ~CPRINT_TALIGN;
} }
else if (str[1] == 'C')
p->flags |= CPRINT_CURSOR; //this can be a little jarring if there's no links, so this forces consistent behaviour.
else if (str[1] == 'W') //wait between each char else if (str[1] == 'W') //wait between each char
p->flags ^= CPRINT_TYPEWRITER; p->flags ^= CPRINT_TYPEWRITER;
else if (str[1] == 'S') //Stay else if (str[1] == 'S') //Stay
@ -526,6 +531,15 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
} }
} }
if (!(p->flags & CPRINT_CURSOR))
{ //autodetect links
for (i = 0; i < p->charcount; i++)
{
if (p->string[i] == CON_LINKSTART)
p->flags |= CPRINT_CURSOR;
}
}
p->time_off = scr_centertime.value; p->time_off = scr_centertime.value;
p->time_start = cl.time; p->time_start = cl.time;
} }
@ -565,6 +579,55 @@ void VARGS Stats_Message(char *msg, ...)
p->time_start = cl.time; p->time_start = cl.time;
} }
static char *SCR_CopyCenterPrint(cprint_t *p) //reads the link under the mouse cursor. non-links are ignored.
{
size_t maxlen, outlen;
char *result;
conchar_t *start = p->cursorchar, *end;
if (!start) //cursor isn't over anything.
return NULL;
//scan backwards to find any link enclosure
for(end = start-1; end >= p->string; end--)
{
if (*end == CON_LINKSTART)
{
//found one
start = end;
break;
}
if (*end == CON_LINKEND)
{
//some other link ended here. don't use its start.
break;
}
}
//scan forwards to find the end of the selected link
if (start < p->string+p->charcount && *start == CON_LINKSTART)
{
for(end = start; end < p->string + p->charcount; end++)
{
if (*end == CON_LINKEND)
{
end++;
break;
}
}
}
else// if (onlyiflink)
return NULL;
maxlen = 1024*1024;
result = Z_Malloc(maxlen+1);
outlen = COM_DeFunString(start, end, result, maxlen, false, false) - result;
result[outlen++] = 0;
return result;
}
#define MAX_CPRINT_LINES 512 #define MAX_CPRINT_LINES 512
void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font) void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
{ {
@ -576,12 +639,12 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
int bottom; int bottom;
int remaining; int remaining;
shader_t *pic; shader_t *pic;
int ch;
conchar_t *line_start[MAX_CPRINT_LINES]; conchar_t *line_start[MAX_CPRINT_LINES];
conchar_t *line_end[MAX_CPRINT_LINES]; conchar_t *line_end[MAX_CPRINT_LINES];
int linecount; int linecount;
// the finale prints the characters one at a time // the finale prints the characters one at a time
if (p->flags & CPRINT_TYPEWRITER) if (p->flags & CPRINT_TYPEWRITER)
remaining = scr_printspeed.value * (cl.time - p->time_start); remaining = scr_printspeed.value * (cl.time - p->time_start);
@ -646,24 +709,26 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect->x+rect->width, rect->y+rect->height, &right, &bottom); Font_BeginString(font, rect->x+rect->width, rect->y+rect->height, &right, &bottom);
linecount = Font_LineBreaks(p->string, p->string + p->charcount, right - left, MAX_CPRINT_LINES, line_start, line_end); linecount = Font_LineBreaks(p->string, p->string + p->charcount, right - left, MAX_CPRINT_LINES, line_start, line_end);
ch = Font_CharHeight();
if (p->flags & CPRINT_TALIGN) if (p->flags & CPRINT_TALIGN)
y = top; y = top;
else if (p->flags & CPRINT_BALIGN) else if (p->flags & CPRINT_BALIGN)
y = bottom - Font_CharHeight()*linecount; y = bottom - ch*linecount;
else if (p->flags & CPRINT_OBITUARTY) else if (p->flags & CPRINT_OBITUARTY)
//'obituary' messages appear at the bottom of the screen //'obituary' messages appear at the bottom of the screen
y = (bottom-top - Font_CharHeight()*linecount) * 0.65 + top; y = (bottom-top - ch*linecount) * 0.65 + top;
else else
{ {
if (linecount <= 5) if (linecount <= 5)
{ {
//small messages appear above and away from the crosshair //small messages appear above and away from the crosshair
y = (bottom-top - Font_CharHeight()*linecount) * 0.35 + top; y = (bottom-top - ch*linecount) * 0.35 + top;
} }
else else
{ {
//longer messages are fully centered //longer messages are fully centered
y = (bottom-top - Font_CharHeight()*linecount) * 0.5 + top; y = (bottom-top - ch*linecount) * 0.5 + top;
} }
} }
@ -683,7 +748,7 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect->x, y, &left, &top); Font_BeginString(font, rect->x, y, &left, &top);
} }
for (l = 0; l < linecount; l++, y += Font_CharHeight()) for (l = 0; l < linecount; l++, y += ch)
{ {
if (y >= bottom) if (y >= bottom)
break; break;
@ -694,6 +759,11 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
else else
x = left + (right - left - Font_LineWidth(line_start[l], line_end[l]))/2; x = left + (right - left - Font_LineWidth(line_start[l], line_end[l]))/2;
if (mousecursor_y >= y && mousecursor_y < y+ch)
{
p->cursorchar = Font_CharAt(mousecursor_x - x, line_start[l], line_end[l]);
}
remaining -= line_end[l]-line_start[l]; remaining -= line_end[l]-line_start[l];
if (remaining <= 0) if (remaining <= 0)
{ {
@ -703,24 +773,102 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
} }
Font_LineDraw(x, y, line_start[l], line_end[l]); Font_LineDraw(x, y, line_start[l], line_end[l]);
} }
Font_EndString(font); Font_EndString(font);
} }
qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
{
int pnum;
cprint_t *p;
char *link;
if (key == K_MOUSE1)
{
//figure out which player has the cursor
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
p = &scr_centerprint[pnum];
if (cl.playerview[pnum].gamerectknown == cls.framecount)
{
link = SCR_CopyCenterPrint(p);
if (link)
{
if (link[0] == '^' && link[1] == '[')
{
//looks like it might be a link!
char *end = NULL;
char *info;
for (info = link + 2; *info; )
{
if (info[0] == '^' && info[1] == ']')
break; //end of tag, with no actual info, apparently
if (*info == '\\')
break;
else if (info[0] == '^' && info[1] == '^')
info+=2;
else
info++;
}
for(end = info; *end; )
{
if (end[0] == '^' && end[1] == ']')
{
//okay, its a valid link that they clicked
*end = 0;
#ifdef PLUGINS
if (!Plug_ConsoleLink(link+2, info, ""))
#endif
#ifdef CSQC_DAT
if (!CSQC_ConsoleLink(link+2, info))
#endif
Key_DefaultLinkClicked(NULL, link+2, info);
break;
}
if (end[0] == '^' && end[1] == '^')
end+=2;
else
end++;
}
}
}
}
}
return true; //handled
}
else if (key == K_MOUSE2)
{
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
p = &scr_centerprint[pnum];
p->flags &= ~CPRINT_CURSOR;
}
return true;
}
return false;
}
void SCR_CheckDrawCenterString (void) void SCR_CheckDrawCenterString (void)
{ {
int pnum; int pnum;
cprint_t *p; cprint_t *p;
Key_Dest_Remove(kdm_centerprint);
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
p = &scr_centerprint[pnum]; p = &scr_centerprint[pnum];
p->cursorchar = NULL;
if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST)) if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST))
continue; //'/P' prefix doesn't time out continue; //'/P' prefix doesn't time out
p->time_off -= host_frametime; p->time_off -= host_frametime;
if (Key_Dest_Has(~kdm_game)) //don't let progs guis/centerprints interfere with the game menu if (Key_Dest_Has(~(kdm_game|kdm_centerprint))) //don't let progs guis/centerprints interfere with the game menu
continue; //should probably allow the console with a scissor region or something. continue; //should probably allow the console with a scissor region or something.
#ifdef QUAKEHUD #ifdef QUAKEHUD
@ -729,7 +877,11 @@ void SCR_CheckDrawCenterString (void)
#endif #endif
if (cl.playerview[pnum].gamerectknown == cls.framecount) if (cl.playerview[pnum].gamerectknown == cls.framecount)
{
SCR_DrawCenterString(&cl.playerview[pnum].gamerect, p, font_default); SCR_DrawCenterString(&cl.playerview[pnum].gamerect, p, font_default);
if (p->flags & CPRINT_CURSOR)
Key_Dest_Add(kdm_centerprint);
}
} }
} }

View File

@ -770,7 +770,7 @@ beam_t *CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end) //f
{ {
// TODO: add support for those finnicky colored railtrails... // TODO: add support for those finnicky colored railtrails...
if (P_ParticleTrail(start, end, rtqw_railtrail, -ent, NULL, NULL)) if (P_ParticleTrail(start, end, rtqw_railtrail, -ent, NULL, NULL))
P_ParticleTrailIndex(start, end, 208, 8, NULL); P_ParticleTrailIndex(start, end, P_INVALID, 208, 8, NULL);
return NULL; return NULL;
} }
break; break;
@ -1573,7 +1573,7 @@ void CL_ParseTEnt (void)
pos2[2] = MSG_ReadCoord (); pos2[2] = MSG_ReadCoord ();
if (P_ParticleTrail(pos, pos2, rtqw_railtrail, 0, NULL, NULL)) if (P_ParticleTrail(pos, pos2, rtqw_railtrail, 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 208, 8, NULL); P_ParticleTrailIndex(pos, pos2, P_INVALID, 208, 8, NULL);
break; break;
case TEH2_STREAM_LIGHTNING_SMALL: case TEH2_STREAM_LIGHTNING_SMALL:
@ -1717,7 +1717,7 @@ void CL_ParseTEnt (void)
MSG_ReadCoord (); MSG_ReadCoord ();
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_nexbeam"), 0, NULL, NULL)) if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_nexbeam"), 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 15, 0, NULL); P_ParticleTrailIndex(pos, pos2, P_INVALID, 15, 0, NULL);
break; break;
case TEDP_SMOKE: case TEDP_SMOKE:
@ -2467,11 +2467,11 @@ void CLQ2_ParseSteam(void)
signed int id = MSG_ReadShort(); signed int id = MSG_ReadShort();
/*qbyte count =*/ MSG_ReadByte(); /*qbyte count =*/ MSG_ReadByte();
MSG_ReadPos(pos); MSG_ReadPos(pos);
MSG_ReadPos(dir); MSG_ReadDir(dir);
/*colour =*/ MSG_ReadByte(); /*colour =*/ MSG_ReadByte();
/*magnitude =*/ MSG_ReadShort(); /*magnitude =*/ MSG_ReadShort();
if (id == -1) if (id != -1)
/*duration =*/ MSG_ReadLong(); /*duration =*/ MSG_ReadLong();
else else
/*duration = 0;*/ /*duration = 0;*/
@ -2500,172 +2500,14 @@ void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float
{ {
S_StartSound(entnum, entchannel, sfx, origin, NULL, fvol, attenuation, -delay, 0, 0); S_StartSound(entnum, entchannel, sfx, origin, NULL, fvol, attenuation, -delay, 0, 0);
} }
void CLQ2_ParseTEnt (void) static qboolean CLQ2_ParseTEnt_RemoveMe(q2particleeffects_t type)
{ { //FIXME: this function needs to die, once we're sure its no longer needed.
beam_t *b;
int type;
int pt;
vec3_t pos, pos2, dir; vec3_t pos, pos2, dir;
explosion_t *ex; explosion_t *ex;
int cnt; int cnt;
int color; int color;
int r; int r;
int ent;
// int magnitude;
type = MSG_ReadByte ();
if (type <= Q2TE_MAX)
{
pt = pt_q2[type];
if (pt == P_INVALID && q2efnames[type])
{
Con_Printf("Q2TE legacy code: te %i\n", type);
goto fixme;
}
}
else
pt = P_INVALID;
switch (type)
{
case Q2TE_GUNSHOT: //grey tall thing with smoke+sparks
case Q2TE_BLOOD: //red tall thing
case Q2TE_SPARKS: //orange tall thing (with not many particles)
case Q2TE_BLASTER: //regular blaster
case Q2TE_SHOTGUN: //gunshot with less particles
case Q2TE_SCREEN_SPARKS://green+grey tall
case Q2TE_SHIELD_SPARKS://blue+grey tall
case Q2TE_BULLET_SPARKS://orange+grey tall+smoke
case Q2TE_GREENBLOOD: //yellow...
case Q2TE_BLASTER2: //green version of te_blaster
case Q2TE_MOREBLOOD: //te_blood*2
case Q2TE_HEATBEAM_SPARKS://white outwards puffs
case Q2TE_HEATBEAM_STEAM://orange outwards puffs
case Q2TE_ELECTRIC_SPARKS://blue tall
case Q2TE_FLECHETTE: //grey version of te_blaster
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffectType(pos, dir, 1, pt);
break;
case Q2TE_BFG_LASER:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
CL_Laser(pos, pos2, 0xd0d1d2d3);
break;
case Q2TE_RAILTRAIL: //blue spiral, grey particles
case Q2TE_BUBBLETRAIL: //grey sparse trail, slow riser
// case Q2TE_BFG_LASER: //green laser
case Q2TE_DEBUGTRAIL: //long lived blue trail
case Q2TE_BUBBLETRAIL2: //grey rising trail
case Q2TE_BLUEHYPERBLASTER: //TE_BLASTER without model+light
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, pt, 0, NULL, NULL);
break;
case Q2TE_EXPLOSION1: //column
case Q2TE_EXPLOSION2: //splits
case Q2TE_ROCKET_EXPLOSION://top blob/column
case Q2TE_GRENADE_EXPLOSION://indistinguishable from TE_EXPLOSION2
case Q2TE_ROCKET_EXPLOSION_WATER://rocket but with different sound
case Q2TE_GRENADE_EXPLOSION_WATER://different sound
case Q2TE_BFG_EXPLOSION://green light+sprite
case Q2TE_BFG_BIGEXPLOSION://green+white fast particles
case Q2TE_BOSSTPORT://splitting+merging+upwards particles.
case Q2TE_PLASMA_EXPLOSION://looks like rocket explosion to me
case Q2TE_PLAIN_EXPLOSION://looks like rocket explosion to me
case Q2TE_CHAINFIST_SMOKE://small smoke
case Q2TE_TRACKER_EXPLOSION://black light, slow particles
case Q2TE_TELEPORT_EFFECT://q1-style teleport
case Q2TE_DBALL_GOAL://q1-style teleport
case Q2TE_NUKEBLAST://dome expansion (blue/white particles)
case Q2TE_WIDOWSPLASH://dome (orange+gravity)
case Q2TE_EXPLOSION1_BIG://buggy model
case Q2TE_EXPLOSION1_NP://looks like a rocket explosion to me
MSG_ReadPos (pos);
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_SPLASH:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
r = MSG_ReadByte () + Q2SPLASH_UNKNOWN;
if (r > Q2SPLASH_MAX)
r = Q2SPLASH_UNKNOWN;
pt = pt_q2[r];
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM); //2, 7, -3
if (b)
{
b->bflags |= STREAM_ATTACHED;
VectorSet(b->offset, 2, 7, -3);
}
break;
case Q2TE_MONSTER_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM);
if (b)
b->bflags |= STREAM_ATTACHED;
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeamOffset (BT_Q2GRAPPLE);
break;
case Q2TE_LIGHTNING:
ent = MSGCL_ReadEntity ();
/*toent =*/ MSGCL_ReadEntity (); //ident only.
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord ();
CL_AddBeam(BT_Q2LIGHTNING, ent, pos, pos2);
break;
case Q2TE_LASER_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
P_RunParticleEffectPalette("q2part.TEQ2_LASER_SPARKS", pos, dir, color, cnt);
break;
/*
case Q2TE_LASER_SPARKS:
case Q2TE_WELDING_SPARKS:
case Q2TE_TUNNEL_SPARKS:
break;
//Q2TE_RAILTRAIL2, ?
//Q2TE_FLAME, ?
case Q2TE_FLASHLIGHT:
break;
case Q2TE_FORCEWALL:
break;
case Q2TE_WIDOWBEAMOUT:
break;
*/
case Q2TE_STEAM:
CLQ2_ParseSteam();
break;
default:
// Con_Printf("CLQ2_ParseTEnt: bad/non-implemented type %i\n", type);
goto fixme;
// Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
// break;
}
return;
fixme:
Con_DPrintf("Q2TE legacy code: te %i\n", type); Con_DPrintf("Q2TE legacy code: te %i\n", type);
switch(type) switch(type)
{ {
@ -2817,7 +2659,7 @@ fixme:
MSG_ReadPos (pos); MSG_ReadPos (pos);
MSG_ReadPos (pos2); MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_RAILTRAIL], 0, NULL, NULL)) if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_RAILTRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 0x74, 8, NULL); P_ParticleTrailIndex(pos, pos2, P_INVALID, 0x74, 8, NULL);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0); Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0);
break; break;
@ -3025,7 +2867,7 @@ fixme:
MSG_ReadPos (pos); MSG_ReadPos (pos);
MSG_ReadPos (pos2); MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_BUBBLETRAIL], 0, NULL, NULL)) if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_BUBBLETRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 4, 8, NULL); P_ParticleTrailIndex(pos, pos2, P_INVALID, 4, 8, NULL);
break; break;
case Q2TE_PARASITE_ATTACK: case Q2TE_PARASITE_ATTACK:
@ -3198,7 +3040,7 @@ fixme:
MSG_ReadPos (pos); MSG_ReadPos (pos);
MSG_ReadPos (pos2); MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), 0, NULL, NULL)) if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 116, 8, NULL); P_ParticleTrailIndex(pos, pos2, P_INVALID, 116, 8, NULL);
break; break;
case Q2TE_PLAIN_EXPLOSION: case Q2TE_PLAIN_EXPLOSION:
@ -3304,23 +3146,19 @@ fixme:
if (P_RunParticleEffectType(pos, dir, 4, ptqw_blood)) if (P_RunParticleEffectType(pos, dir, 4, ptqw_blood))
P_RunParticleEffect(pos, dir, 0xe8, 250); P_RunParticleEffect(pos, dir, 0xe8, 250);
break; break;
/*
case Q2TE_CHAINFIST_SMOKE: case Q2TE_CHAINFIST_SMOKE:
dir[0]=0; dir[1]=0; dir[2]=1; dir[0]=0; dir[1]=0; dir[2]=1;
MSG_ReadPos(&net_message, pos); MSG_ReadPos(pos);
CL_ParticleSmokeEffect (pos, dir, 0, 20, 20); P_RunParticleEffectTypeString(pos, NULL, 1, "TEQ2_CHAINFIST_SMOKE");
break; break;
case Q2TE_ELECTRIC_SPARKS: case Q2TE_ELECTRIC_SPARKS:
MSG_ReadPos (&net_message, pos); MSG_ReadPos (pos);
MSG_ReadDir (&net_message, dir); MSG_ReadDir (dir);
// CL_ParticleEffect (pos, dir, 109, 40); P_RunParticleEffect(pos, dir, 0x75, 40);
CL_ParticleEffect (pos, dir, 0x75, 40); Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/lashit.wav"), 1, ATTN_NORM, 0);
//FIXME : replace or remove this sound
S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
break; break;
*/
case Q2TE_TRACKER_EXPLOSION: case Q2TE_TRACKER_EXPLOSION:
MSG_ReadPos (pos); MSG_ReadPos (pos);
@ -3429,7 +3267,7 @@ fixme:
MSG_ReadPos (pos2); MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 0, NULL, NULL); P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 0, NULL, NULL);
break; break;
case CRTE_STAIN: /* case CRTE_STAIN:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type); Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_FIRE: case CRTE_FIRE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type); Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
@ -3437,9 +3275,178 @@ fixme:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type); Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_SMOKE: case CRTE_SMOKE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type); Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
*/
default: default:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type); return false;
}
return true;
}
void CLQ2_ParseTEnt (void)
{
beam_t *b;
q2particleeffects_t type;
int pt;
vec3_t pos, pos2, dir;
int cnt;
int color;
int r;
int ent;
// int magnitude;
type = MSG_ReadByte ();
if (type <= Q2TE_MAX)
{
pt = pt_q2[type];
if (pt == P_INVALID && q2efnames[type])
{
Con_Printf("Q2TE legacy code: te %i\n", type);
if (CLQ2_ParseTEnt_RemoveMe(type))
return;
}
}
else
pt = P_INVALID;
switch (type)
{
case Q2TE_GUNSHOT: //grey tall thing with smoke+sparks
case Q2TE_BLOOD: //red tall thing
case Q2TE_SPARKS: //orange tall thing (with not many particles)
case Q2TE_BLASTER: //regular blaster
case Q2TE_SHOTGUN: //gunshot with less particles
case Q2TE_SCREEN_SPARKS://green+grey tall
case Q2TE_SHIELD_SPARKS://blue+grey tall
case Q2TE_BULLET_SPARKS://orange+grey tall+smoke
case Q2TE_GREENBLOOD: //yellow...
case Q2TE_BLASTER2: //green version of te_blaster
case Q2TE_MOREBLOOD: //te_blood*2
case Q2TE_HEATBEAM_SPARKS://white outwards puffs
case Q2TE_HEATBEAM_STEAM://orange outwards puffs
case Q2TE_ELECTRIC_SPARKS://blue tall
case Q2TE_FLECHETTE: //grey version of te_blaster
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffectType(pos, dir, 1, pt);
break;
case Q2TE_BFG_LASER:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
CL_Laser(pos, pos2, 0xd0d1d2d3);
break;
case Q2TE_RAILTRAIL: //blue spiral, grey particles
case Q2TE_BUBBLETRAIL: //grey sparse trail, slow riser
// case Q2TE_BFG_LASER: //green laser
case Q2TE_DEBUGTRAIL: //long lived blue trail
case Q2TE_BUBBLETRAIL2: //grey rising trail
case Q2TE_BLUEHYPERBLASTER: //TE_BLASTER without model+light
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, pt, 0, NULL, NULL);
break;
case Q2TE_EXPLOSION1: //column
case Q2TE_EXPLOSION2: //splits
case Q2TE_ROCKET_EXPLOSION://top blob/column
case Q2TE_GRENADE_EXPLOSION://indistinguishable from TE_EXPLOSION2
case Q2TE_ROCKET_EXPLOSION_WATER://rocket but with different sound
case Q2TE_GRENADE_EXPLOSION_WATER://different sound
case Q2TE_BFG_EXPLOSION://green light+sprite
case Q2TE_BFG_BIGEXPLOSION://green+white fast particles
case Q2TE_BOSSTPORT://splitting+merging+upwards particles.
case Q2TE_PLASMA_EXPLOSION://looks like rocket explosion to me
case Q2TE_PLAIN_EXPLOSION://looks like rocket explosion to me
case Q2TE_CHAINFIST_SMOKE://small smoke
case Q2TE_TRACKER_EXPLOSION://black light, slow particles
case Q2TE_TELEPORT_EFFECT://q1-style teleport
case Q2TE_DBALL_GOAL://q1-style teleport
case Q2TE_NUKEBLAST://dome expansion (blue/white particles)
case Q2TE_WIDOWSPLASH://dome (orange+gravity)
case Q2TE_EXPLOSION1_BIG://buggy model
case Q2TE_EXPLOSION1_NP://looks like a rocket explosion to me
MSG_ReadPos (pos);
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_SPLASH:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
r = MSG_ReadByte () + Q2SPLASH_UNKNOWN;
if (r > Q2SPLASH_MAX)
r = Q2SPLASH_UNKNOWN;
pt = pt_q2[r];
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM); //2, 7, -3
if (b)
{
b->bflags |= STREAM_ATTACHED;
VectorSet(b->offset, 2, 7, -3);
}
break;
case Q2TE_MONSTER_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM);
if (b)
b->bflags |= STREAM_ATTACHED;
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeamOffset (BT_Q2GRAPPLE);
break;
case Q2TE_LIGHTNING:
ent = MSGCL_ReadEntity ();
/*toent =*/ MSGCL_ReadEntity (); //ident only.
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord ();
CL_AddBeam(BT_Q2LIGHTNING, ent, pos, pos2);
break;
case Q2TE_LASER_SPARKS:
case Q2TE_WELDING_SPARKS:
case Q2TE_TUNNEL_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
P_RunParticleEffectPalette(va("q2part.%s", q2efnames[type]), pos, dir, color, cnt);
break;
case Q2TE_STEAM:
CLQ2_ParseSteam();
break;
case Q2TE_FORCEWALL:
MSG_ReadPos (pos);
MSG_ReadDir (pos2);
color = MSG_ReadByte ();
P_ParticleTrailIndex(pos, pos2, pt, color, 0, NULL);
break;
case Q2TE_RAILTRAIL2:
case Q2TE_FLAME:
case Q2TE_FLASHLIGHT:
case Q2TE_WIDOWBEAMOUT:
#ifdef __GNUC__
case (Q2TE_FLECHETTE+1) ... Q2PT_MAX:
// case (Q2TE_MAX+1) ... Q2PT_MAX:
// default:
#else
default:
#endif
// Con_Printf("CLQ2_ParseTEnt: bad/non-implemented type %i\n", type);
if (!CLQ2_ParseTEnt_RemoveMe(type))
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
break;
} }
} }
#endif #endif

View File

@ -759,7 +759,7 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->effects = MSG_ReadShort(); to->effects = MSG_ReadShort();
if ( (bits & (Q2U_RENDERFX8|Q2U_RENDERFX16)) == (Q2U_RENDERFX8|Q2U_RENDERFX16) ) if ( (bits & (Q2U_RENDERFX8|Q2U_RENDERFX16)) == (Q2U_RENDERFX8|Q2U_RENDERFX16) )
to->u.q2.renderfx = MSG_ReadLong(); to->u.q2.renderfx = MSG_ReadLong() & 0x0007ffff; //only the standard ones actually supported by vanilla q2.
else if (bits & Q2U_RENDERFX8) else if (bits & Q2U_RENDERFX8)
to->u.q2.renderfx = MSG_ReadByte(); to->u.q2.renderfx = MSG_ReadByte();
else if (bits & Q2U_RENDERFX16) else if (bits & Q2U_RENDERFX16)
@ -1975,7 +1975,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_ROCKET], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_ROCKET], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xdc, 4, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xdc, 4, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.1, 0.05); V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.1, 0.05);
} }
} }
@ -1988,7 +1988,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL2], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL2], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xd0, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xd0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0, 0.2, 0); V_AddLight (ent.keynum, ent.origin, 200, 0, 0.2, 0);
} }
} }
@ -1996,7 +1996,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe0, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xe0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0); V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0);
} }
} }
@ -2013,13 +2013,13 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GIB], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GIB], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe8, 8, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xe8, 8, &cent->trailstate);
} }
else if (effects & Q2EF_GRENADE) else if (effects & Q2EF_GRENADE)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GRENADE], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GRENADE], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 4, 8, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 4, 8, &cent->trailstate);
} }
else if (effects & Q2EF_FLIES) else if (effects & Q2EF_FLIES)
{ {
@ -2050,7 +2050,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG1], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG1], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 242, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 242, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.05, 0.05); V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.05, 0.05);
} }
} }
@ -2058,7 +2058,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG2], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG2], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 115, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 115, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.05, 0.05, 0.2); V_AddLight (ent.keynum, ent.origin, 225, 0.05, 0.05, 0.2);
} }
} }
@ -2068,7 +2068,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TAGTRAIL], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TAGTRAIL], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 220, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 220, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.2, 0.0); V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.2, 0.0);
} }
} }
@ -2093,7 +2093,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TRACKER], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TRACKER], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0, 1, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, -0.2, -0.2, -0.2); V_AddLight (ent.keynum, ent.origin, 200, -0.2, -0.2, -0.2);
} }
} }
@ -2103,14 +2103,14 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
else if (effects & Q2EF_GREENGIB) else if (effects & Q2EF_GREENGIB)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GREENGIB], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GREENGIB], ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 219, 8, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 219, 8, &cent->trailstate);
} }
// RAFAEL // RAFAEL
else if (effects & Q2EF_IONRIPPER) else if (effects & Q2EF_IONRIPPER)
{ {
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_IONRIPPER], ent.keynum, NULL, &cent->trailstate)) if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_IONRIPPER], ent.keynum, NULL, &cent->trailstate))
{ {
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 228, 4, &cent->trailstate); P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 228, 4, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 100, 0.2, 0.1, 0.1); V_AddLight (ent.keynum, ent.origin, 100, 0.2, 0.1, 0.1);
} }
} }

View File

@ -4135,6 +4135,12 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case PTI_BGRA8: case PTI_BGRA8:
mips->encoding = PTI_BGRX8; mips->encoding = PTI_BGRX8;
break; break;
case PTI_RGBA8_SRGB:
mips->encoding = PTI_RGBX8_SRGB;
break;
case PTI_BGRA8_SRGB:
mips->encoding = PTI_BGRX8_SRGB;
break;
case PTI_RGBA16F: case PTI_RGBA16F:
case PTI_RGBA32F: case PTI_RGBA32F:
case PTI_ARGB4444: case PTI_ARGB4444:
@ -4153,6 +4159,8 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case PTI_RGB565: case PTI_RGB565:
case PTI_RGBX8: case PTI_RGBX8:
case PTI_BGRX8: case PTI_BGRX8:
case PTI_RGBX8_SRGB:
case PTI_BGRX8_SRGB:
case PTI_S3RGB1: case PTI_S3RGB1:
break; //already no alpha in these formats break; //already no alpha in these formats
case PTI_DEPTH16: case PTI_DEPTH16:
@ -4276,6 +4284,7 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd
tex->width = imgwidth; tex->width = imgwidth;
tex->height = imgheight; tex->height = imgheight;
//d3d9 needs to reconfigure samplers depending on whether the data is srgb or not.
tex->flags &= ~IF_SRGB; tex->flags &= ~IF_SRGB;
switch(mips->encoding) switch(mips->encoding)
{ {
@ -4285,6 +4294,8 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd
case PTI_BGRX8_SRGB: case PTI_BGRX8_SRGB:
tex->flags |= IF_SRGB; tex->flags |= IF_SRGB;
break; break;
default:
break;
} }
if (flags & IF_NOWORKER) if (flags & IF_NOWORKER)

View File

@ -891,6 +891,18 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL); Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL);
return; return;
} }
c = Info_ValueForKey(info, "say");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nsay %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "echo");
if (*c)
{
Con_Printf("%s\n", c);
return;
}
c = Info_ValueForKey(info, "dir"); c = Info_ValueForKey(info, "dir");
if (*c && !strchr(c, ';') && !strchr(c, '\n')) if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{ {
@ -2215,8 +2227,8 @@ void Key_Init (void)
key_linepos = 0; key_linepos = 0;
key_dest_mask = kdm_game; key_dest_mask = kdm_game;
key_dest_absolutemouse = kdm_console | kdm_editor | kdm_cwindows | kdm_emenu; key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_editor | kdm_cwindows | kdm_emenu;
// //
// init ascii characters in console mode // init ascii characters in console mode
// //
@ -2625,6 +2637,10 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
return; return;
} }
if (Key_Dest_Has(kdm_centerprint))
if (Key_Centerprint(key, unicode, devid))
return;
//anything else is a key binding. //anything else is a key binding.
/*don't auto-repeat binds as it breaks too many scripts*/ /*don't auto-repeat binds as it breaks too many scripts*/

View File

@ -252,12 +252,13 @@ K_MAX
typedef enum //highest has priority typedef enum //highest has priority
{ {
kdm_game = 1u<<0, //should always be set kdm_game = 1u<<0, //should always be set
kdm_message = 1u<<1, kdm_centerprint = 1u<<1, //enabled when there's a centerprint menu with clickable things.
kdm_gmenu = 1u<<2, //menu.dat kdm_message = 1u<<2,
kdm_emenu = 1u<<3, //engine's menus kdm_gmenu = 1u<<3, //menu.dat
kdm_editor = 1u<<4, kdm_emenu = 1u<<4, //engine's menus
kdm_console = 1u<<5, kdm_editor = 1u<<5,
kdm_cwindows = 1u<<6, kdm_console = 1u<<6,
kdm_cwindows = 1u<<7,
} keydestmask_t; } keydestmask_t;
//unsigned int Key_Dest_Get(void); //returns highest priority destination //unsigned int Key_Dest_Get(void); //returns highest priority destination
@ -299,8 +300,10 @@ void IN_WriteButtons(vfsfile_t *f, qboolean all);
void Key_WriteBindings (struct vfsfile_s *f); void Key_WriteBindings (struct vfsfile_s *f);
void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel); void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel);
void Key_ClearStates (void); void Key_ClearStates (void);
qboolean Key_Centerprint(int key, int unicode, unsigned int devid);
void Key_Unbindall_f (void); //aka: Key_Shutdown void Key_Unbindall_f (void); //aka: Key_Shutdown
void Key_ConsoleReplace(const char *instext); void Key_ConsoleReplace(const char *instext);
void Key_DefaultLinkClicked(console_t *con, char *text, char *info);
struct console_s; struct console_s;
qboolean Key_GetConsoleSelectionBox(struct console_s *con, int *sx, int *sy, int *ex, int *ey); qboolean Key_GetConsoleSelectionBox(struct console_s *con, int *sx, int *sy, int *ex, int *ey);

View File

@ -141,6 +141,7 @@ void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int
#define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top) #define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top)
#define CPRINT_PERSIST (1<<17) //P (doesn't time out) #define CPRINT_PERSIST (1<<17) //P (doesn't time out)
#define CPRINT_TYPEWRITER (1<<18) // (char at a time) #define CPRINT_TYPEWRITER (1<<18) // (char at a time)
#define CPRINT_CURSOR (1<<19) //C (use a mouse cursor, also enabled by the presence of a (auto) link)
#endif #endif

View File

@ -257,7 +257,7 @@ static void PClassic_RunParticleEffect4 (vec3_t org, float radius, int color, in
} }
//this function is used as a fallback in case a trail effect is unknown. //this function is used as a fallback in case a trail effect is unknown.
static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk) static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk)
{ {
} }

View File

@ -22,7 +22,7 @@ static void PNULL_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int eff
static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count){} static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count){}
static void PNULL_RunParticleEffectPalette (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count){} static void PNULL_RunParticleEffectPalette (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count){}
static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk){} static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk){}
static qboolean PNULL_InitParticles (void) static qboolean PNULL_InitParticles (void)
{ {

View File

@ -5987,13 +5987,15 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlk
return 0; return 0;
} }
static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk) static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk)
{ {
if (PART_VALID(pe_defaulttrail)) if (type == P_INVALID)
type = pe_defaulttrail;
if (PART_VALID(type))
{ {
part_type[pe_defaulttrail].colorindex = color; part_type[type].colorindex = color;
part_type[pe_defaulttrail].colorrand = crnd; part_type[type].colorrand = crnd;
P_ParticleTrail(start, end, pe_defaulttrail, 0, NULL, tsk); P_ParticleTrail(start, end, type, 0, NULL, tsk);
} }
} }

View File

@ -4704,7 +4704,7 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
{ {
if (model->particletrail == P_INVALID || pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, src->number, NULL, &(le->trailstate))) if (model->particletrail == P_INVALID || pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, src->number, NULL, &(le->trailstate)))
if (model->traildefaultindex >= 0) if (model->traildefaultindex >= 0)
pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); pe->ParticleTrailIndex(ent->v->origin, src->origin, P_INVALID, model->traildefaultindex, 0, &(le->trailstate));
} }
} }

View File

@ -183,6 +183,8 @@ void R2D_Init(void)
extern cvar_t gl_specular_fallback, gl_specular_fallbackexp, gl_texturemode; extern cvar_t gl_specular_fallback, gl_specular_fallbackexp, gl_texturemode;
conback = NULL; conback = NULL;
Cvar_ForceCallback(&gl_texturemode);
draw_mesh.istrifan = true; draw_mesh.istrifan = true;
draw_mesh.numvertexes = 4; draw_mesh.numvertexes = 4;
draw_mesh.numindexes = 6; draw_mesh.numindexes = 6;
@ -377,7 +379,6 @@ void R2D_Init(void)
Cvar_ForceCallback(&gl_conback); Cvar_ForceCallback(&gl_conback);
Cvar_ForceCallback(&vid_conautoscale); Cvar_ForceCallback(&vid_conautoscale);
Cvar_ForceCallback(&gl_font); Cvar_ForceCallback(&gl_font);
Cvar_ForceCallback(&gl_texturemode);
Cvar_ForceCallback(&crosshair); Cvar_ForceCallback(&crosshair);
Cvar_ForceCallback(&crosshaircolor); Cvar_ForceCallback(&crosshaircolor);

View File

@ -3442,21 +3442,6 @@ char *particle_set_q2part =
"scalefactor 0.8\n" "scalefactor 0.8\n"
"}\n" "}\n"
"r_part TEQ2_LASER_SPARKS\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part te_splashsparks\n" "r_part te_splashsparks\n"
"{\n" "{\n"
"texture \"classicparticle\"\n" "texture \"classicparticle\"\n"
@ -3567,7 +3552,56 @@ char *particle_set_q2part =
"colorindex 0xe8\n" "colorindex 0xe8\n"
"}\n" "}\n"
"r_part teq2_laser_sparks\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part teq2_welding_sparks\n"
"{ //identical to teq2_laser_sparks, except for the +form that adds in some extra mesh+lighting effect.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part +teq2_welding_sparks\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/flash/tris.md2\" framestart=0 frameend=2 framerate=10 alpha=-1 fullbright\n"
"lightradius 100 175\n"
"lightradiusfade 400\n"
"lightrgb 1 1 0.3\n"
"}\n"
"r_part teq2_tunnel_sparks\n"
"{ //this is apparently identical to teq2_laser_sparks... either way the protocol provides a palette colour (particle system provides a customised variation)\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part teq2_shield_sparks\n" "r_part teq2_shield_sparks\n"
"{\n" "{\n"
"texture \"classicparticle\"\n" "texture \"classicparticle\"\n"
@ -3682,11 +3716,68 @@ char *particle_set_q2part =
"scalefactor 0.8\n" "scalefactor 0.8\n"
"colorindex 232 7\n" "colorindex 232 7\n"
"}\n" "}\n"
"r_part teq2_moreblood\n"
"{ //teq2_blood, but with count 250 instead of 60.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 250\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 232 7\n"
"}\n"
"r_part teq2_greenblood\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 30\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0xdf 7\n"
"}\n"
"r_part teq2_electric_sparks\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 40\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0x75 7\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part q2_blasterpuff\n" "r_part q2_blasterpuff\n"
"{\n" "{\n"
"count 0 0 1\n" "count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow\n" "model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=0\n"
"}\n"
"r_part q2_blaster2puff\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1\n"
"}\n"
"r_part q2_flechettepuff\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=2\n"
"}\n" "}\n"
"r_part teq2_blaster\n" "r_part teq2_blaster\n"
"{\n" "{\n"
@ -3725,13 +3816,35 @@ char *particle_set_q2part =
"gravity 40\n" "gravity 40\n"
"scalefactor 0.8\n" "scalefactor 0.8\n"
"colorindex 0xd0 7\n" "colorindex 0xd0 7\n"
"assoc q2_blasterpuff /*the model*/\n" "assoc q2_blaster2puff /*the model*/\n"
"lightradius 150\n" "lightradius 150\n"
"lightradiusfade 400\n" "lightradiusfade 400\n"
"lightrgb 0.05 1.0 0.05\n" "lightrgb 0.05 1.0 0.05\n"
"lightshadows 1\n" "lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n" "sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n" "}\n"
"r_part teq2_flechette\n"
"{ //grey version.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 60\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 40\n"
"orgadd 0 15\n"
"veladd 30\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0x6f 7\n"
"assoc q2_flechettepuff /*the model*/\n"
"lightradius 150\n"
"lightradiusfade 400\n"
"lightrgb 0.19 0.41 0.75\n"
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part TR_BLASTERTRAIL\n" "r_part TR_BLASTERTRAIL\n"
"{\n" "{\n"
"texture \"classicparticle\"\n" "texture \"classicparticle\"\n"

View File

@ -2338,20 +2338,12 @@ void Surf_SetupFrame(void)
} }
else if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED || cl.worldmodel->fromgame == fg_doom3 ) else if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED || cl.worldmodel->fromgame == fg_doom3 )
{ {
r_viewleaf = NULL; r_viewcluster = -1;
r_viewleaf2 = NULL; r_viewcluster2 = -1;
} }
#ifdef Q2BSPS #ifdef Q2BSPS
else if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3) else if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
{ {
static mleaf_t fakeleaf;
mleaf_t *leaf;
//FIXME: do we still need this fakeleaf stuff?
r_viewleaf = &fakeleaf;
r_viewleaf->contents = Q1CONTENTS_EMPTY;
r_viewleaf2 = NULL;
leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg); leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
viewcontents = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, pvsorg); viewcontents = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, pvsorg);
r_viewcluster = r_viewcluster2 = leaf->cluster; r_viewcluster = r_viewcluster2 = leaf->cluster;
@ -2383,38 +2375,12 @@ void Surf_SetupFrame(void)
#endif #endif
else else
{ {
r_viewleaf = Mod_PointInLeaf (cl.worldmodel, pvsorg); leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
r_viewcluster = (leaf - cl.worldmodel->leafs)-1;
if (!r_viewleaf) r_viewcluster2 = -1;
if (leaf)
{ {
} switch(leaf->contents)
else if (r_viewleaf->contents == Q1CONTENTS_EMPTY)
{ //look down a bit
VectorCopy (pvsorg, temp);
temp[2] -= 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
r_viewleaf2 = leaf;
else
r_viewleaf2 = NULL;
}
else if (r_viewleaf->contents <= Q1CONTENTS_WATER && r_viewleaf->contents >= Q1CONTENTS_LAVA)
{ //in water, look up a bit.
VectorCopy (pvsorg, temp);
temp[2] += 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents == Q1CONTENTS_EMPTY)
r_viewleaf2 = leaf;
else
r_viewleaf2 = NULL;
}
else
r_viewleaf2 = NULL;
if (r_viewleaf)
{
switch(r_viewleaf->contents)
{ {
case Q1CONTENTS_WATER: case Q1CONTENTS_WATER:
viewcontents |= FTECONTENTS_WATER; viewcontents |= FTECONTENTS_WATER;
@ -2435,6 +2401,24 @@ void Surf_SetupFrame(void)
viewcontents |= FTECONTENTS_LADDER; viewcontents |= FTECONTENTS_LADDER;
break; break;
} }
if (leaf->contents == Q1CONTENTS_EMPTY)
{ //look down a bit
VectorCopy (pvsorg, temp);
temp[2] -= 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
r_viewcluster2 = (leaf - cl.worldmodel->leafs)-1;
}
else if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
{ //in water, look up a bit.
VectorCopy (pvsorg, temp);
temp[2] += 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents == Q1CONTENTS_EMPTY)
r_viewcluster2 = (leaf - cl.worldmodel->leafs)-1;
}
} }
} }
@ -2617,7 +2601,6 @@ struct webostate_s
{ {
char dbgid[12]; char dbgid[12];
model_t *wmodel; model_t *wmodel;
mleaf_t *leaf[2];
int cluster[2]; int cluster[2];
pvsbuffer_t pvs; pvsbuffer_t pvs;
vboarray_t ebo; vboarray_t ebo;
@ -2859,30 +2842,23 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
es->batches[i].idxbuffer = NULL; es->batches[i].idxbuffer = NULL;
} }
//maybe we should just use fatpvs instead, and wait for completion when outside?
if (es->cluster[1] != -1 && es->cluster[0] != es->cluster[1])
{ //view is near to a water boundary. this implies the water crosses the near clip plane. we need both leafs.
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_REPLACE);
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[1], &es->pvs, PVM_MERGE);
}
else
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_FAST);
#if defined(Q2BSPS) || defined(Q3BSPS) #if defined(Q2BSPS) || defined(Q3BSPS)
if (es->wmodel->fromgame == fg_quake2 || es->wmodel->fromgame == fg_quake3) if (es->wmodel->fromgame == fg_quake2 || es->wmodel->fromgame == fg_quake3)
{
if (es->cluster[1] != -1 && es->cluster[0] != es->cluster[1]) //view is near to a water boundary. this implies the water crosses the near clip plane.
{
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_REPLACE);
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[1], &es->pvs, PVM_MERGE);
}
else
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_FAST);
Surf_SimpleWorld_Q3BSP(es, pvs); Surf_SimpleWorld_Q3BSP(es, pvs);
}
else else
#endif #endif
#ifdef Q1BSPS #ifdef Q1BSPS
if (es->wmodel->fromgame == fg_quake || es->wmodel->fromgame == fg_halflife) if (es->wmodel->fromgame == fg_quake || es->wmodel->fromgame == fg_halflife)
{
//maybe we should just use fatpvs instead, and wait for completion when outside?
pvs = Q1BSP_LeafPVS (es->wmodel, es->leaf[0], &es->pvs, false);
if (es->leaf[1]) //view is near to a water boundary. this implies the water crosses the near clip plane.
pvs = Q1BSP_LeafPVS (es->wmodel, es->leaf[1], &es->pvs, true);
Surf_SimpleWorld_Q1BSP(es, pvs); Surf_SimpleWorld_Q1BSP(es, pvs);
}
else else
#endif #endif
{ {
@ -2899,11 +2875,11 @@ R_DrawWorld
============= =============
*/ */
static pvsbuffer_t surf_frustumvis;
void Surf_DrawWorld (void) void Surf_DrawWorld (void)
{ {
//surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care. //surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care.
qbyte *surfvis, *entvis; qbyte *surfvis, *entvis;
static pvsbuffer_t frustumvis_;
RSpeedLocals(); RSpeedLocals();
if (r_refdef.flags & RDF_NOWORLDMODEL) if (r_refdef.flags & RDF_NOWORLDMODEL)
@ -2948,7 +2924,7 @@ void Surf_DrawWorld (void)
if (webostate->lightstylevalues[i] != d_lightstylevalue[i]) if (webostate->lightstylevalues[i] != d_lightstylevalue[i])
break; break;
} }
if (webostate && webostate->leaf[0] == r_viewleaf && webostate->leaf[1] == r_viewleaf2 && i == MAX_LIGHTSTYLES) if (webostate && webostate->cluster[0] == r_viewcluster && webostate->cluster[1] == r_viewcluster2 && i == MAX_LIGHTSTYLES)
{ {
} }
else else
@ -2971,8 +2947,8 @@ void Surf_DrawWorld (void)
webogeneratingstate = true; webogeneratingstate = true;
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1) + currentmodel->pvsbytes); webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1) + currentmodel->pvsbytes);
webogenerating->wmodel = currentmodel; webogenerating->wmodel = currentmodel;
webogenerating->leaf[0] = r_viewleaf; webogenerating->cluster[0] = r_viewcluster;
webogenerating->leaf[1] = r_viewleaf2; webogenerating->cluster[1] = r_viewcluster2;
webogenerating->pvs.buffer = (qbyte*)(webogenerating+1) + sizeof(webogenerating->batches[0])*(currentmodel->numbatches-1); webogenerating->pvs.buffer = (qbyte*)(webogenerating+1) + sizeof(webogenerating->batches[0])*(currentmodel->numbatches-1);
webogenerating->pvs.buffersize = currentmodel->pvsbytes; webogenerating->pvs.buffersize = currentmodel->pvsbytes;
for (i = 0; i < MAX_LIGHTSTYLES; i++) for (i = 0; i < MAX_LIGHTSTYLES; i++)
@ -3056,9 +3032,9 @@ void Surf_DrawWorld (void)
#if defined(Q2BSPS) || defined(Q3BSPS) #if defined(Q2BSPS) || defined(Q3BSPS)
if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3) if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3)
{ {
if (frustumvis_.buffersize < currentmodel->pvsbytes) if (surf_frustumvis.buffersize < currentmodel->pvsbytes)
frustumvis_.buffer = BZ_Realloc(frustumvis_.buffer, frustumvis_.buffersize=currentmodel->pvsbytes); surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes);
frustumvis = frustumvis_.buffer; frustumvis = surf_frustumvis.buffer;
memset(frustumvis, 0, currentmodel->pvsbytes); memset(frustumvis, 0, currentmodel->pvsbytes);
if (!r_refdef.areabitsknown) if (!r_refdef.areabitsknown)
@ -3121,9 +3097,9 @@ void Surf_DrawWorld (void)
if (!(r_novis.ival & 2)) if (!(r_novis.ival & 2))
VectorCopy (r_origin, modelorg); VectorCopy (r_origin, modelorg);
if (frustumvis_.buffersize < currentmodel->pvsbytes) if (surf_frustumvis.buffersize < currentmodel->pvsbytes)
frustumvis_.buffer = BZ_Realloc(frustumvis_.buffer, frustumvis_.buffersize=currentmodel->pvsbytes); surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes);
frustumvis = frustumvis_.buffer; frustumvis = surf_frustumvis.buffer;
memset(frustumvis, 0, currentmodel->pvsbytes); memset(frustumvis, 0, currentmodel->pvsbytes);
if (r_refdef.useperspective) if (r_refdef.useperspective)
@ -3200,6 +3176,9 @@ void Surf_DeInit(void)
if (lightmap) if (lightmap)
BZ_Free(lightmap); BZ_Free(lightmap);
Z_Free(surf_frustumvis.buffer);
memset(&surf_frustumvis, 0, sizeof(surf_frustumvis));
lightmap=NULL; lightmap=NULL;
numlightmaps=0; numlightmaps=0;
@ -3655,8 +3634,6 @@ void Surf_BuildLightmaps (void)
Surf_LightmapMode(); Surf_LightmapMode();
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1; r_oldviewcluster = -1;
r_oldviewcluster2 = -1; r_oldviewcluster2 = -1;
@ -3700,11 +3677,10 @@ void Surf_NewMap (void)
Surf_DeInit(); Surf_DeInit();
r_viewleaf = NULL;
r_oldviewleaf = NULL;
r_viewcluster = -1; r_viewcluster = -1;
r_oldviewcluster = 0; r_oldviewcluster = 0;
r_viewcluster2 = -1; r_viewcluster2 = -1;
r_oldviewcluster2 = 0;
if (cl.worldmodel) if (cl.worldmodel)
{ {
@ -3768,10 +3744,10 @@ void Surf_PreNewMap(void)
#ifdef RTLIGHTS #ifdef RTLIGHTS
r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival; r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival;
#endif #endif
r_viewleaf = NULL; r_viewcluster = -1;
r_oldviewleaf = NULL; r_oldviewcluster = -1;
r_viewleaf2 = NULL; r_viewcluster2 = -1;
r_oldviewleaf2 = NULL; r_oldviewcluster2 = -1;
} }

View File

@ -49,10 +49,25 @@ void QDECL R_SkyBox_Changed (struct cvar_s *var, char *oldvalue)
{ {
if (qrenderer != QR_NONE && cl.worldmodel) if (qrenderer != QR_NONE && cl.worldmodel)
{ {
if (*var->string) R_SetSky(cl.skyname);
R_SetSky(var->string); }
}
void R_ForceSky_f(void)
{
if (Cmd_Argc() < 2)
{
extern cvar_t r_skyboxname;
if (*r_skyboxname.string)
Con_Printf("Current user skybox is %s\n", cl.skyname);
else if (*cl.skyname)
Con_Printf("Current per-map skybox is %s\n", cl.skyname);
else else
R_SetSky(cl.skyname); Con_Printf("no skybox forced.\n", cl.skyname);
}
else
{
Q_strncpyz(cl.skyname, Cmd_Argv(1), sizeof(cl.skyname));
R_SetSky(cl.skyname);
} }
} }
@ -233,6 +248,7 @@ cvar_t vid_conwidth = CVARF ("vid_conwidth", "0",
//see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'. //see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'.
cvar_t vid_renderer = CVARFD ("vid_renderer", "", cvar_t vid_renderer = CVARFD ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), headless (null renderer), vk (vulkan), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering)."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), headless (null renderer), vk (vulkan), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering).");
cvar_t vid_renderer_opts = CVARFD ("_vid_renderer_opts", "", CVAR_NOSET, "The possible video renderer apis, in \"value\" \"description\" pairs, for gamecode to read.");
cvar_t vid_bpp = CVARFD ("vid_bpp", "0", cvar_t vid_bpp = CVARFD ("vid_bpp", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context"); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context");
@ -251,12 +267,15 @@ cvar_t vid_fullscreen_alternative = CVARFD (NULL, "1",
cvar_t vid_height = CVARFD ("vid_height", "0", cvar_t vid_height = CVARFD ("vid_height", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen height to attempt to use, in physical pixels. 0 means use desktop resolution."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen height to attempt to use, in physical pixels. 0 means use desktop resolution.");
cvar_t vid_multisample = CVARFD ("vid_multisample", "0", cvar_t vid_multisample = CVARFD ("vid_multisample", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Set to 4 or so for multisample antialiasing (msaa)."); CVAR_ARCHIVE, "The number of samples to use for Multisample AntiAliasing (aka: msaa). A value of 1 explicitly disables it.");
cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0", cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH); CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_srgb = CVARFD ("vid_srgb", "0", cvar_t vid_srgb = CVARFD ("vid_srgb", "0",
CVAR_ARCHIVE, "0: Off. Colour blending will be wrong.\n1: Only the framebuffer should use sRGB colourspace, textures and colours will be assumed to be linear. This has the effect of brightening the screen.\n2: Use sRGB extensions/support to ensure that the sh"); CVAR_ARCHIVE, "0: Off. Colour blending will be wrong.\n1: Only the framebuffer should use sRGB colourspace, textures and colours will be assumed to be linear. This has the effect of brightening the screen.\n2: Use sRGB extensions/support to ensure that the sh");
cvar_t vid_wndalpha = CVARD ("vid_wndalpha", "1", "When running windowed, specifies the window's transparency level."); cvar_t vid_wndalpha = CVARD ("vid_wndalpha", "1", "When running windowed, specifies the window's transparency level.");
#if defined(_WIN32) && defined(MULTITHREAD)
cvar_t vid_winthread = CVARFD ("vid_winthread", "", CVAR_ARCHIVE|CVAR_RENDERERLATCH, "When enabled, window messages will be handled by a separate thread. This allows the game to continue rendering when Microsoft Windows blocks while resizing etc.");
#endif
//more readable defaults to match conwidth/conheight. //more readable defaults to match conwidth/conheight.
cvar_t vid_width = CVARFD ("vid_width", "0", cvar_t vid_width = CVARFD ("vid_width", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen width to attempt to use, in physical pixels. 0 means use desktop resolution."); CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen width to attempt to use, in physical pixels. 0 means use desktop resolution.");
@ -426,11 +445,15 @@ cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
#endif #endif
#ifdef VKQUAKE #ifdef VKQUAKE
cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0."); cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers."); cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers."); cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_loadglsl = CVARD ("vk_loadglsl", "", "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after."); cvar_t vk_dualqueue = CVARD ("vk_dualqueue", "", "Attempt to use a separate queue for presentation. Blank for default.");
cvar_t vk_dualqueue = CVARD ("vk_dualqueue", "", "Attempt to use a separate queue for presentation. Blank for default."); cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing.");
cvar_t vk_nv_glsl_shader = CVARD ("vk_loadglsl", "", "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
cvar_t vk_nv_dedicated_allocation = CVARD ("vk_nv_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
//cvar_t vk_khr_dedicated_allocation = CVARD ("vk_khr_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
cvar_t vk_khr_push_descriptor = CVARD ("vk_khr_push_descriptor", "", "Enables better descriptor streaming.");
#endif #endif
#if defined(D3DQUAKE) #if defined(D3DQUAKE)
@ -709,9 +732,33 @@ void Renderer_Init(void)
//but register ALL vid_ commands. //but register ALL vid_ commands.
Cvar_Register (&gl_driver, GLRENDEREROPTIONS); Cvar_Register (&gl_driver, GLRENDEREROPTIONS);
Cvar_Register (&vid_vsync, VIDCOMMANDGROUP); Cvar_Register (&vid_vsync, VIDCOMMANDGROUP);
Cvar_Register (&vid_wndalpha, VIDCOMMANDGROUP);
#if defined(_WIN32) && defined(MULTITHREAD)
Cvar_Register (&vid_winthread, VIDCOMMANDGROUP);
#endif
Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP); Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP);
Cvar_Register (&vid_renderer, VIDCOMMANDGROUP); Cvar_Register (&vid_renderer, VIDCOMMANDGROUP);
Cvar_Register (&vid_wndalpha, VIDCOMMANDGROUP); vid_renderer_opts.enginevalue =
#ifdef GLQUAKE
"gl \"OpenGL\" "
#endif
#ifdef VKQUAKE
"vk \"Vulkan\" "
#endif
#ifdef D3D8QUAKE
// "d3d8 \"Direct3D 8\" "
#endif
#ifdef D3D9QUAKE
"d3d9 \"Direct3D 9\" "
#endif
#ifdef D3D11QUAKE
"d3d11 \"Direct3D 11\" "
#endif
#ifdef SWQUAKE
"sw \"Software Rendering\" "
#endif
"";
Cvar_Register (&vid_renderer_opts, VIDCOMMANDGROUP);
#ifndef NACL #ifndef NACL
if (COM_CheckParm("-plugin")) if (COM_CheckParm("-plugin"))
@ -750,10 +797,12 @@ void Renderer_Init(void)
Cvar_Register (&r_norefresh, GLRENDEREROPTIONS); Cvar_Register (&r_norefresh, GLRENDEREROPTIONS);
Cvar_Register (&r_mirroralpha, GLRENDEREROPTIONS); Cvar_Register (&r_mirroralpha, GLRENDEREROPTIONS);
Cvar_Register (&r_skyboxname, GRAPHICALNICETIES);
Cbuf_AddText("alias sky r_skybox\n", RESTRICT_LOCAL); /*alternative name for users*/
Cvar_Register (&r_softwarebanding_cvar, GRAPHICALNICETIES); Cvar_Register (&r_softwarebanding_cvar, GRAPHICALNICETIES);
Cvar_Register (&r_skyboxname, GRAPHICALNICETIES);
Cmd_AddCommand("sky", R_ForceSky_f); //QS compat
Cmd_AddCommand("loadsky", R_ForceSky_f);//DP compat
Cvar_Register(&r_dodgytgafiles, "Hacky bug workarounds"); Cvar_Register(&r_dodgytgafiles, "Hacky bug workarounds");
Cvar_Register(&r_dodgypcxfiles, "Hacky bug workarounds"); Cvar_Register(&r_dodgypcxfiles, "Hacky bug workarounds");
Cvar_Register(&r_dodgymiptex, "Hacky bug workarounds"); Cvar_Register(&r_dodgymiptex, "Hacky bug workarounds");
@ -915,11 +964,16 @@ void Renderer_Init(void)
Cvar_Register (&r_forceprogramify, GLRENDEREROPTIONS); Cvar_Register (&r_forceprogramify, GLRENDEREROPTIONS);
#ifdef VKQUAKE #ifdef VKQUAKE
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS); Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS); Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
Cvar_Register (&vk_debug, VKRENDEREROPTIONS); Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
Cvar_Register (&vk_loadglsl, VKRENDEREROPTIONS); Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS); Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
// Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS);
Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS);
#endif #endif
// misc // misc
@ -1966,9 +2020,14 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
} }
else if (psprite->frames[frame].type == SPR_ANGLED) else if (psprite->frames[frame].type == SPR_ANGLED)
{ {
float f = DotProduct(vpn,currententity->axis[0]);
float r = DotProduct(vright,currententity->axis[0]);
int dir = (atan2(r, f)+1.125*M_PI)*(4/M_PI);
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
// pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*pspritegroup->numframes + 0.5-4)%pspritegroup->numframes]; // pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*pspritegroup->numframes + 0.5-4)%pspritegroup->numframes];
pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 0.5-4)&7]; //int dir = (int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 8 + 0.5-4)&7;
pspriteframe = pspritegroup->frames[dir&7];
} }
else else
{ {
@ -2125,8 +2184,8 @@ texture_t *R_TextureAnimation_Q2 (texture_t *base)
unsigned int r_viewcontents; unsigned int r_viewcontents;
mleaf_t *r_viewleaf, *r_oldviewleaf; //mleaf_t *r_viewleaf, *r_oldviewleaf;
mleaf_t *r_viewleaf2, *r_oldviewleaf2; //mleaf_t *r_viewleaf2, *r_oldviewleaf2;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
int r_visframecount; int r_visframecount;
mleaf_t *r_vischain; // linked list of visible leafs mleaf_t *r_vischain; // linked list of visible leafs
@ -2357,23 +2416,23 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
{ {
vis = cvis[portal] = r_refdef.forcedvis; vis = cvis[portal] = r_refdef.forcedvis;
r_oldviewleaf = NULL; r_oldviewcluster = -1;
r_oldviewleaf2 = NULL; r_oldviewcluster2 = -1;
} }
else else
{ {
if (!portal) if (!portal)
{ {
if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2) if (((r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2) && !r_novis.ival) || r_novis.ival & 2)
return cvis[portal]; return cvis[portal];
r_oldviewleaf = r_viewleaf; r_oldviewcluster = r_viewcluster;
r_oldviewleaf2 = r_viewleaf2; r_oldviewcluster2 = r_viewcluster2;
} }
else else
{ {
r_oldviewleaf = NULL; r_oldviewcluster = -1;
r_oldviewleaf2 = NULL; r_oldviewcluster2 = -1;
} }
if (r_novis.ival) if (r_novis.ival)
@ -2381,14 +2440,18 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
vis = cvis[portal] = curframevis[portal].buffer; vis = cvis[portal] = curframevis[portal].buffer;
memset (curframevis[portal].buffer, 0xff, curframevis[portal].buffersize); memset (curframevis[portal].buffer, 0xff, curframevis[portal].buffersize);
r_oldviewleaf = NULL; r_oldviewcluster = -1;
r_oldviewleaf2 = NULL; r_oldviewcluster2 = -1;
} }
else else
{ {
vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, &curframevis[portal], false); if (r_viewcluster2 != -1 && r_viewcluster2 != r_viewcluster)
if (r_viewleaf2 && r_viewleaf2 != r_viewleaf) {
vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, &curframevis[portal], true); vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster, &curframevis[portal], PVM_REPLACE);
vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster2, &curframevis[portal], PVM_MERGE);
}
else
vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster, &curframevis[portal], PVM_FAST);
} }
} }
@ -2396,7 +2459,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
if (getvisonly) if (getvisonly)
return vis; return vis;
else if (r_viewleaf && r_viewleaf->contents == Q1CONTENTS_SOLID) else if (r_viewcluster == -1)
{ {
//to improve spectating, when the camera is in a wall, we ignore any sky leafs. //to improve spectating, when the camera is in a wall, we ignore any sky leafs.
//this prevents seeing the upwards-facing sky surfaces within the sky volumes. //this prevents seeing the upwards-facing sky surfaces within the sky volumes.

View File

@ -176,6 +176,7 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
int Font_LineWidth(conchar_t *start, conchar_t *end); int Font_LineWidth(conchar_t *start, conchar_t *end);
float Font_LineScaleWidth(conchar_t *start, conchar_t *end); float Font_LineScaleWidth(conchar_t *start, conchar_t *end);
void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end); void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end);
conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end);
extern struct font_s *font_default; extern struct font_s *font_default;
extern struct font_s *font_console; extern struct font_s *font_console;
extern struct font_s *font_tiny; extern struct font_s *font_tiny;

View File

@ -316,15 +316,8 @@ typedef struct {
GUID SubFormat; GUID SubFormat;
} QWAVEFORMATEX; } QWAVEFORMATEX;
const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
{0x80, const static GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
0x00,
0x00,
0xaa,
0x00,
0x38,
0x9b,
0x71}};
#ifdef _IKsPropertySet_ #ifdef _IKsPropertySet_
const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3, const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3,
@ -539,7 +532,7 @@ static unsigned int DSOUND_GetDMAPos(soundcardinfo_t *sc)
s = mmtime - dh->mmstarttime; s = mmtime - dh->mmstarttime;
s >>= (sc->sn.samplebits/8) - 1; s /= (sc->sn.samplebits/8);
s %= (sc->sn.samples); s %= (sc->sn.samples);
@ -664,6 +657,13 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, char *cardname)
sc->sn.numchannels = 1; sc->sn.numchannels = 1;
} }
if (sc->sn.samplebits == 32)
{ //FTE does not support 32bit int audio, rather we interpret samplebits 32 as floats.
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
format.Format.cbSize = 22;
memcpy(&format.SubFormat, &QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID));
}
format.Format.nChannels = sc->sn.numchannels; format.Format.nChannels = sc->sn.numchannels;
format.Format.wBitsPerSample = sc->sn.samplebits; format.Format.wBitsPerSample = sc->sn.samplebits;
format.Format.nSamplesPerSec = sc->sn.speed; format.Format.nSamplesPerSec = sc->sn.speed;

View File

@ -2046,6 +2046,8 @@ void S_DoRestart (qboolean onlyifneeded)
void S_Restart_f (void) void S_Restart_f (void)
{ {
S_EnumerateDevices();
S_DoRestart(false); S_DoRestart(false);
} }

View File

@ -242,6 +242,11 @@ int WAV_InitCard (soundcardinfo_t *sc, int cardnum)
if (sc->sn.speed > 48000) // limit waveout to 48000 until that buffer issue gets solved if (sc->sn.speed > 48000) // limit waveout to 48000 until that buffer issue gets solved
sc->sn.speed = 48000; sc->sn.speed = 48000;
if (sc->sn.samplebits > 16)
sc->sn.samplebits = 16;
else
sc->sn.samplebits = 8;
memset (&format, 0, sizeof(format)); memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM; format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = sc->sn.numchannels; format.nChannels = sc->sn.numchannels;

View File

@ -130,19 +130,27 @@ static qboolean QDECL XAUDIO_InitCard(soundcardinfo_t *sc, const char *cardname)
int dev = 0; int dev = 0;
#endif #endif
xaud_t *xa = Z_Malloc(sizeof(*xa)); xaud_t *xa = Z_Malloc(sizeof(*xa));
WAVEFORMATEX wfmt; WAVEFORMATEXTENSIBLE wfmt;
const static GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
xa->cb.lpVtbl = &cbvtbl; xa->cb.lpVtbl = &cbvtbl;
sc->sn.numchannels = 2; sc->sn.numchannels = 2;
wfmt.wFormatTag = WAVE_FORMAT_PCM; memset(&wfmt, 0, sizeof(wfmt));
wfmt.nChannels = sc->sn.numchannels; wfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
wfmt.nSamplesPerSec = sc->sn.speed; wfmt.Format.nChannels = sc->sn.numchannels;
wfmt.wBitsPerSample = sc->sn.samplebits; wfmt.Format.nSamplesPerSec = sc->sn.speed;
wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8); wfmt.Format.wBitsPerSample = sc->sn.samplebits;
wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign; wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8);
wfmt.cbSize = 0; wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign;
wfmt.Format.cbSize = 0;
if (wfmt.Format.wBitsPerSample == 32)
{
wfmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfmt.Format.cbSize = 22;
memcpy(&wfmt.SubFormat, &QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(wfmt.SubFormat));
}
sc->inactive_sound = true; sc->inactive_sound = true;
xa->buffercount = xa->bufferavail = 3; //submit this many straight up xa->buffercount = xa->bufferavail = 3; //submit this many straight up
@ -198,7 +206,7 @@ static qboolean QDECL XAUDIO_InitCard(soundcardinfo_t *sc, const char *cardname)
sd[0].Flags = 0; sd[0].Flags = 0;
sd[0].pOutputVoice = (IXAudio2Voice*)xa->master; sd[0].pOutputVoice = (IXAudio2Voice*)xa->master;
if (SUCCEEDED(IXAudio2_CreateSourceVoice(xa->ixa, &xa->source, &wfmt, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &xa->cb, &vs, NULL))) if (SUCCEEDED(IXAudio2_CreateSourceVoice(xa->ixa, &xa->source, &wfmt.Format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &xa->cb, &vs, NULL)))
{ {
sc->handle = xa; sc->handle = xa;
sc->GetDMAPos = XAUDIO_GetDMAPos; sc->GetDMAPos = XAUDIO_GetDMAPos;

View File

@ -87,7 +87,7 @@ typedef struct
int samples; // mono samples in buffer (individual, non grouped) int samples; // mono samples in buffer (individual, non grouped)
// int submission_chunk; // don't mix less than this # // int submission_chunk; // don't mix less than this #
int samplepos; // in mono samples int samplepos; // in mono samples
int samplebits; int samplebits; //FIXME: replace with a format enum (with separate framebytes field for lazyness).
int speed; // this many frames per second int speed; // this many frames per second
unsigned char *buffer; // pointer to mixed pcm buffer (not directly used by mixer) unsigned char *buffer; // pointer to mixed pcm buffer (not directly used by mixer)
} dma_t; } dma_t;

View File

@ -1105,13 +1105,15 @@ int COM_EncodeSize(vec3_t mins, vec3_t maxs)
solid = bound(0, (int)-mins[0], 255); solid = bound(0, (int)-mins[0], 255);
solid |= bound(0, (int)-mins[2], 255)<<8; solid |= bound(0, (int)-mins[2], 255)<<8;
solid |= bound(0, (int)((maxs[2]+32768)), 65535)<<16; /*up can be negative*/; solid |= bound(0, (int)((maxs[2]+32768)), 65535)<<16; /*up can be negative*/;
if (solid == 0x80000000)
solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
#else #else
solid = bound(0, (int)-mins[0]/8, 31); solid = bound(0, (int)-mins[0]/8, 31);
solid |= bound(0, (int)-mins[2]/8, 31)<<5; solid |= bound(0, (int)-mins[2]/8, 31)<<5;
solid |= bound(0, (int)((maxs[2]+32)/8), 63)<<10; /*up can be negative*/; solid |= bound(0, (int)((maxs[2]+32)/8), 63)<<10; /*up can be negative*/;
#endif
if (solid == 4096) if (solid == 4096)
solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens. solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
#endif
return solid; return solid;
} }

View File

@ -33,6 +33,7 @@ the second part is some entropy differences that just allows zlib to work more e
I've rewritten the archive/outer part to plug it in to fte more nicely I've rewritten the archive/outer part to plug it in to fte more nicely
the demo/inner part should mostly be the same as dzip, just with some minor tweaks to make it thread-safe (the 'dc' pointer stuff, in case that's ever an issue). the demo/inner part should mostly be the same as dzip, just with some minor tweaks to make it thread-safe (the 'dc' pointer stuff, in case that's ever an issue).
I have explicitly changed longs to ints, to ensure there's no issues with 64bit builds
*/ */
#include "quakedef.h" #include "quakedef.h"
@ -132,7 +133,6 @@ enum {
}; };
//basic types //basic types
#define long int //gah!
typedef unsigned int uInt; //gah! typedef unsigned int uInt; //gah!
typedef qbyte uchar; typedef qbyte uchar;
@ -140,7 +140,7 @@ typedef struct {
uchar voz, pax; uchar voz, pax;
uchar ang0, ang1, ang2; uchar ang0, ang1, ang2;
uchar vel0, vel1, vel2; uchar vel0, vel1, vel2;
long items; int items;
uchar uk10, uk11, invbit; uchar uk10, uk11, invbit;
uchar wpf, av, wpm; uchar wpf, av, wpm;
int health; int health;
@ -174,9 +174,9 @@ typedef struct
uchar copybaseline; uchar copybaseline;
int maxent, lastent, sble; int maxent, lastent, sble;
int entlink[MAX_ENT]; int entlink[MAX_ENT];
long dem_gametime; int dem_gametime;
long outlen; int outlen;
long cam0, cam1, cam2; int cam0, cam1, cam2;
uchar inblk[p_blocksize], outblk[p_blocksize], *inptr; uchar inblk[p_blocksize], outblk[p_blocksize], *inptr;
cdata_t oldcd, newcd; cdata_t oldcd, newcd;
ent_t base[MAX_ENT], oldent[MAX_ENT], newent[MAX_ENT]; ent_t base[MAX_ENT], oldent[MAX_ENT], newent[MAX_ENT];
@ -192,18 +192,18 @@ static void Outfile_Write(decodectx_t *dc, void *outblk, size_t outlen)
} }
} }
static copy_msg(decodectx_t *dc, size_t bytes) static void copy_msg(decodectx_t *dc, size_t bytes)
{ //just copy the data over { //just copy the data over
memcpy(dc->outblk+dc->outlen, dc->inptr, bytes); memcpy(dc->outblk+dc->outlen, dc->inptr, bytes);
dc->outlen += bytes; dc->outlen += bytes;
dc->inptr += bytes; dc->inptr += bytes;
} }
static insert_msg (decodectx_t *dc, void *data, size_t bytes) static void insert_msg (decodectx_t *dc, void *data, size_t bytes)
{ {
memcpy(dc->outblk+dc->outlen, data, bytes); memcpy(dc->outblk+dc->outlen, data, bytes);
dc->outlen += bytes; dc->outlen += bytes;
} }
static discard_msg (decodectx_t *dc, size_t bytes) static void discard_msg (decodectx_t *dc, size_t bytes)
{ {
dc->inptr += bytes; dc->inptr += bytes;
} }
@ -236,7 +236,7 @@ static discard_msg (decodectx_t *dc, size_t bytes)
#define GUI //because it disables v1 #define GUI //because it disables v1
#define getshort(x) LittleShort(*(short*)(x)) #define getshort(x) LittleShort(*(short*)(x))
#define getlong(x) LittleLong(*(long*)(x)) #define getlong(x) LittleLong(*(int*)(x))
#define getfloat(x) LittleFloat(*(float*)(x)) #define getfloat(x) LittleFloat(*(float*)(x))
#define cnvlong(x) LittleLong(x) #define cnvlong(x) LittleLong(x)
@ -336,7 +336,7 @@ void demx_sound(decodectx_t *dc)
void demx_longtime(decodectx_t *dc) void demx_longtime(decodectx_t *dc)
{ {
long tmp = getlong(inptr+1); int tmp = getlong(inptr+1);
dem_gametime += tmp; dem_gametime += tmp;
tmp = cnvlong(dem_gametime); tmp = cnvlong(dem_gametime);
*inptr = DEM_time; *inptr = DEM_time;
@ -347,7 +347,7 @@ void demx_longtime(decodectx_t *dc)
void demx_time(decodectx_t *dc) void demx_time(decodectx_t *dc)
{ {
uchar buf[5]; uchar buf[5];
long tmp = getshort(inptr+1) & 0xffff; int tmp = getshort(inptr+1) & 0xffff;
#ifndef GUI #ifndef GUI
if (dem_decode_type == TYPE_DEMV1) { demx_longtime(); return; } if (dem_decode_type == TYPE_DEMV1) { demx_longtime(); return; }
@ -420,7 +420,7 @@ void create_clientdata_msg(decodectx_t *dc)
uchar buf[32]; uchar buf[32];
uchar *ptr = buf+3; uchar *ptr = buf+3;
int mask = newcd.invbit? 0 : 0x0200; int mask = newcd.invbit? 0 : 0x0200;
long tmp; int tmp;
buf[0] = DEM_clientdata; buf[0] = DEM_clientdata;
@ -645,7 +645,7 @@ void demx_updateentity(decodectx_t *dc)
int mask, i, entity; int mask, i, entity;
int baseval = 0, prev; int baseval = 0, prev;
ent_t n, o; ent_t n, o;
long tmp; int tmp;
#ifndef GUI #ifndef GUI
if (dem_decode_type == TYPE_DEMV1) { demv1_updateentity(); return; } if (dem_decode_type == TYPE_DEMV1) { demv1_updateentity(); return; }
@ -841,7 +841,7 @@ void dem_uncompress_init (decodectx_t *dc, int type)
uInt dem_uncompress_block(decodectx_t *dc) uInt dem_uncompress_block(decodectx_t *dc)
{ {
long a1; int a1;
uchar cfields; uchar cfields;
#ifdef GUI #ifdef GUI
int uemask = 0x30, cdmask = 0x40; int uemask = 0x30, cdmask = 0x40;
@ -971,7 +971,6 @@ uInt dem_uncompress (decodectx_t *dc, uInt maxsize)
//pack mutex must be held for this function. //pack mutex must be held for this function.
qboolean FSDZ_ExtractFile(qbyte *out, size_t outsize, dzarchive_t *pack, mdzfile_t *src) qboolean FSDZ_ExtractFile(qbyte *out, size_t outsize, dzarchive_t *pack, mdzfile_t *src)
{ {
qboolean dedemo = false;
switch(src->ztype) switch(src->ztype)
{ {
case TYPE_PAK: case TYPE_PAK:
@ -1024,7 +1023,6 @@ qboolean FSDZ_ExtractFile(qbyte *out, size_t outsize, dzarchive_t *pack, mdzfile
unsigned char inbuffer[p_blocksize]; unsigned char inbuffer[p_blocksize];
int ret; int ret;
size_t inremaining = src->csize; size_t inremaining = src->csize;
size_t decompressed = 0;
decodectx_t *dc = NULL; decodectx_t *dc = NULL;
z_stream strm = { z_stream strm = {
@ -1380,7 +1378,7 @@ searchpathfuncs_t *QDECL FSDZ_LoadArchive (vfsfile_t *file, const char *desc, co
read = VFS_READ(packhandle, &header, sizeof(header)); read = VFS_READ(packhandle, &header, sizeof(header));
if (read < sizeof(header) || header.id[0] != 'D' || header.id[1] != 'Z') if (read < sizeof(header) || header.id[0] != 'D' || header.id[1] != 'Z')
{ {
Con_Printf("%s is not a dz - %c%c\n", desc); Con_Printf("%s is not a dz - %c%c\n", desc, header.id[0], header.id[1]);
return NULL; return NULL;
} }
if (header.major_ver > 2/* || (header.major_ver == 2 && header.minor_ver > 9)*/) if (header.major_ver > 2/* || (header.major_ver == 2 && header.minor_ver > 9)*/)

View File

@ -543,7 +543,7 @@ static void IPLog_Identify_f(void)
else else
Con_Printf("%s: not connected, nor raw address\n", Cmd_Argv(0)); Con_Printf("%s: not connected, nor raw address\n", Cmd_Argv(0));
} }
static qboolean IPLog_Dump(const char *fname) static int IPLog_Dump(const char *fname)
{ {
size_t i; size_t i;
vfsfile_t *f; vfsfile_t *f;
@ -551,6 +551,9 @@ static qboolean IPLog_Dump(const char *fname)
if (!*fname) if (!*fname)
fname = "iplog.txt"; fname = "iplog.txt";
if (!iplog_num && !COM_FCheckExists(fname))
return 2; //no entries, nothing to overwrite
f = FS_OpenVFS(fname, "wb", FS_PUBBASEGAMEONLY); f = FS_OpenVFS(fname, "wb", FS_PUBBASEGAMEONLY);
if (!f) if (!f)
return false; return false;
@ -590,11 +593,18 @@ static void IPLog_Dump_f(void)
if (FS_NativePath(fname, FS_GAMEONLY, native, sizeof(native))) if (FS_NativePath(fname, FS_GAMEONLY, native, sizeof(native)))
Q_strncpyz(native, fname, sizeof(native)); Q_strncpyz(native, fname, sizeof(native));
IPLog_Merge_File(fname); //merge from the existing file, so that we're hopefully more robust if multiple processes are poking the same file. IPLog_Merge_File(fname); //merge from the existing file, so that we're hopefully more robust if multiple processes are poking the same file.
if (!IPLog_Dump(fname)) switch (IPLog_Dump(fname))
Con_Printf("unable to write %s\n", fname);
else
{ {
case 0:
Con_Printf("unable to write %s\n", fname);
break;
default:
case 1:
Con_Printf("wrote %s\n", native); Con_Printf("wrote %s\n", native);
break;
case 2:
Con_Printf("nothing to write\n");
break;
} }
} }
static void IPLog_Merge_f(void) static void IPLog_Merge_f(void)

View File

@ -159,8 +159,9 @@ typedef enum
Q2PT_RESPAWN, Q2PT_RESPAWN,
Q2PT_PLAYER_TELEPORT, Q2PT_PLAYER_TELEPORT,
Q2PT_FOOTSTEP Q2PT_FOOTSTEP,
Q2PT_MAX
} q2particleeffects_t; } q2particleeffects_t;
extern int pt_q2[]; extern int pt_q2[];
#endif #endif
@ -255,7 +256,7 @@ typedef struct {
void (*RunParticleEffect4) (vec3_t org, float radius, int color, int effect, int count); void (*RunParticleEffect4) (vec3_t org, float radius, int color, int effect, int count);
void (*RunParticleEffectPalette) (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count); void (*RunParticleEffectPalette) (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count);
void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk); void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk); //P_INVALID is fine for the type here, you'll get a default trail.
qboolean (*InitParticles) (void); qboolean (*InitParticles) (void);
void (*ShutdownParticles) (void); void (*ShutdownParticles) (void);
void (*DelinkTrailstate) (trailstate_t **tsk); void (*DelinkTrailstate) (trailstate_t **tsk);

View File

@ -1147,13 +1147,14 @@ typedef struct usercmd_s
qbyte lightlevel; qbyte lightlevel;
//freestyle //freestyle
float msec; float msec; //replace msec, but with more precision
int buttons; int buttons; //replaces buttons, but with more bits.
int weapon; int weapon; //q3 has a separate weapon field to supplement impulse.
int servertime; int servertime; //q3 networks the time in order to calculate msecs
float fservertime; float fservertime;//used as part of nq msec calcs
float fclienttime; float fclienttime;//not used?
//prydon cursor crap
vec2_t cursor_screen; vec2_t cursor_screen;
vec3_t cursor_start; vec3_t cursor_start;
vec3_t cursor_impact; vec3_t cursor_impact;
@ -1161,17 +1162,17 @@ typedef struct usercmd_s
} usercmd_t; } usercmd_t;
typedef struct q2usercmd_s typedef struct q2usercmd_s
{ { //visible to gamecode so can't be changed (and the prediction code)
qbyte msec; qbyte msec;
qbyte buttons; qbyte buttons;
short angles[3]; short angles[3];
short forwardmove, sidemove, upmove; short forwardmove, sidemove, upmove;
qbyte impulse; qbyte impulse;
qbyte lightlevel; qbyte lightlevel;
} q2usercmd_t; } q2usercmd_t;
typedef struct q1usercmd_s typedef struct q1usercmd_s
{ { //as written to qwd demos so can't be changed.
qbyte msec; qbyte msec;
vec3_t angles; vec3_t angles;
short forwardmove, sidemove, upmove; short forwardmove, sidemove, upmove;

View File

@ -1739,6 +1739,7 @@ Rendering functions (Client only)
Server only functions Server only functions
*/ */
#ifndef CLIENTONLY #ifndef CLIENTONLY
static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer, pvsmerge_t merge);
//does the recursive work of Q1BSP_FatPVS //does the recursive work of Q1BSP_FatPVS
static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbuffer_t *pvsbuffer) static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbuffer_t *pvsbuffer)
@ -1753,7 +1754,7 @@ static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbu
{ {
if (node->contents != Q1CONTENTS_SOLID) if (node->contents != Q1CONTENTS_SOLID)
{ {
Q1BSP_LeafPVS (mod, (mleaf_t *)node, pvsbuffer, true); Q1BSP_ClusterPVS(mod, ((mleaf_t *)node - mod->leafs)-1, pvsbuffer, PVM_MERGE);
} }
return; return;
} }
@ -1935,25 +1936,12 @@ static qbyte *Q1BSP_DecompressVis (qbyte *in, model_t *model, qbyte *decompresse
static pvsbuffer_t mod_novis; static pvsbuffer_t mod_novis;
static pvsbuffer_t mod_tempvis; static pvsbuffer_t mod_tempvis;
qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, pvsbuffer_t *buffer, qboolean merge) void Q1BSP_Shutdown(void)
{ {
if (leaf == model->leafs) Z_Free(mod_novis.buffer);
{ memset(&mod_novis, 0, sizeof(mod_novis));
if (mod_novis.buffersize < model->pvsbytes) Z_Free(mod_tempvis.buffer);
{ memset(&mod_tempvis, 0, sizeof(mod_tempvis));
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes);
memset(mod_novis.buffer, 0xff, mod_novis.buffersize);
}
return mod_novis.buffer;
}
if (!buffer)
buffer = &mod_tempvis;
if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
return Q1BSP_DecompressVis (leaf->compressed_vis, model, buffer->buffer, buffer->buffersize, merge);
} }
//pvs is 1-based. clusters are 0-based. otherwise, q1bsp has a 1:1 mapping. //pvs is 1-based. clusters are 0-based. otherwise, q1bsp has a 1:1 mapping.
@ -1990,20 +1978,34 @@ static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer
return Q1BSP_DecompressVis (model->leafs[cluster].compressed_vis, model, buffer->buffer, buffer->buffersize, merge==PVM_MERGE); return Q1BSP_DecompressVis (model->leafs[cluster].compressed_vis, model, buffer->buffer, buffer->buffersize, merge==PVM_MERGE);
} }
/*static qbyte *Q1BSP_ClusterPHS (model_t *model, int cluster, pvsbuffer_t *buffer) /*static qbyte *Q1BSP_ClusterPHS (model_t *model, int cluster, pvsbuffer_t *buffer, pvsmerge_t merge)
{ {
if (cluster == -1 || !model->phs) if (cluster == -1 || !model->phs)
{ //without any phs info, this turns into a broadcast. {
if (mod_novis.buffersize < model->pvsbytes) if (merge == PVM_FAST)
{ {
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes); if (mod_novis.buffersize < model->pvsbytes)
memset(mod_novis.buffer, 0xff, mod_novis.buffersize); {
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes);
memset(mod_novis.buffer, 0xff, mod_novis.buffersize);
}
return mod_novis.buffer;
} }
return mod_novis.buffer; if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
memset(buffer->buffer, 0xff, model->pvsbytes);
return buffer->buffer;
} }
cluster++;
return model->phs + cluster * model->pvsbytes; if (merge == PVM_FAST)
return model->pvs + cluster * model->pvsbytes;
if (!buffer)
buffer = &mod_tempvis;
if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
memcpy(buffer->buffer, model->pvs + cluster * model->pvsbytes, model->pvsbytes);
return buffer->buffer;
}*/ }*/
//returns the leaf number, which is used as a bit index into the pvs. //returns the leaf number, which is used as a bit index into the pvs.

View File

@ -1708,14 +1708,7 @@ void MSG_Q3_ReadDeltaUsercmd(int key, const usercmd_t *from, usercmd_t *to)
to->servertime = MSG_ReadBits(8) + from->servertime; to->servertime = MSG_ReadBits(8) + from->servertime;
else else
to->servertime = MSG_ReadBits(32); to->servertime = MSG_ReadBits(32);
to->msec = 0; //first of a packet should always be an absolute value, which makes the old value awkward.
if ((unsigned int)(to->servertime - from->servertime) > 255)
{
Con_DPrintf("msecs clamped\n");
to->msec = 255;
}
else
to->msec = to->servertime - from->servertime;
if (!MSG_ReadBits(1)) if (!MSG_ReadBits(1))
{ {

View File

@ -1447,8 +1447,9 @@ void GLBE_Init(void)
if (gl_config.glversion >= 3.0 && gl_config_nofixedfunc) if (gl_config.glversion >= 3.0 && gl_config_nofixedfunc)
{ {
//docs say this line should be okay in gl3+. nvidia do not seem to agree. GL_STENCIL_BITS is depricated however. so for now, just assume. //docs say this line should be okay in gl3+. nvidia do not seem to agree. GL_STENCIL_BITS is depricated however. so for now, just assume.
//qglGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_EXT, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &gl_stencilbits); qglGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_EXT, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &gl_stencilbits);
gl_stencilbits = 8; if (qglGetError())
gl_stencilbits = 8;
} }
else else
qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits); qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits);
@ -1484,9 +1485,17 @@ void GLBE_Init(void)
if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival)
{ {
if (r_shadow_shadowmapping.ival) if (r_shadow_shadowmapping.ival)
{
GLBE_RegisterLightShader(LSHADER_SMAP); GLBE_RegisterLightShader(LSHADER_SMAP);
GLBE_RegisterLightShader(LSHADER_SMAP|LSHADER_CUBE);
GLBE_RegisterLightShader(LSHADER_SMAP|LSHADER_SPOT);
}
else else
GLBE_RegisterLightShader(0); {
GLBE_RegisterLightShader(LSHADER_STANDARD);
GLBE_RegisterLightShader(LSHADER_STANDARD|LSHADER_CUBE);
GLBE_RegisterLightShader(LSHADER_STANDARD|LSHADER_SPOT);
}
} }
#endif #endif

View File

@ -220,11 +220,11 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
R2D_Flush(); R2D_Flush();
#if 1 #if 1
/*filter the screen into a downscaled image*/ /*filter the screen into a downscaled image*/
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false); VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_filter); VKBE_RT_Begin(&vk_rt_filter);
vk.sourcecolour = source; vk.sourcecolour = source;
R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter); R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter);
R2D_Flush(); VKBE_RT_End(&vk_rt_filter);
intex = &vk_rt_filter.q_colour; intex = &vk_rt_filter.q_colour;
#else #else
intex = source; intex = source;
@ -251,29 +251,27 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
r_worldentity.glowmod[1] = 0; r_worldentity.glowmod[1] = 0;
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false); VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[1][i]); VKBE_RT_Begin(&vk_rt_bloom[1][i]);
vk.sourcecolour = intex; vk.sourcecolour = intex;
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur); R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush(); VKBE_RT_End(&vk_rt_bloom[1][i]);
r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 1.0 / texheight[i]; r_worldentity.glowmod[1] = 1.0 / texheight[i];
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false); VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[0][i]); VKBE_RT_Begin(&vk_rt_bloom[0][i]);
vk.sourcecolour = &vk_rt_bloom[1][i].q_colour; vk.sourcecolour = &vk_rt_bloom[1][i].q_colour;
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur); R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush(); VKBE_RT_End(&vk_rt_bloom[0][i]);
intex = &vk_rt_bloom[0][i].q_colour; intex = &vk_rt_bloom[0][i].q_colour;
} }
r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0; r_worldentity.glowmod[1] = 0;
VKBE_RT_Begin(oldfbo);
//go back to the screen fbo
/*combine them onto the screen*/ /*combine them onto the screen*/
bloomfinal->defaulttextures->base = intex; bloomfinal->defaulttextures->base = intex;
@ -288,10 +286,10 @@ void VK_R_BloomShutdown(void)
int i; int i;
for (i = 0; i < MAXLEVELS; i++) for (i = 0; i < MAXLEVELS; i++)
{ {
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false); VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false); VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false, RT_IMAGEFLAGS);
} }
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false); VKBE_RT_Gen(&vk_rt_filter, 0, 0, false, RT_IMAGEFLAGS);
R_InitBloomTextures(); R_InitBloomTextures();
} }

View File

@ -66,12 +66,10 @@ void GLDraw_Init (void)
if (gl_config.gles && gl_config.glversion < 3.0) if (gl_config.gles && gl_config.glversion < 3.0)
r_softwarebanding = false; r_softwarebanding = false;
if (!gl_config.gles) if (gl_config.arb_framebuffer_srgb)
{ {
extern cvar_t vid_srgb; extern cvar_t vid_srgb;
GLint srgb; vid.srgb = vid_srgb.ival>1;
qglGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &srgb);
vid.srgb = vid_srgb.ival>1 && srgb;
if (vid.srgb) if (vid.srgb)
qglEnable(GL_FRAMEBUFFER_SRGB); qglEnable(GL_FRAMEBUFFER_SRGB);
} }

View File

@ -1816,6 +1816,22 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
} }
} }
conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end)
{
int lx = 0, nx;
struct font_s *font = curfont;
unsigned int codeflags, codepoint;
conchar_t *nc;
for (; start < end; lx = nx, start = nc)
{
nc = Font_Decode(start, &codeflags, &codepoint);
nx = Font_CharEndCoord(font, lx, codeflags, codepoint);
if (x >= lx && x < nx)
return start;
}
return NULL;
}
/*Note: *all* strings after the current one will inherit the same colour, until one changes it explicitly /*Note: *all* strings after the current one will inherit the same colour, until one changes it explicitly
correct usage of this function thus requires calling this with 1111 before Font_EndString*/ correct usage of this function thus requires calling this with 1111 before Font_EndString*/
void Font_InvalidateColour(vec4_t newcolour) void Font_InvalidateColour(vec4_t newcolour)

View File

@ -5847,6 +5847,7 @@ void Mod_LoadDoomSprite (model_t *mod)
mspriteframe_t frame; mspriteframe_t frame;
size_t c; size_t c;
unsigned int *colpointers; unsigned int *colpointers;
vec3_t t;
mod->type = mod_dummy; mod->type = mod_dummy;
@ -5908,6 +5909,8 @@ void Mod_LoadDoomSprite (model_t *mod)
} }
Z_Free(coldata); Z_Free(coldata);
ClearBounds(mod->mins, mod->maxs);
//do the actual loading. //do the actual loading.
for (ofs = 4; ofs < *(int*)files; ofs+=strlen(files+ofs)+1) for (ofs = 4; ofs < *(int*)files; ofs+=strlen(files+ofs)+1)
{ {
@ -5915,11 +5918,18 @@ void Mod_LoadDoomSprite (model_t *mod)
header = (doomimage_t *)FS_LoadMallocFile(name, &fsize); header = (doomimage_t *)FS_LoadMallocFile(name, &fsize);
frame.up = +header->ypos; //the 5 is because doom likes drawing sprites slightly downwards, in the floor.
frame.down = -header->height + header->ypos; frame.up = header->ypos + 5;
frame.down = header->ypos-header->height + 5;
frame.left = -header->xpos; frame.left = -header->xpos;
frame.right = header->width - header->xpos; frame.right = header->width - header->xpos;
t[0] = t[1] = max(abs(frame.left),abs(frame.right));
t[2] = frame.up;
AddPointToBounds(t, mod->mins, mod->maxs);
t[0] *= -1;
t[1] *= -1;
t[2] = frame.down;
if (header->width*header->height <= sizeof(image)) if (header->width*header->height <= sizeof(image))
{ {

View File

@ -539,7 +539,6 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node);
void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace);
qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, pvsbuffer_t *buffer, qboolean merge);
/* /*
============================================================================== ==============================================================================

View File

@ -5810,7 +5810,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args)
"}\n" "}\n"
); );
} }
else if (*r_skyboxname.string) else if (*r_skyboxname.string || *cl.skyname)
{ {
builtin = ( builtin = (
"{\n" "{\n"

View File

@ -1480,7 +1480,8 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
{ {
int cluster = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin); int cluster = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
sh_shmesh->litleaves[cluster>>3] |= 1<<(cluster&7); if (cluster >= 0)
sh_shmesh->litleaves[cluster>>3] |= 1<<(cluster&7);
} }
break; break;
} }

View File

@ -1089,6 +1089,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbuffer"); qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbuffer");
qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatus"); qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatus");
qglGetFramebufferAttachmentParameteriv = (void *)getglext("glGetFramebufferAttachmentParameteriv"); qglGetFramebufferAttachmentParameteriv = (void *)getglext("glGetFramebufferAttachmentParameteriv");
gl_config.arb_framebuffer_srgb = GL_CheckExtension("GL_ARB_framebuffer_sRGB");
} }
else if (GL_CheckExtension("GL_EXT_framebuffer_object")) else if (GL_CheckExtension("GL_EXT_framebuffer_object"))
{ {

View File

@ -118,11 +118,12 @@ extern cvar_t vid_conwidth, vid_conautoscale;
extern cvar_t vid_width; extern cvar_t vid_width;
extern cvar_t vid_height; extern cvar_t vid_height;
extern cvar_t vid_wndalpha; extern cvar_t vid_wndalpha;
extern cvar_t vid_winthread;
static qboolean VID_SetWindowedMode (rendererstate_t *info); //-1 on bpp or hz for default. static qboolean VID_SetWindowedMode (rendererstate_t *info); //-1 on bpp or hz for default.
static qboolean VID_SetFullDIBMode (rendererstate_t *info); //-1 on bpp or hz for default. static qboolean VID_SetFullDIBMode (rendererstate_t *info); //-1 on bpp or hz for default.
#ifdef MULTITHREADED #ifdef MULTITHREAD
#define WTHREAD //While the user is resizing a window, the entire thread that owns said window becomes frozen. in order to cope with window resizing, its easiest to just create a separate thread to be microsoft's plaything. our main game thread can then just keep rendering. hopefully that won't bug out on the present. #define WTHREAD //While the user is resizing a window, the entire thread that owns said window becomes frozen. in order to cope with window resizing, its easiest to just create a separate thread to be microsoft's plaything. our main game thread can then just keep rendering. hopefully that won't bug out on the present.
#endif #endif
#ifdef WTHREAD #ifdef WTHREAD
@ -1341,7 +1342,7 @@ static qboolean CreateMainWindow(rendererstate_t *info, qboolean withthread)
qboolean stat; qboolean stat;
#ifdef WTHREAD #ifdef WTHREAD
if (withthread) if (withthread && vid_winthread.ival)
{ {
void *cond = Sys_CreateConditional(); void *cond = Sys_CreateConditional();
Sys_LockConditional(cond); Sys_LockConditional(cond);
@ -1715,6 +1716,7 @@ static void VID_UpdateWindowStatus (HWND hWnd)
case MODE_VULKAN: case MODE_VULKAN:
if (vid.pixelwidth != window_width || vid.pixelheight != window_height) if (vid.pixelwidth != window_width || vid.pixelheight != window_height)
vk.neednewswapchain = true; vk.neednewswapchain = true;
break;
#endif #endif
default: default:
vid.pixelwidth = window_width; vid.pixelwidth = window_width;
@ -2741,9 +2743,9 @@ void MainThreadWndProc(void *ctx, void *data, size_t msg, size_t ex)
break; break;
#ifdef HAVE_CDPLAYER #ifdef HAVE_CDPLAYER
case MM_MCINOTIFY: case MM_MCINOTIFY:
CDAudio_MessageHandler (mainwindow, uMsg, ctx, data); CDAudio_MessageHandler (mainwindow, msg, (WPARAM)ctx, (LPARAM)data);
break; break;
#endif #endif
} }
} }
@ -3071,7 +3073,7 @@ static LONG WINAPI GLMainWndProc (
#ifdef HAVE_CDPLAYER #ifdef HAVE_CDPLAYER
case MM_MCINOTIFY: case MM_MCINOTIFY:
#ifdef WTHREAD #ifdef WTHREAD
COM_AddWork(WG_MAIN, MainThreadWndProc, wParam, lParam, uMsg, 0); COM_AddWork(WG_MAIN, MainThreadWndProc, (void*)wParam, (void*)lParam, uMsg, 0);
lRet = 0; lRet = 0;
#else #else
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); //FIXME: thread lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); //FIXME: thread

View File

@ -46,10 +46,18 @@ static shader_t *skygridface;
void R_SetSky(char *skyname) void R_SetSky(char *skyname)
{ {
extern cvar_t r_skyboxname;
forcedskyshader = NULL;
if (!qrenderer)
return;
if (*r_skyboxname.string) //user's setting overrides.
skyname = r_skyboxname.string;
Shader_NeedReload(false);
if (*skyname) if (*skyname)
forcedskyshader = R_RegisterCustom(va("skybox_%s", skyname), SUF_NONE, Shader_DefaultSkybox, NULL); forcedskyshader = R_RegisterCustom(va("skybox_%s", skyname), SUF_NONE, Shader_DefaultSkybox, NULL);
else
forcedskyshader = NULL;
skyboxface = R_RegisterShader("skyboxface", SUF_NONE, skyboxface = R_RegisterShader("skyboxface", SUF_NONE,
"{\n" "{\n"

View File

@ -150,6 +150,12 @@ typedef struct {
unsigned short first; unsigned short first;
} dssector_t; } dssector_t;
typedef struct {
struct msector_s *sector;
unsigned short segcount;
unsigned short first;
} mssector_t;
typedef struct { typedef struct {
short x; short x;
short y; short y;
@ -178,7 +184,7 @@ typedef struct {
short tag; short tag;
} dsector_t; } dsector_t;
typedef struct { typedef struct msector_s {
int visframe; int visframe;
int floortex; int floortex;
int ceilingtex; int ceilingtex;
@ -224,7 +230,7 @@ typedef struct doommap_s
plane_t *nodeplane; plane_t *nodeplane;
unsigned int numnodes; unsigned int numnodes;
dssector_t *ssector; //aka: leafs mssector_t *ssector; //aka: leafs
unsigned int numssectors; unsigned int numssectors;
msector_t *sector; msector_t *sector;
@ -261,12 +267,11 @@ void Doom_SetModelFunc(model_t *mod);
//physics //physics
/*walk the bsp tree*/ /*walk the bsp tree*/
int Doom_SectorNearPoint(doommap_t *dm, vec3_t p) msector_t *Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
{ {
ddoomnode_t *node; ddoomnode_t *node;
plane_t *plane; plane_t *plane;
int num; int num;
int seg;
float d; float d;
num = dm->numnodes-1; num = dm->numnodes-1;
while (1) while (1)
@ -274,11 +279,7 @@ int Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
if (num & NODE_IS_SSECTOR) if (num & NODE_IS_SSECTOR)
{ {
num -= NODE_IS_SSECTOR; num -= NODE_IS_SSECTOR;
for (seg = dm->ssector[num].first; seg < dm->ssector[num].first + dm->ssector[num].segcount; seg++) return dm->ssector[num].sector;
if (dm->seg[seg].linedef != 0xffff)
break;
return dm->sidedef[dm->linedef[dm->seg[seg].linedef].sidedef[dm->seg[seg].direction]].sector;
} }
node = dm->node + num; node = dm->node + num;
@ -294,16 +295,16 @@ int Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
num = node->node1; num = node->node1;
} }
return num; return NULL;
} }
int Doom_PointContents(model_t *model, vec3_t axis[3], vec3_t p) int Doom_PointContents(model_t *model, vec3_t axis[3], vec3_t p)
{ {
doommap_t *dm = model->meshinfo; doommap_t *dm = model->meshinfo;
int sec = Doom_SectorNearPoint(dm, p); msector_t *sec = Doom_SectorNearPoint(dm, p);
if (p[2] < dm->sector[sec].floorheight) if (p[2] < sec->floorheight)
return FTECONTENTS_SOLID; return FTECONTENTS_SOLID;
if (p[2] > dm->sector[sec].ceilingheight) if (p[2] > sec->ceilingheight)
return FTECONTENTS_SOLID; return FTECONTENTS_SOLID;
return FTECONTENTS_EMPTY; return FTECONTENTS_EMPTY;
} }
@ -315,26 +316,27 @@ use blockmap for walls
*/ */
qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean iscapsule, unsigned int contentstype, trace_t *trace) qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean iscapsule, unsigned int contentstype, trace_t *trace)
{ {
#if 0 doommap_t *dm = model->meshinfo;
#if 1
#define TRACESTEP 16 #define TRACESTEP 16
unsigned short *linedefs; unsigned short *linedefs;
dlinedef_t *ld; dlinedef_t *ld;
int bmi, obmi; int bmi, obmi;
vec3_t delta; vec3_t delta;
int sec1 = Doom_SectorNearPoint(start); msector_t *sec1 = Doom_SectorNearPoint(dm, start);
vec3_t p1, pointonplane, ofs; vec3_t p1, pointonplane, ofs;
float d1, d2, c1, c2, planedist; float d1, d2, c1, c2, planedist;
plane_t *lp; plane_t *lp;
mdoomvertex_t *v1, *v2; mdoomvertex_t *v1, *v2;
int j; int j;
float p2f; float p1f, p2f;
float clipfrac; float clipfrac;
#define DIST_EPSILON (0.03125) #define DIST_EPSILON (0.03125)
// Con_Printf("%i\n", sec1); // Con_Printf("%i\n", sec1);
if (start[2] < dm->sector[sec1].floorheight-mins[2]) //whoops, started outside... ? if (start[2] < sec1->floorheight-mins[2]) //whoops, started outside... ?
{ {
trace->fraction = 0; trace->fraction = 0;
trace->allsolid = trace->startsolid = true; trace->allsolid = trace->startsolid = true;
@ -346,11 +348,11 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1; trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-mins[2]; trace->plane.dist = sec1->floorheight-mins[2];
return false; return false;
} }
if (start[2] > dm->sector[sec1].ceilingheight-maxs[2]) //whoops, started outside... ? if (start[2] > sec1->ceilingheight-maxs[2]) //whoops, started outside... ?
{ {
trace->fraction = 0; trace->fraction = 0;
trace->allsolid = trace->startsolid = true; trace->allsolid = trace->startsolid = true;
@ -360,7 +362,7 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1; trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-maxs[2]); trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
return false; return false;
} }
@ -375,6 +377,9 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->endpos[1] = end[1]; trace->endpos[1] = end[1];
trace->endpos[2] = end[2]; trace->endpos[2] = end[2];
VectorCopy(start, p1);
p1f = 0;
trace->fraction = 1; trace->fraction = 1;
while(1) while(1)
{ {
@ -383,7 +388,7 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
if (bmi >= 0 && bmi < dm->blockmap->rows*dm->blockmap->columns) if (bmi >= 0 && bmi < dm->blockmap->rows*dm->blockmap->columns)
if (bmi != obmi) if (bmi != obmi)
{ {
#if 1 #if 0
short dummy; short dummy;
linedefs = &dummy; linedefs = &dummy;
for (dummy = 0; dummy < dm->numlinedefs; dummy++) for (dummy = 0; dummy < dm->numlinedefs; dummy++)
@ -436,29 +441,29 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else else
c1 = (d1-DIST_EPSILON) / (d1 - d2); c1 = (d1-DIST_EPSILON) / (d1 - d2);
c2 = 1-c1; c2 = 1-c1;
pointonplane[0] = start[0]*c2 + p2[0]*c1; pointonplane[0] = start[0]*c2 + end[0]*c1;
/* if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0]) /* if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0])
continue; continue;
if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0]) if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0])
continue; continue;
*/ pointonplane[1] = start[1]*c2 + p2[1]*c1; */ pointonplane[1] = start[1]*c2 + end[1]*c1;
/* if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1]) /* if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1])
continue; continue;
if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1]) if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1])
continue; continue;
*/ */
pointonplane[2] = start[2]*c2 + p2[2]*c1; pointonplane[2] = start[2]*c2 + end[2]*c1;
Con_Printf("Started in wall\n"); Con_Printf("Started in wall\n");
j = dm->sidedef[ld->sidedef[d1 < planedist]].sector; j = dm->sidedef[ld->sidedef[d1 < planedist]].sector;
//yup, we are in the thing //yup, we are in the thing
//prevent ourselves from entering the back-sector's floor/ceiling //prevent ourselves from entering the back-sector's floor/ceiling at the point of impact
if (pointonplane[2] < dm->sector[j].floorheight-hull->clip_mins[2]) //whoops, started outside... ? if (pointonplane[2] < dm->sector[j].floorheight-mins[2]) //whoops, started outside... ?
{ {
Con_Printf("Started in floor\n"); Con_Printf("Started in floor\n");
trace->allsolid = trace->startsolid = false; trace->allsolid = trace->startsolid = false;
trace->endpos[2] = dm->sector[j].floorheight-hull->clip_mins[2]; trace->endpos[2] = dm->sector[j].floorheight-mins[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]); trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(end[2] - start[2]);
trace->endpos[0] = start[0]+delta[0]*trace->fraction*p2f; trace->endpos[0] = start[0]+delta[0]*trace->fraction*p2f;
trace->endpos[1] = start[1]+delta[1]*trace->fraction*p2f; trace->endpos[1] = start[1]+delta[1]*trace->fraction*p2f;
// if (IS_NAN(trace->endpos[2])) // if (IS_NAN(trace->endpos[2]))
@ -466,22 +471,22 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1; trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[j].floorheight-hull->clip_mins[2]; trace->plane.dist = dm->sector[j].floorheight-mins[2];
continue; continue;
} }
if (pointonplane[2] > dm->sector[j].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ? if (pointonplane[2] > dm->sector[j].ceilingheight-maxs[2]) //whoops, started outside... ?
{ {
Con_Printf("Started in ceiling\n"); Con_Printf("Started in ceiling\n");
trace->allsolid = trace->startsolid = false; trace->allsolid = trace->startsolid = false;
trace->endpos[0] = pointonplane[0]; trace->endpos[0] = pointonplane[0];
trace->endpos[1] = pointonplane[1]; trace->endpos[1] = pointonplane[1];
trace->endpos[2] = dm->sector[j].ceilingheight-hull->clip_maxs[2]; trace->endpos[2] = dm->sector[j].ceilingheight-maxs[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]); trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(end[2] - start[2]);
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1; trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[j].ceilingheight-hull->clip_maxs[2]); trace->plane.dist = -(dm->sector[j].ceilingheight-maxs[2]);
continue; continue;
} }
} }
@ -504,17 +509,17 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else else
c1 = (d1-DIST_EPSILON) / (d1 - d2); c1 = (d1-DIST_EPSILON) / (d1 - d2);
c2 = 1-c1; c2 = 1-c1;
pointonplane[0] = start[0]*c2 + p2[0]*c1; pointonplane[0] = start[0]*c2 + end[0]*c1;
if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0]) if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+maxs[0])
continue; continue;
if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0]) if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+mins[0])
continue; continue;
pointonplane[1] = start[1]*c2 + p2[1]*c1; pointonplane[1] = start[1]*c2 + end[1]*c1;
if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1]) if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+maxs[1])
continue; continue;
if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1]) if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+mins[1])
continue; continue;
pointonplane[2] = start[2]*c2 + p2[2]*c1; pointonplane[2] = start[2]*c2 + end[2]*c1;
if (ld->flags & LINEDEF_IMPASSABLE || ld->sidedef[1] == 0xffff) //unconditionally unpassable. if (ld->flags & LINEDEF_IMPASSABLE || ld->sidedef[1] == 0xffff) //unconditionally unpassable.
{ //unconditionally clipped. { //unconditionally clipped.
@ -528,10 +533,10 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else else
sec2 = &dm->sector[dm->sidedef[ld->sidedef[0]].sector]; sec2 = &dm->sector[dm->sidedef[ld->sidedef[0]].sector];
if (pointonplane[2] < sec2->floorheight-hull->clip_mins[2]) if (pointonplane[2] < sec2->floorheight-mins[2])
{ //hit the floor first. { //hit the floor first.
c1 = fabs(dm->sector[sec1].floorheight-hull->clip_mins[2] - start[2]); c1 = fabs(sec1->floorheight-mins[2] - start[2]);
c2 = fabs(p2[2] - start[2]); c2 = fabs(end[2] - start[2]);
if (!c2) if (!c2)
c1 = 1; c1 = 1;
else else
@ -541,21 +546,21 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// Con_Printf("Hit floor\n"); // Con_Printf("Hit floor\n");
trace->fraction = c1; trace->fraction = c1;
trace->allsolid = trace->startsolid = true; trace->allsolid = trace->startsolid = true;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1; trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-hull->clip_mins[2]; trace->plane.dist = sec1->floorheight-mins[2];
} }
continue; continue;
} }
if (pointonplane[2] > sec2->ceilingheight-hull->clip_maxs[2]) if (pointonplane[2] > sec2->ceilingheight-maxs[2])
{ //hit the floor first. { //hit the floor first.
c1 = fabs((dm->sector[sec1].ceilingheight-hull->clip_maxs[2]) - start[2]); c1 = fabs((sec1->ceilingheight-maxs[2]) - start[2]);
c2 = fabs(p2[2] - start[2]); c2 = fabs(end[2] - start[2]);
if (!c2) if (!c2)
c1 = 1; c1 = 1;
else else
@ -567,13 +572,13 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// Con_Printf("Hit ceiling\n"); // Con_Printf("Hit ceiling\n");
trace->fraction = c1; trace->fraction = c1;
trace->allsolid = trace->startsolid = true; trace->allsolid = trace->startsolid = true;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1; trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-hull->clip_maxs[2]); trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
} }
continue; continue;
} }
@ -586,10 +591,10 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
if(sec2->ceilingheight == sec2->floorheight) if(sec2->ceilingheight == sec2->floorheight)
sec2->ceilingheight += 64; sec2->ceilingheight += 64;
if (pointonplane[2] > sec2->floorheight-hull->clip_mins[2] && if (pointonplane[2] > sec2->floorheight-mins[2] &&
pointonplane[2] < sec2->ceilingheight-hull->clip_maxs[2]) pointonplane[2] < sec2->ceilingheight-maxs[2])
{ {
Con_Printf("Two sided passed\n"); // Con_Printf("Two sided passed\n");
continue; continue;
} }
@ -639,14 +644,14 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// VectorMA(start, p2f*trace->fraction, delta, p2); // VectorMA(start, p2f*trace->fraction, delta, p2);
if (p2[2] != start[2]) if (end[2] != start[2])
{ {
if (sec1 == Doom_SectorNearPoint(p2)) //special test. if (sec1 == Doom_SectorNearPoint(dm, trace->endpos)) //special test.
{ {
if (p2[2] <= dm->sector[sec1].floorheight-hull->clip_mins[2]) //whoops, started outside... ? if (end[2] <= sec1->floorheight-mins[2]) //whoops, started outside... ?
{ {
p1f = fabs(dm->sector[sec1].floorheight-hull->clip_mins[2] - start[2]); p1f = fabs(sec1->floorheight-mins[2] - start[2]);
p2f = fabs(p2[2] - start[2]); p2f = fabs(end[2] - start[2]);
if (!p2f) if (!p2f)
c1 = 1; c1 = 1;
else else
@ -655,22 +660,22 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
{ {
trace->fraction = c1; trace->fraction = c1;
trace->allsolid = trace->startsolid = false; trace->allsolid = trace->startsolid = false;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1; trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-hull->clip_mins[2]; trace->plane.dist = sec1->floorheight-mins[2];
} }
// if (IS_NAN(trace->endpos[2])) // if (IS_NAN(trace->endpos[2]))
// Con_Printf("Nanny\n"); // Con_Printf("Nanny\n");
} }
if (p2[2] >= dm->sector[sec1].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ? if (end[2] >= sec1->ceilingheight-maxs[2]) //whoops, started outside... ?
{ {
p1f = fabs(dm->sector[sec1].ceilingheight-hull->clip_maxs[2] - start[2]); p1f = fabs(sec1->ceilingheight-maxs[2] - start[2]);
p2f = fabs(p2[2] - start[2]); p2f = fabs(end[2] - start[2]);
if (!p2f) if (!p2f)
c1 = 1; c1 = 1;
else else
@ -679,13 +684,13 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
{ {
trace->fraction = c1; trace->fraction = c1;
trace->allsolid = trace->startsolid = false; trace->allsolid = trace->startsolid = false;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]); trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]); trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]); trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0; trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0; trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1; trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-hull->clip_maxs[2]); trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
} }
// if (IS_NAN(trace->endpos[2])) // if (IS_NAN(trace->endpos[2]))
@ -1438,8 +1443,6 @@ static void Triangulate_Sectors(doommap_t *dm, dsector_t *sectorl, qboolean glbs
int seg, nsec; int seg, nsec;
int i, sec=-1; int i, sec=-1;
dm->sector = Z_Malloc(dm->numsectors * sizeof(*dm->sector));
if (glbspinuse) if (glbspinuse)
{ {
for (i = 0; i < dm->numssectors; i++) for (i = 0; i < dm->numssectors; i++)
@ -1832,7 +1835,7 @@ static void CleanWalls(doommap_t *dm, dsidedef_t *sidedefsl)
void QuakifyThings(doommap_t *dm) void QuakifyThings(doommap_t *dm)
{ {
int sector; msector_t *sector;
int spawnflags; int spawnflags;
char *name; char *name;
int i; int i;
@ -1850,6 +1853,7 @@ void QuakifyThings(doommap_t *dm)
for (i = 0; i < dm->numthings; i++) for (i = 0; i < dm->numthings; i++)
{ {
float zbias = 24;
switch(dm->thing[i].type) switch(dm->thing[i].type)
{ {
case THING_PLAYER: //fixme: spit out a coop spawn too. case THING_PLAYER: //fixme: spit out a coop spawn too.
@ -1889,6 +1893,7 @@ void QuakifyThings(doommap_t *dm)
default: default:
name = va2(thingname, sizeof(thingname), "thing_%i", dm->thing[i].type); name = va2(thingname, sizeof(thingname), "thing_%i", dm->thing[i].type);
zbias = 0;
break; break;
} }
@ -1896,7 +1901,7 @@ void QuakifyThings(doommap_t *dm)
point[1] = dm->thing[i].ypos; point[1] = dm->thing[i].ypos;
point[2] = 0; point[2] = 0;
sector = Doom_SectorNearPoint(dm, point); sector = Doom_SectorNearPoint(dm, point);
zpos = dm->sector[sector].floorheight + 24; //things have no z coord, so find the sector they're in zpos = sector->floorheight + zbias; //things have no z coord, so find the sector they're in
spawnflags = SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_DEATHMATCH; spawnflags = SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_DEATHMATCH;
if (dm->thing[i].flags & THING_EASY) if (dm->thing[i].flags & THING_EASY)
@ -1991,16 +1996,29 @@ static void MoveWorld(doommap_t *dm)
if (min[0]>=-4096 && max[0]<=4096) if (min[0]>=-4096 && max[0]<=4096)
if (min[1]>=-4096 && max[1]<=4096) if (min[1]>=-4096 && max[1]<=4096)
return; //doesn't need adjusting, live with it. adj[0] = adj[1] = 0; //doesn't need adjusting, live with it.
if (max[0]-min[0]>=8192 || max[1]-min[1]>=8192) if (max[0]-min[0]>=8192 || max[1]-min[1]>=8192)
{ {
Con_Printf(CON_WARNING "Warning: Map is too large for the network protocol\n"); Con_Printf(CON_WARNING "Warning: Map is too large for the network protocol\n");
return; adj[0] = adj[1] = 0;
}
else
{
adj[0] = (max[0]-4096)&~63; //don't harm the tiling.
adj[1] = (max[1]-4096)&~63;
} }
adj[0] = (max[0]-4096)&~63; //don't harm the tiling. dm->model->mins[0] = min[0] - adj[0];
adj[1] = (max[1]-4096)&~63; dm->model->mins[1] = min[1] - adj[1];
dm->model->mins[2] = -32768;
dm->model->maxs[0] = max[0] - adj[0];
dm->model->maxs[1] = max[1] - adj[1];
dm->model->maxs[2] = 32767;
if (!adj[0] && !adj[1])
return;
Con_Printf("Adjusting map (%i %i)\n", -adj[0], -adj[1]); Con_Printf("Adjusting map (%i %i)\n", -adj[0], -adj[1]);
@ -2102,13 +2120,37 @@ static void Doom_LoadVerticies(doommap_t *dm, char *name)
static void Doom_LoadSSectors(doommap_t *dm, char *name) static void Doom_LoadSSectors(doommap_t *dm, char *name)
{ {
dssector_t *in;
size_t fsize; size_t fsize;
unsigned int i;
char tmp[MAX_QPATH]; char tmp[MAX_QPATH];
dm->ssector = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize); in = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize);
if (!dm->ssector) if (!in)
dm->ssector = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize); in = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize);
//FIXME: "gNd3" means that it's glbsp version 3. //FIXME: "gNd3" means that it's glbsp version 3.
dm->numssectors = fsize/sizeof(*dm->ssector); dm->numssectors = fsize/sizeof(*in);
dm->ssector = Z_Malloc(dm->numssectors * sizeof(*dm->ssector));
for (i = 0; i < dm->numssectors; i++)
{
dm->ssector[i].segcount = in[i].segcount;
dm->ssector[i].first = in[i].first;
}
Z_Free(in);
}
static void Doom_CalcSubsectorSectors(doommap_t *dm)
{ //kinda shitty
unsigned int num, seg;
for (num = 0; num < dm->numssectors; num++)
{
dm->ssector[num].sector = &dm->sector[dm->sidedef[dm->linedef[dm->seg[dm->ssector[num].first].linedef].sidedef[dm->seg[dm->ssector[num].first].direction]].sector];
for (seg = dm->ssector[num].first+1; seg < dm->ssector[num].first + dm->ssector[num].segcount; seg++)
if (dm->seg[seg].linedef != 0xffff)
{
dm->ssector[num].sector = &dm->sector[dm->sidedef[dm->linedef[dm->seg[seg].linedef].sidedef[dm->seg[seg].direction]].sector];
break;
}
}
} }
static void Doom_LoadSSegs(doommap_t *dm, char *name) static void Doom_LoadSSegs(doommap_t *dm, char *name)
@ -2210,6 +2252,7 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
} }
sectorl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sectors", name), &fsize); sectorl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sectors", name), &fsize);
dm->numsectors = fsize/sizeof(*sectorl); dm->numsectors = fsize/sizeof(*sectorl);
dm->sector = Z_Malloc(dm->numsectors * sizeof(*dm->sector));
#ifndef SERVERONLY #ifndef SERVERONLY
dm->numtextures=0; dm->numtextures=0;
@ -2229,7 +2272,7 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
sidedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sidedefs", name), &fsize); sidedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sidedefs", name), &fsize);
dm->numsidedefs = fsize/sizeof(*sidedefsl); dm->numsidedefs = fsize/sizeof(*sidedefsl);
dm->blockmap = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.blockmap", name), &fsize); dm->blockmap = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.blockmap", name), &fsize);
// blockmaps = fsize;
#ifndef SERVERONLY #ifndef SERVERONLY
Doom_LoadTextureInfos(); Doom_LoadTextureInfos();
#endif #endif
@ -2262,9 +2305,12 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
mod->fromgame = fg_doom; mod->fromgame = fg_doom;
mod->type = mod_brush; mod->type = mod_brush;
mod->nodes = (void*)0x1; mod->nodes = (void*)0x1;
mod->numclusters = dm->numsectors;
CleanWalls(dm, sidedefsl); CleanWalls(dm, sidedefsl);
Doom_CalcSubsectorSectors(dm);
Triangulate_Sectors(dm, sectorl, !!gl_nodes); Triangulate_Sectors(dm, sectorl, !!gl_nodes);
QuakifyThings(dm); QuakifyThings(dm);
@ -2273,11 +2319,11 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
return true; return true;
} }
void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir) static void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{ {
doommap_t *dm = model->meshinfo; doommap_t *dm = model->meshinfo;
msector_t *sec; msector_t *sec;
sec = dm->sector + Doom_SectorNearPoint(dm, point); sec = Doom_SectorNearPoint(dm, point);
res_dir[0] = 0; res_dir[0] = 0;
res_dir[1] = 1; res_dir[1] = 1;
@ -2291,31 +2337,41 @@ void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec
} }
//return pvs bits for point //return pvs bits for point
unsigned int Doom_FatPVS(struct model_s *model, vec3_t org, pvsbuffer_t *pvsbuffer, qboolean merge) static unsigned int Doom_FatPVS(struct model_s *model, vec3_t org, pvsbuffer_t *pvsbuffer, qboolean merge)
{ {
//FIXME: use REJECT lump. //FIXME: use REJECT lump.
return 0; return 0;
} }
//check if an ent is within the given pvs //check if an ent is within the given pvs
qboolean Doom_EdictInFatPVS(struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer) static qboolean Doom_EdictInFatPVS(struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
{ //FIXME: use REJECT lump. { //FIXME: use REJECT lump.
return true; return true;
} }
static int Doom_ClusterForPoint(struct model_s *model, vec3_t point)
{
doommap_t *dm = model->meshinfo;
return Doom_SectorNearPoint(dm, point) - dm->sector;
}
static qbyte *Doom_ClusterPVS(struct model_s *model, int cluster, pvsbuffer_t *pvsbuffer, pvsmerge_t merge)
{ //FIXME: use REJECT lump.
return NULL;
}
//generate useful info for correct functioning of Doom_EdictInFatPVS. //generate useful info for correct functioning of Doom_EdictInFatPVS.
void Doom_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs) static void Doom_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
{ {
//work out the sectors this ent is in for easy pvs. //work out the sectors this ent is in for easy pvs.
} }
//requires lightmaps - not supported. //requires lightmaps - not supported.
void Doom_StainNode(struct mnode_s *node, float *parms) static void Doom_StainNode(struct mnode_s *node, float *parms)
{ {
} }
//requires lightmaps - not supported. //requires lightmaps - not supported.
void Doom_MarkLights(struct dlight_s *light, int bit, struct mnode_s *node) static void Doom_MarkLights(struct dlight_s *light, int bit, struct mnode_s *node)
{ {
} }
@ -2327,6 +2383,8 @@ void Doom_SetModelFunc(model_t *mod)
mod->funcs.FatPVS = Doom_FatPVS; mod->funcs.FatPVS = Doom_FatPVS;
mod->funcs.EdictInFatPVS = Doom_EdictInFatPVS; mod->funcs.EdictInFatPVS = Doom_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Doom_FindTouchedLeafs; mod->funcs.FindTouchedLeafs = Doom_FindTouchedLeafs;
mod->funcs.ClusterForPoint = Doom_ClusterForPoint;
mod->funcs.ClusterPVS = Doom_ClusterPVS;
mod->funcs.LightPointValues = Doom_LightPointValues; mod->funcs.LightPointValues = Doom_LightPointValues;
mod->funcs.StainNode = Doom_StainNode; mod->funcs.StainNode = Doom_StainNode;
@ -2334,8 +2392,8 @@ void Doom_SetModelFunc(model_t *mod)
// mod->funcs.LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize); // mod->funcs.LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize);
mod->funcs.NativeTrace = Doom_Trace; mod->funcs.NativeTrace = Doom_Trace;
mod->funcs.PointContents = Doom_PointContents; mod->funcs.PointContents = Doom_PointContents;
//Doom_SetCollisionFuncs(mod); //Doom_SetCollisionFuncs(mod);
} }

View File

@ -226,11 +226,12 @@ typedef struct {
qboolean geometryshaders; qboolean geometryshaders;
qboolean ext_framebuffer_objects;
qboolean arb_framebuffer_srgb;
// qboolean arb_fragment_program; // qboolean arb_fragment_program;
qboolean arb_shader_objects; qboolean arb_shader_objects;
qboolean arb_shadow; qboolean arb_shadow;
qboolean arb_depth_texture; qboolean arb_depth_texture;
qboolean ext_framebuffer_objects;
qboolean ext_stencil_wrap; qboolean ext_stencil_wrap;
qboolean ext_packed_depth_stencil; qboolean ext_packed_depth_stencil;
qboolean arb_depth_clamp; qboolean arb_depth_clamp;
@ -300,8 +301,6 @@ extern vec3_t r_origin;
// //
extern refdef_t r_refdef; extern refdef_t r_refdef;
extern unsigned int r_viewcontents; extern unsigned int r_viewcontents;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2 extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2
extern texture_t *r_notexture_mip; extern texture_t *r_notexture_mip;
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern int d_lightstylevalue[256]; // 8.8 fraction of base light value

View File

@ -610,7 +610,9 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
#define GL_FRAMEBUFFER_SRGB 0x8DB9 #define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA #endif
#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT
#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
#endif #endif
#ifndef GL_EXT_texture_sRGB #ifndef GL_EXT_texture_sRGB
@ -754,7 +756,9 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
#endif #endif
#ifndef GL_ARB_framebuffer_object #ifndef GL_ARB_framebuffer_object
#define GL_DRAW_FRAMEBUFFER_ARB 0x8CA9
#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 #define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_ARB 0x8210
#endif #endif
#ifndef GL_VERSION_3_0 #ifndef GL_VERSION_3_0

File diff suppressed because it is too large Load Diff

View File

@ -18,21 +18,6 @@ r_part pe_default
scalefactor 0.8 scalefactor 0.8
} }
r_part TEQ2_LASER_SPARKS
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part te_splashsparks r_part te_splashsparks
{ {
texture "classicparticle" texture "classicparticle"
@ -143,7 +128,56 @@ r_part te_splashblood
colorindex 0xe8 colorindex 0xe8
} }
r_part teq2_laser_sparks
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part teq2_welding_sparks
{ //identical to teq2_laser_sparks, except for the +form that adds in some extra mesh+lighting effect.
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part +teq2_welding_sparks
{
count 0 0 1
model "models/objects/flash/tris.md2" framestart=0 frameend=2 framerate=10 alpha=-1 fullbright
lightradius 100 175
lightradiusfade 400
lightrgb 1 1 0.3
}
r_part teq2_tunnel_sparks
{ //this is apparently identical to teq2_laser_sparks... either way the protocol provides a palette colour (particle system provides a customised variation)
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part teq2_shield_sparks r_part teq2_shield_sparks
{ {
texture "classicparticle" texture "classicparticle"
@ -258,11 +292,68 @@ r_part teq2_blood
scalefactor 0.8 scalefactor 0.8
colorindex 232 7 colorindex 232 7
} }
r_part teq2_moreblood
{ //teq2_blood, but with count 250 instead of 60.
texture "classicparticle"
tcoords 0 0 16 16 32
count 250
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 232 7
}
r_part teq2_greenblood
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 30
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0xdf 7
}
r_part teq2_electric_sparks
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 40
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0x75 7
sound "weapons/lashit.wav" 1 1 0 0
}
r_part q2_blasterpuff r_part q2_blasterpuff
{ {
count 0 0 1 count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=0
}
r_part q2_blaster2puff
{
count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1
}
r_part q2_flechettepuff
{
count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=2
} }
r_part teq2_blaster r_part teq2_blaster
{ {
@ -301,13 +392,35 @@ r_part teq2_blaster2
gravity 40 gravity 40
scalefactor 0.8 scalefactor 0.8
colorindex 0xd0 7 colorindex 0xd0 7
assoc q2_blasterpuff /*the model*/ assoc q2_blaster2puff /*the model*/
lightradius 150 lightradius 150
lightradiusfade 400 lightradiusfade 400
lightrgb 0.05 1.0 0.05 lightrgb 0.05 1.0 0.05
lightshadows 1 lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0 sound "weapons/lashit.wav" 1 1 0 0
} }
r_part teq2_flechette
{ //grey version.
texture "classicparticle"
tcoords 0 0 16 16 32
count 60
scale 1
alpha 1
die 0.3 0.8
randomvel 40
orgadd 0 15
veladd 30
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0x6f 7
assoc q2_flechettepuff /*the model*/
lightradius 150
lightradiusfade 400
lightrgb 0.19 0.41 0.75
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part TR_BLASTERTRAIL r_part TR_BLASTERTRAIL
{ {
texture "classicparticle" texture "classicparticle"

View File

@ -282,7 +282,7 @@ optimisations_t optimisations[] =
{&opt_locals_overlapping, "lo", 2, FLAG_KILLSDEBUGGERS, "locals_overlapping", "Store all locals in a single section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps.\nHowever, locals are no longer automatically initialised to 0 (and never were in the case of recursion, but at least then its the same type).\nIf locals appear uninitialised, fteqcc will disable this optimisation for the affected functions, you can optionally get a warning about these locals using: #pragma warning enable F302"}, {&opt_locals_overlapping, "lo", 2, FLAG_KILLSDEBUGGERS, "locals_overlapping", "Store all locals in a single section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps.\nHowever, locals are no longer automatically initialised to 0 (and never were in the case of recursion, but at least then its the same type).\nIf locals appear uninitialised, fteqcc will disable this optimisation for the affected functions, you can optionally get a warning about these locals using: #pragma warning enable F302"},
{&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."}, {&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
{&opt_classfields, "cf", 2, FLAG_KILLSDEBUGGERS, "class_fields", "Strip class field names. This will harm debugging and can result in 'gibberish' names appearing in saved games. Has no effect on engines other than FTEQW, which will not recognise these anyway."}, {&opt_classfields, "cf", 2, FLAG_KILLSDEBUGGERS, "class_fields", "Strip class field names. This will harm debugging and can result in 'gibberish' names appearing in saved games. Has no effect on engines other than FTEQW, which will not recognise these anyway."},
// {&opt_stripunusedfields, "uf", 4, 0, "strip_unused_fields","Strips any fields that have no references. This may result in extra warnings at load time, or disabling support for mapper-specified alpha in engines that do not provide that."}, // {&opt_stripunusedfields, "uf", 4, 0, "strip_unused_fields","FIXME: needs relocs. Strips any fields that have no references. This may result in extra warnings at load time, or disabling support for mapper-specified alpha in engines that do not provide that."},
{NULL} {NULL}
}; };

View File

@ -11536,7 +11536,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Input_Frame", "__used void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."}, {"CSQC_Input_Frame", "__used void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_RendererRestarted", "void(string rendererdescription)", CS, "Called by the engine after the video was restarted. This serves to notify the CSQC that any render targets that it may have cached were purged, and will need to be regenerated."}, {"CSQC_RendererRestarted", "void(string rendererdescription)", CS, "Called by the engine after the video was restarted. This serves to notify the CSQC that any render targets that it may have cached were purged, and will need to be regenerated."},
{"CSQC_ConsoleCommand", "float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."}, {"CSQC_ConsoleCommand", "float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
{"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."}, {"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself.\nWARNING: link text can potentially come from other players, so be careful about what you allow to be changed."},
{"CSQC_Ent_Update", "void(float isnew)", CS}, {"CSQC_Ent_Update", "void(float isnew)", CS},
{"CSQC_Ent_Remove", "void()", CS}, {"CSQC_Ent_Remove", "void()", CS},
{"CSQC_Event_Sound", "float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod, float flags"/*", float timeofs*/")", CS}, {"CSQC_Event_Sound", "float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod, float flags"/*", float timeofs*/")", CS},

View File

@ -1343,31 +1343,42 @@ void SV_AutoSave(void)
return; return;
if (sv.state != ss_active) if (sv.state != ss_active)
return; return;
switch(svs.gametype)
//don't bother to autosave multiplayer games. {
//this may be problematic with splitscreen, but coop rules tend to apply there anyway. default: //probably broken. don't ever try.
if (sv.allocated_client_slots != 1)
return; return;
for (i = 0; i < sv.allocated_client_slots; i++) #ifdef VM_LUA
{ case GT_LUA:
if (svs.clients[i].state == cs_spawned) #endif
case GT_Q1QVM:
case GT_PROGS:
//don't bother to autosave multiplayer games.
//this may be problematic with splitscreen, but coop rules tend to apply there anyway.
if (sv.allocated_client_slots != 1)
return;
for (i = 0; i < sv.allocated_client_slots; i++)
{ {
if (svs.clients[i].edict->v->health <= 0) if (svs.clients[i].state == cs_spawned)
return; //autosaves with a dead player are just cruel. {
if (svs.clients[i].edict->v->health <= 0)
return; //autosaves with a dead player are just cruel.
if ((int)svs.clients[i].edict->v->flags & (FL_GODMODE | FL_NOTARGET)) if ((int)svs.clients[i].edict->v->flags & (FL_GODMODE | FL_NOTARGET))
return; //autosaves to highlight cheaters is also just spiteful. return; //autosaves to highlight cheaters is also just spiteful.
if (svs.clients[i].edict->v->movetype != MOVETYPE_WALK) if (svs.clients[i].edict->v->movetype != MOVETYPE_WALK)
return; //noclip|fly are cheaters, toss|bounce are bad at playing. etc. return; //noclip|fly are cheaters, toss|bounce are bad at playing. etc.
if (!((int)svs.clients[i].edict->v->flags & FL_ONGROUND)) if (!((int)svs.clients[i].edict->v->flags & FL_ONGROUND))
return; //autosaves while people are jumping are awkward. return; //autosaves while people are jumping are awkward.
if (svs.clients[i].edict->v->velocity[0] || svs.clients[i].edict->v->velocity[1] || svs.clients[i].edict->v->velocity[2]) if (svs.clients[i].edict->v->velocity[0] || svs.clients[i].edict->v->velocity[1] || svs.clients[i].edict->v->velocity[2])
return; //people running around are likely to result in poor saves return; //people running around are likely to result in poor saves
}
} }
break;
} }
autosavename = M_ChooseAutoSave(); autosavename = M_ChooseAutoSave();

View File

@ -303,10 +303,10 @@ static qboolean SV_AddCSQCUpdate (client_t *client, edict_t *ent)
#ifndef PEXT_CSQC #ifndef PEXT_CSQC
return false; return false;
#else #else
if (!(client->csqcactive)) if (!ent->xv->SendEntity)
return false; return false;
if (!ent->xv->SendEntity) if (!(client->csqcactive))
return false; return false;
csqcent[csqcnuments++] = ent; csqcent[csqcnuments++] = ent;
@ -3682,8 +3682,11 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
} }
else else
{ {
// ignore ents without visible models // many ents are not intended to be networked.
if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC) && ent->v->skin >= 0) if (!(ent->xv->SendEntity && client->csqcactive) && //if SendEntity is set then its definitely important, even if not visible.
(!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && // also definitely valid if it has a model
!((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC) && //needs to be networked if its giving off realtime lights, even when it has no model.
ent->v->skin >= 0) //ents with negative skins are networked too. eg ladder volumes.
continue; continue;
if (cameras) //self doesn't get a pvs test, to cover teleporters if (cameras) //self doesn't get a pvs test, to cover teleporters

View File

@ -75,19 +75,19 @@ cvar_t pm_walljump = CVARF("pm_walljump", "", CVAR_SERVERINFO);
#define cvargroup_serverphysics "server physics variables" #define cvargroup_serverphysics "server physics variables"
void WPhys_Init(void) void WPhys_Init(void)
{ {
Cvar_Register (&sv_maxvelocity, cvargroup_serverphysics); Cvar_Register (&sv_maxvelocity, cvargroup_serverphysics);
Cvar_Register (&sv_gravity, cvargroup_serverphysics); Cvar_Register (&sv_gravity, cvargroup_serverphysics);
Cvar_Register (&sv_stopspeed, cvargroup_serverphysics); Cvar_Register (&sv_stopspeed, cvargroup_serverphysics);
Cvar_Register (&sv_maxspeed, cvargroup_serverphysics); Cvar_Register (&sv_maxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_spectatormaxspeed, cvargroup_serverphysics); Cvar_Register (&sv_spectatormaxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_accelerate, cvargroup_serverphysics); Cvar_Register (&sv_accelerate, cvargroup_serverphysics);
Cvar_Register (&sv_airaccelerate, cvargroup_serverphysics); Cvar_Register (&sv_airaccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics); Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_friction, cvargroup_serverphysics); Cvar_Register (&sv_friction, cvargroup_serverphysics);
Cvar_Register (&sv_waterfriction, cvargroup_serverphysics); Cvar_Register (&sv_waterfriction, cvargroup_serverphysics);
Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics); Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics);
Cvar_Register (&sv_sound_land, cvargroup_serverphysics); Cvar_Register (&sv_sound_land, cvargroup_serverphysics);
Cvar_Register (&sv_stepheight, cvargroup_serverphysics); Cvar_Register (&sv_stepheight, cvargroup_serverphysics);
Cvar_Register (&sv_gameplayfix_noairborncorpse, cvargroup_serverphysics); Cvar_Register (&sv_gameplayfix_noairborncorpse, cvargroup_serverphysics);
Cvar_Register (&sv_gameplayfix_multiplethinks, cvargroup_serverphysics); Cvar_Register (&sv_gameplayfix_multiplethinks, cvargroup_serverphysics);
@ -1365,7 +1365,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
#pragma warningmsg("The following line might help boost framerates a lot in rmq, not sure if they violate expected behaviour in other mods though - check that they're safe.") #pragma warningmsg("The following line might help boost framerates a lot in rmq, not sure if they violate expected behaviour in other mods though - check that they're safe.")
VectorNegate(gravitydir, trace.plane.normal); VectorNegate(gravitydir, trace.plane.normal);
} }
if (trace.fraction == 1) if (trace.fraction == 1 || !trace.ent)
return; return;
if (ED_ISFREE(ent)) if (ED_ISFREE(ent))
return; return;

View File

@ -691,6 +691,9 @@ static cvar_t *VARGS Q2Cvar_Get (const char *var_name, const char *value, int fl
//q2 gamecode knows about these flags. anything else is probably a bug, or 3rd-party extension. //q2 gamecode knows about these flags. anything else is probably a bug, or 3rd-party extension.
flags &= (CVAR_NOSET|CVAR_SERVERINFO|CVAR_USERINFO|CVAR_ARCHIVE|CVAR_LATCH); flags &= (CVAR_NOSET|CVAR_SERVERINFO|CVAR_USERINFO|CVAR_ARCHIVE|CVAR_LATCH);
if (!strcmp(var_name, "gamedir"))
var_name = "fs_gamedir";
var = Cvar_Get(var_name, value, flags, "Quake2 game variables"); var = Cvar_Get(var_name, value, flags, "Quake2 game variables");
if (!var) if (!var)
{ {

View File

@ -2906,7 +2906,6 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
// read delta sequenced usercmds // read delta sequenced usercmds
from = &nullcmd; from = &nullcmd;
from->servertime = client->lastcmd.servertime;
for(i=0, to=commands; i<cmdCount; i++, to++) for(i=0, to=commands; i<cmdCount; i++, to++)
{ {
MSG_Q3_ReadDeltaUsercmd(key, from, to); MSG_Q3_ReadDeltaUsercmd(key, from, to);
@ -2963,11 +2962,13 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
temp.sidemove *= client->maxspeed/127.0f; temp.sidemove *= client->maxspeed/127.0f;
temp.forwardmove *= client->maxspeed/127.0f; temp.forwardmove *= client->maxspeed/127.0f;
temp.upmove *= client->maxspeed/127.0f; temp.upmove *= client->maxspeed/127.0f;
temp.msec = bound(0, to->servertime - temp.servertime, 255);
temp.buttons &= ~2; temp.buttons &= ~2;
if (temp.buttons & 64) if (temp.buttons & 64)
temp.buttons |= 2; temp.buttons |= 2;
SV_RunCmd(&temp, false); SV_RunCmd(&temp, false);
client->lastcmd.servertime = to->servertime;
} }
} }
if (svs.gametype != GT_QUAKE3) if (svs.gametype != GT_QUAKE3)

View File

@ -559,7 +559,9 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
VectorAdd (ent->v->origin, ent->v->maxs, ent->v->absmax); VectorAdd (ent->v->origin, ent->v->maxs, ent->v->absmax);
} }
if (ent->v->modelindex) if (!ent->v->solid)
ent->solidsize = ES_SOLID_BSP;
else// if (1)///*ent->v->modelindex || */ent->v->model)
{ {
model_t *mod = w->Get_CModel(w, ent->v->modelindex); model_t *mod = w->Get_CModel(w, ent->v->modelindex);
if (mod && mod->type == mod_brush) if (mod && mod->type == mod_brush)
@ -567,8 +569,6 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
else else
ent->solidsize = COM_EncodeSize(ent->v->mins, ent->v->maxs); ent->solidsize = COM_EncodeSize(ent->v->mins, ent->v->maxs);
} }
else
ent->solidsize = ES_SOLID_BSP;
// //
// to make items easier to pick up and allow them to be grabbed off // to make items easier to pick up and allow them to be grabbed off
@ -1167,7 +1167,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
} }
// did we clip the move? // did we clip the move?
if (trace.fraction < 1 || trace.startsolid) if (trace.fraction < 1 || trace.startsolid || trace.allsolid)
trace.ent = ent; trace.ent = ent;
return trace; return trace;

View File

@ -24,8 +24,8 @@ makevulkanblob: makevulkanblob.c
vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@ ./makevulkanblob $< $@
vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h #vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@ # ./makevulkanblob $< $@
all: generatebuiltinsl $(ALLNAMES) all: generatebuiltinsl $(ALLNAMES)

View File

@ -1,18 +1,28 @@
!!cvarf r_glsl_turbscale=1 !!permu FOG
!!cvarb r_fog_exp2=true
!!cvarf r_glsl_turbscale_reflect=1
!!cvarf r_glsl_turbscale_refract=1
!!cvarf gl_maxdist=8192 !!cvarf gl_maxdist=8192
!!cvarf gl_mindist=4 !!cvarf gl_mindist=4
!!samps normalmap diffuse 4 !!samps normalmap diffuse 4
!!argb reflect=0 //s_t1 is a reflection instead of diffusemap !!argb reflect=0 //s_t1 is a reflection instead of diffusemap
!!argf strength=0.1 //0.1 = fairly gentle, 0.2 = big waves !!argf strength_refl=0.1 //0.1 = fairly gentle, 0.2 = big waves
!!argf fresnel=5.0 //water should be around 5 !!argf strength_refr=0.1 //0.1 = fairly gentle, 0.2 = big waves
!!argf txscale=0.2 //wave strength !!argf fresnel_exp=5.0 //water should be around 5
!!argf fresnel_range=1.0
!!argf fresnel_min=1.0
!!argf txscale1=0.2 //wave strength
!!argf txscale2=0.2 //wave strength
!!argb ripplemap=0 //s_t2 contains a ripplemap !!argb ripplemap=0 //s_t2 contains a ripplemap
!!arg3f tint=0.7 0.8 0.7 //some colour value !!arg3f tint_refr=0.7 0.8 0.7 //some colour value
!!arg3f tint_refl=0.7 0.8 0.7 //some colour value
!!argb depth=0 //s_t3 is a depth image !!argb depth=0 //s_t3 is a depth image
!!argf alpha=0 //blend in the alpha channel
!!arg3f fogtint=0.2 0.3 0.2 //tints as it gets deeper !!arg3f fogtint=0.2 0.3 0.2 //tints as it gets deeper
#include "sys/defs.h" #include "sys/defs.h"
#include "sys/fog.h"
layout(location=0) varying vec2 tc; layout(location=0) varying vec2 tc;
layout(location=1) varying vec4 tf; layout(location=1) varying vec4 tf;
@ -49,15 +59,16 @@ void main (void)
ntc.t = tc.t + sin(tc.s+e_time)*0.125; ntc.t = tc.t + sin(tc.s+e_time)*0.125;
//generate the two wave patterns from the normalmap //generate the two wave patterns from the normalmap
n = (texture2D(s_normalmap, arg_txscale*tc + vec2(e_time*0.1, 0.0)).xyz); n = (texture2D(s_normalmap, arg_txscale1*tc + vec2(e_time*0.1, 0.0)).xyz);
n += (texture2D(s_normalmap, arg_txscale*tc - vec2(0, e_time*0.097)).xyz); n += (texture2D(s_normalmap, arg_txscale2*tc - vec2(0, e_time*0.097)).xyz);
n -= 1.0 - 4.0/256.0; n -= 1.0 - 4.0/256.0;
if (arg_ripplemap) if (arg_ripplemap)
n += texture2D(s_ripplemap, stc).rgb*3.0; n += texture2D(s_ripplemap, stc).rgb*3.0;
n = normalize(n);
//the fresnel term decides how transparent the water should be //the fresnel term decides how transparent the water should be
fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), arg_fresnel); fres = pow(1.0-abs(dot(n, normalize(eye))), arg_fresnel_exp) * arg_fresnel_range + arg_fresnel_min;
if (arg_depth) if (arg_depth)
{ {
@ -91,14 +102,14 @@ void main (void)
//refraction image (and water fog, if possible) //refraction image (and water fog, if possible)
refr = texture2D(s_refract, stc + n.st*arg_strength*cvar_r_glsl_turbscale).rgb * arg_tint; refr = texture2D(s_refract, stc + n.st*arg_strength_refr*cvar_r_glsl_turbscale_refract).rgb * arg_tint_refr;
if (arg_depth) if (arg_depth)
refr = mix(refr, arg_fogtint, min(depth/4096.0, 1.0)); refr = mix(refr, arg_fogtint, min(depth/4096.0, 1.0));
//reflection/diffuse //reflection/diffuse
if (arg_reflect) if (arg_reflect)
refl = texture2D(s_reflect, stc - n.st*arg_strength*cvar_r_glsl_turbscale).rgb; refl = texture2D(s_reflect, stc - n.st*arg_strength_refl*cvar_r_glsl_turbscale_reflect).rgb * arg_tint_refl;
else else
refl = texture2D(s_diffuse, ntc).xyz; refl = texture2D(s_diffuse, ntc).xyz;
//FIXME: add specular tints //FIXME: add specular tints
@ -106,6 +117,13 @@ else
//interplate by fresnel //interplate by fresnel
refr = mix(refr, refl, fres); refr = mix(refr, refl, fres);
if (arg_alpha != 0)
{
vec4 ts = texture2D(s_diffuse, ntc);
vec4 surf = fog4blend(vec4(ts.rgb, arg_alpha*ts.a));
refr = mix(refr, surf.rgb, surf.a);
}
//done //done
gl_FragColor = vec4(refr, 1.0); gl_FragColor = vec4(refr, 1.0);
} }

View File

@ -208,16 +208,9 @@ typedef struct
float curtime; float curtime;
const entity_t *curentity; const entity_t *curentity;
const dlight_t *curdlight; const dlight_t *curdlight;
// vec3_t curdlight_colours;
shader_t *curshader; shader_t *curshader;
shader_t *depthonly; shader_t *depthonly;
texnums_t *curtexnums; texnums_t *curtexnums;
int curvertdecl;
// unsigned int shaderbits;
// unsigned int curcull;
// float depthbias;
// float depthfactor;
// unsigned int lastpasscount;
vbo_t *batchvbo; vbo_t *batchvbo;
batch_t *curbatch; batch_t *curbatch;
batch_t dummybatch; batch_t dummybatch;
@ -252,7 +245,6 @@ typedef struct
//descriptor sets are: 0) entity+light 1) batch textures + pass textures //descriptor sets are: 0) entity+light 1) batch textures + pass textures
VkDescriptorSet descriptorsets[1]; VkDescriptorSet descriptorsets[1];
// VkDescriptorPool texturedescpool[2];
//commandbuffer state, to avoid redundant state changes. //commandbuffer state, to avoid redundant state changes.
VkPipeline activepipeline; VkPipeline activepipeline;
@ -456,6 +448,8 @@ static void VK_FinishProg(program_t *prog, const char *name)
descSetLayoutCreateInfo.bindingCount = db-dbs; descSetLayoutCreateInfo.bindingCount = db-dbs;
descSetLayoutCreateInfo.pBindings = dbs; descSetLayoutCreateInfo.pBindings = dbs;
if (vk.khr_push_descriptor)
descSetLayoutCreateInfo.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
VkAssert(vkCreateDescriptorSetLayout(vk.device, &descSetLayoutCreateInfo, NULL, &desclayout)); VkAssert(vkCreateDescriptorSetLayout(vk.device, &descSetLayoutCreateInfo, NULL, &desclayout));
prog->desclayout = desclayout; prog->desclayout = desclayout;
} }
@ -1142,10 +1136,9 @@ qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name)
prog->pipelines = NULL; //generated as needed, depending on blend states etc. prog->pipelines = NULL; //generated as needed, depending on blend states etc.
return true; return true;
} }
void VKBE_DeleteProg(program_t *prog) static void VKBE_ReallyDeleteProg(program_t *prog)
{ { //nothing else is refering to this data any more, its safe to obliterate it.
struct pipeline_s *pipe; struct pipeline_s *pipe;
Z_Free(prog->cvardata);
while(prog->pipelines) while(prog->pipelines)
{ {
pipe = prog->pipelines; pipe = prog->pipelines;
@ -1157,15 +1150,25 @@ void VKBE_DeleteProg(program_t *prog)
} }
if (prog->layout) if (prog->layout)
vkDestroyPipelineLayout(vk.device, prog->layout, vkallocationcb); vkDestroyPipelineLayout(vk.device, prog->layout, vkallocationcb);
prog->layout = VK_NULL_HANDLE;
if (prog->desclayout) if (prog->desclayout)
vkDestroyDescriptorSetLayout(vk.device, prog->desclayout, vkallocationcb); vkDestroyDescriptorSetLayout(vk.device, prog->desclayout, vkallocationcb);
prog->desclayout = VK_NULL_HANDLE;
if (prog->vert) if (prog->vert)
vkDestroyShaderModule(vk.device, prog->vert, vkallocationcb); vkDestroyShaderModule(vk.device, prog->vert, vkallocationcb);
prog->vert = VK_NULL_HANDLE;
if (prog->frag) if (prog->frag)
vkDestroyShaderModule(vk.device, prog->frag, vkallocationcb); vkDestroyShaderModule(vk.device, prog->frag, vkallocationcb);
}
void VKBE_DeleteProg(program_t *prog)
{
//schedule the deletes when its safe to do so.
VK_AtFrameEnd(VKBE_ReallyDeleteProg, prog, sizeof(*prog));
//clear stuff out so that the caller doesn't get confused.
Z_Free(prog->cvardata);
prog->pipelines = NULL;
prog->layout = VK_NULL_HANDLE;
prog->desclayout = VK_NULL_HANDLE;
prog->vert = VK_NULL_HANDLE;
prog->frag = VK_NULL_HANDLE; prog->frag = VK_NULL_HANDLE;
} }
@ -1217,7 +1220,6 @@ void VKBE_Init(void)
be_maxpasses = 1; be_maxpasses = 1;
memset(&shaderstate, 0, sizeof(shaderstate)); memset(&shaderstate, 0, sizeof(shaderstate));
shaderstate.inited = true; shaderstate.inited = true;
shaderstate.curvertdecl = -1;
for (i = 0; i < MAXRLIGHTMAPS; i++) for (i = 0; i < MAXRLIGHTMAPS; i++)
shaderstate.dummybatch.lightmap[i] = -1; shaderstate.dummybatch.lightmap[i] = -1;
@ -1366,66 +1368,82 @@ static VkDescriptorSet VKBE_TempDescriptorSet(VkDescriptorSetLayout layout)
} }
//creates a new dynamic buffer for us to use while streaming. because spoons. //creates a new dynamic buffer for us to use while streaming. because spoons.
static struct dynbuffer *VKBE_AllocNewBuffer(struct dynbuffer **link, enum dynbuf_e type) static struct dynbuffer *VKBE_AllocNewBuffer(struct dynbuffer **link, enum dynbuf_e type, VkDeviceSize minsize)
{ {
VkBufferUsageFlags ufl[] = {VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT}; VkBufferUsageFlags ufl[] = {VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
VkBufferCreateInfo bufinf = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; VkBufferCreateInfo bufinf = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
VkMemoryRequirements mem_reqs; VkMemoryRequirements mem_reqs;
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
struct dynbuffer *n = Z_Malloc(sizeof(*n)); struct dynbuffer *n = Z_Malloc(sizeof(*n));
qboolean usestaging = (vk_usedynamicstaging & (1u<<type))!=0;
bufinf.flags = 0; while(1)
bufinf.size = n->size = (1u<<20);
bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
if (vk_usedynamicstaging & (1u<<type))
{ {
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT; bufinf.flags = 0;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf); bufinf.size = n->size = (1u<<20);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf); bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs); while (bufinf.size < minsize)
bufinf.size *= 2;
n->size = bufinf.size;
if (type != DB_STAGING && usestaging)
{
//create two buffers, one staging/host buffer and one device buffer
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory));
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0));
n->renderbuf = n->devicebuf;
}
else
{ //single buffer. we'll write directly to the buffer.
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
n->renderbuf = n->stagingbuf;
}
//now allocate some host-visible memory for the buffer that we're going to map.
vkGetBufferMemoryRequirements(vk.device, n->stagingbuf, &mem_reqs);
n->align = mem_reqs.alignment-1; n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size; memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); memAllocInfo.memoryTypeIndex = ~0;
// if (memAllocInfo.memoryTypeIndex == ~0)
// memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (memAllocInfo.memoryTypeIndex == ~0 && n->renderbuf == n->stagingbuf) //probably won't get anything, but whatever.
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0) if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); //device will still be okay with this usage... memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory)); if (memAllocInfo.memoryTypeIndex == ~0)
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0)); { //if we can't find any usable memory, force staging instead.
vkDestroyBuffer(vk.device, n->stagingbuf, vkallocationcb);
if (usestaging)
Sys_Error("Unable to allocate buffer memory");
usestaging = true;
continue;
}
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->stagingmemory));
VkAssert(vkBindBufferMemory(vk.device, n->stagingbuf, n->stagingmemory, 0));
n->renderbuf = n->devicebuf; VkAssert(vkMapMemory(vk.device, n->stagingmemory, 0, n->size, 0, &n->ptr)); //persistent-mapped.
n->stagingcoherent = !!(vk.memory_properties.memoryTypes[memAllocInfo.memoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
n->next = *link;
*link = n;
return n;
} }
else
{
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
n->renderbuf = n->stagingbuf;
}
vkGetBufferMemoryRequirements(vk.device, n->stagingbuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
// if (memAllocInfo.memoryTypeIndex == ~0)
// memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
Sys_Error("Unable to allocate buffer memory");
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->stagingmemory));
VkAssert(vkBindBufferMemory(vk.device, n->stagingbuf, n->stagingmemory, 0));
VkAssert(vkMapMemory(vk.device, n->stagingmemory, 0, n->size, 0, &n->ptr)); //persistent-mapped.
n->next = *link;
*link = n;
return n;
} }
static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t datasize, VkBuffer *buf, VkDeviceSize *offset) static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t datasize, VkBuffer *buf, VkDeviceSize *offset)
{ //FIXME: ubos need alignment { //FIXME: ubos need alignment
@ -1434,11 +1452,14 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
if (b->offset + datasize > b->size) if (b->offset + datasize > b->size)
{ {
//flush the old one, just in case. //flush the old one, just in case.
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE}; if (!b->stagingcoherent)
range.offset = b->flushed; {
range.size = b->offset-b->flushed; VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
range.memory = b->stagingmemory; range.offset = b->flushed;
vkFlushMappedMemoryRanges(vk.device, 1, &range); range.size = b->offset-b->flushed;
range.memory = b->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
}
if (b->devicebuf != VK_NULL_HANDLE) if (b->devicebuf != VK_NULL_HANDLE)
{ {
@ -1452,7 +1473,7 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
} }
if (!b->next) if (!b->next)
VKBE_AllocNewBuffer(&b->next, type); VKBE_AllocNewBuffer(&b->next, type, datasize);
b = vk.dynbuf[type] = b->next; b = vk.dynbuf[type] = b->next;
b->offset = 0; b->offset = 0;
b->flushed = 0; b->flushed = 0;
@ -1462,7 +1483,7 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
*offset = b->offset; *offset = b->offset;
ret = (qbyte*)b->ptr + b->offset; ret = (qbyte*)b->ptr + b->offset;
b->offset += datasize; b->offset += datasize; //FIXME: alignment
return ret; return ret;
} }
@ -1474,18 +1495,21 @@ void VKBE_InitFramePools(struct vkframe *frame)
for (i = 0; i < DB_MAX; i++) for (i = 0; i < DB_MAX; i++)
{ {
frame->dynbufs[i] = NULL; frame->dynbufs[i] = NULL;
VKBE_AllocNewBuffer(&frame->dynbufs[i], i); VKBE_AllocNewBuffer(&frame->dynbufs[i], i, 0);
} }
frame->descpools = VKBE_CreateDescriptorPool(); frame->descpools = vk.khr_push_descriptor?NULL:VKBE_CreateDescriptorPool();
{ frame->numcbufs = 0;
frame->maxcbufs = 0;
frame->cbufs = NULL;
/*{
VkCommandBufferAllocateInfo cbai = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO}; VkCommandBufferAllocateInfo cbai = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
cbai.commandPool = vk.cmdpool; cbai.commandPool = vk.cmdpool;
cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cbai.commandBufferCount = 1; cbai.commandBufferCount = frame->maxcbufs;
VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, &frame->cbuf)); VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, frame->cbufs));
} }*/
{ {
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}; VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
@ -1509,10 +1533,13 @@ void VKBE_FlushDynamicBuffers(void)
if (d->flushed == d->offset) if (d->flushed == d->offset)
continue; continue;
range.offset = d->flushed; if (!d->stagingcoherent)
range.size = d->offset - d->flushed; {
range.memory = d->stagingmemory; range.offset = d->flushed;
vkFlushMappedMemoryRanges(vk.device, 1, &range); range.size = d->offset - d->flushed;
range.memory = d->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
}
if (d->devicebuf != VK_NULL_HANDLE) if (d->devicebuf != VK_NULL_HANDLE)
{ {
@ -1553,8 +1580,11 @@ void VKBE_RestartFrame(void)
shaderstate.activepipeline = VK_NULL_HANDLE; shaderstate.activepipeline = VK_NULL_HANDLE;
vk.descpool = vk.frame->descpools; vk.descpool = vk.frame->descpools;
vkResetDescriptorPool(vk.device, vk.descpool->pool, 0); if (vk.descpool)
vk.descpool->availsets = vk.descpool->totalsets; {
vkResetDescriptorPool(vk.device, vk.descpool->pool, 0);
vk.descpool->availsets = vk.descpool->totalsets;
}
} }
void VKBE_ShutdownFramePools(struct vkframe *frame) void VKBE_ShutdownFramePools(struct vkframe *frame)
@ -1712,14 +1742,14 @@ static void T_Gen_CurrentRender(void)
if (img->width != vid.fbpwidth || img->height != vid.fbpheight) if (img->width != vid.fbpwidth || img->height != vid.fbpheight)
{ {
//FIXME: free the old image when its safe to do so. //FIXME: free the old image when its safe to do so.
*img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, PTI_BGRA8, PTI_2D); *img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, PTI_BGRA8, PTI_2D, true);
if (!img->sampler) if (!img->sampler)
VK_CreateSampler(shaderstate.tex_currentrender->flags, img); VK_CreateSampler(shaderstate.tex_currentrender->flags, img);
} }
vkCmdEndRenderPass(vk.frame->cbuf); vkCmdEndRenderPass(vk.rendertarg->cbuf);
//submit now? //submit now?
@ -1744,17 +1774,17 @@ static void T_Gen_CurrentRender(void)
region.extent.height = vid.fbpheight; region.extent.height = vid.fbpheight;
region.extent.depth = 1; region.extent.depth = 1;
set_image_layout(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT); set_image_layout(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT);
set_image_layout(vk.frame->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT); set_image_layout(vk.rendertarg->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdCopyImage(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); vkCmdCopyImage(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk.frame->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT); set_image_layout(vk.rendertarg->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT);
set_image_layout(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); set_image_layout(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
} }
//submit now? //submit now?
//barrier? //barrier?
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(vk.rendertarg->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
//fixme: viewport+scissor? //fixme: viewport+scissor?
} }
@ -2760,7 +2790,9 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
rs.depthBiasEnable = VK_FALSE; rs.depthBiasEnable = VK_FALSE;
ms.pSampleMask = NULL; ms.pSampleMask = NULL;
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; ms.rasterizationSamples = vk.multisamplebits;
// ms.sampleShadingEnable = VK_TRUE; //call the fragment shader multiple times, instead of just once per final pixel
// ms.minSampleShading = 0.25;
ds.depthTestEnable = (blendflags&SBITS_MISC_NODEPTHTEST)?VK_FALSE:VK_TRUE; ds.depthTestEnable = (blendflags&SBITS_MISC_NODEPTHTEST)?VK_FALSE:VK_TRUE;
ds.depthWriteEnable = (blendflags&SBITS_MISC_DEPTHWRITE)?VK_TRUE:VK_FALSE; ds.depthWriteEnable = (blendflags&SBITS_MISC_DEPTHWRITE)?VK_TRUE:VK_FALSE;
if (blendflags & SBITS_MISC_DEPTHEQUALONLY) if (blendflags & SBITS_MISC_DEPTHEQUALONLY)
@ -2964,7 +2996,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
return; return;
} }
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline); vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline);
} }
static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int blendflags, unsigned int permu) static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int blendflags, unsigned int permu)
{ {
@ -2993,7 +3025,7 @@ static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int
{ {
shaderstate.activepipeline = pipe->pipeline; shaderstate.activepipeline = pipe->pipeline;
if (shaderstate.activepipeline) if (shaderstate.activepipeline)
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline); vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline);
} }
return; return;
} }
@ -3062,7 +3094,7 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
//most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required) //most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required)
//that isn't enough for all our textures, so we need to make stuff up as required. //that isn't enough for all our textures, so we need to make stuff up as required.
{ {
VkDescriptorSet set = shaderstate.descriptorsets[0] = VKBE_TempDescriptorSet(p->desclayout); VkDescriptorSet set = shaderstate.descriptorsets[0] = vk.khr_push_descriptor?VK_NULL_HANDLE:VKBE_TempDescriptorSet(p->desclayout);
VkWriteDescriptorSet descs[MAX_TMUS], *desc = descs; VkWriteDescriptorSet descs[MAX_TMUS], *desc = descs;
VkDescriptorImageInfo imgs[MAX_TMUS], *img = imgs; VkDescriptorImageInfo imgs[MAX_TMUS], *img = imgs;
unsigned int i; unsigned int i;
@ -3144,9 +3176,13 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
for (i = 0; i < p->numsamplers; i++) for (i = 0; i < p->numsamplers; i++)
BE_SetupTextureDescriptor(SelectPassTexture(pass+i), r_blackimage, set, descs, desc++, img++); BE_SetupTextureDescriptor(SelectPassTexture(pass+i), r_blackimage, set, descs, desc++, img++);
vkUpdateDescriptorSets(vk.device, desc-descs, descs, 0, NULL); if (!set)
vkCmdPushDescriptorSetKHR(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, desc-descs, descs);
else
vkUpdateDescriptorSets(vk.device, desc-descs, descs, 0, NULL);
} }
vkCmdBindDescriptorSets(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.descriptorsets), shaderstate.descriptorsets, 0, NULL); if (!vk.khr_push_descriptor)
vkCmdBindDescriptorSets(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.descriptorsets), shaderstate.descriptorsets, 0, NULL);
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount); RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
RQuantAdd(RQUANT_DRAWS, 1); RQuantAdd(RQUANT_DRAWS, 1);
@ -3239,7 +3275,7 @@ static void BE_DrawMeshChain_Internal(void)
{ {
m = shaderstate.meshlist[0]; m = shaderstate.meshlist[0];
vkCmdBindIndexBuffer(vk.frame->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.rendertarg->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
idxfirst = m->vbofirstelement; idxfirst = m->vbofirstelement;
vertcount = m->vbofirstvert + m->numvertexes; vertcount = m->vbofirstvert + m->numvertexes;
@ -3251,7 +3287,7 @@ static void BE_DrawMeshChain_Internal(void)
vertcount = shaderstate.batchvbo->vertcount; vertcount = shaderstate.batchvbo->vertcount;
idxcount = shaderstate.batchvbo->indexcount; idxcount = shaderstate.batchvbo->indexcount;
vkCmdBindIndexBuffer(vk.frame->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.rendertarg->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
} }
else else
{ {
@ -3273,7 +3309,7 @@ static void BE_DrawMeshChain_Internal(void)
map[i] = m->indexes[i]+m->vbofirstvert; map[i] = m->indexes[i]+m->vbofirstvert;
map += m->numindexes; map += m->numindexes;
} }
vkCmdBindIndexBuffer(vk.frame->cbuf, buf, offset, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf, offset, VK_INDEX_TYPE);
idxfirst = 0; idxfirst = 0;
} }
} }
@ -3304,7 +3340,7 @@ static void BE_DrawMeshChain_Internal(void)
map += m->numindexes; map += m->numindexes;
vertcount += m->numvertexes; vertcount += m->numvertexes;
} }
vkCmdBindIndexBuffer(vk.frame->cbuf, buf, offset, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf, offset, VK_INDEX_TYPE);
idxfirst = 0; idxfirst = 0;
} }
@ -3522,9 +3558,9 @@ static void BE_DrawMeshChain_Internal(void)
} }
} }
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(altshader->prog, altshader->passes, altshader->flags, idxcount)) if (BE_SetupMeshProgram(altshader->prog, altshader->passes, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
} }
else if (1) else if (1)
{ {
@ -3559,9 +3595,9 @@ static void BE_DrawMeshChain_Internal(void)
vertexbuffers[VK_BUFF_TDIR] = shaderstate.staticbuf; vertexbuffers[VK_BUFF_TDIR] = shaderstate.staticbuf;
vertexoffsets[VK_BUFF_TDIR] = vertexoffsets[VK_BUFF_SDIR] + sizeof(vec3_t)*65536; vertexoffsets[VK_BUFF_TDIR] = vertexoffsets[VK_BUFF_SDIR] + sizeof(vec3_t)*65536;
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(p->prog, p, altshader->flags, idxcount)) if (BE_SetupMeshProgram(p->prog, p, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
continue; continue;
} }
@ -3609,19 +3645,19 @@ static void BE_DrawMeshChain_Internal(void)
vertexbuffers[VK_BUFF_COL] = shaderstate.staticbuf; vertexbuffers[VK_BUFF_COL] = shaderstate.staticbuf;
vertexoffsets[VK_BUFF_COL] = 0; vertexoffsets[VK_BUFF_COL] = 0;
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(shaderstate.programfixedemu[1], p, altshader->flags, idxcount)) if (BE_SetupMeshProgram(shaderstate.programfixedemu[1], p, altshader->flags, idxcount))
{ {
vkCmdPushConstants(vk.frame->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour); vkCmdPushConstants(vk.rendertarg->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour);
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
} }
} }
else else
{ {
BE_GenerateColourMods(vertcount, p, &vertexbuffers[VK_BUFF_COL], &vertexoffsets[VK_BUFF_COL]); BE_GenerateColourMods(vertcount, p, &vertexbuffers[VK_BUFF_COL], &vertexoffsets[VK_BUFF_COL]);
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(shaderstate.programfixedemu[0], p, altshader->flags, idxcount)) if (BE_SetupMeshProgram(shaderstate.programfixedemu[0], p, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
} }
} }
} }
@ -3929,15 +3965,16 @@ void VKBE_GenBrushModelVBO(model_t *mod)
} }
} }
/*Wipes a vbo*/ struct vkbe_clearvbo
void VKBE_ClearVBO(vbo_t *vbo)
{ {
//FIXME: may still be in use by an active commandbuffer. struct vk_frameend fe;
vbo_t *vbo;
};
static void VKBE_SafeClearVBO(void *vboptr)
{
vbo_t *vbo = *(vbo_t**)vboptr;
VkDeviceMemory *retarded; VkDeviceMemory *retarded;
if (vbo->indicies.vk.buff || vbo->coord.vk.buff)
vkDeviceWaitIdle(vk.device); //just in case
if (vbo->indicies.vk.buff) if (vbo->indicies.vk.buff)
{ {
vkDestroyBuffer(vk.device, vbo->indicies.vk.buff, vkallocationcb); vkDestroyBuffer(vk.device, vbo->indicies.vk.buff, vkallocationcb);
@ -3956,12 +3993,18 @@ void VKBE_ClearVBO(vbo_t *vbo)
BZ_Free(vbo); BZ_Free(vbo);
} }
/*Wipes a vbo*/
void VKBE_ClearVBO(vbo_t *vbo)
{
VK_AtFrameEnd(VKBE_SafeClearVBO, &vbo, sizeof(vbo));
}
void VK_UploadLightmap(lightmapinfo_t *lm) void VK_UploadLightmap(lightmapinfo_t *lm)
{ {
extern cvar_t gl_lightmap_nearest; extern cvar_t gl_lightmap_nearest;
struct pendingtextureinfo mips; struct pendingtextureinfo mips;
image_t *tex; image_t *tex;
lm->modified = false; lm->modified = false;
if (!TEXVALID(lm->lightmap_texture)) if (!TEXVALID(lm->lightmap_texture))
{ {
@ -3971,28 +4014,69 @@ void VK_UploadLightmap(lightmapinfo_t *lm)
} }
tex = lm->lightmap_texture; tex = lm->lightmap_texture;
mips.extrafree = NULL; if (0)//vk.frame && tex->vkimage)
mips.type = PTI_2D; { //the inline streaming path.
mips.mip[0].data = lm->lightmaps; //the double-copy sucks but at least ensures that the dma copies stuff from THIS frame and not some of the next one too.
mips.mip[0].needfree = false; int *data;
mips.mip[0].width = lm->width; VkBufferImageCopy bic;
mips.mip[0].height = lm->height; VkBuffer buf;
switch(lightmap_fmt) //size_t x = 0, w = lm->width;
{ size_t x = lm->rectchange.l, w = lm->rectchange.r - lm->rectchange.l;
case TF_BGRA32: size_t y = lm->rectchange.t, h = lm->rectchange.b - lm->rectchange.t, i;
mips.encoding = PTI_BGRX8;
break;
default:
Sys_Error("Unsupported encoding\n");
break;
}
mips.mipcount = 1;
VK_LoadTextureMips(tex, &mips);
tex->status = TEX_LOADED;
tex->width = lm->width;
tex->height = lm->height;
lm->lightmap_texture = tex; data = VKBE_AllocateBufferSpace(DB_STAGING, w * h * 4, &buf, &bic.bufferOffset);
bic.bufferRowLength = w;
bic.bufferImageHeight = h;
bic.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bic.imageSubresource.mipLevel = 0;
bic.imageSubresource.baseArrayLayer = 0;
bic.imageSubresource.layerCount = 1;
bic.imageOffset.x = x;
bic.imageOffset.y = y;
bic.imageOffset.z = 0;
bic.imageExtent.width = w;
bic.imageExtent.height = h;
bic.imageExtent.depth = 1;
if (w == lm->width) //can just copy the lot in a single call.
memcpy(data, lm->lightmaps + 4*(y * lm->width), w*h*4);
else
{ //there's unused data on each row, oh well.
for (i = 0; i < h; i++)
memcpy(data + i * w, lm->lightmaps + 4*((y+i) * lm->width + x), w*4);
}
vkCmdCopyBufferToImage(vk.rendertarg->cbuf, buf, tex->vkimage->image, tex->vkimage->layout, 1, &bic);
}
else
{ //the slow out-of-frame generic path.
mips.extrafree = NULL;
mips.type = PTI_2D;
mips.mip[0].data = lm->lightmaps;
mips.mip[0].needfree = false;
mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height;
switch(lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8;
break;
default:
Sys_Error("Unsupported encoding\n");
break;
}
mips.mipcount = 1;
VK_LoadTextureMips(tex, &mips);
tex->status = TEX_LOADED;
tex->width = lm->width;
tex->height = lm->height;
}
//invert the size so we're not always updating the entire thing.
lm->rectchange.l = lm->width;
lm->rectchange.t = lm->height;
lm->rectchange.r = 0;
lm->rectchange.b = 0;
lm->modified = false;
} }
/*upload all lightmaps at the start to reduce lags*/ /*upload all lightmaps at the start to reduce lags*/
static void BE_UploadLightmaps(qboolean force) static void BE_UploadLightmaps(qboolean force)
@ -4364,7 +4448,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
viewport.height = r_refdef.pxrect.height; viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0; viewport.minDepth = 0;
viewport.maxDepth = ndr; viewport.maxDepth = ndr;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport); vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
} }
} }
@ -4443,7 +4527,6 @@ void VKBE_RT_Destroy(struct vk_rendertarg *targ)
struct vkbe_rtpurge struct vkbe_rtpurge
{ {
struct vk_fencework fw;
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
vk_image_t colour; vk_image_t colour;
vk_image_t depth; vk_image_t depth;
@ -4455,7 +4538,7 @@ static void VKBE_RT_Purge(void *ptr)
VK_DestroyVkTexture(&ctx->depth); VK_DestroyVkTexture(&ctx->depth);
VK_DestroyVkTexture(&ctx->colour); VK_DestroyVkTexture(&ctx->colour);
} }
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear) void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags)
{ {
//sooooo much work... //sooooo much work...
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
@ -4470,12 +4553,12 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
targ->restartinfo.clearValueCount = 2; targ->restartinfo.clearValueCount = 2;
targ->depthcleared = true; //will be once its activated. targ->depthcleared = true; //will be once its activated.
if (targ->width == width && targ->height == height) if (targ->width == width && targ->height == height && targ->q_colour.flags == flags)
return; //no work to do. return; //no work to do.
if (targ->framebuffer) if (targ->framebuffer)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE! { //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge, sizeof(*purge)); purge = VK_AtFrameEnd(VKBE_RT_Purge, NULL, sizeof(*purge));
purge->framebuffer = targ->framebuffer; purge->framebuffer = targ->framebuffer;
purge->colour = targ->colour; purge->colour = targ->colour;
purge->depth = targ->depth; purge->depth = targ->depth;
@ -4489,6 +4572,7 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
targ->q_colour.status = TEX_LOADED; targ->q_colour.status = TEX_LOADED;
targ->q_colour.width = width; targ->q_colour.width = width;
targ->q_colour.height = height; targ->q_colour.height = height;
targ->q_colour.flags = flags;
targ->width = width; targ->width = width;
targ->height = height; targ->height = height;
@ -4496,7 +4580,7 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
if (width == 0 && height == 0) if (width == 0 && height == 0)
return; //destroyed return; //destroyed
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM; colour_imginfo.format = vk.backbufformat;
colour_imginfo.flags = 0; colour_imginfo.flags = 0;
colour_imginfo.imageType = VK_IMAGE_TYPE_2D; colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
colour_imginfo.extent.width = width; colour_imginfo.extent.width = width;
@ -4568,14 +4652,14 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
{ {
VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
lmsampinfo.minFilter = lmsampinfo.magFilter = VK_FILTER_LINEAR; lmsampinfo.minFilter = lmsampinfo.magFilter = (flags&IF_NEAREST)?VK_FILTER_NEAREST:VK_FILTER_LINEAR;
lmsampinfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; lmsampinfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
lmsampinfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; lmsampinfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; lmsampinfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0; lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE; lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0; lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0; lmsampinfo.minLod = 0;
lmsampinfo.maxLod = 0; lmsampinfo.maxLod = 0;
@ -4589,15 +4673,16 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->depth.sampler)); VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->depth.sampler));
} }
targ->colour.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; targ->colour.layout = VK_IMAGE_LAYOUT_UNDEFINED;
targ->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; targ->mscolour.layout = VK_IMAGE_LAYOUT_UNDEFINED;
targ->depth.layout = VK_IMAGE_LAYOUT_UNDEFINED;
{ {
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}; VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
VkImageView attachments[2] = {targ->colour.view, targ->depth.view}; VkImageView attachments[3] = {targ->colour.view, targ->depth.view, targ->mscolour.view};
fbinfo.flags = 0; fbinfo.flags = 0;
fbinfo.renderPass = vk.renderpass[2]; fbinfo.renderPass = vk.renderpass[2];
fbinfo.attachmentCount = countof(attachments); fbinfo.attachmentCount = (vk.multisamplebits!=VK_SAMPLE_COUNT_1_BIT)?3:2;
fbinfo.pAttachments = attachments; fbinfo.pAttachments = attachments;
fbinfo.width = width; fbinfo.width = width;
fbinfo.height = height; fbinfo.height = height;
@ -4618,7 +4703,6 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
struct vkbe_rtpurge_cube struct vkbe_rtpurge_cube
{ {
struct vk_fencework fw;
vk_image_t colour; vk_image_t colour;
vk_image_t depth; vk_image_t depth;
struct struct
@ -4663,7 +4747,7 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
if (targ->size) if (targ->size)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE! { //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, sizeof(*purge)); purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, NULL, sizeof(*purge));
for (f = 0; f < 6; f++) for (f = 0; f < 6; f++)
{ {
purge->face[f].framebuffer = targ->face[f].framebuffer; purge->face[f].framebuffer = targ->face[f].framebuffer;
@ -4741,7 +4825,7 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0; lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE; lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0; lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0; lmsampinfo.minLod = 0;
lmsampinfo.maxLod = 0; lmsampinfo.maxLod = 0;
@ -4842,9 +4926,6 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
if (vk.rendertarg == targ) if (vk.rendertarg == targ)
return; return;
if (vk.rendertarg)
vkCmdEndRenderPass(vk.frame->cbuf);
r_refdef.pxrect.x = 0; r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0; r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = targ->width; r_refdef.pxrect.width = targ->width;
@ -4854,7 +4935,33 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
vid.fbpwidth = targ->width; vid.fbpwidth = targ->width;
vid.fbpheight = targ->height; vid.fbpheight = targ->height;
vkCmdBeginRenderPass(vk.frame->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE); #if 0
targ->cbuf = vk.rendertarg->cbuf;
if (vk.rendertarg)
vkCmdEndRenderPass(vk.rendertarg->cbuf);
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
targ->cbuf = VK_AllocFrameCBuf();
{
VkCommandBufferBeginInfo begininf = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
VkCommandBufferInheritanceInfo inh = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO};
begininf.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
begininf.pInheritanceInfo = &inh;
inh.renderPass = VK_NULL_HANDLE; //unused
inh.subpass = 0; //unused
inh.framebuffer = VK_NULL_HANDLE; //unused
inh.occlusionQueryEnable = VK_FALSE;
inh.queryFlags = 0;
inh.pipelineStatistics = 0;
vkBeginCommandBuffer(targ->cbuf, &begininf);
}
#endif
targ->prevtarg = vk.rendertarg;
vk.rendertarg = targ;
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
//future reuse shouldn't clear stuff //future reuse shouldn't clear stuff
if (targ->restartinfo.clearValueCount) if (targ->restartinfo.clearValueCount)
{ {
@ -4862,7 +4969,6 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
targ->restartinfo.renderPass = vk.renderpass[0]; targ->restartinfo.renderPass = vk.renderpass[0];
targ->restartinfo.clearValueCount = 0; targ->restartinfo.clearValueCount = 0;
} }
vk.rendertarg = targ;
{ {
VkRect2D wrekt; VkRect2D wrekt;
@ -4873,25 +4979,52 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
viewport.height = r_refdef.pxrect.height; viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0; viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange; viewport.maxDepth = shaderstate.depthrange;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport); vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x; wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y; wrekt.offset.y = viewport.y;
wrekt.extent.width = viewport.width; wrekt.extent.width = viewport.width;
wrekt.extent.height = viewport.height; wrekt.extent.height = viewport.height;
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt); vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
} }
} }
void VKBE_RT_End(struct vk_rendertarg *targ)
{
if (R2D_Flush)
R2D_Flush();
vk.rendertarg = vk.rendertarg->prevtarg;
vid.fbpwidth = vk.rendertarg->width;
vid.fbpheight = vk.rendertarg->height;
#if 0
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
vkCmdEndRenderPass(targ->cbuf);
vkEndCommandBuffer(targ->cbuf);
VK_Submit_Work(targ->cbuf, VK_NULL_HANDLE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_NULL_HANDLE, VK_NULL_HANDLE, NULL, NULL);
// VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork)
#endif
}
static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs) static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
{ {
extern cvar_t r_refractreflect_scale;
float oldil; float oldil;
int oldbem; int oldbem;
struct vk_rendertarg *targ; struct vk_rendertarg *targ;
//these flags require rendering some view as an fbo //these flags require rendering some view as an fbo
if (r_refdef.recurse) if (r_refdef.recurse)
return false; return false;
if (r_refdef.recurse == r_portalrecursion.ival || r_refdef.recurse == R_MAX_RECURSE)
return false;
if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK) if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK)
return false; return false;
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
return false; //multisample rendering can't deal with this.
oldbem = shaderstate.mode; oldbem = shaderstate.mode;
oldil = shaderstate.identitylighting; oldil = shaderstate.identitylighting;
targ = vk.rendertarg; targ = vk.rendertarg;
@ -4903,11 +5036,12 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.x = 0; r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0; r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2; r_refdef.vrect.width = max(1, vid.fbvwidth*r_refractreflect_scale.value);
r_refdef.vrect.height = vid.fbvheight/2; r_refdef.vrect.height = max(1, vid.fbvheight*r_refractreflect_scale.value);
VKBE_RT_Gen(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2, false); VKBE_RT_Gen(&shaderstate.rt_reflection, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_reflection); VKBE_RT_Begin(&shaderstate.rt_reflection);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1); R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
VKBE_RT_End(&shaderstate.rt_reflection);
r_refdef.vrect = orect; r_refdef.vrect = orect;
r_refdef.pxrect = oprect; r_refdef.pxrect = oprect;
} }
@ -4923,18 +5057,17 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0; r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2; r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2; r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Gen(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2, false); VKBE_RT_Gen(&shaderstate.rt_refraction, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_refraction); VKBE_RT_Begin(&shaderstate.rt_refraction);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
VKBE_RT_End(&shaderstate.rt_refraction);
r_refdef.vrect = ovrect; r_refdef.vrect = ovrect;
r_refdef.pxrect = oprect; r_refdef.pxrect = oprect;
shaderstate.tex_refraction = &shaderstate.rt_refraction.q_colour; shaderstate.tex_refraction = &shaderstate.rt_refraction.q_colour;
VKBE_RT_Begin(targ);
} }
else else
{ {
VKBE_RT_Begin(targ);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 3); R_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
T_Gen_CurrentRender(); T_Gen_CurrentRender();
shaderstate.tex_refraction = shaderstate.tex_currentrender; shaderstate.tex_refraction = shaderstate.tex_currentrender;
@ -4994,7 +5127,6 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
BE_RT_End(); BE_RT_End();
} }
*/ */
VKBE_RT_Begin(targ);
VKBE_SelectMode(oldbem); VKBE_SelectMode(oldbem);
shaderstate.identitylighting = oldil; shaderstate.identitylighting = oldil;
@ -5557,7 +5689,7 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
rect.rect.extent.height = r_refdef.pxrect.height; rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1; rect.layerCount = 1;
rect.baseArrayLayer = 0; rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect); vkCmdClearAttachments(vk.rendertarg->cbuf, 1, &clr, 1, &rect);
} }
VKBE_SelectMode(BEM_DEPTHONLY); VKBE_SelectMode(BEM_DEPTHONLY);
VKBE_SubmitBatch(batch); VKBE_SubmitBatch(batch);
@ -5652,15 +5784,9 @@ struct vk_shadowbuffer *VKBE_GenerateShadowBuffer(vecV_t *verts, int numverts, i
return buf; return buf;
} }
} }
struct vk_shadowbuffer_destroy
{
struct vk_fencework fw;
struct vk_shadowbuffer buf;
};
static void VKBE_DestroyShadowBuffer_Delayed(void *ctx) static void VKBE_DestroyShadowBuffer_Delayed(void *ctx)
{ {
struct vk_shadowbuffer_destroy *d = ctx; struct vk_shadowbuffer *buf = ctx;
struct vk_shadowbuffer *buf = &d->buf;
vkDestroyBuffer(vk.device, buf->vbuffer, vkallocationcb); vkDestroyBuffer(vk.device, buf->vbuffer, vkallocationcb);
vkDestroyBuffer(vk.device, buf->ibuffer, vkallocationcb); vkDestroyBuffer(vk.device, buf->ibuffer, vkallocationcb);
vkFreeMemory(vk.device, buf->vmemory, vkallocationcb); vkFreeMemory(vk.device, buf->vmemory, vkallocationcb);
@ -5670,8 +5796,7 @@ void VKBE_DestroyShadowBuffer(struct vk_shadowbuffer *buf)
{ {
if (buf && buf->isstatic) if (buf && buf->isstatic)
{ {
struct vk_shadowbuffer_destroy *ctx = VK_AtFrameEnd(VKBE_DestroyShadowBuffer_Delayed, sizeof(*ctx)); struct vk_shadowbuffer_destroy *ctx = VK_AtFrameEnd(VKBE_DestroyShadowBuffer_Delayed, buf, sizeof(*buf));
ctx->buf = *buf;
Z_Free(buf); Z_Free(buf);
} }
} }
@ -5694,10 +5819,10 @@ void VKBE_RenderShadowBuffer(struct vk_shadowbuffer *buf)
"}\n" "}\n"
); );
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, 1, &buf->vbuffer, &buf->voffset); vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, 1, &buf->vbuffer, &buf->voffset);
vkCmdBindIndexBuffer(vk.frame->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE);
if (BE_SetupMeshProgram(depthonlyshader->passes[0].prog, depthonlyshader->passes, 0, buf->numindicies)) if (BE_SetupMeshProgram(depthonlyshader->prog, depthonlyshader->passes, 0, buf->numindicies))
vkCmdDrawIndexed(vk.frame->cbuf, buf->numindicies, 1, 0, 0, 0); vkCmdDrawIndexed(vk.rendertarg->cbuf, buf->numindicies, 1, 0, 0, 0);
} }
@ -5740,7 +5865,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
// const qboolean altqueue = false; // const qboolean altqueue = false;
// if (!altqueue) // if (!altqueue)
// vkCmdEndRenderPass(vk.frame->cbuf); vkCmdEndRenderPass(vk.rendertarg->cbuf);
if (shad->width != width || shad->height != height) if (shad->width != width || shad->height != height)
{ {
@ -5851,7 +5976,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0; lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE; lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0; lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareEnable = VK_TRUE; lmsampinfo.compareEnable = VK_TRUE;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL; lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0; lmsampinfo.minLod = 0;
@ -5889,7 +6014,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
imgbarrier.subresourceRange.layerCount = 1; imgbarrier.subresourceRange.layerCount = 1;
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imgbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imgbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(vk.frame->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier); vkCmdPipelineBarrier(vk.rendertarg->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
} }
{ {
@ -5905,7 +6030,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
rpass.renderArea.extent.height = height; rpass.renderArea.extent.height = height;
rpass.clearValueCount = 1; rpass.clearValueCount = 1;
rpass.pClearValues = &clearval; rpass.pClearValues = &clearval;
vkCmdBeginRenderPass(vk.frame->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(vk.rendertarg->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE);
} }
//viewport+scissor will be done elsewhere //viewport+scissor will be done elsewhere
@ -5922,7 +6047,7 @@ void VKBE_DoneShadows(void)
//we've rendered the shadowmap, but now we need to blit it to the screen //we've rendered the shadowmap, but now we need to blit it to the screen
//so set stuff back to the main view. FIXME: do these in batches to ease the load on tilers. //so set stuff back to the main view. FIXME: do these in batches to ease the load on tilers.
vkCmdEndRenderPass(vk.frame->cbuf); vkCmdEndRenderPass(vk.rendertarg->cbuf);
/*if (altqueue) /*if (altqueue)
{ {
@ -5955,7 +6080,7 @@ void VKBE_DoneShadows(void)
} }
*/ */
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(vk.rendertarg->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
viewport.x = r_refdef.pxrect.x; viewport.x = r_refdef.pxrect.x;
viewport.y = r_refdef.pxrect.y;//r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL... viewport.y = r_refdef.pxrect.y;//r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
@ -5963,7 +6088,7 @@ void VKBE_DoneShadows(void)
viewport.height = r_refdef.pxrect.height; viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0; viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange; viewport.maxDepth = shaderstate.depthrange;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport); vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
} }
@ -6002,13 +6127,13 @@ void VKBE_BeginShadowmapFace(void)
viewport.height = r_refdef.pxrect.height; viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0; viewport.minDepth = 0;
viewport.maxDepth = 1; viewport.maxDepth = 1;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport); vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x; wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y; wrekt.offset.y = viewport.y;
wrekt.extent.width = viewport.width; wrekt.extent.width = viewport.width;
wrekt.extent.height = viewport.height; wrekt.extent.height = viewport.height;
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt); vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
} }
#endif #endif
@ -6168,7 +6293,7 @@ void VKBE_VBO_Destroy(vboarray_t *vearray, void *mem)
if (!vearray->vk.buff) if (!vearray->vk.buff)
return; //not actually allocated... return; //not actually allocated...
fence = VK_AtFrameEnd(VKBE_DoneBufferStaging, sizeof(*fence)); fence = VK_AtFrameEnd(VKBE_DoneBufferStaging, NULL, sizeof(*fence));
fence->buf = vearray->vk.buff; fence->buf = vearray->vk.buff;
fence->mem = *retarded; fence->mem = *retarded;
@ -6208,7 +6333,7 @@ void VKBE_Scissor(srect_t *rect)
wrekt.extent.height = vid.fbpheight; wrekt.extent.height = vid.fbpheight;
} }
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt); vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@
VKFunc(GetPhysicalDeviceSurfaceCapabilitiesKHR) \ VKFunc(GetPhysicalDeviceSurfaceCapabilitiesKHR) \
VKFunc(GetPhysicalDeviceMemoryProperties) \ VKFunc(GetPhysicalDeviceMemoryProperties) \
VKFunc(GetPhysicalDeviceFormatProperties) \ VKFunc(GetPhysicalDeviceFormatProperties) \
VKFunc(GetPhysicalDeviceFeatures) \
VKFunc(DestroySurfaceKHR) \ VKFunc(DestroySurfaceKHR) \
VKFunc(CreateDevice) \ VKFunc(CreateDevice) \
VKFunc(DestroyInstance) \ VKFunc(DestroyInstance) \
@ -78,6 +79,7 @@
VKFunc(CmdBindIndexBuffer) \ VKFunc(CmdBindIndexBuffer) \
VKFunc(CmdBindVertexBuffers) \ VKFunc(CmdBindVertexBuffers) \
VKFunc(CmdPushConstants) \ VKFunc(CmdPushConstants) \
VKFunc(CmdPushDescriptorSetKHR) \
VKFunc(CmdClearAttachments) \ VKFunc(CmdClearAttachments) \
VKFunc(CmdClearColorImage) \ VKFunc(CmdClearColorImage) \
VKFunc(CmdClearDepthStencilImage) \ VKFunc(CmdClearDepthStencilImage) \
@ -191,30 +193,35 @@ typedef struct vk_image_s
uint32_t layers; uint32_t layers;
uint32_t mipcount; uint32_t mipcount;
uint32_t encoding; uint32_t encoding;
uint32_t type; uint32_t type; //PTI_2D/3D/CUBE
} vk_image_t; } vk_image_t;
enum dynbuf_e enum dynbuf_e
{ {
DB_VBO, DB_VBO,
DB_EBO, DB_EBO,
DB_UBO, DB_UBO,
DB_STAGING,
DB_MAX DB_MAX
}; };
struct vk_rendertarg struct vk_rendertarg
{ {
VkCommandBuffer cbuf; //cbuf allocated for this render target.
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
vk_image_t colour, depth; vk_image_t colour, depth, mscolour;
image_t q_colour, q_depth; //extra sillyness... image_t q_colour, q_depth, q_mscolour; //extra sillyness...
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
qboolean multisample;
qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't. qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't.
VkRenderPassBeginInfo restartinfo; VkRenderPassBeginInfo restartinfo;
VkSemaphore presentsemaphore; VkSemaphore presentsemaphore;
qboolean firstuse; qboolean firstuse;
struct vk_rendertarg *prevtarg;
}; };
struct vk_rendertarg_cube struct vk_rendertarg_cube
{ {
@ -233,9 +240,14 @@ extern struct vulkaninfo_s
{ {
unsigned short triplebuffer; unsigned short triplebuffer;
qboolean vsync; qboolean vsync;
qboolean headless;
qboolean allowsubmissionthread; qboolean allowsubmissionthread;
qboolean khr_swapchain; //aka: not headless. we're actually rendering stuff!
qboolean nv_glsl_shader; //we can load glsl shaders. probably missing lots of reflection info though, so this is probably too limited.
qboolean nv_dedicated_allocation; //nvidia-specific extension that provides hints that there's no memory aliasing going on.
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
qboolean khr_push_descriptor; //more efficient descriptor streaming
VkInstance instance; VkInstance instance;
VkDevice device; VkDevice device;
VkPhysicalDevice gpu; VkPhysicalDevice gpu;
@ -247,6 +259,7 @@ extern struct vulkaninfo_s
VkQueue queue_alt[1]; VkQueue queue_alt[1];
VkPhysicalDeviceMemoryProperties memory_properties; VkPhysicalDeviceMemoryProperties memory_properties;
VkCommandPool cmdpool; VkCommandPool cmdpool;
VkPhysicalDeviceLimits limits;
#define ACQUIRELIMIT 8 #define ACQUIRELIMIT 8
VkFence acquirefences[ACQUIRELIMIT]; VkFence acquirefences[ACQUIRELIMIT];
@ -268,6 +281,7 @@ extern struct vulkaninfo_s
int filterpic[3]; int filterpic[3];
int mipcap[2]; int mipcap[2];
float max_anistophy; float max_anistophy;
float max_anistophy_limit;
struct descpool struct descpool
{ {
@ -282,11 +296,12 @@ extern struct vulkaninfo_s
size_t offset; //size written by the cpu (that might not yet be flushed) size_t offset; //size written by the cpu (that might not yet be flushed)
size_t size; //maximum buffer size size_t size; //maximum buffer size
size_t align; size_t align;
qboolean stagingcoherent;
VkBuffer stagingbuf; VkBuffer stagingbuf;
VkDeviceMemory stagingmemory; VkDeviceMemory stagingmemory;
VkBuffer devicebuf; VkBuffer devicebuf;
VkDeviceMemory devicememory; VkDeviceMemory devicememory;
VkBuffer renderbuf; //either staging or device. VkBuffer renderbuf; //either staging or device. this is the buffer that we tell vulkan about
void *ptr; void *ptr;
struct dynbuffer *next; struct dynbuffer *next;
@ -295,27 +310,34 @@ extern struct vulkaninfo_s
struct vk_rendertarg *rendertarg; struct vk_rendertarg *rendertarg;
struct vkframe { struct vkframe {
struct vkframe *next; struct vkframe *next;
VkCommandBuffer cbuf;
struct dynbuffer *dynbufs[DB_MAX]; struct dynbuffer *dynbufs[DB_MAX];
struct descpool *descpools; struct descpool *descpools;
VkCommandBuffer *cbufs;
size_t numcbufs;
size_t maxcbufs;
VkFence finishedfence; VkFence finishedfence;
struct vk_fencework *frameendjobs; struct vk_frameend {
struct vk_frameend *next;
void (*FrameEnded) (void*);
} *frameendjobs;
struct vk_rendertarg *backbuf; struct vk_rendertarg *backbuf;
} *frame, *unusedframes; } *frame, *unusedframes;
struct vk_fencework *frameendjobs; struct vk_frameend *frameendjobs;
uint32_t backbuf_count; uint32_t backbuf_count;
VkRenderPass shadow_renderpass; //clears depth etc. VkRenderPass shadow_renderpass; //clears depth etc.
VkRenderPass renderpass[3]; //initial, resume VkRenderPass renderpass[3]; //reload-both(resume prior renderpass), clear-depth-dontcare-colour(gl_clear==0), clear-both(cl_clear!=0)
VkSwapchainKHR swapchain; VkSwapchainKHR swapchain;
uint32_t bufferidx; uint32_t bufferidx;
VkSampleCountFlagBits multisamplebits;
VkFormat depthformat; VkFormat depthformat;
VkFormat backbufformat; VkFormat backbufformat;
qboolean srgbcapable; qboolean srgbcapable;
qboolean neednewswapchain; qboolean neednewswapchain; //something changed that invalidates the old one.
qboolean devicelost; //we seriously fucked up somewhere. or the gpu is shite.
struct vkwork_s struct vkwork_s
{ {
@ -367,6 +389,9 @@ qboolean R_CanBloom(void);
struct programshared_s; struct programshared_s;
qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile); qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
VkCommandBuffer VK_AllocFrameCBuf(void);
void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork);
void VKBE_Init(void); void VKBE_Init(void);
void VKBE_InitFramePools(struct vkframe *frame); void VKBE_InitFramePools(struct vkframe *frame);
void VKBE_RestartFrame(void); void VKBE_RestartFrame(void);
@ -403,8 +428,9 @@ void VKBE_BeginShadowmapFace(void);
void VKBE_DoneShadows(void); void VKBE_DoneShadows(void);
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear); void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear); void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags);
void VKBE_RT_Begin(struct vk_rendertarg *targ); void VKBE_RT_Begin(struct vk_rendertarg *targ);
void VKBE_RT_End(struct vk_rendertarg *targ);
void VKBE_RT_Destroy(struct vk_rendertarg *targ); void VKBE_RT_Destroy(struct vk_rendertarg *targ);
@ -416,7 +442,7 @@ struct stagingbuf
size_t size; size_t size;
VkBufferUsageFlags usage; VkBufferUsageFlags usage;
}; };
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, unsigned int encoding, unsigned int type); vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, unsigned int encoding, unsigned int type, qboolean rendertarget);
void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkImageLayout new_image_layout, VkAccessFlags dstaccess); void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkImageLayout new_image_layout, VkAccessFlags dstaccess);
void VK_CreateSampler(unsigned int flags, vk_image_t *img); void VK_CreateSampler(unsigned int flags, vk_image_t *img);
void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage); void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage);
@ -424,7 +450,7 @@ VkBuffer VKBE_FinishStaging(struct stagingbuf *n, VkDeviceMemory *memptr);
void *VK_FencedBegin(void (*passed)(void *work), size_t worksize); void *VK_FencedBegin(void (*passed)(void *work), size_t worksize);
void VK_FencedSubmit(void *work); void VK_FencedSubmit(void *work);
void VK_FencedCheck(void); void VK_FencedCheck(void);
void *VK_AtFrameEnd(void (*passed)(void *work), size_t worksize); void *VK_AtFrameEnd(void (*passed)(void *work), void *data, size_t worksize);

View File

@ -2,7 +2,7 @@
// File: vk_platform.h // File: vk_platform.h
// //
/* /*
** Copyright (c) 2014-2015 The Khronos Group Inc. ** Copyright (c) 2014-2017 The Khronos Group Inc.
** **
** Licensed under the Apache License, Version 2.0 (the "License"); ** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License. ** you may not use this file except in compliance with the License.
@ -51,13 +51,13 @@ extern "C"
#define VKAPI_ATTR #define VKAPI_ATTR
#define VKAPI_CALL __stdcall #define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL #define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__) #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
// Android does not support Vulkan in native code using the "armeabi" ABI. #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs" #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__) // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling // calling convention, i.e. float parameters are passed in registers. This
// convention, even if the application's native code is compiled with the // is true even if the rest of the application passes floats on the stack,
// armeabi-v7a calling convention. // as it does by default when compiling for the armeabi-v7a NDK ABI.
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp"))) #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define VKAPI_CALL #define VKAPI_CALL
#define VKAPI_PTR VKAPI_ATTR #define VKAPI_PTR VKAPI_ATTR

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@ nonstatic void(mitem_desktop desktop) M_Options_Video =
pos += 8; pos += 8;
fr.add(spawn(mitem_text, item_text:_("Apply / Restart"), item_command:"vid_restart", item_scale:8, item_flags:IF_RIGHTALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MID|RS_Y_MAX_OWN_MIN, [0, pos], [-8, 8]); pos += 8; fr.add(spawn(mitem_text, item_text:_("Apply / Restart"), item_command:"vid_restart", item_scale:8, item_flags:IF_RIGHTALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MID|RS_Y_MAX_OWN_MIN, [0, pos], [-8, 8]); pos += 8;
pos += 8; pos += 8;
if (cvar_type("vid_renderer")) fr.add(menuitemcombo_spawn(_("Renderer"), "vid_renderer", '280 8', cvar_string("_vid_renderer_opts")), fl, [0, pos], [0, 8]); pos += 8;
//add the options //add the options
if (!dp_workarounds) if (!dp_workarounds)

View File

@ -420,6 +420,8 @@ float(entity to, float sendflags) MySendEntity =
if (sendflags & 128) if (sendflags & 128)
WriteByte(MSG_ENTITY, self.modelindex); //sending a modelindex is smaller than sending an entire string. WriteByte(MSG_ENTITY, self.modelindex); //sending a modelindex is smaller than sending an entire string.
return TRUE; //handled. If you return FALSE here, the entity will be considered invisible to the player.
}; };
In your spawn function: In your spawn function: