diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d5b61aba9..fea411540 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -64,7 +64,7 @@ jobs: - job: Linux pool: - vmImage: 'ubuntu-20.04' + vmImage: 'ubuntu-22.04' strategy: matrix: GCC: diff --git a/external_deps/build.sh b/external_deps/build.sh index 5af307622..b78a9f529 100755 --- a/external_deps/build.sh +++ b/external_deps/build.sh @@ -85,8 +85,8 @@ LDFLAGS='' log() { level="${1}"; shift - printf '%s: %s\n' "${level^^}" "${@}" >&2 - [ "${level}" != 'error' ] + printf '%s: %s\n' "${level}" "${@}" >&2 + [ "${level}" != 'ERROR' ] } # Extract an archive into the given subdirectory of the build dir and cd to it @@ -120,7 +120,7 @@ extract() { rmdir "${2}-dmg" ;; *) - log error "Unknown archive type for ${1}" + log ERROR "Unknown archive type for ${1}" ;; esac cd "${2}" @@ -132,13 +132,13 @@ download() { while [ ! -f "${tarball_file}" ]; do if [ -z "${1:-}" ] then - log error "No more mirror to download ${tarball_file} from" + log ERROR "No more mirror to download ${tarball_file} from" fi local download_url="${1}"; shift log status "Downloading ${download_url}" if ! "${CURL}" -R -L --fail -o "${tarball_file}" "${download_url}" then - log warning "Failed to download ${download_url}" + log WARNING "Failed to download ${download_url}" rm -f "${tarball_file}" fi done @@ -167,6 +167,7 @@ download_extract() { } # Build pkg-config +# Still needed, at least on macos, for opusfile build_pkgconfig() { local dir_name="pkg-config-${PKGCONFIG_VERSION}" local archive_name="${dir_name}.tar.gz" @@ -178,7 +179,7 @@ build_pkgconfig() { cd "${dir_name}" # The default -O2 is dropped when there's user-provided CFLAGS. - CFLAGS="${CFLAGS} -O2" ./configure --host="${HOST}" --prefix="${PREFIX}" --libdir="${PREFIX}/lib" --with-internal-glib + CFLAGS="${CFLAGS} -O2 -Wno-error=int-conversion" ./configure --host="${HOST}" --prefix="${PREFIX}" --libdir="${PREFIX}/lib" --with-internal-glib make make install } @@ -198,7 +199,7 @@ build_nasm() { cp "${dir_name}/nasm" "${PREFIX}/bin" ;; *) - log error 'Unsupported platform for NASM' + log ERROR 'Unsupported platform for NASM' ;; esac } @@ -340,7 +341,7 @@ build_sdl2() { case "${PLATFORM}" in windows-*-mingw) cd "${dir_name}" - make install-package arch="${HOST}" prefix="${PREFIX}" + cp -rv "${HOST}"/* "${PREFIX}/" ;; windows-*-msvc) cd "${dir_name}" @@ -357,7 +358,7 @@ build_sdl2() { local sdl2_lib_dir='lib/x64' ;; *) - log error 'Unsupported platform for SDL2' + log ERROR 'Unsupported platform for SDL2' ;; esac @@ -396,10 +397,16 @@ build_glew() { "${download_only}" && return cd "${dir_name}" + # env hack: CFLAGS.EXTRA is populated with some flags, which are sometimess necessary for + # compilation, in the makefile with +=. If CFLAGS.EXTRA is set on the command line, those + # += will be ignored. But if it is set via the environment, the two sources are actually + # concatenated how we would like. Bash doesn't allow variables with a dot so use env. + # The hack doesn't work on Mac's ancient Make (the env var has no effect), so we have to + # manually re-add the required flags there. case "${PLATFORM}" in windows-*-*) - make SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" - make install SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make install SYSTEM="linux-mingw${BITNESS}" GLEW_DEST="${PREFIX}" CC="${CC}" AR="${AR}" RANLIB="${RANLIB}" STRIP="${HOST}-strip" LD="${LD}" mv "${PREFIX}/lib/glew32.dll" "${PREFIX}/bin/" rm "${PREFIX}/lib/libglew32.a" cp lib/libglew32.dll.a "${PREFIX}/lib/" @@ -410,11 +417,12 @@ build_glew() { install_name_tool -id "@rpath/libGLEW.${GLEW_VERSION}.dylib" "${PREFIX}/lib/libGLEW.${GLEW_VERSION}.dylib" ;; linux-*-*) - make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" - make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" LIBDIR="${PREFIX}/lib" + local strip="${HOST/-unknown-/-}-strip" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" STRIP="${strip}" + env CFLAGS.EXTRA="${CFLAGS}" LDFLAGS.EXTRA="${LDFLAGS}" make install GLEW_DEST="${PREFIX}" CC="${CC}" LD="${CC}" LIBDIR="${PREFIX}/lib" ;; *) - log error 'Unsupported platform for GLEW' + log ERROR 'Unsupported platform for GLEW' ;; esac } @@ -460,7 +468,7 @@ build_jpeg() { # Other platforms can build but we need need to explicitly # set CMAKE_SYSTEM_NAME for CMAKE_CROSSCOMPILING to be set # and CMAKE_SYSTEM_PROCESSOR to not be ignored by cmake. - log error 'Unsupported platform for JPEG' + log ERROR 'Unsupported platform for JPEG' ;; esac @@ -482,7 +490,7 @@ build_jpeg() { local SYSTEM_PROCESSOR='arm' ;; *) - log error 'Unsupported platform for JPEG' + log ERROR 'Unsupported platform for JPEG' ;; esac @@ -539,7 +547,7 @@ build_openal() { -DCMAKE_BUILD_TYPE=Release -DALSOFT_EXAMPLES=OFF) ;; *) - log error 'Unsupported platform for OpenAL' + log ERROR 'Unsupported platform for OpenAL' ;; esac @@ -695,7 +703,7 @@ build_wasisdk() { *-amd64-*) ;; *) - log error "wasi doesn't have release for ${PLATFORM}" + log ERROR "wasi doesn't have release for ${PLATFORM}" ;; esac @@ -735,7 +743,7 @@ build_wasmtime() { local WASMTIME_ARCH=aarch64 ;; *) - log error "wasmtime doesn't have release for ${PLATFORM}" + log ERROR "wasmtime doesn't have release for ${PLATFORM}" ;; esac @@ -863,7 +871,7 @@ build_naclruntime() { local NACL_ARCH=x86-64 ;; *) - log error 'Unsupported platform for naclruntime' + log ERROR 'Unsupported platform for naclruntime' ;; esac @@ -881,6 +889,30 @@ build_naclruntime() { cp "scons-out/opt-linux-${NACL_ARCH}/staging/sel_ldr" "${PREFIX}/nacl_loader" } +# Check for DLL dependencies on MinGW stuff. For MSVC platforms this is bad because it should work +# without having MinGW installed. For MinGW platforms it is still bad because it might not work +# when building with different flavors, or newer/older versions. +build_depcheck() { + "${download_only}" && return + + case "${PLATFORM}" in + windows-*-*) + local good=true + for dll in $(find "${PREFIX}/bin" -type f -name '*.dll'); do + # https://wiki.unvanquished.net/wiki/MinGW#Built-in_DLL_dependencies + if objdump -p "${dll}" | grep -oP '(?<=DLL Name: )(libgcc_s|libstdc|libssp|libwinpthread).*'; then + echo "${dll} depends on above DLLs" + good=false + fi + done + "${good}" || log ERROR 'Built DLLs depend on MinGW runtime DLLs' + ;; + *) + log ERROR 'Unsupported platform for depcheck' + ;; + esac +} + # The import libraries generated by MinGW seem to have issues, so we use LLVM's version instead. # So LLVM must be installed, e.g. 'sudo apt install llvm' build_genlib() { @@ -903,7 +935,7 @@ build_genlib() { local MACHINE='i386:x86-64' ;; *) - log error 'Unsupported platform for genlib' + log ERROR 'Unsupported platform for genlib' ;; esac @@ -917,7 +949,7 @@ build_genlib() { done ;; *) - log error 'Unsupported platform for genlib' + log ERROR 'Unsupported platform for genlib' ;; esac } @@ -971,6 +1003,9 @@ build_install() { find "${PKG_PREFIX}/bin" -name '*.dll' -execdir "${HOST}-strip" --strip-unneeded -- {} \; find "${PKG_PREFIX}/lib" -name '*.a' -execdir rm -f -- {} \; find "${PKG_PREFIX}/lib" -name '*.exp' -execdir rm -f -- {} \; + + # Fix import lib paths to use MSVC-style instead of MinGW ones (see 'genlib' target) + find "${PKG_PREFIX}/lib/cmake" -name '*.cmake' -execdir sed -i -E 's@[.]dll[.]a\b@.lib@g' {} \; ;; esac @@ -1038,7 +1073,7 @@ common_setup_arch() { CXXFLAGS+=' -march=armv7-a -mfpu=neon' ;; *) - log error 'Unsupported platform' + log ERROR 'Unsupported platform' ;; esac } @@ -1140,13 +1175,13 @@ setup_linux-arm64-default() { common_setup linux aarch64-unknown-linux-gnu } -base_windows_amd64_msvc_packages='pkgconfig zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk genlib' +base_windows_amd64_msvc_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk depcheck genlib' all_windows_amd64_msvc_packages="${base_windows_amd64_msvc_packages}" base_windows_i686_msvc_packages="${base_windows_amd64_msvc_packages}" all_windows_i686_msvc_packages="${base_windows_amd64_msvc_packages}" -base_windows_amd64_mingw_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk' +base_windows_amd64_mingw_packages='zlib gmp nettle curl sdl2 glew png jpeg webp openal ogg vorbis opus opusfile naclsdk depcheck' all_windows_amd64_mingw_packages="${base_windows_amd64_mingw_packages}" base_windows_i686_mingw_packages="${base_windows_amd64_mingw_packages}" diff --git a/external_deps/cygtar.py b/external_deps/cygtar.py index e1cfd1ef4..1a5d5211f 100755 --- a/external_deps/cygtar.py +++ b/external_deps/cygtar.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # Copyright (c) 2012 The Native Client Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -78,12 +78,12 @@ def CreateCygwinSymlink(filepath, target): lnk.close() break except EnvironmentError: - print 'Try %d: Failed open %s -> %s\n' % (cnt, filepath, target) + print('Try %d: Failed open %s -> %s\n' % (cnt, filepath, target)) # Verify the file was created if not os.path.isfile(filepath): - print 'Try %d: Failed create %s -> %s\n' % (cnt, filepath, target) - print 'Giving up.' + print('Try %d: Failed create %s -> %s\n' % (cnt, filepath, target)) + print('Giving up.') return False # Now set the system attribute bit so that Cygwin knows it's a link. @@ -92,8 +92,8 @@ def CreateCygwinSymlink(filepath, target): return subprocess.call(['cmd', '/C', 'C:\\Windows\\System32\\attrib.exe', '+S', ToNativePath(filepath)]) except EnvironmentError: - print 'Try %d: Failed attrib %s -> %s\n' % (cnt, filepath, target) - print 'Giving up.' + print('Try %d: Failed attrib %s -> %s\n' % (cnt, filepath, target)) + print('Giving up.') return False @@ -122,8 +122,8 @@ def CreateWin32Hardlink(filepath, targpath, try_mklink): shutil.copyfile(targpath, filepath) return False except EnvironmentError: - print 'Try %d: Failed hardlink %s -> %s\n' % (cnt, filepath, targpath) - print 'Giving up.' + print('Try %d: Failed hardlink %s -> %s\n' % (cnt, filepath, targpath)) + print('Giving up.') return try_mklink @@ -170,7 +170,7 @@ def __DumpInfo(self, tarinfo): if tarinfo.isfile(): typeinfo = 'F' reable_size = ReadableSizeOf(tarinfo.size) - print '%s %s : %s %s' % (reable_size, typeinfo, tarinfo.name, lnk) + print('%s %s : %s %s' % (reable_size, typeinfo, tarinfo.name, lnk)) return tarinfo def __AddFile(self, tarinfo, fileobj=None): @@ -232,7 +232,7 @@ def Add(self, filepath, prefix=None): # At this point we only allow addition of "FILES" if not tarinfo.isfile(): - print 'Failed to add non real file: %s' % filepath + print('Failed to add non real file: %s' % filepath) return False # Now check if it is a Cygwin style link disguised as a file. diff --git a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png b/pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png deleted file mode 100644 index 7953eb440..000000000 Binary files a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1a.png and /dev/null differ diff --git a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png b/pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png deleted file mode 100644 index 489da8bd9..000000000 Binary files a/pkg/daemon_src.dpkdir/lights/mkintsquarelight1b.png and /dev/null differ diff --git a/pkg/daemon_src.dpkdir/lights/round.png b/pkg/daemon_src.dpkdir/lights/round.png deleted file mode 100644 index 24d23e570..000000000 Binary files a/pkg/daemon_src.dpkdir/lights/round.png and /dev/null differ diff --git a/pkg/daemon_src.dpkdir/lights/squarelight1.png b/pkg/daemon_src.dpkdir/lights/squarelight1.png deleted file mode 100644 index e7b683410..000000000 Binary files a/pkg/daemon_src.dpkdir/lights/squarelight1.png and /dev/null differ diff --git a/pkg/daemon_src.dpkdir/scripts/engine.shader b/pkg/daemon_src.dpkdir/scripts/engine.shader index 57b77ef51..35c98039e 100644 --- a/pkg/daemon_src.dpkdir/scripts/engine.shader +++ b/pkg/daemon_src.dpkdir/scripts/engine.shader @@ -28,46 +28,3 @@ gfx/2d/bigchars rgbgen vertex } } - -lights/defaultDynamicLight -{ - { - stage attenuationMapZ - map lights/mkintsquarelight1a - edgeClamp - } - { - stage attenuationMapXY - forceHighQuality - map lights/round - colored - zeroClamp - } -} - -lights/defaultPointLight -{ - // this will also be the falloff for any - // point light shaders that don't specify one - lightFalloffImage lights/mkintsquarelight1a - { - stage attenuationMapXY - forceHighQuality - map lights/squarelight1 - colored - zeroClamp - } -} - -lights/defaultProjectedLight -{ - // by default, stay bright almost all the way to the end - lightFalloffImage lights/mkintsquarelight1b - { - stage attenuationMapXY - forceHighQuality - map lights/squarelight1 - colored - zeroClamp - } -} diff --git a/src.cmake b/src.cmake index 1af07da64..e5e4f4974 100644 --- a/src.cmake +++ b/src.cmake @@ -78,6 +78,7 @@ set(COMMONTESTLIST ) set(RENDERERLIST + ${ENGINE_DIR}/renderer/BufferBind.h ${ENGINE_DIR}/renderer/DetectGLVendors.cpp ${ENGINE_DIR}/renderer/DetectGLVendors.h ${ENGINE_DIR}/renderer/gl_shader.cpp @@ -96,6 +97,8 @@ set(RENDERERLIST ${ENGINE_DIR}/renderer/GeometryCache.h ${ENGINE_DIR}/renderer/GeometryOptimiser.cpp ${ENGINE_DIR}/renderer/GeometryOptimiser.h + ${ENGINE_DIR}/renderer/GLMemory.cpp + ${ENGINE_DIR}/renderer/GLMemory.h ${ENGINE_DIR}/renderer/InternalImage.cpp ${ENGINE_DIR}/renderer/InternalImage.h ${ENGINE_DIR}/renderer/Material.cpp @@ -183,12 +186,8 @@ set(GLSLSOURCELIST ${ENGINE_DIR}/renderer/glsl_source/vertexSkinning_vp.glsl # Regular shaders - ${ENGINE_DIR}/renderer/glsl_source/debugShadowMap_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/debugShadowMap_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/fogQuake3_fp.glsl - ${ENGINE_DIR}/renderer/glsl_source/forwardLighting_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/forwardLighting_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/generic_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/generic_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/heatHaze_vp.glsl @@ -203,8 +202,6 @@ set(GLSLSOURCELIST ${ENGINE_DIR}/renderer/glsl_source/reflection_CB_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/screen_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/screen_fp.glsl - ${ENGINE_DIR}/renderer/glsl_source/shadowFill_vp.glsl - ${ENGINE_DIR}/renderer/glsl_source/shadowFill_fp.glsl ${ENGINE_DIR}/renderer/glsl_source/skybox_vp.glsl ${ENGINE_DIR}/renderer/glsl_source/skybox_fp.glsl ) diff --git a/src/common/Defs.h b/src/common/Defs.h index dd5e1dce6..35da643c5 100644 --- a/src/common/Defs.h +++ b/src/common/Defs.h @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** No case, No spaces */ #define PRODUCT_NAME_LOWER "unvanquished" -#define PRODUCT_VERSION "0.55.3" +#define PRODUCT_VERSION "0.55.4" /** Default base package */ #define DEFAULT_BASE_PAK PRODUCT_NAME_LOWER diff --git a/src/engine/qcommon/q_shared.h b/src/engine/qcommon/q_shared.h index 24bde5953..8ade82d37 100644 --- a/src/engine/qcommon/q_shared.h +++ b/src/engine/qcommon/q_shared.h @@ -1899,6 +1899,7 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) using GameStateCSs = std::array; +// TODO(0.56): NUKE all #define REF_FORCE_DLIGHT ( 1 << 31 ) // RF, passed in through overdraw parameter, force this dlight under all conditions #define REF_JUNIOR_DLIGHT ( 1 << 30 ) // (SA) this dlight does not light surfaces. it only affects dynamic light grid #define REF_DIRECTED_DLIGHT ( 1 << 29 ) // ydnar: global directional light, origin should be interpreted as a normal vector diff --git a/src/engine/renderer/BufferBind.h b/src/engine/renderer/BufferBind.h new file mode 100644 index 000000000..3c4d53766 --- /dev/null +++ b/src/engine/renderer/BufferBind.h @@ -0,0 +1,70 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// BufferBind.h + +#ifndef BUFFERBIND_H +#define BUFFERBIND_H + +namespace BufferBind { + enum : uint32_t { + // UBO + MATERIALS = 0, + TEX_DATA = 1, + LIGHTMAP_DATA = 2, + LIGHTS = 3, + + SURFACE_BATCHES = 4, + + // SSBO + SURFACE_DESCRIPTORS = 0, + SURFACE_COMMANDS = 1, + CULLED_COMMANDS = 2, + PORTAL_SURFACES = 4, + + GEOMETRY_CACHE_INPUT_VBO = 5, + GEOMETRY_CACHE_VBO = 6, + GEOMETRY_CACHE_IBO = 7, + + COMMAND_COUNTERS_STORAGE = 9, + TEX_DATA_STORAGE = 11, + STAGING = 12, + + DEBUG = 10, + + // Atomic + COMMAND_COUNTERS_ATOMIC = 0 + }; +}; + +#endif // BUFFERBIND_H diff --git a/src/engine/renderer/GLMemory.cpp b/src/engine/renderer/GLMemory.cpp new file mode 100644 index 000000000..e1efaa554 --- /dev/null +++ b/src/engine/renderer/GLMemory.cpp @@ -0,0 +1,128 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// GLMemory.cpp + +#include "common/Common.h" + +#include "GLMemory.h" + +// 128 MB, should be enough to fit anything in BAR without going overboard +const GLsizeiptr GLStagingBuffer::SIZE = 128 * 1024 * 1024 / sizeof( uint32_t ); + +GLStagingBuffer stagingBuffer; + +void GLBufferCopy( GLBuffer* src, GLBuffer* dst, GLintptr srcOffset, GLintptr dstOffset, GLsizeiptr size ) { + glCopyNamedBufferSubData( src->id, dst->id, + srcOffset * sizeof( uint32_t ), dstOffset * sizeof( uint32_t ), size * sizeof( uint32_t ) ); +} + +uint32_t* GLStagingBuffer::MapBuffer( const GLsizeiptr size ) { + if ( size > SIZE ) { + Sys::Drop( "Couldn't map GL staging buffer: size too large (%u/%u)", size, SIZE ); + } + + if ( pointer + size > SIZE ) { + FlushAll(); + + GLsync sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); + + constexpr GLuint64 SYNC_TIMEOUT = 10000000000; // 10 seconds + if ( glClientWaitSync( sync, GL_SYNC_FLUSH_COMMANDS_BIT, SYNC_TIMEOUT ) == GL_TIMEOUT_EXPIRED ) { + Sys::Drop( "Failed GL staging buffer copy sync" ); + } + glDeleteSync( sync ); + + pointer = 0; + current = 0; + last = 0; + } + + uint32_t* ret = buffer.GetData() + pointer; + last = pointer; + pointer += size; + + return ret; +} + +void GLStagingBuffer::FlushBuffer() { + buffer.FlushRange( current, pointer - current ); + + GL_CheckErrors(); + + current = pointer; +} + +void GLStagingBuffer::QueueStagingCopy( GLBuffer* dst, const GLsizeiptr dstOffset ) { + copyQueue[currentCopy].dst = dst; + copyQueue[currentCopy].dstOffset = dstOffset; + copyQueue[currentCopy].stagingOffset = last; + copyQueue[currentCopy].size = pointer - last; + + currentCopy++; + + if ( currentCopy == MAX_COPIES ) { + FlushStagingCopyQueue(); + } +} + +void GLStagingBuffer::FlushStagingCopyQueue() { + for ( GLStagingCopy& copy : copyQueue ) { + if ( copy.dst ) { + GLBufferCopy( &buffer, copy.dst, copy.stagingOffset, copy.dstOffset, copy.size ); + copy.dst = nullptr; + } + } + + currentCopy = 0; + + GL_CheckErrors(); +} + +void GLStagingBuffer::FlushAll() { + FlushBuffer(); + FlushStagingCopyQueue(); +} + +void GLStagingBuffer::InitGLBuffer() { + buffer.GenBuffer(); + + buffer.BufferStorage( SIZE, 1, nullptr ); + buffer.MapAll(); + + GL_CheckErrors(); +} + +void GLStagingBuffer::FreeGLBuffer() { + buffer.DelBuffer(); +} diff --git a/src/engine/renderer/GLMemory.h b/src/engine/renderer/GLMemory.h new file mode 100644 index 000000000..faba711ec --- /dev/null +++ b/src/engine/renderer/GLMemory.h @@ -0,0 +1,78 @@ +/* +=========================================================================== + +Daemon BSD Source Code +Copyright (c) 2025 Daemon Developers +All rights reserved. + +This file is part of the Daemon BSD Source Code (Daemon Source Code). + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================== +*/ +// GLMemory.h + +#ifndef GLMEMORY_H +#define GLMEMORY_H + +#include "gl_shader.h" + +void GLBufferCopy( GLBuffer* src, GLBuffer* dst, GLintptr srcOffset, GLintptr dstOffset, GLsizeiptr size ); + +struct GLStagingCopy { + GLBuffer* dst; + GLsizeiptr stagingOffset; + GLsizeiptr dstOffset; + GLsizeiptr size; +}; + +class GLStagingBuffer { + public: + uint32_t* MapBuffer( const GLsizeiptr size ); + void FlushBuffer(); + void QueueStagingCopy( GLBuffer* dst, const GLsizeiptr dstOffset ); + void FlushStagingCopyQueue(); + void FlushAll(); + + void InitGLBuffer(); + void FreeGLBuffer(); + + private: + static const GLsizeiptr SIZE; + + GLsizeiptr pointer = 0; + GLsizeiptr current = 0; + GLsizeiptr last = 0; + + static const uint32_t MAX_COPIES = 16; + GLStagingCopy copyQueue[MAX_COPIES]; + uint32_t currentCopy = 0; + + GLBuffer buffer = GLBuffer( "staging", BufferBind::STAGING, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, + GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); +}; + +extern GLStagingBuffer stagingBuffer; + +#endif // GLMEMORY_H diff --git a/src/engine/renderer/GeometryCache.cpp b/src/engine/renderer/GeometryCache.cpp index 8845df99f..085011a33 100644 --- a/src/engine/renderer/GeometryCache.cpp +++ b/src/engine/renderer/GeometryCache.cpp @@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "common/Common.h" #include "GeometryCache.h" - +#include "GLMemory.h" #include "tr_local.h" GeometryCache geometryCache; @@ -61,12 +61,6 @@ void GeometryCache::FreeGLBuffers() { VAO.DelVAO(); } -void GeometryCache::AllocBuffers() { - VBO.BufferData( mapVerticesNumber * 8, nullptr, GL_STATIC_DRAW ); - - IBO.BufferData( mapIndicesNumber, nullptr, GL_STATIC_DRAW ); -} - void GeometryCache::AddMapGeometry( const uint32_t verticesNumber, const uint32_t indicesNumber, const vertexAttributeSpec_t* attrBegin, const vertexAttributeSpec_t* attrEnd, const glIndex_t* indices ) { @@ -75,28 +69,28 @@ void GeometryCache::AddMapGeometry( const uint32_t verticesNumber, const uint32_ VAO.Bind(); - AllocBuffers(); - VAO.SetAttrs( attrBegin, attrEnd ); VAO.SetVertexBuffer( VBO, 0 ); VAO.SetIndexBuffer( IBO ); VBO.BufferStorage( mapVerticesNumber * 8, 1, nullptr ); - VBO.MapAll(); - uint32_t* VBOVerts = VBO.GetData(); + uint32_t* VBOVerts = stagingBuffer.MapBuffer( mapVerticesNumber * 8 ); for ( const vertexAttributeSpec_t* spec = attrBegin; spec < attrEnd; spec++ ) { vboAttributeLayout_t& attr = VAO.attrs[spec->attrIndex]; R_CopyVertexAttribute( attr, *spec, mapVerticesNumber, ( byte* ) VBOVerts ); } - VBO.UnmapBuffer(); + + stagingBuffer.QueueStagingCopy( &VBO, 0 ); IBO.BufferStorage( mapIndicesNumber, 1, nullptr ); - IBO.MapAll(); - uint32_t* IBOIndices = IBO.GetData(); + uint32_t* IBOIndices = stagingBuffer.MapBuffer( mapIndicesNumber ); memcpy( IBOIndices, indices, mapIndicesNumber * sizeof( uint32_t ) ); - IBO.UnmapBuffer(); + + stagingBuffer.QueueStagingCopy( &IBO, 0 ); + + stagingBuffer.FlushAll(); glBindVertexArray( backEnd.currentVAO ); } diff --git a/src/engine/renderer/GeometryCache.h b/src/engine/renderer/GeometryCache.h index 42f6d5c72..ad01502ff 100644 --- a/src/engine/renderer/GeometryCache.h +++ b/src/engine/renderer/GeometryCache.h @@ -46,7 +46,6 @@ class GeometryCache { void InitGLBuffers(); void FreeGLBuffers(); - void AllocBuffers(); void AddMapGeometry( const uint32_t verticesNumber, const uint32_t indicesNumber, const vertexAttributeSpec_t* attrBegin, const vertexAttributeSpec_t* attrEnd, @@ -58,9 +57,9 @@ class GeometryCache { GLVAO VAO = GLVAO( 0 ); - GLBuffer inputVBO = GLBuffer( "geometryCacheInputVBO", Util::ordinal( BufferBind::GEOMETRY_CACHE_INPUT_VBO ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); - GLBuffer VBO = GLBuffer( "geometryCacheVBO", Util::ordinal( BufferBind::GEOMETRY_CACHE_VBO ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); - GLBuffer IBO = GLBuffer( "geometryCacheIBO", Util::ordinal( BufferBind::UNUSED ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); + GLBuffer inputVBO = GLBuffer( "geometryCacheInputVBO", BufferBind::GEOMETRY_CACHE_INPUT_VBO, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); + GLBuffer VBO = GLBuffer( "geometryCacheVBO", BufferBind::GEOMETRY_CACHE_VBO, 0, 0 ); + GLBuffer IBO = GLBuffer( "geometryCacheIBO", BufferBind::GEOMETRY_CACHE_IBO, 0, 0 ); }; extern GeometryCache geometryCache; diff --git a/src/engine/renderer/GeometryOptimiser.cpp b/src/engine/renderer/GeometryOptimiser.cpp index 1ab9791a0..7b8793803 100644 --- a/src/engine/renderer/GeometryOptimiser.cpp +++ b/src/engine/renderer/GeometryOptimiser.cpp @@ -27,6 +27,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "GeometryOptimiser.h" +#include "ShadeCommon.h" +#include "GeometryCache.h" + static int LeafSurfaceCompare( const void* a, const void* b ) { bspSurface_t* aa, * bb; @@ -58,16 +61,16 @@ static int LeafSurfaceCompare( const void* a, const void* b ) { } // sort by leaf - if ( aa->interactionBits < bb->interactionBits ) { + if ( aa->scratch2 < bb->scratch2 ) { return -1; - } else if ( aa->interactionBits > bb->interactionBits ) { + } else if ( aa->scratch2 > bb->scratch2 ) { return 1; } // sort by leaf marksurfaces index to increase the likelihood of multidraw merging in the backend - if ( aa->lightCount < bb->lightCount ) { + if ( aa->scratch1 < bb->scratch1 ) { return -1; - } else if ( aa->lightCount > bb->lightCount ) { + } else if ( aa->scratch1 > bb->scratch1 ) { return 1; } return 0; @@ -147,8 +150,8 @@ static void CoreResetSurfaceViewCounts( bspSurface_t** rendererSurfaces, int num bspSurface_t* surface = rendererSurfaces[i]; surface->viewCount = -1; - surface->lightCount = -1; - surface->interactionBits = 0; + surface->scratch1 = -1; + surface->scratch2 = 0; } } @@ -175,8 +178,8 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i int fogIndex1 = surf1->fogIndex; int lightMapNum1 = surf1->lightmapNum; surf1->viewCount = surf1 - world->surfaces; - surf1->lightCount = j; - surf1->interactionBits = i; + surf1->scratch1 = j; + surf1->scratch2 = i; bool merged = false; for ( int k = j + 1; k < leaf->numMarkSurfaces; k++ ) { @@ -198,14 +201,14 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i } surf2->viewCount = surf1->viewCount; - surf2->lightCount = k; - surf2->interactionBits = i; + surf2->scratch1 = k; + surf2->scratch2 = i; merged = true; } if ( !merged ) { surf1->viewCount = -1; - surf1->lightCount = -1; + surf1->scratch1 = -1; // don't clear the leaf number so // surfaces that arn't merged are placed // closer to other leafs in the vbo @@ -420,35 +423,131 @@ void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, s Log::Notice( "Merged %i vertices into %i in %i ms", numVerticesIn, numVerticesOut, Sys::Milliseconds() - start ); } -/* static void ProcessMaterialSurface( MaterialSurface& surface, std::vector& materialSurfaces, - std::vector& processedMaterialSurfaces, - srfVert_t* verts, glIndex_t* indices ) { - if ( surface.count == MAX_MATERIAL_SURFACE_TRIS ) { - materialSurfaces.emplace_back( surface ); +static void ProcessMaterialSurface( MaterialSurface* surface, SurfaceIndexes* surfaceIdxs, + std::vector& processedSurfaces, + const srfVert_t* vertexes, glIndex_t* idxs, uint32_t* numIndices ) { + vec3_t mins; + vec3_t maxs; + ClearBounds( mins, maxs ); + + for ( uint32_t i = 0; i < surface->count; i++ ) { + AddPointToBounds( vertexes[surfaceIdxs->idxs[i]].xyz, mins, maxs ); } - while ( surface.count > MAX_MATERIAL_SURFACE_TRIS ) { - MaterialSurface srf = surface; + const uint32_t oldFirstIndex = surface->firstIndex; + surface->firstIndex = *numIndices; + + memcpy( idxs + ( *numIndices ), surfaceIdxs->idxs, surface->count * sizeof( glIndex_t ) ); + + *numIndices += surface->count; + + SphereFromBounds( mins, maxs, surface->origin, &surface->radius ); + + processedSurfaces.emplace_back( *surface ); + + surface->firstIndex = oldFirstIndex; +} + +static void OptimiseMaterialSurfaces( std::vector& materialSurfaces, + const uint32_t gridSize[3], const uint32_t cellSize[3], const vec3_t worldMins, + std::function materialSurfaceSort, + const srfVert_t* vertices, const glIndex_t* indices, + glIndex_t* idxs, + std::vector& processedMaterialSurfaces, uint32_t& numIndices ) { + + Grid surfaceGrid( true ); + surfaceGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + surfaceGrid.Clear(); + + Grid surfaceIdxsGrid( true ); + surfaceIdxsGrid.SetSize( gridSize[0], gridSize[1], gridSize[2] ); + + MaterialSurface* surface = &materialSurfaces[0]; + MaterialSurface* surface2; + bool addedSurfaces = false; + + std::function processGrid = [&]() { + if ( !addedSurfaces ) { + surface = surface2; + return; + } + + for ( Grid::Iterator it = surfaceGrid.begin(); it != surfaceGrid.end(); it++ ) { + if ( *it ) { + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( it - surfaceGrid.begin() ); + surface->count = *it; + ProcessMaterialSurface( surface, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); + } + } + + surfaceGrid.Clear(); + + surface = surface2; + addedSurfaces = false; + }; + + for ( uint32_t surfaceIndex = 0; surfaceIndex < materialSurfaces.size(); surfaceIndex++ ) { + surface2 = &materialSurfaces[surfaceIndex]; + if ( surface2->skyBrush ) { + continue; + } + + if ( materialSurfaceSort( *surface, *surface2 ) ) { + processGrid(); + } + + for ( uint32_t i = 0; i < surface2->count; i += 3 ) { + glIndex_t tri[3] = { indices[i + surface2->firstIndex], indices[i + 1 + surface2->firstIndex], + indices[i + 2 + surface2->firstIndex] }; + + srfVert_t triVerts[3] = { vertices[tri[0]], vertices[tri[1]], vertices[tri[2]] }; + + vec3_t origin; + VectorAdd( triVerts[0].xyz, triVerts[1].xyz, origin ); + VectorAdd( origin, triVerts[2].xyz, origin ); + + VectorScale( origin, 1.0f / 3.0f, origin ); + VectorSubtract( origin, worldMins, origin ); + + uint32_t gridOrigin[3]{ uint32_t( origin[0] / cellSize[0] ), uint32_t( origin[1] / cellSize[1] ), + uint32_t( origin[2] / cellSize[2] ) }; + + uint32_t* count = &surfaceGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + SurfaceIndexes* srfIdxs = &surfaceIdxsGrid( gridOrigin[0], gridOrigin[1], gridOrigin[2] ); + + memcpy( srfIdxs->idxs + ( *count ), tri, 3 * sizeof( glIndex_t ) ); + + *count += 3; + + if ( *count + 3 >= MAX_MATERIAL_SURFACE_INDEXES ) { + const uint32_t oldCount = surface2->count; + surface2->count = *count; - srf.count = MAX_MATERIAL_SURFACE_TRIS; - surface.count -= MAX_MATERIAL_SURFACE_TRIS; - surface.firstIndex += MAX_MATERIAL_SURFACE_TRIS; + ProcessMaterialSurface( surface2, srfIdxs, processedMaterialSurfaces, vertices, idxs, &numIndices ); - processedMaterialSurfaces.push_back( srf ); + surface2->count = oldCount; + *count = 0; + } else { + addedSurfaces = true; + } + } } -} */ -std::vector OptimiseMapGeometryMaterial(bspSurface_t** rendererSurfaces, int numSurfaces ) { + processGrid(); +} + +std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, + const srfVert_t* vertices, const int numVerticesIn, const glIndex_t* indices, const int numIndicesIn ) { std::vector materialSurfaces; + std::vector materialSurfacesExtended; materialSurfaces.reserve( numSurfaces ); + materialSurfacesExtended.reserve( numSurfaces ); - std::vector processedMaterialSurfaces; - processedMaterialSurfaces.reserve( numSurfaces ); - - // std::unordered_map triEdges; - - vec3_t worldBounds[2] = {}; materialSystem.buildOneShader = false; + vec3_t worldBounds[2] = {}; + vec3_t worldBoundsExtended[2] = {}; + ClearBounds( worldBounds[0], worldBounds[1] ); + ClearBounds( worldBoundsExtended[0], worldBoundsExtended[1] ); for ( int i = 0; i < numSurfaces; i++ ) { bspSurface_t* surface = rendererSurfaces[i]; @@ -476,20 +575,159 @@ std::vector OptimiseMapGeometryMaterial(bspSurface_t** renderer VectorCopy( ( ( srfGeneric_t* ) surface->data )->origin, srf.origin ); srf.radius = ( ( srfGeneric_t* ) surface->data )->radius; - BoundsAdd( worldBounds[0], worldBounds[1], - ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); - materialSystem.GenerateMaterial( &srf ); - materialSurfaces.emplace_back( srf ); + static const float MAX_NORMAL_SURFACE_DISTANCE = 65536.0f * sqrtf( 2.0f ); + if ( VectorLength( ( ( srfGeneric_t* ) surface->data )->bounds[0] ) > MAX_NORMAL_SURFACE_DISTANCE + || VectorLength( ( ( srfGeneric_t* ) surface->data )->bounds[1] ) > MAX_NORMAL_SURFACE_DISTANCE ) { + BoundsAdd( worldBoundsExtended[0], worldBoundsExtended[1], + ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); + + materialSurfacesExtended.emplace_back( srf ); + } else { + BoundsAdd( worldBounds[0], worldBounds[1], + ( ( srfGeneric_t* ) surface->data )->bounds[0], ( ( srfGeneric_t* ) surface->data )->bounds[1] ); + + materialSurfaces.emplace_back( srf ); + } } + vec3_t fullWorldBounds[2]; + VectorCopy( worldBounds[0], fullWorldBounds[0] ); + VectorCopy( worldBounds[1], fullWorldBounds[1] ); + BoundsAdd( fullWorldBounds[0], fullWorldBounds[1], worldBoundsExtended[0], worldBoundsExtended[1] ); + + materialSystem.SetWorldBounds( fullWorldBounds ); + materialSystem.buildOneShader = true; + /* GenerateWorldMaterialsBuffer() must be called before the surface merging loop, because it will compare the UBO offsets, + which are set by this call */ materialSystem.GenerateWorldMaterialsBuffer(); + + std::vector processedMaterialSurfaces; + processedMaterialSurfaces.reserve( numSurfaces ); + + std::function + materialSurfaceSort = []( const MaterialSurface& lhs, const MaterialSurface& rhs ) { + if ( lhs.stages < rhs.stages ) { + return true; + } else if ( lhs.stages > rhs.stages ) { + return false; + } + + for ( uint8_t stage = 0; stage < lhs.stages; stage++ ) { + if ( lhs.materialPackIDs[stage] < rhs.materialPackIDs[stage] ) { + return true; + } else if ( lhs.materialPackIDs[stage] > rhs.materialPackIDs[stage] ) { + return false; + } + + if ( lhs.materialIDs[stage] < rhs.materialIDs[stage] ) { + return true; + } else if ( lhs.materialIDs[stage] > rhs.materialIDs[stage] ) { + return false; + } + + shaderStage_t* pStage = lhs.shaderStages[stage]; + pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + + const uint32_t surfaceMaterialID = + pStage->materialOffset + pStage->variantOffsets[lhs.shaderVariant[stage]]; + + pStage = rhs.shaderStages[stage]; + pStage = pStage->materialRemappedStage ? pStage->materialRemappedStage : pStage; + + const uint32_t surfaceMaterialID2 = + pStage->materialOffset + pStage->variantOffsets[rhs.shaderVariant[stage]]; + + if ( surfaceMaterialID < surfaceMaterialID2 ) { + return true; + } else if ( surfaceMaterialID > surfaceMaterialID2 ) { + return false; + } + + uint32_t texData = lhs.texDataDynamic[stage] + ? ( lhs.texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS + : lhs.texDataIDs[stage] << TEX_BUNDLE_BITS; + texData |= ( HasLightMap( &lhs ) ? GetLightMapNum( &lhs ) : 255 ) << LIGHTMAP_BITS; + + uint32_t texData2 = rhs.texDataDynamic[stage] + ? ( rhs.texDataIDs[stage] + materialSystem.GetTexDataSize() ) << TEX_BUNDLE_BITS + : rhs.texDataIDs[stage] << TEX_BUNDLE_BITS; + texData2 |= ( HasLightMap( &rhs ) ? GetLightMapNum( &rhs ) : 255 ) << LIGHTMAP_BITS; + + if ( texData < texData2 ) { + return true; + } else if ( texData > texData2 ) { + return false; + } + } + + return lhs.firstIndex < rhs.firstIndex; + }; + + glIndex_t* idxs = ( glIndex_t* ) ri.Hunk_AllocateTempMemory( numIndicesIn * sizeof( glIndex_t ) ); + uint32_t numIndices = 0; + + uint32_t gridSize[3] {}; + uint32_t cellSize[3]; + vec3_t worldSize; + VectorSubtract( worldBounds[1], worldBounds[0], worldSize ); + for ( int i = 0; i < 3; i++ ) { + if ( worldSize[i] < 32768 ) { + cellSize[i] = 1024; + } else { + cellSize[i] = 2048; + } + + gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; + } + + Log::Debug( "BSP material surface grid cell size: %u %u %u", cellSize[0], cellSize[1], cellSize[2] ); + + std::sort( materialSurfaces.begin(), materialSurfaces.end(), materialSurfaceSort ); + + OptimiseMaterialSurfaces( materialSurfaces, gridSize, cellSize, world->nodes[0].mins, + materialSurfaceSort, + vertices, indices, idxs, processedMaterialSurfaces, numIndices ); + + /* On some maps surfaces go outside the 64k range, used for background and sky brushes. + We process them separately so we can use a larger cell size there, otherwise we'll run out of memory. + The regular surfaces can continue using samller grid sizes this way, + resulting in actually useable bounding spheres */ + if( materialSurfacesExtended.size() ) { + VectorSubtract( worldBoundsExtended[1], worldBoundsExtended[0], worldSize ); + for ( int i = 0; i < 3; i++ ) { + cellSize[i] = std::max( 2048.0f, worldSize[i] / 32.0f ); + + gridSize[i] = ( worldSize[i] + cellSize[i] - 1 ) / cellSize[i]; + } + + Log::Debug( "BSP material surface extended grid cell size: %u %u %u", cellSize[0], cellSize[1], cellSize[2] ); + + std::sort( materialSurfacesExtended.begin(), materialSurfacesExtended.end(), materialSurfaceSort ); + + OptimiseMaterialSurfaces( materialSurfacesExtended, gridSize, cellSize, world->nodes[0].mins, + materialSurfaceSort, + vertices, indices, idxs, processedMaterialSurfaces, numIndices ); + } + materialSystem.GeneratePortalBoundingSpheres(); - materialSystem.SetWorldBounds( worldBounds ); - materialSystem.GenerateWorldCommandBuffer( materialSurfaces ); + materialSystem.GenerateWorldCommandBuffer( processedMaterialSurfaces ); + + materialSystem.BindBuffers(); + + vertexAttributeSpec_t attrs[] { + { ATTR_INDEX_POSITION, GL_FLOAT, GL_FLOAT, &vertices[0].xyz, 3, sizeof( *vertices ), 0 }, + { ATTR_INDEX_COLOR, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, &vertices[0].lightColor, 4, sizeof( *vertices ), ATTR_OPTION_NORMALIZE }, + { ATTR_INDEX_QTANGENT, GL_SHORT, GL_SHORT, &vertices[0].qtangent, 4, sizeof( *vertices ), ATTR_OPTION_NORMALIZE }, + { ATTR_INDEX_TEXCOORD, GL_FLOAT, GL_HALF_FLOAT, &vertices[0].st, 4, sizeof( *vertices ), 0 }, + }; + + geometryCache.AddMapGeometry( numVerticesIn, numIndices, std::begin( attrs ), std::end( attrs ), idxs ); + + ri.Hunk_FreeTempMemory( idxs ); return materialSurfaces; } diff --git a/src/engine/renderer/GeometryOptimiser.h b/src/engine/renderer/GeometryOptimiser.h index 263d70af7..3a24a972d 100644 --- a/src/engine/renderer/GeometryOptimiser.h +++ b/src/engine/renderer/GeometryOptimiser.h @@ -41,30 +41,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static const uint32_t MAX_MATERIAL_SURFACE_TRIS = 64; static const uint32_t MAX_MATERIAL_SURFACE_INDEXES = 3 * MAX_MATERIAL_SURFACE_TRIS; -static const uint32_t MAX_MATERIAL_SURFACE_DISTANCE = 256; - -struct TriEdge { - enum State : uint32_t { - MERGEABLE_TRUE = BIT( 27 ), - MERGEABLE_FALSE = BIT( 28 ), - MERGEABLE_NOT_PROCESSED = BIT( 29 ), - NONE = BIT( 30 ) - }; - - uint32_t index1; - uint32_t index2; -}; - -struct TriEdgeHasher { - size_t operator()( const TriEdge& triEdge ) { - return std::hash{} ( triEdge.index1 ) ^ ( std::hash{} ( triEdge.index2 ) << 16 ); - } -}; - -struct TriIndex { - int tri1 = -1; - int tri2 = -1; -}; struct MapVertHasher { size_t operator()( const srfVert_t& vert ) const { @@ -97,6 +73,10 @@ struct MapVertEqual { } }; +struct SurfaceIndexes { + glIndex_t idxs[MAX_MATERIAL_SURFACE_INDEXES]; +}; + void MarkShaderBuildNONE( const shaderStage_t* ); void MarkShaderBuildNOP( const shaderStage_t* ); void MarkShaderBuildGeneric3D( const shaderStage_t* pStage ); @@ -120,6 +100,7 @@ void OptimiseMapGeometryCore( world_t* world, bspSurface_t** rendererSurfaces, i void MergeLeafSurfacesCore( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces ); void MergeDuplicateVertices( bspSurface_t** rendererSurfaces, int numSurfaces, srfVert_t* vertices, int numVerticesIn, glIndex_t* indices, int numIndicesIn, int& numVerticesOut, int& numIndicesOut ); -std::vector OptimiseMapGeometryMaterial( bspSurface_t** rendererSurfaces, int numSurfaces ); +std::vector OptimiseMapGeometryMaterial( world_t* world, bspSurface_t** rendererSurfaces, int numSurfaces, + const srfVert_t* vertices, const int numVerticesIn, const glIndex_t* indices, const int numIndicesIn ); #endif // GEOMETRY_OPTIMISER_H diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index eb8488f4f..e665bff88 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -35,21 +35,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "tr_local.h" #include "Material.h" +#include "BufferBind.h" #include "ShadeCommon.h" #include "GeometryCache.h" +#include "GLMemory.h" -GLUBO materialsUBO( "materials", Util::ordinal( BufferBind::MATERIALS ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer texDataBuffer( "texData", Util::ordinal( BufferBind::TEX_DATA ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO lightMapDataUBO( "lightMapData", Util::ordinal( BufferBind::LIGHTMAP_DATA ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); +GLUBO materialsUBO( "materials", BufferBind::MATERIALS, 0, 0 ); +GLBuffer texDataBuffer( "texData", BufferBind::TEX_DATA, 0, 0 ); +GLUBO lightMapDataUBO( "lightMapData", BufferBind::LIGHTMAP_DATA, 0, 0 ); -GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", Util::ordinal( BufferBind::SURFACE_DESCRIPTORS ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLSSBO surfaceCommandsSSBO( "surfaceCommands", Util::ordinal( BufferBind::SURFACE_COMMANDS ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLBuffer culledCommandsBuffer( "culledCommands", Util::ordinal( BufferBind::CULLED_COMMANDS ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLUBO surfaceBatchesUBO( "surfaceBatches", Util::ordinal( BufferBind::SURFACE_BATCHES ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); -GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", Util::ordinal( BufferBind::COMMAND_COUNTERS_ATOMIC ), GL_MAP_WRITE_BIT, GL_MAP_FLUSH_EXPLICIT_BIT ); -GLSSBO portalSurfacesSSBO( "portalSurfaces", Util::ordinal( BufferBind::PORTAL_SURFACES ), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, 0 ); +GLSSBO surfaceDescriptorsSSBO( "surfaceDescriptors", BufferBind::SURFACE_DESCRIPTORS, 0, 0 ); +GLSSBO surfaceCommandsSSBO( "surfaceCommands", BufferBind::SURFACE_COMMANDS, 0, 0 ); +GLBuffer culledCommandsBuffer( "culledCommands", BufferBind::CULLED_COMMANDS, 0, 0 ); +GLUBO surfaceBatchesUBO( "surfaceBatches", BufferBind::SURFACE_BATCHES, 0, 0 ); +GLBuffer atomicCommandCountersBuffer( "atomicCommandCounters", BufferBind::COMMAND_COUNTERS_ATOMIC, 0, 0 ); +GLSSBO portalSurfacesSSBO( "portalSurfaces", BufferBind::PORTAL_SURFACES, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, 0 ); -GLSSBO debugSSBO( "debug", Util::ordinal( BufferBind::DEBUG ), GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); +GLSSBO debugSSBO( "debug", BufferBind::DEBUG, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_RANGE_BIT ); PortalView portalStack[MAX_VIEWS]; @@ -425,10 +427,13 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { totalStageSize = offset; // 4 bytes per component - materialsUBO.BufferData( offset, nullptr, GL_DYNAMIC_DRAW ); - uint32_t* materialsData = materialsUBO.MapBufferRange( offset ); + materialsUBO.BufferStorage( totalStageSize, 1, nullptr ); - GenerateMaterialsBuffer( materialStages, offset, materialsData ); + uint32_t* materialsData = stagingBuffer.MapBuffer( totalStageSize ); + + GenerateMaterialsBuffer( materialStages, totalStageSize, materialsData ); + + stagingBuffer.QueueStagingCopy( &materialsUBO, 0 ); for ( shaderStage_t* pStage : materialStages ) { if ( pStage->dynamic ) { @@ -436,7 +441,7 @@ void MaterialSystem::GenerateWorldMaterialsBuffer() { } } - materialsUBO.UnmapBuffer(); + GL_CheckErrors(); } void MaterialSystem::GenerateMaterialsBuffer( std::vector& stages, const uint32_t size, uint32_t* materialsData ) { @@ -496,42 +501,20 @@ void MaterialSystem::GenerateTexturesBuffer( std::vector& textures, void MaterialSystem::GenerateWorldCommandBuffer( std::vector& surfaces ) { Log::Debug( "Generating world command buffer" ); - totalBatchCount = 0; - - uint32_t batchOffset = 0; - uint32_t globalID = 0; - for ( MaterialPack& pack : materialPacks ) { - for ( Material& material : pack.materials ) { - material.surfaceCommandBatchOffset = batchOffset; - - const uint32_t cmdCount = material.drawCommandCount; - const uint32_t batchCount = cmdCount % SURFACE_COMMANDS_PER_BATCH == 0 ? cmdCount / SURFACE_COMMANDS_PER_BATCH - : cmdCount / SURFACE_COMMANDS_PER_BATCH + 1; - - material.surfaceCommandBatchOffset = batchOffset; - material.surfaceCommandBatchCount = batchCount; - - batchOffset += batchCount; - material.globalID = globalID; - - totalBatchCount += batchCount; - globalID++; - } + // TexBundles + if ( glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ) { + texDataBufferType = GL_UNIFORM_BUFFER; + texDataBindingPoint = BufferBind::TEX_DATA; + } else { + texDataBufferType = GL_SHADER_STORAGE_BUFFER; + texDataBindingPoint = BufferBind::TEX_DATA_STORAGE; } - Log::Debug( "Total batch count: %u", totalBatchCount ); - - surfaceDescriptorsCount = totalDrawSurfs; - descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; - surfaceDescriptorsSSBO.BufferData( surfaceDescriptorsCount * descriptorSize, nullptr, GL_STATIC_DRAW ); - uint32_t* surfaceDescriptors = surfaceDescriptorsSSBO.MapBufferRange( surfaceDescriptorsCount * descriptorSize ); + const uint32_t texDataSize = ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE; + texDataBuffer.BufferStorage( texDataSize, 1, nullptr ); - texDataBufferType = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER; - - texDataBuffer.BufferStorage( ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE, 1, nullptr ); - texDataBuffer.MapAll(); - TexBundle* textureBundles = ( TexBundle* ) texDataBuffer.GetData(); - memset( textureBundles, 0, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * sizeof( uint32_t ) ); + TexBundle* textureBundles = ( TexBundle* ) stagingBuffer.MapBuffer( texDataSize ); + memset( textureBundles, 0, texDataSize * sizeof( uint32_t ) ); GenerateTexturesBuffer( texData, textureBundles ); @@ -539,15 +522,15 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s GenerateTexturesBuffer( dynamicTexData, textureBundles ); + stagingBuffer.QueueStagingCopy( &texDataBuffer, 0 ); + dynamicTexDataOffset = texData.size() * TEX_BUNDLE_SIZE; dynamicTexDataSize = dynamicTexData.size() * TEX_BUNDLE_SIZE; - texDataBuffer.FlushAll(); - texDataBuffer.UnmapBuffer(); - + // Lightmaps/Deluxemaps lightMapDataUBO.BufferStorage( MAX_LIGHTMAPS * LIGHTMAP_SIZE, 1, nullptr ); - lightMapDataUBO.MapAll(); - uint64_t* lightMapData = ( uint64_t* ) lightMapDataUBO.GetData(); + + uint64_t* lightMapData = ( uint64_t* ) stagingBuffer.MapBuffer( MAX_LIGHTMAPS * LIGHTMAP_SIZE ); memset( lightMapData, 0, MAX_LIGHTMAPS * LIGHTMAP_SIZE * sizeof( uint32_t ) ); for ( uint32_t i = 0; i < tr.lightmaps.size(); i++ ) { @@ -582,25 +565,49 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s lightMapData[255 * 2 + 1] = tr.blackImage->texture->bindlessTextureHandle; } - lightMapDataUBO.FlushAll(); - lightMapDataUBO.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &lightMapDataUBO, 0 ); - surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; + // Surface batches + for ( MaterialSurface& surface : surfaces ) { + if ( surface.skyBrush ) { + continue; + } - surfaceCommandsSSBO.BufferStorage( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); - surfaceCommandsSSBO.MapAll(); - SurfaceCommand* surfaceCommands = ( SurfaceCommand* ) surfaceCommandsSSBO.GetData(); - memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) * MAX_VIEWFRAMES ); + for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { + Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; + material->drawCommandCount++; + } + } - culledCommandsBuffer.BufferStorage( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); - culledCommandsBuffer.MapAll(); - GLIndirectCommand* culledCommands = ( GLIndirectCommand* ) culledCommandsBuffer.GetData(); - memset( culledCommands, 0, surfaceCommandsCount * sizeof( GLIndirectCommand ) * MAX_VIEWFRAMES ); - culledCommandsBuffer.FlushAll(); + totalBatchCount = 0; + uint32_t batchOffset = 0; + uint32_t globalID = 0; + for ( MaterialPack& pack : materialPacks ) { + for ( Material& material : pack.materials ) { + material.surfaceCommandBatchOffset = batchOffset; + + const uint32_t cmdCount = material.drawCommandCount; + const uint32_t batchCount = cmdCount % SURFACE_COMMANDS_PER_BATCH == 0 ? cmdCount / SURFACE_COMMANDS_PER_BATCH + : cmdCount / SURFACE_COMMANDS_PER_BATCH + 1; + + material.surfaceCommandBatchOffset = batchOffset; + material.surfaceCommandBatchCount = batchCount; - surfaceBatchesUBO.BufferData( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE, nullptr, GL_STATIC_DRAW ); + batchOffset += batchCount; + material.globalID = globalID; + + material.drawCommandCount = 0; + + totalBatchCount += batchCount; + globalID++; + } + } + + Log::Debug( "Total batch count: %u", totalBatchCount ); + + surfaceBatchesUBO.BufferStorage( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE, 1, nullptr ); SurfaceCommandBatch* surfaceCommandBatches = - ( SurfaceCommandBatch* ) surfaceBatchesUBO.MapBufferRange( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); + ( SurfaceCommandBatch* ) stagingBuffer.MapBuffer( MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); // memset( (void*) surfaceCommandBatches, 0, MAX_SURFACE_COMMAND_BATCHES * SURFACE_COMMAND_BATCH_SIZE ); // Fuck off gcc @@ -621,10 +628,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s } } - atomicCommandCountersBuffer.BufferStorage( MAX_COMMAND_COUNTERS * MAX_VIEWS, MAX_FRAMES, nullptr ); - atomicCommandCountersBuffer.MapAll(); - uint32_t* atomicCommandCounters = ( uint32_t* ) atomicCommandCountersBuffer.GetData(); - memset( atomicCommandCounters, 0, MAX_COMMAND_COUNTERS * MAX_VIEWFRAMES * sizeof( uint32_t ) ); + stagingBuffer.QueueStagingCopy( &surfaceBatchesUBO, 0 ); /* For use in debugging compute shaders Intended for use with Nsight Graphics to format the output */ @@ -637,6 +641,32 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s debugSSBO.UnmapBuffer(); } + // Surfaces + surfaceCommandsCount = totalBatchCount * SURFACE_COMMANDS_PER_BATCH; + + culledCommandsBuffer.BufferStorage( surfaceCommandsCount * INDIRECT_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); + + atomicCommandCountersBuffer.BufferStorage( MAX_COMMAND_COUNTERS * MAX_VIEWS, MAX_FRAMES, nullptr ); + uint32_t* atomicCommandCounters = stagingBuffer.MapBuffer( MAX_COMMAND_COUNTERS * MAX_VIEWS ); + memset( atomicCommandCounters, 0, MAX_COMMAND_COUNTERS * MAX_VIEWFRAMES * sizeof( uint32_t ) ); + + stagingBuffer.QueueStagingCopy( &atomicCommandCountersBuffer, 0 ); + + stagingBuffer.FlushAll(); + + surfaceDescriptorsCount = surfaces.size(); + + descriptorSize = BOUNDING_SPHERE_SIZE + maxStages; + surfaceDescriptorsSSBO.BufferStorage( surfaceDescriptorsCount * descriptorSize, 1, nullptr ); + uint32_t* surfaceDescriptors = stagingBuffer.MapBuffer( surfaceDescriptorsCount * descriptorSize ); + + stagingBuffer.QueueStagingCopy( &surfaceDescriptorsSSBO, 0 ); + + surfaceCommandsSSBO.BufferStorage( surfaceCommandsCount * SURFACE_COMMAND_SIZE * MAX_VIEWFRAMES, 1, nullptr ); + SurfaceCommand* surfaceCommands = + ( SurfaceCommand* ) stagingBuffer.MapBuffer( surfaceCommandsCount * SURFACE_COMMAND_SIZE ); + memset( surfaceCommands, 0, surfaceCommandsCount * sizeof( SurfaceCommand ) ); + for ( MaterialSurface& surface : surfaces ) { if ( surface.skyBrush ) { continue; @@ -650,7 +680,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s for ( uint8_t stage = 0; stage < surface.stages; stage++ ) { Material* material = &materialPacks[surface.materialPackIDs[stage]].materials[surface.materialIDs[stage]]; - uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + material->drawCommandCount2; + uint32_t cmdID = material->surfaceCommandBatchOffset * SURFACE_COMMANDS_PER_BATCH + material->drawCommandCount; // Add 1 because cmd 0 == no-command surfaceDescriptor.surfaceCommandIDs[stage] = cmdID + 1; @@ -670,7 +700,7 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s surfaceCommand.drawCommand.baseInstance |= ( HasLightMap( &surface ) ? GetLightMapNum( &surface ) : 255 ) << LIGHTMAP_BITS; surfaceCommands[cmdID] = surfaceCommand; - material->drawCommandCount2++; + material->drawCommandCount++; } memcpy( surfaceDescriptors, &surfaceDescriptor, descriptorSize * sizeof( uint32_t ) ); @@ -678,29 +708,46 @@ void MaterialSystem::GenerateWorldCommandBuffer( std::vector& s } for ( int i = 0; i < MAX_VIEWFRAMES; i++ ) { - memcpy( surfaceCommands + surfaceCommandsCount * i, surfaceCommands, surfaceCommandsCount * sizeof( SurfaceCommand ) ); + stagingBuffer.QueueStagingCopy( &surfaceCommandsSSBO, i * surfaceCommandsCount * SURFACE_COMMAND_SIZE ); } + + stagingBuffer.FlushAll(); uint32_t totalCount = 0; for ( MaterialPack& pack : materialPacks ) { totalCount += pack.materials.size(); } - Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, surfaces.size() ); + Log::Notice( "Generated %u BSP materials from %u BSP surfaces", totalCount, surfaceDescriptorsCount ); Log::Notice( "Materials UBO: total: %.2f kb, dynamic: %.2f kb, texData: %.2f kb", totalStageSize * 4 / 1024.0f, dynamicStagesSize * 4 / 1024.0f, ( texData.size() + dynamicTexData.size() ) * TEX_BUNDLE_SIZE * 4 / 1024.0f ); - surfaceDescriptorsSSBO.UnmapBuffer(); + GL_CheckErrors(); +} - surfaceCommandsSSBO.UnmapBuffer(); +void MaterialSystem::BindBuffers() { + materialsUBO.BindBufferBase(); + texDataBuffer.BindBufferBase( texDataBufferType, texDataBindingPoint ); + lightMapDataUBO.BindBufferBase(); - culledCommandsBuffer.UnmapBuffer(); + culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); + atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - atomicCommandCountersBuffer.UnmapBuffer(); + atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, BufferBind::COMMAND_COUNTERS_STORAGE ); - surfaceBatchesUBO.UnmapBuffer(); + surfaceDescriptorsSSBO.BindBufferBase(); + surfaceCommandsSSBO.BindBufferBase(); + culledCommandsBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER ); + surfaceBatchesUBO.BindBufferBase(); + atomicCommandCountersBuffer.BindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); - GL_CheckErrors(); + if ( totalPortals > 0 ) { + portalSurfacesSSBO.BindBufferBase(); + } + + if ( r_materialDebug.Get() ) { + debugSSBO.BindBufferBase(); + } } void MaterialSystem::GenerateDepthImages( const int width, const int height, imageParams_t imageParms ) { @@ -740,7 +787,6 @@ void BindShaderGeneric3D( Material* material ) { // Set shader uniforms. if ( material->tcGenEnvironment ) { gl_genericShaderMaterial->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); - gl_genericShaderMaterial->SetUniform_ViewUp( backEnd.orientation.axis[2] ); } gl_genericShaderMaterial->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); @@ -791,14 +837,10 @@ void BindShaderLightMapping( Material* material ) { } if ( glConfig2.realtimeLighting ) { - gl_lightMappingShaderMaterial->SetUniformBlock_Lights( tr.dlightUBO ); - // bind u_LightTiles - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { - gl_lightMappingShaderMaterial->SetUniform_LightTilesBindless( - GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) - ); - } + gl_lightMappingShaderMaterial->SetUniform_LightTilesBindless( + GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) + ); } gl_lightMappingShaderMaterial->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); @@ -1317,8 +1359,6 @@ void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pSta packIDs[materialPack] = id; - materials[previousMaterialID].drawCommandCount++; - stage++; } @@ -1326,8 +1366,6 @@ void MaterialSystem::ProcessStage( MaterialSurface* surface, shaderStage_t* pSta A material represents a distinct global OpenGL state (e. g. blend function, depth test, depth write etc.) Materials can have a dependency on other materials to make sure that consecutive stages are rendered in the proper order */ void MaterialSystem::GenerateMaterial( MaterialSurface* surface ) { - totalDrawSurfs++; - uint32_t stage = 0; uint32_t previousMaterialID = 0; @@ -1429,43 +1467,39 @@ void MaterialSystem::AddStageTextures( MaterialSurface* surface, shader_t* shade surface->texDataDynamic[stage] = dynamic; if ( glConfig2.realtimeLighting ) { - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { - material->AddTexture( tr.lighttileRenderImage->texture ); - } + material->AddTexture( tr.lighttileRenderImage->texture ); } } -// Dynamic surfaces are those whose values in the SSBO can be updated +// Dynamic surfaces are those whose values in the UBOs/SSBO might require updating void MaterialSystem::UpdateDynamicSurfaces() { if ( dynamicStagesSize > 0 ) { - uint32_t* materialsData = materialsUBO.MapBufferRange( dynamicStagesOffset, dynamicStagesSize ); + uint32_t* materialsData = stagingBuffer.MapBuffer( dynamicStagesSize ); GenerateMaterialsBuffer( dynamicStages, dynamicStagesSize, materialsData ); - materialsUBO.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &materialsUBO, dynamicStagesOffset ); } if ( dynamicTexDataSize > 0 ) { TexBundle* textureBundles = - ( TexBundle* ) texDataBuffer.MapBufferRange( dynamicTexDataOffset, dynamicTexDataSize ); + ( TexBundle* ) stagingBuffer.MapBuffer( dynamicTexDataSize ); GenerateTexturesBuffer( dynamicTexData, textureBundles ); - texDataBuffer.UnmapBuffer(); + stagingBuffer.QueueStagingCopy( &texDataBuffer, dynamicTexDataOffset ); } + stagingBuffer.FlushAll(); + GL_CheckErrors(); } void MaterialSystem::UpdateFrameData() { - atomicCommandCountersBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - gl_clearSurfacesShader->BindProgram( 0 ); gl_clearSurfacesShader->SetUniform_Frame( nextFrame ); gl_clearSurfacesShader->DispatchCompute( MAX_VIEWS, 1, 1 ); - atomicCommandCountersBuffer.UnBindBufferBase( GL_SHADER_STORAGE_BUFFER, Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - GL_CheckErrors(); } @@ -1517,6 +1551,8 @@ void MaterialSystem::DepthReduction() { glMemoryBarrier( GL_SHADER_IMAGE_ACCESS_BARRIER_BIT ); } + + GL_CheckErrors(); } void MaterialSystem::CullSurfaces() { @@ -1524,22 +1560,6 @@ void MaterialSystem::CullSurfaces() { DepthReduction(); } - surfaceDescriptorsSSBO.BindBufferBase(); - surfaceCommandsSSBO.BindBufferBase(); - culledCommandsBuffer.BindBufferBase( GL_SHADER_STORAGE_BUFFER ); - surfaceBatchesUBO.BindBufferBase(); - atomicCommandCountersBuffer.BindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); - - if ( totalPortals > 0 ) { - portalSurfacesSSBO.BindBufferBase(); - } - - if ( r_materialDebug.Get() ) { - debugSSBO.BindBufferBase(); - } - - GL_CheckErrors(); - for ( uint32_t view = 0; view < frames[nextFrame].viewCount; view++ ) { vec3_t origin; frustum_t* frustum = &frames[nextFrame].viewFrames[view].frustum; @@ -1559,12 +1579,12 @@ void MaterialSystem::CullSurfaces() { } gl_cullShader->BindProgram( 0 ); - uint32_t globalWorkGroupX = totalDrawSurfs % MAX_COMMAND_COUNTERS == 0 ? - totalDrawSurfs / MAX_COMMAND_COUNTERS : totalDrawSurfs / MAX_COMMAND_COUNTERS + 1; + uint32_t globalWorkGroupX = surfaceDescriptorsCount % MAX_COMMAND_COUNTERS == 0 ? + surfaceDescriptorsCount / MAX_COMMAND_COUNTERS : surfaceDescriptorsCount / MAX_COMMAND_COUNTERS + 1; GL_Bind( depthImage ); gl_cullShader->SetUniform_Frame( nextFrame ); gl_cullShader->SetUniform_ViewID( view ); - gl_cullShader->SetUniform_TotalDrawSurfs( totalDrawSurfs ); + gl_cullShader->SetUniform_SurfaceDescriptorsCount( surfaceDescriptorsCount ); gl_cullShader->SetUniform_UseFrustumCulling( r_gpuFrustumCulling.Get() ); gl_cullShader->SetUniform_UseOcclusionCulling( r_gpuOcclusionCulling.Get() ); gl_cullShader->SetUniform_CameraPosition( origin ); @@ -1610,20 +1630,6 @@ void MaterialSystem::CullSurfaces() { gl_processSurfacesShader->DispatchCompute( totalBatchCount, 1, 1 ); } - surfaceDescriptorsSSBO.UnBindBufferBase(); - surfaceCommandsSSBO.UnBindBufferBase(); - culledCommandsBuffer.UnBindBufferBase( GL_SHADER_STORAGE_BUFFER ); - surfaceBatchesUBO.UnBindBufferBase(); - atomicCommandCountersBuffer.UnBindBufferBase( GL_ATOMIC_COUNTER_BUFFER ); - - if ( totalPortals > 0 ) { - portalSurfacesSSBO.UnBindBufferBase(); - } - - if ( r_materialDebug.Get() ) { - debugSSBO.UnBindBufferBase(); - } - GL_CheckErrors(); } @@ -1742,7 +1748,7 @@ void MaterialSystem::Free() { buildOneShader = true; - totalDrawSurfs = 0; + surfaceDescriptorsCount = 0; currentFrame = 0; nextFrame = 1; @@ -1842,7 +1848,6 @@ void MaterialSystem::AddPortalSurfaces() { return; } - portalSurfacesSSBO.BindBufferBase(); PortalSurface* portalSurfs = ( PortalSurface* ) portalSurfacesSSBO.GetCurrentAreaData(); viewCount = 0; // This will recursively find potentially visible portals in each view based on the data read back from the GPU @@ -1881,8 +1886,6 @@ void MaterialSystem::RenderMaterials( const shaderSort_t fromSort, const shaderS frameStart = false; } - materialsUBO.BindBufferBase(); - geometryCache.Bind(); for ( MaterialPack& materialPack : materialPacks ) { @@ -2013,13 +2016,6 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) } material.texturesResident = true; - culledCommandsBuffer.BindBuffer( GL_DRAW_INDIRECT_BUFFER ); - - atomicCommandCountersBuffer.BindBuffer( GL_PARAMETER_BUFFER_ARB ); - - texDataBuffer.BindBufferBase( texDataBufferType ); - lightMapDataUBO.BindBufferBase(); - if ( r_showGlobalMaterials.Get() && material.sort != 0 && ( material.shaderBinder == BindShaderLightMapping || material.shaderBinder == BindShaderGeneric3D ) ) { vec3_t color; @@ -2130,13 +2126,6 @@ void MaterialSystem::RenderMaterial( Material& material, const uint32_t viewID ) } } - culledCommandsBuffer.UnBindBuffer( GL_DRAW_INDIRECT_BUFFER ); - - atomicCommandCountersBuffer.UnBindBuffer( GL_PARAMETER_BUFFER_ARB ); - - texDataBuffer.UnBindBufferBase( texDataBufferType ); - lightMapDataUBO.UnBindBufferBase(); - if ( material.usePolygonOffset ) { glDisable( GL_POLYGON_OFFSET_FILL ); } diff --git a/src/engine/renderer/Material.h b/src/engine/renderer/Material.h index 2fd085ada..8ce90cbb1 100644 --- a/src/engine/renderer/Material.h +++ b/src/engine/renderer/Material.h @@ -150,7 +150,6 @@ struct Material { int fog = 0; uint32_t drawCommandCount = 0; - uint32_t drawCommandCount2 = 0; bool texturesResident = false; std::vector textures; @@ -307,23 +306,6 @@ struct SurfaceCommandBatch { uint32_t materialIDs[2] { 0, 0 }; }; -enum class BufferBind { - MATERIALS = 1, // LightTile UBO uses binding point 0, so avoid it here - TEX_DATA = 6, - LIGHTMAP_DATA = 2, - SURFACE_DESCRIPTORS = 0, - SURFACE_COMMANDS = 1, - CULLED_COMMANDS = 2, - SURFACE_BATCHES = 3, - COMMAND_COUNTERS_ATOMIC = 0, - COMMAND_COUNTERS_STORAGE = 4, // Avoid needlessly rebinding buffers - PORTAL_SURFACES = 5, - GEOMETRY_CACHE_INPUT_VBO = 6, - GEOMETRY_CACHE_VBO = 7, - DEBUG = 10, - UNUSED = INT32_MAX -}; - class MaterialSystem { public: vec3_t worldViewBounds[2]; @@ -382,6 +364,12 @@ class MaterialSystem { void InitGLBuffers(); void FreeGLBuffers(); + void BindBuffers(); + + uint32_t GetTexDataSize() const { + return texData.size(); + } + void AddStageTextures( MaterialSurface* surface, shader_t* shader, shaderStage_t* pStage, const uint32_t stage, Material* material ); void AddStage( MaterialSurface* surface, shaderStage_t* pStage, uint32_t stage, const bool mayUseVertexOverbright, const bool vertexLit, const bool fullbright ); @@ -413,11 +401,9 @@ class MaterialSystem { image_t* depthImage; int depthImageLevels; - uint32_t totalDrawSurfs; - uint32_t totalBatchCount = 0; - uint32_t surfaceCommandsCount = 0; uint32_t surfaceDescriptorsCount = 0; + uint32_t totalBatchCount = 0; uint32_t packIDs[3] = { 0, 0, 0 }; @@ -425,6 +411,7 @@ class MaterialSystem { std::vector dynamicStages; GLenum texDataBufferType; + GLuint texDataBindingPoint; std::vector texData; std::vector dynamicTexData; diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 2227ca6d7..3c9dd7b68 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -64,9 +64,6 @@ GLShader_generic *gl_genericShader = nullptr; GLShader_genericMaterial *gl_genericShaderMaterial = nullptr; GLShader_lightMapping *gl_lightMappingShader = nullptr; GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial = nullptr; -GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ = nullptr; -GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ = nullptr; -GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun = nullptr; GLShader_fogQuake3 *gl_fogQuake3Shader = nullptr; GLShader_fogQuake3Material *gl_fogQuake3ShaderMaterial = nullptr; GLShader_heatHaze *gl_heatHazeShader = nullptr; @@ -78,10 +75,8 @@ GLShader_reflection *gl_reflectionShader = nullptr; GLShader_reflectionMaterial *gl_reflectionShaderMaterial = nullptr; GLShader_screen *gl_screenShader = nullptr; GLShader_screenMaterial *gl_screenShaderMaterial = nullptr; -GLShader_shadowFill *gl_shadowFillShader = nullptr; GLShader_skybox *gl_skyboxShader = nullptr; GLShader_skyboxMaterial *gl_skyboxShaderMaterial = nullptr; -GLShader_debugShadowMap *gl_debugShadowMapShader = nullptr; GLShaderManager gl_shaderManager; namespace // Implementation details @@ -291,7 +286,7 @@ void GLShaderManager::UpdateShaderProgramUniformLocations( GLShader* shader, Sha uniform->UpdateShaderProgramUniformLocation( shaderProgram ); } - if( glConfig2.uniformBufferObjectAvailable ) { + if( glConfig2.uniformBufferObjectAvailable && !glConfig2.shadingLanguage420PackAvailable ) { // create buffer for storing uniform block indexes shaderProgram->uniformBlockIndexes = ( GLuint* ) Z_Malloc( sizeof( GLuint ) * numUniformBlocks ); @@ -308,6 +303,10 @@ static inline void AddDefine( std::string& defines, const std::string& define, i defines += Str::Format("#ifndef %s\n#define %s %d\n#endif\n", define, define, value); } +static inline void AddDefine( std::string& defines, const std::string& define, uint32_t value ) { + defines += Str::Format( "#ifndef %s\n#define %s %d\n#endif\n", define, define, value ); +} + // Epsilon for float is 5.96e-08, so exponential notation with 8 decimal places should give exact values. static inline void AddDefine( std::string& defines, const std::string& define, float value ) @@ -320,11 +319,6 @@ static inline void AddDefine( std::string& defines, const std::string& define, f defines += Str::Format("#ifndef %s\n#define %s vec2(%.8e, %.8e)\n#endif\n", define, define, v1, v2); } -static inline void AddDefine( std::string& defines, const std::string& define ) -{ - defines += Str::Format("#ifndef %s\n#define %s\n#endif\n", define, define); -} - // Has to match enum genFunc_t in tr_local.h static const char *const genFuncNames[] = { "DSTEP_NONE", @@ -422,6 +416,7 @@ struct addedExtension_t { static const std::vector fragmentVertexAddedExtensions = { { glConfig2.gpuShader4Available, 130, "EXT_gpu_shader4" }, { glConfig2.gpuShader5Available, 400, "ARB_gpu_shader5" }, + { glConfig2.shadingLanguage420PackAvailable, 420, "ARB_shading_language_420pack" }, { glConfig2.textureFloatAvailable, 130, "ARB_texture_float" }, { glConfig2.textureGatherAvailable, 400, "ARB_texture_gather" }, { glConfig2.textureIntegerAvailable, 0, "EXT_texture_integer" }, @@ -494,10 +489,12 @@ static void AddConst( std::string& str, const std::string& name, float value ) str += Str::Format("const float %s = %.8e;\n", name, value); } +#if 0 static void AddConst( std::string& str, const std::string& name, float v1, float v2 ) { str += Str::Format("const vec2 %s = vec2(%.8e, %.8e);\n", name, v1, v2); } +#endif static std::string GenVersionDeclaration( const std::vector &addedExtensions ) { // Declare version. @@ -585,9 +582,10 @@ static std::string GenVertexHeader() { } if ( glConfig2.usingMaterialSystem ) { - AddDefine( str, "BIND_MATERIALS", Util::ordinal( BufferBind::MATERIALS ) ); - AddDefine( str, "BIND_TEX_DATA", Util::ordinal( BufferBind::TEX_DATA ) ); - AddDefine( str, "BIND_LIGHTMAP_DATA", Util::ordinal( BufferBind::LIGHTMAP_DATA ) ); + AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); + AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_TEX_DATA_STORAGE", BufferBind::TEX_DATA_STORAGE ); + AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } return str; @@ -624,10 +622,15 @@ static std::string GenFragmentHeader() { str += "#define baseInstance in_baseInstance\n\n"; } + if ( glConfig2.shadingLanguage420PackAvailable ) { + AddDefine( str, "BIND_LIGHTS", BufferBind::LIGHTS ); + } + if ( glConfig2.usingMaterialSystem ) { - AddDefine( str, "BIND_MATERIALS", Util::ordinal( BufferBind::MATERIALS ) ); - AddDefine( str, "BIND_TEX_DATA", Util::ordinal( BufferBind::TEX_DATA ) ); - AddDefine( str, "BIND_LIGHTMAP_DATA", Util::ordinal( BufferBind::LIGHTMAP_DATA ) ); + AddDefine( str, "BIND_MATERIALS", BufferBind::MATERIALS ); + AddDefine( str, "BIND_TEX_DATA", BufferBind::TEX_DATA ); + AddDefine( str, "BIND_TEX_DATA_STORAGE", BufferBind::TEX_DATA_STORAGE ); + AddDefine( str, "BIND_LIGHTMAP_DATA", BufferBind::LIGHTMAP_DATA ); } return str; @@ -644,15 +647,15 @@ static std::string GenComputeHeader() { AddDefine( str, "MAX_SURFACE_COMMAND_BATCHES", MAX_SURFACE_COMMAND_BATCHES ); AddDefine( str, "MAX_COMMAND_COUNTERS", MAX_COMMAND_COUNTERS ); - AddDefine( str, "BIND_SURFACE_DESCRIPTORS", Util::ordinal( BufferBind::SURFACE_DESCRIPTORS ) ); - AddDefine( str, "BIND_SURFACE_COMMANDS", Util::ordinal( BufferBind::SURFACE_COMMANDS ) ); - AddDefine( str, "BIND_CULLED_COMMANDS", Util::ordinal( BufferBind::CULLED_COMMANDS ) ); - AddDefine( str, "BIND_SURFACE_BATCHES", Util::ordinal( BufferBind::SURFACE_BATCHES ) ); - AddDefine( str, "BIND_COMMAND_COUNTERS_ATOMIC", Util::ordinal( BufferBind::COMMAND_COUNTERS_ATOMIC ) ); - AddDefine( str, "BIND_COMMAND_COUNTERS_STORAGE", Util::ordinal( BufferBind::COMMAND_COUNTERS_STORAGE ) ); - AddDefine( str, "BIND_PORTAL_SURFACES", Util::ordinal( BufferBind::PORTAL_SURFACES ) ); + AddDefine( str, "BIND_SURFACE_DESCRIPTORS", BufferBind::SURFACE_DESCRIPTORS ); + AddDefine( str, "BIND_SURFACE_COMMANDS", BufferBind::SURFACE_COMMANDS ); + AddDefine( str, "BIND_CULLED_COMMANDS", BufferBind::CULLED_COMMANDS ); + AddDefine( str, "BIND_SURFACE_BATCHES", BufferBind::SURFACE_BATCHES ); + AddDefine( str, "BIND_COMMAND_COUNTERS_ATOMIC", BufferBind::COMMAND_COUNTERS_ATOMIC ); + AddDefine( str, "BIND_COMMAND_COUNTERS_STORAGE", BufferBind::COMMAND_COUNTERS_STORAGE ); + AddDefine( str, "BIND_PORTAL_SURFACES", BufferBind::PORTAL_SURFACES ); - AddDefine( str, "BIND_DEBUG", Util::ordinal( BufferBind::DEBUG ) ); + AddDefine( str, "BIND_DEBUG", BufferBind::DEBUG ); } if ( glConfig2.usingBindlessTextures ) { @@ -680,7 +683,6 @@ static std::string GenEngineConstants() { AddDefine( str, "r_zNear", r_znear->value ); AddDefine( str, "M_PI", static_cast< float >( M_PI ) ); - AddDefine( str, "MAX_SHADOWMAPS", MAX_SHADOWMAPS ); AddDefine( str, "MAX_REF_LIGHTS", MAX_REF_LIGHTS ); AddDefine( str, "NUM_LIGHT_LAYERS", glConfig2.realtimeLightLayers ); AddDefine( str, "TILE_SIZE", TILE_SIZE ); @@ -689,98 +691,9 @@ static std::string GenEngineConstants() { AddDefine( str, "r_tileStep", glState.tileStep[0], glState.tileStep[1] ); - if ( glConfig2.shadowMapping ) - { - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - case shadowingMode_t::SHADOWING_ESM32: - AddDefine( str, "ESM", 1 ); - break; - case shadowingMode_t::SHADOWING_VSM16: - case shadowingMode_t::SHADOWING_VSM32: - AddDefine( str, "VSM", 1 ); - - if ( glConfig.hardwareType == glHardwareType_t::GLHW_R300 ) - { - AddDefine( str, "VSM_CLAMP", 1 ); - } - break; - case shadowingMode_t::SHADOWING_EVSM32: - AddDefine( str, "EVSM", 1 ); - - // The exponents for the EVSM techniques should be less than ln(FLT_MAX/FILTER_SIZE)/2 {ln(FLT_MAX/1)/2 ~44.3} - // 42.9 is the maximum possible value for FILTER_SIZE=15 - // 42.0 is the truncated value that we pass into the sample - AddConst( str, "r_EVSMExponents", 42.0f, 42.0f ); - - if ( r_evsmPostProcess->integer ) - { - AddDefine( str, "r_EVSMPostProcess", 1 ); - } - break; - default: - DAEMON_ASSERT( false ); - break; - } - - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - case shadowingMode_t::SHADOWING_ESM32: - break; - case shadowingMode_t::SHADOWING_VSM16: - AddConst( str, "VSM_EPSILON", 0.0001f ); - break; - case shadowingMode_t::SHADOWING_VSM32: - // GLHW_R300 should not be GLDRV_OPENGL3 anyway. - if ( glConfig.driverType != glDriverType_t::GLDRV_OPENGL3 - || glConfig.hardwareType == glHardwareType_t::GLHW_R300 ) - { - AddConst( str, "VSM_EPSILON", 0.0001f ); - } - else - { - AddConst( str, "VSM_EPSILON", 0.000001f ); - } - break; - case shadowingMode_t::SHADOWING_EVSM32: - // This may be wrong, but the code did that before it was rewritten. - AddConst( str, "VSM_EPSILON", 0.0001f ); - break; - default: - DAEMON_ASSERT( false ); - break; - } - - if ( r_lightBleedReduction->value ) - AddConst( str, "r_lightBleedReduction", r_lightBleedReduction->value ); - - if ( r_overDarkeningFactor->value ) - AddConst( str, "r_overDarkeningFactor", r_overDarkeningFactor->value ); - - if ( r_shadowMapDepthScale->value ) - AddConst( str, "r_shadowMapDepthScale", r_shadowMapDepthScale->value ); - - if ( r_debugShadowMaps->integer ) - AddDefine( str, "r_debugShadowMaps", r_debugShadowMaps->integer ); - - if ( r_softShadows->integer == 6 ) - AddDefine( str, "PCSS", 1 ); - else if ( r_softShadows->integer ) - AddConst( str, "r_PCFSamples", r_softShadows->value + 1.0f ); - - if ( r_parallelShadowSplits->integer ) - AddDefine( str, Str::Format( "r_parallelShadowSplits_%d", r_parallelShadowSplits->integer ) ); - - if ( r_showParallelShadowSplits->integer ) - AddDefine( str, "r_showParallelShadowSplits", 1 ); - } - if ( glConfig2.realtimeLighting ) { AddDefine( str, "r_realtimeLighting", 1 ); - AddDefine( str, "r_realtimeLightingRenderer", r_realtimeLightingRenderer.Get() ); } if ( r_showNormalMaps->integer ) @@ -1268,6 +1181,10 @@ void GLShaderManager::BuildAll( const bool buildOnlyMarked ) { cacheLoadCount, cacheLoadTime, cacheSaveCount, cacheSaveTime ); } +void GLShaderManager::BindBuffers() { + glBindBufferBase( GL_UNIFORM_BUFFER, BufferBind::LIGHTS, tr.dlightUBO ); +} + std::string GLShaderManager::ProcessInserts( const std::string& shaderText ) const { std::string out; std::istringstream shaderTextStream( shaderText ); @@ -1424,8 +1341,6 @@ void GLShaderManager::InitShader( GLShader* shader ) { continue; } - shader->BuildShaderCompileMacros( compileMacros ); - const uint32_t uniqueMacros = shader->GetUniqueCompileMacros( i, shaderType.type ); ShaderDescriptor* desc = FindShader( shader->_name, shaderType.mainText, shaderType.GLType, shaderType.headers, @@ -1610,19 +1525,19 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str // 6 kb for materials const uint32_t count = ( 4096 + 2048 ) / shader->GetPaddedSize(); std::string materialBlock = "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::MATERIALS ) ) + + std::to_string( BufferBind::MATERIALS ) + ") uniform materialsUBO {\n" " Material materials[" + std::to_string( count ) + "]; \n" "};\n\n"; std::string texBuf = glConfig2.maxUniformBlockSize >= MIN_MATERIAL_UBO_SIZE ? "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::TEX_DATA ) ) + + std::to_string( BufferBind::TEX_DATA ) + ") uniform texDataUBO {\n" " TexData texData[" + std::to_string( MAX_TEX_BUNDLES ) + "]; \n" "};\n\n" : "layout(std430, binding = " - + std::to_string( Util::ordinal( BufferBind::TEX_DATA ) ) + + std::to_string( BufferBind::TEX_DATA ) + ") restrict readonly buffer texDataSSBO {\n" " TexData texData[];\n" "};\n\n"; @@ -1648,7 +1563,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str " uvec2 u_DeluxeMap;\n" "};\n\n" "layout(std140, binding = " - + std::to_string( Util::ordinal( BufferBind::LIGHTMAP_DATA ) ) + + std::to_string( BufferBind::LIGHTMAP_DATA ) + ") uniform lightMapDataUBO {\n" " LightMapData lightMapData[256];\n" "};\n\n" @@ -1726,7 +1641,7 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str /* Remove local uniform declarations, but avoid removing uniform / storage blocks; * their values will be sourced from a buffer instead - * Global uniforms (like u_ViewUp and u_ViewOrigin) will still be set as regular uniforms */ + * Global uniforms (like u_ViewOrigin) will still be set as regular uniforms */ while( std::getline( shaderTextStream, line, '\n' ) ) { bool skip = false; if ( line.find( "uniform" ) < line.find( "//" ) && line.find( ";" ) != std::string::npos ) { @@ -2460,7 +2375,6 @@ GLShader_generic::GLShader_generic() : u_DepthMap( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), - u_ViewUp( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), @@ -2495,7 +2409,6 @@ GLShader_genericMaterial::GLShader_genericMaterial() : u_DepthMap( this ), u_TextureMatrix( this ), u_ViewOrigin( this ), - u_ViewUp( this ), u_AlphaThreshold( this ), u_ModelMatrix( this ), u_ModelViewProjectionMatrix( this ), @@ -2649,226 +2562,6 @@ void GLShader_lightMappingMaterial::SetShaderProgramUniforms( ShaderProgramDescr } } -GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ(): - GLShader( "forwardLighting_omniXYZ", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_AttenuationMapXY( this ), - u_AttenuationMapZ( this ), - u_ShadowMap( this ), - u_ShadowClipMap( this ), - u_RandomMap( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightOrigin( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) -{ -} - -void GLShader_forwardLighting_omniXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - -GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ(): - GLShader( "forwardLighting_projXYZ", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_AttenuationMapXY( this ), - u_AttenuationMapZ( this ), - u_ShadowMap0( this ), - u_ShadowClipMap0( this ), - u_RandomMap( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightOrigin( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), - u_ShadowMatrix( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) -{ -} - -void GLShader_forwardLighting_projXYZ::BuildShaderCompileMacros( std::string& compileMacros ) -{ - compileMacros += "LIGHT_PROJ "; -} - -void GLShader_forwardLighting_projXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - -GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun(): - GLShader( "forwardLighting_directionalSun", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "forwardLighting", "forwardLighting" ), - u_DiffuseMap( this ), - u_NormalMap( this ), - u_MaterialMap( this ), - u_ShadowMap0( this ), - u_ShadowMap1( this ), - u_ShadowMap2( this ), - u_ShadowMap3( this ), - u_ShadowMap4( this ), - u_ShadowClipMap0( this ), - u_ShadowClipMap1( this ), - u_ShadowClipMap2( this ), - u_ShadowClipMap3( this ), - u_ShadowClipMap4( this ), - u_HeightMap( this ), - u_TextureMatrix( this ), - u_SpecularExponent( this ), - u_AlphaThreshold( this ), - u_ColorModulateColorGen_Float( this ), - u_ColorModulateColorGen_Uint( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_ViewOrigin( this ), - u_LightDir( this ), - u_LightColor( this ), - u_LightRadius( this ), - u_LightScale( this ), - u_LightAttenuationMatrix( this ), - u_ShadowTexelSize( this ), - u_ShadowBlur( this ), - u_ShadowMatrix( this ), - u_ShadowParallelSplitDistances( this ), - u_ModelMatrix( this ), - u_ViewMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - u_ReliefDepthScale( this ), - u_ReliefOffsetBias( this ), - u_NormalScale( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP( this ), - GLCompileMacro_USE_RELIEF_MAPPING( this ), - GLCompileMacro_USE_SHADOWING( this ) -{ -} - -void GLShader_forwardLighting_directionalSun::BuildShaderCompileMacros( std::string& compileMacros ) -{ - compileMacros += "LIGHT_DIRECTIONAL "; -} - -void GLShader_forwardLighting_directionalSun::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); - //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3); - //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap1" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap2" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap3" ), 8 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap4" ), 9 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 10 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap1" ), 11 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap2" ), 12 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap3" ), 13 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap4" ), 14 ); - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); -} - -GLShader_shadowFill::GLShader_shadowFill() : - GLShader( "shadowFill", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, - false, "shadowFill", "shadowFill" ), - u_ColorMap( this ), - u_TextureMatrix( this ), - u_AlphaThreshold( this ), - u_LightOrigin( this ), - u_LightRadius( this ), - u_ModelMatrix( this ), - u_ModelViewProjectionMatrix( this ), - u_Color_Float( this ), - u_Color_Uint( this ), - u_Bones( this ), - u_VertexInterpolation( this ), - GLDeformStage( this ), - GLCompileMacro_USE_VERTEX_SKINNING( this ), - GLCompileMacro_USE_VERTEX_ANIMATION( this ), - GLCompileMacro_LIGHT_DIRECTIONAL( this ) -{ -} - -void GLShader_shadowFill::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); -} - GLShader_reflection::GLShader_reflection(): GLShader( "reflection", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, false, "reflection_CB", "reflection_CB" ), @@ -3155,19 +2848,6 @@ void GLShader_blur::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderPro glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } -GLShader_debugShadowMap::GLShader_debugShadowMap() : - GLShader( "debugShadowMap", ATTR_POSITION, - false, "debugShadowMap", "debugShadowMap" ), - u_CurrentMap( this ), - u_ModelViewProjectionMatrix( this ) -{ -} - -void GLShader_debugShadowMap::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) -{ - glUniform1i( glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); -} - GLShader_liquid::GLShader_liquid() : GLShader( "liquid", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, false, "liquid", "liquid" ), @@ -3348,7 +3028,7 @@ GLShader_cull::GLShader_cull() : false, "cull" ), u_Frame( this ), u_ViewID( this ), - u_TotalDrawSurfs( this ), + u_SurfaceDescriptorsCount( this ), u_SurfaceCommandsOffset( this ), u_Frustum( this ), u_UseFrustumCulling( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index eb500c0a5..60c44bf2e 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GL_SHADER_H #include "tr_local.h" +#include "BufferBind.h" #include #define USE_UNIFORM_FIREWALL 1 @@ -181,7 +182,6 @@ class GLShader { void PostProcessUniforms(); uint32_t GetUniqueCompileMacros( size_t permutation, const int type ) const; bool GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut, const int type ) const; - virtual void BuildShaderCompileMacros( std::string& /*vertexInlines*/ ) { }; virtual void SetShaderProgramUniforms( ShaderProgramDescriptor* /*shaderProgram*/ ) { }; int SelectProgram(); public: @@ -368,6 +368,8 @@ class GLShaderManager { bool BuildPermutation( GLShader* shader, int macroIndex, int deformIndex, const bool buildOneShader ); void BuildAll( const bool buildOnlyMarked ); void FreeAll(); + + void BindBuffers(); private: struct InfoLogEntry { int line; @@ -1232,12 +1234,13 @@ class GLUniformBlock protected: GLShader *_shader; std::string _name; - size_t _locationIndex; + size_t _locationIndex; // Only valid if GL_ARB_shading_language_420pack is not available + const GLuint _bindingPoint; // Only valid if GL_ARB_shading_language_420pack is available - GLUniformBlock( GLShader *shader, const char *name ) : + GLUniformBlock( GLShader *shader, const char *name, const GLuint bindingPoint ) : _shader( shader ), _name( name ), - _locationIndex( 0 ) + _bindingPoint( bindingPoint ) { _shader->RegisterUniformBlock( this ); } @@ -1259,10 +1262,14 @@ class GLUniformBlock } void SetBuffer( GLuint buffer ) { + if ( glConfig2.shadingLanguage420PackAvailable ) { + return; + } + ShaderProgramDescriptor *p = _shader->GetProgram(); - GLuint blockIndex = p->uniformBlockIndexes[ _locationIndex ]; + GLuint blockIndex = p->uniformBlockIndexes[_locationIndex]; - ASSERT_EQ(p, glState.currentProgram); + ASSERT_EQ( p, glState.currentProgram ); if( blockIndex != GL_INVALID_INDEX ) { glBindBufferBase( GL_UNIFORM_BUFFER, blockIndex, buffer ); @@ -1277,6 +1284,8 @@ class GLBuffer { std::string name; const GLuint64 SYNC_TIMEOUT = 10000000000; // 10 seconds + GLuint id; + GLBuffer( const char* newName, const GLuint newBindingPoint, const GLbitfield newFlags, const GLbitfield newMapFlags ) : name( newName ), internalTarget( 0 ), @@ -1325,6 +1334,8 @@ class GLBuffer { maxAreas = areaCount; glNamedBufferStorage( id, areaSize * areaCount * sizeof( uint32_t ), data, flags ); syncs.resize( areaCount ); + + GL_CheckErrors(); } void AreaIncr() { @@ -1365,6 +1376,10 @@ class GLBuffer { glFlushMappedNamedBufferRange( id, 0, maxAreas * areaSize * sizeof( uint32_t ) ); } + void FlushRange( const GLsizeiptr offset, const GLsizeiptr size ) { + glFlushMappedNamedBufferRange( id, offset * sizeof( uint32_t ), size * sizeof( uint32_t ) ); + } + uint32_t* MapBufferRange( const GLuint count ) { return MapBufferRange( 0, count ); } @@ -1393,14 +1408,13 @@ class GLBuffer { void DelBuffer() { glDeleteBuffers( 1, &id ); + mapped = false; } private: const GLenum internalTarget; const GLuint internalBindingPoint; - GLuint id; - bool mapped = false; const GLbitfield flags; const GLbitfield mapFlags; @@ -1535,7 +1549,6 @@ class GLCompileMacro USE_HEIGHTMAP_IN_NORMALMAP, USE_RELIEF_MAPPING, USE_REFLECTIVE_SPECULAR, - USE_SHADOWING, LIGHT_DIRECTIONAL, USE_DEPTH_FADE, USE_PHYSICAL_MAPPING, @@ -1967,35 +1980,6 @@ class GLCompileMacro_LIGHT_DIRECTIONAL : } }; -class GLCompileMacro_USE_SHADOWING : - GLCompileMacro -{ -public: - GLCompileMacro_USE_SHADOWING( GLShader *shader ) : - GLCompileMacro( shader ) - { - } - - const char *GetName() const override - { - return "USE_SHADOWING"; - } - - EGLCompileMacro GetType() const override - { - return EGLCompileMacro::USE_SHADOWING; - } - - int GetShaderTypes() const override { - return ShaderType::FRAGMENT; - } - - void SetShadowing( bool enable ) - { - SetMacro( enable ); - } -}; - class GLCompileMacro_USE_DEPTH_FADE : GLCompileMacro { @@ -2231,22 +2215,6 @@ class u_GlowMap : } }; -class u_RandomMap : - GLUniformSampler2D { - public: - u_RandomMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_RandomMap" ) { - } - - void SetUniform_RandomMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_RandomMap() { - return this->GetLocation(); - } -}; - class u_PortalMap : GLUniformSampler2D { public: @@ -2391,230 +2359,6 @@ class u_CurrentMap : } }; -class u_AttenuationMapXY : - GLUniformSampler2D { - public: - u_AttenuationMapXY( GLShader* shader ) : - GLUniformSampler2D( shader, "u_AttenuationMapXY" ) { - } - - void SetUniform_AttenuationMapXYBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_AttenuationMapXY() { - return this->GetLocation(); - } -}; - -class u_AttenuationMapZ : - GLUniformSampler2D { - public: - u_AttenuationMapZ( GLShader* shader ) : - GLUniformSampler2D( shader, "u_AttenuationMapZ" ) { - } - - void SetUniform_AttenuationMapZBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_AttenuationMapZ() { - return this->GetLocation(); - } -}; - -class u_ShadowMap : - GLUniformSampler2D { - public: - u_ShadowMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap" ) { - } - - void SetUniform_ShadowMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap() { - return this->GetLocation(); - } -}; - -class u_ShadowMap0 : - GLUniformSampler2D { - public: - u_ShadowMap0( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap0" ) { - } - - void SetUniform_ShadowMap0Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap0() { - return this->GetLocation(); - } -}; - -class u_ShadowMap1 : - GLUniformSampler2D { - public: - u_ShadowMap1( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap1" ) { - } - - void SetUniform_ShadowMap1Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap1() { - return this->GetLocation(); - } -}; - -class u_ShadowMap2 : - GLUniformSampler2D { - public: - u_ShadowMap2( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap2" ) { - } - - void SetUniform_ShadowMap2Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap2() { - return this->GetLocation(); - } -}; - -class u_ShadowMap3 : - GLUniformSampler2D { - public: - u_ShadowMap3( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap3" ) { - } - - void SetUniform_ShadowMap3Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap3() { - return this->GetLocation(); - } -}; - -class u_ShadowMap4 : - GLUniformSampler2D { - public: - u_ShadowMap4( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowMap4" ) { - } - - void SetUniform_ShadowMap4Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowMap4() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap : - GLUniformSampler2D { - public: - u_ShadowClipMap( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap" ) { - } - - void SetUniform_ShadowClipMapBindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap0 : - GLUniformSampler2D { - public: - u_ShadowClipMap0( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap0" ) { - } - - void SetUniform_ShadowClipMap0Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap0() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap1 : - GLUniformSampler2D { - public: - u_ShadowClipMap1( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap1" ) { - } - - void SetUniform_ShadowClipMap1Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap1() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap2 : - GLUniformSampler2D { - public: - u_ShadowClipMap2( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap2" ) { - } - - void SetUniform_ShadowClipMap2Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap2() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap3 : - GLUniformSampler2D { - public: - u_ShadowClipMap3( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap3" ) { - } - - void SetUniform_ShadowClipMap3Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap3() { - return this->GetLocation(); - } -}; - -class u_ShadowClipMap4 : - GLUniformSampler2D { - public: - u_ShadowClipMap4( GLShader* shader ) : - GLUniformSampler2D( shader, "u_ShadowClipMap4" ) { - } - - void SetUniform_ShadowClipMap4Bindless( GLuint64 bindlessHandle ) { - this->SetValueBindless( bindlessHandle ); - } - - GLint GetUniformLocation_ShadowClipMap4() { - return this->GetLocation(); - } -}; - class u_TextureMatrix : GLUniformMatrix32f { @@ -2712,186 +2456,6 @@ class u_ViewOrigin : } }; -class u_ViewUp : - GLUniform3f -{ -public: - u_ViewUp( GLShader *shader ) : - GLUniform3f( shader, "u_ViewUp", true ) - { - } - - void SetUniform_ViewUp( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightDir : - GLUniform3f -{ -public: - u_LightDir( GLShader *shader ) : - GLUniform3f( shader, "u_LightDir" ) - { - } - - void SetUniform_LightDir( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightOrigin : - GLUniform3f -{ -public: - u_LightOrigin( GLShader *shader ) : - GLUniform3f( shader, "u_LightOrigin" ) - { - } - - void SetUniform_LightOrigin( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightColor : - GLUniform3f -{ -public: - u_LightColor( GLShader *shader ) : - GLUniform3f( shader, "u_LightColor" ) - { - } - - void SetUniform_LightColor( const vec3_t v ) - { - this->SetValue( v ); - } -}; - -class u_LightRadius : - GLUniform1f -{ -public: - u_LightRadius( GLShader *shader ) : - GLUniform1f( shader, "u_LightRadius" ) - { - } - - void SetUniform_LightRadius( float value ) - { - this->SetValue( value ); - } -}; - -class u_LightScale : - GLUniform1f -{ -public: - u_LightScale( GLShader *shader ) : - GLUniform1f( shader, "u_LightScale" ) - { - } - - void SetUniform_LightScale( float value ) - { - this->SetValue( value ); - } -}; - -class u_LightAttenuationMatrix : - GLUniformMatrix4f -{ -public: - u_LightAttenuationMatrix( GLShader *shader ) : - GLUniformMatrix4f( shader, "u_LightAttenuationMatrix" ) - { - } - - void SetUniform_LightAttenuationMatrix( const matrix_t m ) - { - this->SetValue( GL_FALSE, m ); - } -}; - -class u_LightFrustum : - GLUniform4fv -{ -public: - u_LightFrustum( GLShader *shader ) : - GLUniform4fv( shader, "u_LightFrustum", 6 ) - { - } - - void SetUniform_LightFrustum( vec4_t lightFrustum[ 6 ] ) - { - this->SetValue( 6, lightFrustum ); - } -}; - -class u_ShadowTexelSize : - GLUniform1f -{ -public: - u_ShadowTexelSize( GLShader *shader ) : - GLUniform1f( shader, "u_ShadowTexelSize" ) - { - } - - void SetUniform_ShadowTexelSize( float value ) - { - this->SetValue( value ); - } -}; - -class u_ShadowBlur : - GLUniform1f -{ -public: - u_ShadowBlur( GLShader *shader ) : - GLUniform1f( shader, "u_ShadowBlur" ) - { - } - - void SetUniform_ShadowBlur( float value ) - { - this->SetValue( value ); - } -}; - -class u_ShadowMatrix : - GLUniformMatrix4fv -{ -public: - u_ShadowMatrix( GLShader *shader ) : - GLUniformMatrix4fv( shader, "u_ShadowMatrix", MAX_SHADOWMAPS ) - { - } - - void SetUniform_ShadowMatrix( matrix_t m[ MAX_SHADOWMAPS ] ) - { - this->SetValue( MAX_SHADOWMAPS, GL_FALSE, m ); - } -}; - -class u_ShadowParallelSplitDistances : - GLUniform4f -{ -public: - u_ShadowParallelSplitDistances( GLShader *shader ) : - GLUniform4f( shader, "u_ShadowParallelSplitDistances" ) - { - } - - void SetUniform_ShadowParallelSplitDistances( const vec4_t v ) - { - this->SetValue( v ); - } -}; - class u_RefractionIndex : GLUniform1f { @@ -3200,15 +2764,15 @@ class u_P11 : } }; -class u_TotalDrawSurfs : +class u_SurfaceDescriptorsCount : GLUniform1ui { public: - u_TotalDrawSurfs( GLShader* shader ) : - GLUniform1ui( shader, "u_TotalDrawSurfs", true ) { + u_SurfaceDescriptorsCount( GLShader* shader ) : + GLUniform1ui( shader, "u_SurfaceDescriptorsCount", true ) { } - void SetUniform_TotalDrawSurfs( const uint totalDrawSurfs ) { - this->SetValue( totalDrawSurfs ); + void SetUniform_SurfaceDescriptorsCount( const uint SurfaceDescriptorsCount ) { + this->SetValue( SurfaceDescriptorsCount ); } }; @@ -4050,7 +3614,7 @@ class u_Lights : { public: u_Lights( GLShader *shader ) : - GLUniformBlock( shader, "u_Lights" ) + GLUniformBlock( shader, "u_Lights", BufferBind::LIGHTS ) { } @@ -4066,7 +3630,6 @@ class GLShader_generic : public u_DepthMap, public u_TextureMatrix, public u_ViewOrigin, - public u_ViewUp, public u_AlphaThreshold, public u_ModelMatrix, public u_ModelViewProjectionMatrix, @@ -4097,7 +3660,6 @@ class GLShader_genericMaterial : public u_DepthMap, public u_TextureMatrix, public u_ViewOrigin, - public u_ViewUp, public u_AlphaThreshold, public u_ModelMatrix, public u_ModelViewProjectionMatrix, @@ -4218,175 +3780,6 @@ class GLShader_lightMappingMaterial : void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; -class GLShader_forwardLighting_omniXYZ : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_AttenuationMapXY, - public u_AttenuationMapZ, - public u_ShadowMap, - public u_ShadowClipMap, - public u_RandomMap, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightOrigin, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, -{ -public: - GLShader_forwardLighting_omniXYZ(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - -class GLShader_forwardLighting_projXYZ : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_AttenuationMapXY, - public u_AttenuationMapZ, - public u_ShadowMap0, - public u_ShadowClipMap0, - public u_RandomMap, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightOrigin, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, - public u_ShadowMatrix, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, -{ -public: - GLShader_forwardLighting_projXYZ(); - void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - -class GLShader_forwardLighting_directionalSun : - public GLShader, - public u_DiffuseMap, - public u_NormalMap, - public u_MaterialMap, - public u_ShadowMap0, - public u_ShadowMap1, - public u_ShadowMap2, - public u_ShadowMap3, - public u_ShadowMap4, - public u_ShadowClipMap0, - public u_ShadowClipMap1, - public u_ShadowClipMap2, - public u_ShadowClipMap3, - public u_ShadowClipMap4, - public u_HeightMap, - public u_TextureMatrix, - public u_SpecularExponent, - public u_AlphaThreshold, - public u_ColorModulateColorGen_Float, - public u_ColorModulateColorGen_Uint, - public u_Color_Float, - public u_Color_Uint, - public u_ViewOrigin, - public u_LightDir, - public u_LightColor, - public u_LightRadius, - public u_LightScale, - public u_LightAttenuationMatrix, - public u_ShadowTexelSize, - public u_ShadowBlur, - public u_ShadowMatrix, - public u_ShadowParallelSplitDistances, - public u_ModelMatrix, - public u_ViewMatrix, - public u_ModelViewProjectionMatrix, - public u_Bones, - public u_VertexInterpolation, - public u_ReliefDepthScale, - public u_ReliefOffsetBias, - public u_NormalScale, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP, - public GLCompileMacro_USE_RELIEF_MAPPING, - public GLCompileMacro_USE_SHADOWING //, -{ -public: - GLShader_forwardLighting_directionalSun(); - void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - -class GLShader_shadowFill : - public GLShader, - public u_ColorMap, - public u_TextureMatrix, - public u_AlphaThreshold, - public u_LightOrigin, - public u_LightRadius, - public u_ModelMatrix, - public u_ModelViewProjectionMatrix, - public u_Color_Float, - public u_Color_Uint, - public u_Bones, - public u_VertexInterpolation, - public GLDeformStage, - public GLCompileMacro_USE_VERTEX_SKINNING, - public GLCompileMacro_USE_VERTEX_ANIMATION, - public GLCompileMacro_LIGHT_DIRECTIONAL -{ -public: - GLShader_shadowFill(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - class GLShader_reflection : public GLShader, public u_ColorMapCube, @@ -4621,16 +4014,6 @@ class GLShader_blur : void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; -class GLShader_debugShadowMap : - public GLShader, - public u_CurrentMap, - public u_ModelViewProjectionMatrix -{ -public: - GLShader_debugShadowMap(); - void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; -}; - class GLShader_liquid : public GLShader, public u_CurrentMap, @@ -4770,7 +4153,7 @@ class GLShader_cull : public GLShader, public u_Frame, public u_ViewID, - public u_TotalDrawSurfs, + public u_SurfaceDescriptorsCount, public u_SurfaceCommandsOffset, public u_Frustum, public u_UseFrustumCulling, @@ -4839,9 +4222,6 @@ extern GLShader_generic *gl_genericShader; extern GLShader_genericMaterial *gl_genericShaderMaterial; extern GLShader_lightMapping *gl_lightMappingShader; extern GLShader_lightMappingMaterial *gl_lightMappingShaderMaterial; -extern GLShader_forwardLighting_omniXYZ *gl_forwardLightingShader_omniXYZ; -extern GLShader_forwardLighting_projXYZ *gl_forwardLightingShader_projXYZ; -extern GLShader_forwardLighting_directionalSun *gl_forwardLightingShader_directionalSun; extern GLShader_fogQuake3 *gl_fogQuake3Shader; extern GLShader_fogQuake3Material *gl_fogQuake3ShaderMaterial; extern GLShader_heatHaze *gl_heatHazeShader; @@ -4853,10 +4233,8 @@ extern GLShader_reflection *gl_reflectionShader; extern GLShader_reflectionMaterial *gl_reflectionShaderMaterial; extern GLShader_screen *gl_screenShader; extern GLShader_screenMaterial *gl_screenShaderMaterial; -extern GLShader_shadowFill *gl_shadowFillShader; extern GLShader_skybox *gl_skyboxShader; extern GLShader_skyboxMaterial *gl_skyboxShaderMaterial; -extern GLShader_debugShadowMap *gl_debugShadowMapShader; extern GLShaderManager gl_shaderManager; #endif // GL_SHADER_H diff --git a/src/engine/renderer/glsl_source/computeLight_fp.glsl b/src/engine/renderer/glsl_source/computeLight_fp.glsl index 514fe4b27..f3c23bf9e 100644 --- a/src/engine/renderer/glsl_source/computeLight_fp.glsl +++ b/src/engine/renderer/glsl_source/computeLight_fp.glsl @@ -70,7 +70,7 @@ vec4 EnvironmentalSpecularFactor( vec3 viewDir, vec3 normal ) #endif #endif -#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || (defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1) +#if defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || defined(r_realtimeLighting) void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightColor, vec4 diffuseColor, vec4 materialColor, inout vec4 color ) @@ -134,7 +134,7 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol #endif // r_specularMapping #endif // !USE_PHYSICAL_MAPPING } -#endif // defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) || (defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1) +#endif // defined(USE_DELUXE_MAPPING) || defined(USE_GRID_DELUXE_MAPPING) defined(r_realtimeLighting) #if !defined(USE_DELUXE_MAPPING) && !defined(USE_GRID_DELUXE_MAPPING) void computeLight( in vec3 lightColor, vec4 diffuseColor, inout vec4 color ) { @@ -142,7 +142,7 @@ void computeDeluxeLight( vec3 lightDir, vec3 normal, vec3 viewDir, vec3 lightCol } #endif // !defined(USE_DELUXE_MAPPING) && !defined(USE_GRID_DELUXE_MAPPING) -#if defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 +#if defined(r_realtimeLighting) struct Light { vec3 center; @@ -153,7 +153,11 @@ struct Light { float angle; }; +#if defined( HAVE_ARB_shading_language_420pack ) +layout(std140, binding = BIND_LIGHTS) uniform u_Lights { +#else layout(std140) uniform u_Lights { +#endif Light lights[MAX_REF_LIGHTS]; }; @@ -223,6 +227,10 @@ void computeDynamicLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 return; } + #if defined(r_showLightTiles) + uint totalLights = 0u; + #endif + vec2 tile = floor( gl_FragCoord.xy * ( 1.0 / float( TILE_SIZE ) ) ) + 0.5; for( uint layer = 0u; layer < uint( NUM_LIGHT_LAYERS ); layer++ ) { @@ -243,14 +251,17 @@ void computeDynamicLights( vec3 P, vec3 normal, vec3 viewDir, vec4 diffuse, vec4 computeDynamicLight( idx, P, normal, viewDir, diffuse, material, color ); lightCount++; } + #if defined(r_showLightTiles) + totalLights += lightCount; + #endif } #if defined(r_showLightTiles) - if ( lightCount > 0 ) { - color = vec4( float( lightCount ) / u_numLights, float( lightCount ) / u_numLights, - float( lightCount ) / u_numLights, 1.0 ); + if ( totalLights > 0 ) { + color = vec4( float( totalLights ) / u_numLights, float( totalLights ) / u_numLights, + float( totalLights ) / u_numLights, 1.0 ); } #endif } -#endif // defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 +#endif // defined(r_realtimeLighting) diff --git a/src/engine/renderer/glsl_source/cull_cp.glsl b/src/engine/renderer/glsl_source/cull_cp.glsl index 201cdc284..7333e3ffd 100644 --- a/src/engine/renderer/glsl_source/cull_cp.glsl +++ b/src/engine/renderer/glsl_source/cull_cp.glsl @@ -70,7 +70,7 @@ layout(std430, binding = BIND_PORTAL_SURFACES) restrict buffer portalSurfacesSSB uniform uint u_Frame; uniform uint u_ViewID; -uniform uint u_TotalDrawSurfs; +uniform uint u_SurfaceDescriptorsCount; uniform uint u_SurfaceCommandsOffset; uniform vec4 u_Frustum[6]; // xyz - normal, w - distance uniform bool u_UseFrustumCulling; @@ -198,7 +198,7 @@ void main() { } // Regular surfaces - if( globalInvocationID >= u_TotalDrawSurfs ) { + if( globalInvocationID >= u_SurfaceDescriptorsCount ) { return; } SurfaceDescriptor surface = surfaces[globalInvocationID]; diff --git a/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl b/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl deleted file mode 100644 index 9f29c1005..000000000 --- a/src/engine/renderer/glsl_source/debugShadowMap_fp.glsl +++ /dev/null @@ -1,72 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* debugShadowMap_fp.glsl */ - -/* swizzle one- and two-component textures to RG */ -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -uniform sampler2D u_ShadowMap; - -IN(smooth) vec2 var_TexCoord; - -DECLARE_OUTPUT(vec4) - -void main() -{ -#if defined(ESM) - - float shadowMoments = texture2D(u_ShadowMap, var_TexCoord).SWIZ1; - - float shadowDistance = shadowMoments; - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); - -#elif defined(VSM) - vec2 shadowMoments = texture2D(u_ShadowMap, var_TexCoord).SWIZ2; - - float shadowDistance = shadowMoments.r; - float shadowDistanceSquared = shadowMoments.g; - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); - -#elif defined(EVSM) - - vec4 shadowMoments = texture2D(u_ShadowMap, var_TexCoord); - -#if defined(r_EVSMPostProcess) - float shadowDistance = shadowMoments.r; -#else - float shadowDistance = log(shadowMoments.b); -#endif - - outputColor = vec4(shadowDistance, 0.0, 0.0, 1.0); -#else - discard; -#endif -} diff --git a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl b/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl deleted file mode 100644 index 211ac3bc5..000000000 --- a/src/engine/renderer/glsl_source/debugShadowMap_vp.glsl +++ /dev/null @@ -1,38 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* debugShadowMap_vp.glsl */ - -IN vec3 attr_Position; -IN vec2 attr_TexCoord0; - -uniform mat4 u_ModelViewProjectionMatrix; - -OUT(smooth) vec2 var_TexCoord; - -void main() -{ - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); - - var_TexCoord = attr_TexCoord0.st; -} diff --git a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl b/src/engine/renderer/glsl_source/forwardLighting_fp.glsl deleted file mode 100644 index 1021815f2..000000000 --- a/src/engine/renderer/glsl_source/forwardLighting_fp.glsl +++ /dev/null @@ -1,1046 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2007-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* forwardLighting_fp.glsl */ - -// computeSpecularity is the only thing used from this file -#insert computeLight_fp - -#insert reliefMapping_fp - -/* swizzle one- and two-component textures to RG */ -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -uniform sampler2D u_DiffuseMap; -uniform sampler2D u_MaterialMap; -uniform sampler2D u_AttenuationMapXY; -uniform sampler2D u_AttenuationMapZ; - -#if defined(LIGHT_DIRECTIONAL) -uniform sampler2D u_ShadowMap0; -uniform sampler2D u_ShadowMap1; -uniform sampler2D u_ShadowMap2; -uniform sampler2D u_ShadowMap3; -uniform sampler2D u_ShadowMap4; -uniform sampler2D u_ShadowClipMap0; -uniform sampler2D u_ShadowClipMap1; -uniform sampler2D u_ShadowClipMap2; -uniform sampler2D u_ShadowClipMap3; -uniform sampler2D u_ShadowClipMap4; -#elif defined(LIGHT_PROJ) -uniform sampler2D u_ShadowMap0; -uniform sampler2D u_ShadowClipMap0; -#else -uniform samplerCube u_ShadowMap; -uniform samplerCube u_ShadowClipMap; -#endif - -uniform sampler2D u_RandomMap; // random normals - -uniform vec3 u_ViewOrigin; - -#if defined(LIGHT_DIRECTIONAL) -uniform vec3 u_LightDir; -#else -uniform vec3 u_LightOrigin; -#endif -uniform vec3 u_LightColor; -uniform float u_LightRadius; -uniform float u_LightScale; -uniform float u_AlphaThreshold; - -uniform mat4 u_ShadowMatrix[MAX_SHADOWMAPS]; -uniform vec4 u_ShadowParallelSplitDistances; -uniform float u_ShadowTexelSize; -uniform float u_ShadowBlur; - -uniform mat4 u_ViewMatrix; - -IN(smooth) vec3 var_Position; -IN(smooth) vec2 var_TexCoords; -IN(smooth) vec4 var_TexAttenuation; -IN(smooth) vec4 var_Tangent; -IN(smooth) vec4 var_Binormal; -IN(smooth) vec4 var_Normal; -IN(smooth) vec4 var_Color; - -DECLARE_OUTPUT(vec4) - -/* -================ -MakeNormalVectors - -Given a normalized forward vector, create two -other perpendicular vectors -================ -*/ -void MakeNormalVectors(const vec3 forward, inout vec3 right, inout vec3 up) -{ - // this rotate and negate guarantees a vector - // not colinear with the original - right.y = -forward.x; - right.z = forward.y; - right.x = forward.z; - - float d = dot(right, forward); - right += forward * -d; - normalize(right); - up = cross(right, forward); // GLSL cross product is the same as in Q3A -} - -float Rand(vec2 co) -{ - return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); -} - -float Noise(vec2 co) -{ - return Rand(floor(co * 128.0)); -} - -vec3 RandomVec3(vec2 uv) -{ - vec3 dir; - -#if 1 - float r = Rand(uv); - float angle = 2.0 * M_PI * r;// / 360.0; - - dir = normalize(vec3(cos(angle), sin(angle), r)); -#else - // dir = texture2D(u_NoiseMap, gl_FragCoord.st / r_FBufSize).rgb; - dir = normalize(2.0 * (texture2D(u_RandomMap, uv).xyz - 0.5)); -#endif - - return dir; -} - - -/* -source: http://en.wikipedia.org/wiki/Chebyshev%27s_inequality - -X = distribution -mu = mean -sigma = standard deviation - -=> then for any real number k > 0: - -Pr(X -mu >= k * sigma) <= 1 / ( 1 + k^2) -*/ - -#if defined(VSM) || defined(EVSM) -float linstep(float low, float high, float v) -{ - return clamp((v - low)/(high - low), 0.0, 1.0); -} - -float ChebyshevUpperBound(vec2 shadowMoments, float vertexDistance, float minVariance) -{ - float shadowDistance = shadowMoments.x; - float shadowDistanceSquared = shadowMoments.y; - - // compute variance - float E_x2 = shadowDistanceSquared; - float Ex_2 = shadowDistance * shadowDistance; - - float variance = max(E_x2 - Ex_2, max(minVariance, VSM_EPSILON)); - // float variance = smoothstep(minVariance, 1.0, max(E_x2 - Ex_2, 0.0)); - - // compute probabilistic upper bound - float d = vertexDistance - shadowDistance; - float pMax = variance / (variance + (d * d)); - -#if defined(r_lightBleedReduction) - pMax = linstep(r_lightBleedReduction, 1.0, pMax); -#endif - - // one-tailed Chebyshev with k > 0 - return (vertexDistance <= shadowDistance ? 1.0 : pMax); -} -#endif - - -#if defined(EVSM) -vec2 WarpDepth(float depth) -{ - // rescale depth into [-1, 1] - depth = 2.0 * depth - 1.0; - float pos = exp( r_EVSMExponents.x * depth); - float neg = -exp(-r_EVSMExponents.y * depth); - - return vec2(pos, neg); -} - -vec4 ShadowDepthToEVSM(float depth) -{ - vec2 warpedDepth = WarpDepth(depth); - return vec4(warpedDepth.x, warpedDepth.x * warpedDepth.x, warpedDepth.y, warpedDepth.y * warpedDepth.y); -} -#endif // #if defined(EVSM) - -vec4 FixShadowMoments( vec4 moments ) -{ -#if !defined(EVSM) || defined(r_EVSMPostProcess) - return vec4( moments.SWIZ2, moments.SWIZ2 ); -#else - return moments; -#endif -} - -#if defined(LIGHT_DIRECTIONAL) - -void FetchShadowMoments(vec3 Pworld, out vec4 shadowVert, - out vec4 shadowMoments, out vec4 shadowClipMoments) -{ - // transform to camera space - vec4 Pcam = u_ViewMatrix * vec4(Pworld.xyz, 1.0); - float vertexDistanceToCamera = -Pcam.z; - -#if defined(r_parallelShadowSplits_1) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_2) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_3) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[3] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap3, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap3, shadowVert.xyw); - } -#elif defined(r_parallelShadowSplits_4) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - shadowVert = u_ShadowMatrix[1] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap1, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap1, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - shadowVert = u_ShadowMatrix[2] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap2, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap2, shadowVert.xyw); - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.w) - { - shadowVert = u_ShadowMatrix[3] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap3, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap3, shadowVert.xyw); - } - else - { - shadowVert = u_ShadowMatrix[4] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap4, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap4, shadowVert.xyw); - } -#else - { - shadowVert = u_ShadowMatrix[0] * vec4(Pworld.xyz, 1.0); - shadowMoments = texture2DProj(u_ShadowMap0, shadowVert.xyw); - shadowClipMoments = texture2DProj(u_ShadowClipMap0, shadowVert.xyw); - } -#endif - - shadowMoments = FixShadowMoments(shadowMoments); - shadowClipMoments = FixShadowMoments(shadowClipMoments); - -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(shadowMoments.x); - shadowClipMoments = ShadowDepthToEVSM(shadowClipMoments.x); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec3 Pworld, float filterWidth, float samples, out vec4 clipMoments) -{ - vec3 forward, right, up; - - // filterWidth *= u_LightRadius; - - forward = normalize(-u_LightDir); - MakeNormalVectors(forward, right, up); - - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = vec4(0.0, 0.0, 0.0, 0.0); - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 shadowVert; - vec4 shadowMoments; - vec4 shadowClipMoments; - - FetchShadowMoments(Pworld + right * i + up * j, shadowVert, shadowMoments, shadowClipMoments); - moments += shadowMoments; - clipMoments += shadowClipMoments; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand.z = 0; - // rand = normalize(rand) * filterWidth; - - vec4 shadowVert; - vec4 shadowMoments; - vec4 shadowClipMoments; - - FetchShadowMoments(Pworld + right * rand.x + up * rand.y, shadowVert, shadowMoments, shadowClipMoments); - moments += shadowMoments; - clipMoments += shadowClipMoments; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - - - -#elif defined(LIGHT_PROJ) - -void FetchShadowMoments(vec2 st, out vec4 shadowMoments, out vec4 shadowClipMoments) -{ -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(texture2D(u_ShadowMap0, st).SWIZ1); - shadowClipMoments = ShadowDepthToEVSM(texture2D(u_ShadowClipMap0, st).SWIZ1); -#else - shadowMoments = FixShadowMoments(texture2D(u_ShadowMap0, st)); - shadowClipMoments = FixShadowMoments(texture2D(u_ShadowClipMap0, st)); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec4 shadowVert, float filterWidth, float samples, out vec4 clipMoments) -{ - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = moments; - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 sm, scm; - FetchShadowMoments(shadowVert.xy / shadowVert.w + vec2(i, j), sm, scm); - moments += sm; - clipMoments += scm; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand = vec3(0.0, 0.0, 1.0); - // rand.z = 0; - // rand = normalize(rand);// * filterWidth; - - vec4 sm, scm; - FetchShadowMoments(shadowVert.xy / shadowVert.w + rand.xy, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - -#else - -void FetchShadowMoments(vec3 incidentRay, out vec4 shadowMoments, out vec4 shadowClipMoments) -{ -#if defined(EVSM) && defined(r_EVSMPostProcess) - shadowMoments = ShadowDepthToEVSM(textureCube(u_ShadowMap, incidentRay).SWIZ1); - shadowClipMoments = ShadowDepthToEVSM(textureCube(u_ShadowClipMap, incidentRay).SWIZ1); -#else - shadowMoments = FixShadowMoments(textureCube(u_ShadowMap, incidentRay)); - shadowClipMoments = FixShadowMoments(textureCube(u_ShadowClipMap, incidentRay)); -#endif -} - -#if defined(r_PCFSamples) -vec4 PCF(vec4 incidentRay, float filterWidth, float samples, out vec4 clipMoments) -{ - vec3 forward, right, up; - - forward = normalize(incidentRay.xyz); - MakeNormalVectors(forward, right, up); - - vec4 moments = vec4(0.0, 0.0, 0.0, 0.0); - clipMoments = moments; - -#if 0 - // compute step size for iterating through the kernel - float stepSize = 2.0 * filterWidth / samples; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - vec4 sm, scm; - FetchShadowMoments(incidentRay.xyz + right * i + up * j, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#else - for(int i = 0; i < samples; i++) - { - for(int j = 0; j < samples; j++) - { - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize + vec2(i, j)) * filterWidth; - // rand.z = 0; - // rand = normalize(rand) * filterWidth; - - vec4 sm, scm; - FetchShadowMoments(incidentRay.xyz + right * rand.x + up * rand.y, sm, scm); - moments += sm; - clipMoments += scm; - } - } -#endif - - // return average of the samples - float factor = (1.0 / (samples * samples)); - moments *= factor; - clipMoments *= factor; - return moments; -} -#endif // #if defined(r_PCFSamples) - -#endif - - -#if 0//defined(PCSS) - - -#if defined(LIGHT_DIRECTIONAL) -// TODO SumBlocker for sun shadowing - -#elif defined(LIGHT_PROJ) -float SumBlocker(vec4 shadowVert, float vertexDistance, float filterWidth, float samples) -{ - float stepSize = 2.0 * filterWidth / samples; - - float blockerCount = 0.0; - float blockerSum = 0.0; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - float shadowDistance = texture2DProj(u_ShadowMap0, vec3(shadowVert.xy + vec2(i, j), shadowVert.w)).SWIZ1; - // float shadowDistance = texture2D(u_ShadowMap, shadowVert.xy / shadowVert.w + vec2(i, j)).x; - - // FIXME VSM_CLAMP - - if(vertexDistance > shadowDistance) - { - blockerCount += 1.0; - blockerSum += shadowDistance; - } - } - } - - float result; - if(blockerCount > 0.0) - result = blockerSum / blockerCount; - else - result = 0.0; - - return result; -} -#else -// case LIGHT_OMNI -float SumBlocker(vec4 incidentRay, float vertexDistance, float filterWidth, float samples) -{ - vec3 forward, right, up; - - forward = normalize(incidentRay.xyz); - MakeNormalVectors(forward, right, up); - - float stepSize = 2.0 * filterWidth / samples; - - float blockerCount = 0.0; - float blockerSum = 0.0; - - for(float i = -filterWidth; i < filterWidth; i += stepSize) - { - for(float j = -filterWidth; j < filterWidth; j += stepSize) - { - float shadowDistance = textureCube(u_ShadowMap, incidentRay.xyz + right * i + up * j).SWIZ1; - - if(vertexDistance > shadowDistance) - { - blockerCount += 1.0; - blockerSum += shadowDistance; - } - } - } - - float result; - if(blockerCount > 0.0) - result = blockerSum / blockerCount; - else - result = -1.0; - - return result; -} -#endif - -float EstimatePenumbra(float vertexDistance, float blocker) -{ - float penumbra; - - if(blocker == 0.0) - penumbra = 0.0; - else - penumbra = ((vertexDistance - blocker) * u_LightRadius) / blocker; - - return penumbra; -} - -vec4 PCSS( vec4 incidentRay, float vertexDistance, float PCFSamples ) -{ - // step 1: find blocker estimate - const float blockerSamples = 6.0; - float blockerSearchWidth = u_ShadowTexelSize * u_LightRadius / vertexDistance; - float blocker = SumBlocker(incidentRay, vertexDistance, blockerSearchWidth, blockerSamples); - - // step 2: estimate penumbra using parallel planes approximation - float penumbra = EstimatePenumbra(vertexDistance, blocker); - - // step 3: compute percentage-closer filter - vec4 shadowMoments; - - if(penumbra > 0.0 && blocker > -1.0) - { - // float maxpen = PCFsamples * (1.0 / u_ShadowTexelSize); - // if(penumbra > maxpen) - // penumbra = maxpen; - // - - // shadowMoments = PCF(incidentRay, penumbra, PCFsamples); - vec4 clipMoments; - shadowMoments = PCF(incidentRay, u_ShadowTexelSize * u_ShadowBlur * penumbra, PCFsamples, clipMoments); - } - else - { - shadowMoments = FetchShadowMoments(incidentRay); - } -} -#endif - -float ShadowTest( float vertexDistance, vec4 shadowMoments, vec4 shadowClipMoments ) -{ - float shadow = 1.0; -#if defined( ESM ) - float shadowDistance = shadowMoments.x; - - // standard shadow mapping - if( vertexDistance <= 1.0 ) - shadow = step( vertexDistance, shadowDistance ); - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - shadow *= step( vertexDistance, shadowClipMoments.x ); - } - - //shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0; - // exponential shadow mapping - // shadow = clamp(exp(r_overDarkeningFactor * (shadowDistance - log(vertexDistance))), 0.0, 1.0); - // shadow = clamp(exp(r_overDarkeningFactor * shadowDistance) * exp(-r_overDarkeningFactor * vertexDistance), 0.0, 1.0); - // shadow = smoothstep(0.0, 1.0, shadow); - -#if defined(r_debugShadowMaps) && defined( HAVE_EXT_gpu_shader4 ) - outputColor.r = (r_debugShadowMaps & 1) != 0 ? shadowDistance : 0.0; - outputColor.g = (r_debugShadowMaps & 2) != 0 ? -(shadowDistance - vertexDistance) : 0.0; - outputColor.b = (r_debugShadowMaps & 4) != 0 ? shadow : 0.0; - outputColor.a = 1.0; -#endif - -#elif defined( VSM ) -#if defined(VSM_CLAMP) - // convert to [-1, 1] vector space - shadowMoments = 2.0 * (shadowMoments - 0.5); -#endif - - shadow = ChebyshevUpperBound(shadowMoments.xy, vertexDistance, VSM_EPSILON); - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - shadow *= ChebyshevUpperBound(shadowClipMoments.xy, vertexDistance, VSM_EPSILON); - } -#elif defined( EVSM ) - vec2 warpedVertexDistances = WarpDepth(vertexDistance); - - // derivative of warping at depth - vec2 depthScale = VSM_EPSILON * r_EVSMExponents * warpedVertexDistances; - vec2 minVariance = depthScale * depthScale; - - float posContrib = ChebyshevUpperBound(shadowMoments.xy, warpedVertexDistances.x, minVariance.x); - float negContrib = ChebyshevUpperBound(shadowMoments.zw, warpedVertexDistances.y, minVariance.y); - - shadow = min(posContrib, negContrib); - -#if defined(r_debugShadowMaps) && defined( HAVE_EXT_gpu_shader4 ) - outputColor.r = (r_debugShadowMaps & 1) != 0 ? posContrib : 0.0; - outputColor.g = (r_debugShadowMaps & 2) != 0 ? negContrib : 0.0; - outputColor.b = (r_debugShadowMaps & 4) != 0 ? shadow : 0.0; - outputColor.a = 1.0; -#endif - - if( u_LightScale < 0.0 ) { - shadow = 1.0 - shadow; - posContrib = ChebyshevUpperBound(shadowClipMoments.xy, warpedVertexDistances.x, minVariance.x); - negContrib = ChebyshevUpperBound(shadowClipMoments.zw, warpedVertexDistances.y, minVariance.y); - - shadow *= 1.0 - min(posContrib, negContrib); - } -#endif - return shadow; -} - -/* -Some explanations by Marco Salvi about exponential shadow mapping: - -Now you are filtering exponential values which rapidly go out of range, -to avoid this issue you can filter the logarithm of these values (and the go back to exp space) - -For example if you averaging two exponential value such as exp(A) and exp(B) you have: - -a*exp(A) + b*exp(B) (a and b are some filter weights) - -but you can rewrite the same expression as: - -exp(A) * (a + b*exp(B-A)) , - -exp(A) * exp( log (a + b*exp(B-A)))), - -and: - -exp(A + log(a + b*exp(B-A)) - -Now your sum of exponential is written as a single exponential, if you take the logarithm of it you can then just work on its argument: - -A + log(a + b*exp(B-A)) - -Basically you end up filtering the argument of your exponential functions, which are just linear depth values, -so you enjoy the same range you have with less exotic techniques. -Just don't forget to go back to exp space when you use the final filtered value. - - -Though hardware texture filtering is not mathematically correct in log space it just causes a some overdarkening, nothing major. - -If you have your shadow map filtered in log space occlusion is just computed like this (let assume we use bilinear filtering): - -float occluder = tex2D( esm_sampler, esm_uv ); -float occlusion = exp( occluder - receiver ); - -while with filtering in exp space you have: - -float exp_occluder = tex2D( esm_sampler, esm_uv ); -float occlusion = exp_occluder / exp( receiver ); - -EDIT: if more complex filters are used (trilinear, aniso, with mip maps) you need to generate mip maps using log filteirng as well. -*/ - -/* -float log_conv(float x0, float X, float y0, float Y) -{ - return (X + log(x0 + (y0 * exp(Y - X)))); -} -*/ - -void main() -{ -#if 0 - // create random noise vector - vec3 rand = RandomVec3(gl_FragCoord.st / r_FBufSize); - - outputColor = vec4(rand * 0.5 + 0.5, 1.0); - return; -#endif - - - float shadow = 1.0; -#if defined(USE_SHADOWING) - const float SHADOW_BIAS = 0.010; -#if defined(LIGHT_DIRECTIONAL) - - - vec4 shadowVert; - vec4 shadowMoments, shadowClipMoments; - FetchShadowMoments(var_Position.xyz, shadowVert, shadowMoments, shadowClipMoments); - - float vertexDistance = shadowVert.z - SHADOW_BIAS; - // FIXME -#if 0 // defined(r_PCFSamples) - shadowMoments = PCF(var_Position.xyz, u_ShadowTexelSize * u_ShadowBlur, r_PCFSamples); -#endif - -#if 0 - outputColor = vec4(u_ShadowTexelSize * u_ShadowBlur * u_LightRadius, 0.0, 0.0, 1.0); - return; -#endif - -#if defined(r_showParallelShadowSplits) - // transform to camera space - vec4 Pcam = u_ViewMatrix * vec4(var_Position.xyz, 1.0); - float vertexDistanceToCamera = -Pcam.z; - -#if defined(r_parallelShadowSplits_1) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_2) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_3) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - outputColor = vec4(0.0, 0.0, 1.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#elif defined(r_parallelShadowSplits_4) - if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.x) - { - outputColor = vec4(1.0, 0.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.y) - { - outputColor = vec4(0.0, 1.0, 0.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.z) - { - outputColor = vec4(0.0, 0.0, 1.0, 1.0); - return; - } - else if(vertexDistanceToCamera < u_ShadowParallelSplitDistances.w) - { - outputColor = vec4(1.0, 1.0, 0.0, 1.0); - return; - } - else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#else - { - outputColor = vec4(1.0, 0.0, 1.0, 1.0); - return; - } -#endif -#endif // #if defined(r_showParallelShadowSplits) - -#elif defined(LIGHT_PROJ) - - vec4 shadowVert = u_ShadowMatrix[0] * vec4(var_Position.xyz, 1.0); - - // compute incident ray - vec3 incidentRay = var_Position.xyz - u_LightOrigin; - - float vertexDistance = length(incidentRay) / u_LightRadius - SHADOW_BIAS; - if( vertexDistance >= 1.0f ) { - discard; - return; - } - -#if defined(r_PCFSamples) -#if 0//defined( PCSS ) - vec4 shadowMoments = PCSS(vertexDistance, r_PCFSamples); -#else - vec4 shadowClipMoments; - vec4 shadowMoments = PCF(shadowVert, u_ShadowTexelSize * u_ShadowBlur, r_PCFSamples, shadowClipMoments); -#endif -#else - - // no filter - vec4 shadowMoments, shadowClipMoments; - - FetchShadowMoments(shadowVert.xy / shadowVert.w, shadowMoments, shadowClipMoments); - -#endif - -#else - // compute incident ray - vec3 incidentRay = var_Position.xyz - u_LightOrigin; - float incidentRayLen = length(incidentRay); - float vertexDistance = incidentRayLen / u_LightRadius - SHADOW_BIAS; - -#if 0 - outputColor = vec4(u_ShadowTexelSize * u_ShadowBlur * incidentRayLen, 0.0, 0.0, 1.0); - return; -#endif - -#if defined(r_PCFSamples) -#if 0//defined(PCSS) - vec4 shadowMoments = PCSS(vec4(incidentRay, 0.0), r_PCFSamples); -#else - vec4 shadowClipMoments; - vec4 shadowMoments = PCF(vec4(incidentRay, 0.0), u_ShadowTexelSize * u_ShadowBlur * incidentRayLen, r_PCFSamples, shadowClipMoments); -#endif -#else - // no extra filtering, single tap - vec4 shadowMoments, shadowClipMoments; - FetchShadowMoments(incidentRay, shadowMoments, shadowClipMoments); -#endif -#endif - shadow = ShadowTest(vertexDistance, shadowMoments, shadowClipMoments); - -#if defined(r_debugShadowMaps) - return; -#endif - - if(shadow <= 0.0) - { - discard; - return; - } - -#endif // USE_SHADOWING - - // compute light direction in world space -#if defined(LIGHT_DIRECTIONAL) - vec3 lightDir = u_LightDir; -#else - vec3 lightDir = normalize(u_LightOrigin - var_Position); -#endif - - vec2 texCoords = var_TexCoords; - - mat3 tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz); - - // compute view direction in world space - vec3 viewDir = normalize(u_ViewOrigin - var_Position.xyz); - -#if defined(USE_RELIEF_MAPPING) - // compute texcoords offset from heightmap - #if defined(USE_HEIGHTMAP_IN_NORMALMAP) - vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_NormalMap); - #else - vec2 texOffset = ReliefTexOffset(texCoords, viewDir, tangentToWorldMatrix, u_HeightMap); - #endif - - texCoords += texOffset; -#endif // USE_RELIEF_MAPPING - - // compute half angle in world space - vec3 H = normalize(lightDir + viewDir); - - // compute normal in world space from normal map - vec3 normal = NormalInWorldSpace(texCoords, tangentToWorldMatrix, u_NormalMap); - - // compute the light term - float NL = clamp(dot(normal, lightDir), 0.0, 1.0); - - // compute the diffuse term - vec4 diffuse = texture2D(u_DiffuseMap, texCoords); - if( abs(diffuse.a + u_AlphaThreshold) <= 1.0 ) - { - discard; - return; - } - diffuse.rgb *= u_LightColor * NL; - -#if !defined(USE_PHYSICAL_MAPPING) -#if defined(r_specularMapping) - // compute the specular term - vec4 materialColor = texture2D(u_MaterialMap, texCoords); - float NdotH = clamp(dot(normal, H), 0.0, 1.0); - vec3 specular = computeSpecularity(u_LightColor, materialColor, NdotH); -#endif // r_specularMapping -#endif // !USE_PHYSICAL_MAPPING - - // compute light attenuation -#if defined(LIGHT_PROJ) - vec3 attenuationXY = texture2DProj(u_AttenuationMapXY, var_TexAttenuation.xyw).rgb; - vec3 attenuationZ = texture2D(u_AttenuationMapZ, vec2(var_TexAttenuation.z + 0.5, 0.0)).rgb; // FIXME - -#elif defined(LIGHT_DIRECTIONAL) - vec3 attenuationXY = vec3(1.0); - vec3 attenuationZ = vec3(1.0); - -#else - vec3 attenuationXY = texture2D(u_AttenuationMapXY, var_TexAttenuation.xy).rgb; - vec3 attenuationZ = texture2D(u_AttenuationMapZ, vec2(var_TexAttenuation.z, 0)).rgb; -#endif - - // compute final color - vec4 color = diffuse; - -#if !defined(USE_PHYSICAL_MAPPING) -#if defined(r_specularMapping) - color.rgb += specular; -#endif // r_specularMapping -#endif // !USE_PHYSICAL_MAPPING - -#if !defined(LIGHT_DIRECTIONAL) - color.rgb *= attenuationXY; - color.rgb *= attenuationZ; -#endif - color.rgb *= abs(u_LightScale); - color.rgb *= shadow; - - color.rgb *= var_Color.rgb; - - if( u_LightScale < 0.0 ) { - color.rgb = vec3( clamp(dot(color.rgb, vec3( 0.3333 ) ), 0.3, 0.7 ) ); - } - - outputColor = color; - -#if 0 -#if defined(USE_RELIEF_MAPPING) - outputColor = vec4(vec3(1.0, 0.0, 0.0), diffuse.a); -#else - outputColor = vec4(vec3(0.0, 0.0, 1.0), diffuse.a); -#endif -#endif - -#if 0 -#if defined(USE_VERTEX_SKINNING) - outputColor = vec4(vec3(1.0, 0.0, 0.0), diffuse.a); -#elif defined(USE_VERTEX_ANIMATION) - outputColor = vec4(vec3(0.0, 0.0, 1.0), diffuse.a); -#else - outputColor = vec4(vec3(0.0, 1.0, 0.0), diffuse.a); -#endif -#endif -} diff --git a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl b/src/engine/renderer/glsl_source/forwardLighting_vp.glsl deleted file mode 100644 index dfaaf9be8..000000000 --- a/src/engine/renderer/glsl_source/forwardLighting_vp.glsl +++ /dev/null @@ -1,92 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* forwardLighting_vp.glsl */ - -#insert common -#insert vertexSimple_vp -#insert vertexSkinning_vp -#insert vertexAnimation_vp - -uniform mat3x2 u_TextureMatrix; -uniform mat4 u_LightAttenuationMatrix; -uniform mat4 u_ModelMatrix; -uniform mat4 u_ModelViewProjectionMatrix; - -uniform colorModulatePack u_ColorModulateColorGen; -uniform colorPack u_Color; - -uniform float u_Time; - -OUT(smooth) vec3 var_Position; -OUT(smooth) vec2 var_TexCoords; - -OUT(smooth) vec4 var_TexAttenuation; - -OUT(smooth) vec4 var_Tangent; -OUT(smooth) vec4 var_Binormal; -OUT(smooth) vec4 var_Normal; - -OUT(smooth) vec4 var_Color; - -void DeformVertex( inout vec4 pos, - inout vec3 normal, - inout vec2 st, - inout vec4 color, - in float time); - -void main() -{ - vec4 position; - localBasis LB; - vec2 texCoord, lmCoord; - vec4 color; - - VertexFetch( position, LB, color, texCoord, lmCoord); - - // assign color - ColorModulateColor( u_ColorModulateColorGen, u_Color, color ); - - DeformVertex( position, - LB.normal, - texCoord.st, - color, - u_Time); - - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * position; - - // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; - - var_Tangent.xyz = mat3(u_ModelMatrix) * LB.tangent; - var_Binormal.xyz = mat3(u_ModelMatrix) * LB.binormal; - var_Normal.xyz = mat3(u_ModelMatrix) * LB.normal; - - // calc light xy,z attenuation in light space - var_TexAttenuation = u_LightAttenuationMatrix * position; - - // transform diffusemap texcoords - var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; - - var_Color = color; -} diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index 1652e12b3..fee293836 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -119,7 +119,7 @@ void main() #if defined(r_specularMapping) || defined(r_physicalMapping) // Compute the material term. vec4 material = texture2D(u_MaterialMap, texCoords); - #elif ( defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 )\ + #elif defined(r_realtimeLighting) \ || defined( USE_DELUXE_MAPPING ) || defined(USE_GRID_DELUXE_MAPPING ) // The computeDynamicLights function requires this variable to exist. vec4 material = vec4( 0.0, 0.0, 0.0, 1.0 ); @@ -200,7 +200,7 @@ void main() #endif // Blend dynamic lights. - #if defined(r_realtimeLighting) && r_realtimeLightingRenderer == 1 + #if defined(r_realtimeLighting) computeDynamicLights(var_Position, normal, viewDir, diffuse, material, color, u_LightTiles); #endif diff --git a/src/engine/renderer/glsl_source/lighttile_fp.glsl b/src/engine/renderer/glsl_source/lighttile_fp.glsl index 331d46ca4..559199a29 100644 --- a/src/engine/renderer/glsl_source/lighttile_fp.glsl +++ b/src/engine/renderer/glsl_source/lighttile_fp.glsl @@ -45,7 +45,11 @@ struct Light { float angle; }; +#if defined( HAVE_ARB_shading_language_420pack ) +layout(std140, binding = BIND_LIGHTS) uniform u_Lights { +#else layout(std140) uniform u_Lights { +#endif Light lights[MAX_REF_LIGHTS]; }; diff --git a/src/engine/renderer/glsl_source/shadowFill_fp.glsl b/src/engine/renderer/glsl_source/shadowFill_fp.glsl deleted file mode 100644 index 2b4160f2f..000000000 --- a/src/engine/renderer/glsl_source/shadowFill_fp.glsl +++ /dev/null @@ -1,125 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* shadowFill_fp.glsl */ - -uniform sampler2D u_ColorMap; -uniform float u_AlphaThreshold; -uniform vec3 u_LightOrigin; -uniform float u_LightRadius; - -IN(smooth) vec3 var_Position; -IN(smooth) vec2 var_TexCoords; -IN(smooth) vec4 var_Color; - -DECLARE_OUTPUT(vec4) - -#if defined(HAVE_ARB_texture_rg) -# define SWIZ1 r -# define SWIZ2 rg -#else -# define SWIZ1 a -# define SWIZ2 ar -#endif - -#if defined(EVSM) - -vec2 WarpDepth(float depth) -{ - // rescale depth into [-1, 1] - depth = 2.0 * depth - 1.0; - float pos = exp( r_EVSMExponents.x * depth); - float neg = -exp(-r_EVSMExponents.y * depth); - - return vec2(pos, neg); -} - -vec4 ShadowDepthToEVSM(float depth) -{ - vec2 warpedDepth = WarpDepth(depth); - return vec4(warpedDepth.x, warpedDepth.x * warpedDepth.x, warpedDepth.y, warpedDepth.y * warpedDepth.y); -} - -#endif // #if defined(EVSM) - -void main() -{ - vec4 color = texture2D(u_ColorMap, var_TexCoords); - - if( abs(color.a + u_AlphaThreshold) <= 1.0 ) - { - discard; - return; - } - - -#if defined(VSM) - - float distance; - -#if defined(LIGHT_DIRECTIONAL) - distance = gl_FragCoord.z; -#else - distance = length(var_Position - u_LightOrigin) / u_LightRadius; -#endif - - float distanceSquared = distance * distance; - - // shadowmap can be float RGBA or luminance alpha so store distanceSquared into alpha - -#if defined(VSM_CLAMP) - // convert to [0,1] color space - outputColor.SWIZ2 = vec2(distance, distanceSquared) * 0.5 + 0.5; -#else - outputColor.SWIZ2 = vec2(distance, distanceSquared); -#endif - -#elif defined(EVSM) || defined(ESM) - - float distance; -#if defined(LIGHT_DIRECTIONAL) - { - distance = gl_FragCoord.z;// * r_shadowMapDepthScale; - //distance /= gl_FragCoord.w; - //distance = var_Position.z / var_Position.w; - //distance = var_Position.z; - } -#else - { - distance = (length(var_Position - u_LightOrigin) / u_LightRadius); // * r_shadowMapDepthScale; - } -#endif - -#if defined(EVSM) -#if !defined(r_EVSMPostProcess) - outputColor = ShadowDepthToEVSM(distance); -#else - outputColor.SWIZ1 = distance; -#endif -#else - outputColor.SWIZ1 = distance; -#endif // defined(EVSM) - -#else - outputColor = vec4(0.0, 0.0, 0.0, 0.0); -#endif -} diff --git a/src/engine/renderer/glsl_source/shadowFill_vp.glsl b/src/engine/renderer/glsl_source/shadowFill_vp.glsl deleted file mode 100644 index 9c082423d..000000000 --- a/src/engine/renderer/glsl_source/shadowFill_vp.glsl +++ /dev/null @@ -1,78 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2011 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/* shadowFill_vp.glsl */ - -#insert common -#insert vertexSimple_vp -#insert vertexSkinning_vp -#insert vertexAnimation_vp - -uniform colorPack u_Color; - -uniform mat3x2 u_TextureMatrix; -uniform mat4 u_ModelMatrix; -uniform mat4 u_ModelViewProjectionMatrix; - -uniform float u_Time; - -OUT(smooth) vec3 var_Position; -OUT(smooth) vec2 var_TexCoords; -OUT(smooth) vec4 var_Color; - -void DeformVertex( inout vec4 pos, - inout vec3 normal, - inout vec2 st, - inout vec4 color, - in float time); - -void main() -{ - vec4 position; - localBasis LB; - vec2 texCoord, lmCoord; - vec4 color; - - VertexFetch( position, LB, color, texCoord, lmCoord ); - - DeformVertex( position, - LB.normal, - texCoord, - color, - u_Time); - - // transform vertex position into homogenous clip-space - gl_Position = u_ModelViewProjectionMatrix * position; - // transform position into world space -#if defined(LIGHT_DIRECTIONAL) - var_Position = gl_Position.xyz / gl_Position.w; -#else - // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; -#endif - - // transform texcoords - var_TexCoords = (u_TextureMatrix * vec3(texCoord, 1.0)).st; - - // assign color - var_Color = UnpackColor( u_Color ); -} diff --git a/src/engine/renderer/shaders.cpp b/src/engine/renderer/shaders.cpp index 40f14d107..a2252be13 100644 --- a/src/engine/renderer/shaders.cpp +++ b/src/engine/renderer/shaders.cpp @@ -37,12 +37,8 @@ #include "vertexSimple_vp.glsl.h" #include "vertexSkinning_vp.glsl.h" -#include "debugShadowMap_vp.glsl.h" -#include "debugShadowMap_fp.glsl.h" #include "fogQuake3_vp.glsl.h" #include "fogQuake3_fp.glsl.h" -#include "forwardLighting_vp.glsl.h" -#include "forwardLighting_fp.glsl.h" #include "generic_vp.glsl.h" #include "generic_fp.glsl.h" #include "heatHaze_vp.glsl.h" @@ -57,8 +53,6 @@ #include "reflection_CB_fp.glsl.h" #include "screen_vp.glsl.h" #include "screen_fp.glsl.h" -#include "shadowFill_vp.glsl.h" -#include "shadowFill_fp.glsl.h" #include "skybox_vp.glsl.h" #include "skybox_fp.glsl.h" @@ -78,7 +72,7 @@ std::unordered_map shadermap({ { "depthReduction_cp.glsl", std::string( reinterpret_cast< const char* >( depthReduction_cp_glsl ), sizeof( depthReduction_cp_glsl ) ) }, { "processSurfaces_cp.glsl", std::string( reinterpret_cast< const char* >( processSurfaces_cp_glsl ), sizeof( processSurfaces_cp_glsl ) ) }, - // Screen-space shaders + // Screen-space shaders { "screenSpace_vp.glsl", std::string( reinterpret_cast< const char* >( screenSpace_vp_glsl ), sizeof( screenSpace_vp_glsl ) ) }, { "blur_fp.glsl", std::string( reinterpret_cast< const char* >( blur_fp_glsl ), sizeof( blur_fp_glsl ) ) }, { "cameraEffects_fp.glsl", std::string( reinterpret_cast< const char* >( cameraEffects_fp_glsl ), sizeof( cameraEffects_fp_glsl ) ) }, @@ -105,12 +99,8 @@ std::unordered_map shadermap({ { "vertexSkinning_vp.glsl", std::string( reinterpret_cast< const char* >( vertexSkinning_vp_glsl ), sizeof( vertexSkinning_vp_glsl ) ) }, // Regular shaders - { "debugShadowMap_vp.glsl", std::string( reinterpret_cast< const char* >( debugShadowMap_vp_glsl ), sizeof( debugShadowMap_vp_glsl ) ) }, - { "debugShadowMap_fp.glsl", std::string( reinterpret_cast< const char* >( debugShadowMap_fp_glsl ), sizeof( debugShadowMap_fp_glsl ) ) }, { "fogQuake3_vp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_vp_glsl ), sizeof( fogQuake3_vp_glsl ) ) }, { "fogQuake3_fp.glsl", std::string( reinterpret_cast< const char* >( fogQuake3_fp_glsl ), sizeof( fogQuake3_fp_glsl ) ) }, - { "forwardLighting_vp.glsl", std::string( reinterpret_cast< const char* >( forwardLighting_vp_glsl ), sizeof( forwardLighting_vp_glsl ) ) }, - { "forwardLighting_fp.glsl", std::string( reinterpret_cast< const char* >( forwardLighting_fp_glsl ), sizeof( forwardLighting_fp_glsl ) ) }, { "generic_vp.glsl", std::string( reinterpret_cast< const char* >( generic_vp_glsl ), sizeof( generic_vp_glsl ) ) }, { "generic_fp.glsl", std::string( reinterpret_cast< const char* >( generic_fp_glsl ), sizeof( generic_fp_glsl ) ) }, { "heatHaze_vp.glsl", std::string( reinterpret_cast< const char* >( heatHaze_vp_glsl ), sizeof( heatHaze_vp_glsl ) ) }, @@ -125,8 +115,6 @@ std::unordered_map shadermap({ { "reflection_CB_fp.glsl", std::string( reinterpret_cast< const char* >( reflection_CB_fp_glsl ), sizeof( reflection_CB_fp_glsl ) ) }, { "screen_vp.glsl", std::string( reinterpret_cast< const char* >( screen_vp_glsl ), sizeof( screen_vp_glsl ) ) }, { "screen_fp.glsl", std::string( reinterpret_cast< const char* >( screen_fp_glsl ), sizeof( screen_fp_glsl ) ) }, - { "shadowFill_vp.glsl", std::string( reinterpret_cast< const char* >( shadowFill_vp_glsl ), sizeof( shadowFill_vp_glsl ) ) }, - { "shadowFill_fp.glsl", std::string( reinterpret_cast< const char* >( shadowFill_fp_glsl ), sizeof( shadowFill_fp_glsl ) ) }, { "skybox_vp.glsl", std::string( reinterpret_cast< const char* >( skybox_vp_glsl ), sizeof( skybox_vp_glsl ) ) }, { "skybox_fp.glsl", std::string( reinterpret_cast< const char* >( skybox_fp_glsl ), sizeof( skybox_fp_glsl ) ) }, }); diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index bc2be2de6..617a233c3 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -540,7 +540,7 @@ qhandle_t RE_RegisterAnimation( const char *name ) return 0; } - if ( Str::IsPrefix( "MD5Version", buffer ) ) + if ( Str::IsPrefix( MD5_IDENTSTRING, buffer ) ) { loaded = R_LoadMD5Anim( anim, buffer.c_str(), name ); } @@ -610,7 +610,7 @@ static ListAnimationsCmd listAnimationsCmdRegistration; R_CullMD5 ============= */ -static void R_CullMD5( trRefEntity_t *ent ) +static cullResult_t R_CullMD5( trRefEntity_t *ent ) { int i; @@ -638,19 +638,16 @@ static void R_CullMD5( trRefEntity_t *ent ) { case cullResult_t::CULL_IN: tr.pc.c_box_cull_md5_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_md5_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_md5_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -674,9 +671,7 @@ void R_AddMD5Surfaces( trRefEntity_t *ent ) // cull the entire model if merged bounding box of both frames // is outside the view frustum - R_CullMD5( ent ); - - if ( ent->cull == cullResult_t::CULL_OUT ) + if ( R_CullMD5( ent ) == cullResult_t::CULL_OUT ) { return; } @@ -792,315 +787,6 @@ void R_AddMD5Surfaces( trRefEntity_t *ent ) } } -/* -================= -R_AddIQMInteractions -================= -*/ -void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - int i; - IQModel_t *model; - srfIQModel_t *surface; - shader_t *shader = nullptr; - bool personalModel; - byte cubeSideBits = CUBESIDE_CLIPALL; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - - if( !iaType ) { - return; - } - } - - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - model = tr.currentModel->iqm; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->num_surfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->num_surfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // generate interactions with all surfaces - for ( i = 0, surface = model->surfaces; i < model->num_surfaces; i++, surface++ ) - { - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = R_GetShaderByHandle( surface->shader->index ); - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) surface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } -} - -/* -================= -R_AddMD5Interactions -================= -*/ -void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - md5Model_t *model; - md5Surface_t *surface; - bool personalModel; - byte cubeSideBits = CUBESIDE_CLIPALL; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = Util::enum_cast(iaType & ~IA_LIGHT); - } - - if( !iaType ) - { - return; - } - - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - model = tr.currentModel->md5; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - if ( !r_vboModels.Get() || !model->numVBOSurfaces || - ( !glConfig2.vboVertexSkinningAvailable && ent->e.skeleton.type == refSkeletonType_t::SK_ABSOLUTE ) ) - { - shader_t *shader = nullptr; - - // generate interactions with all surfaces - int i; - for ( i = 0, surface = model->surfaces; i < model->numSurfaces; i++, surface++ ) - { - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = R_GetShaderByHandle( surface->shaderIndex ); - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, (surfaceType_t*) surface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } - else - { - int i; - srfVBOMD5Mesh_t *vboSurface; - shader_t *shader; - - for ( i = 0; i < model->numVBOSurfaces; i++ ) - { - vboSurface = model->vboSurfaces[ i ]; - - if ( ent->e.customShader ) - { - shader = R_GetShaderByHandle( ent->e.customShader ); - } - else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) - { - skin_t *skin; - - skin = R_GetSkinByHandle( ent->e.customSkin ); - - // match the surface name to something in the skin file - shader = tr.defaultShader; - - // FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces - if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] ) - { - shader = skin->surfaces[ i ]->shader; - } - - if ( shader == tr.defaultShader ) - { - Log::Warn("no shader for surface %i in skin %s", i, skin->name ); - } - else if ( shader->defaultShader ) - { - Log::Warn("shader %s in skin %s not found", shader->name, skin->name ); - } - } - else - { - shader = vboSurface->shader; - } - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) - { - continue; - } - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, (surfaceType_t*) vboSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } -} - /* ============== IQMCheckSkeleton diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index f67c2117b..b0dbce22c 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -34,6 +34,8 @@ backEndState_t backEnd; static Cvar::Cvar r_clear( "r_clear", "Clear screen before painting over it on every frame", Cvar::NONE, false ); Cvar::Cvar r_drawSky( "r_drawSky", "Draw the sky (clear the sky if disabled)", Cvar::NONE, true ); +static Cvar::Cvar r_showEntityBounds( + "r_showEntityBounds", "show bboxes used for culling (1: wireframe; 2: translucent solid)", Cvar::CHEAT, 0); void GL_Bind( image_t *image ) { @@ -847,7 +849,6 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, oldFogNum = -1; oldDepthRange = false; depthRange = false; - backEnd.currentLight = nullptr; lastSurf = backEnd.viewParms.firstDrawSurf[ Util::ordinal(toSort) + 1 ]; for ( i = backEnd.viewParms.firstDrawSurf[ Util::ordinal(fromSort) ]; i < lastSurf; i++ ) @@ -967,1601 +968,6 @@ static void RB_RenderDrawSurfaces( shaderSort_t fromSort, shaderSort_t toSort, GL_CheckErrors(); } -/* - * helper function for parallel split shadow mapping - */ -static int MergeInteractionBounds( const matrix_t lightViewProjectionMatrix, interaction_t *ia, int iaCount, vec3_t bounds[ 2 ], bool shadowCasters ) -{ - int i; - int j; - surfaceType_t *surface; - vec4_t point; - vec4_t transf; - vec3_t worldBounds[ 2 ]; - int numCasters; - - frustum_t frustum; - cplane_t *clipPlane; - int r; - - numCasters = 0; - ClearBounds( bounds[ 0 ], bounds[ 1 ] ); - - // calculate frustum planes using the modelview projection matrix - R_SetupFrustum2( frustum, lightViewProjectionMatrix ); - - while ( iaCount < backEnd.viewParms.numInteractions ) - { - surface = ia->surface; - - if ( shadowCasters ) - { - if ( !(ia->type & IA_SHADOW) ) - { - goto skipInteraction; - } - } - else - { - // we only merge shadow receivers - if ( !(ia->type & IA_LIGHT) ) - { - goto skipInteraction; - } - } - - if ( *surface == surfaceType_t::SF_FACE || *surface == surfaceType_t::SF_GRID || *surface == surfaceType_t::SF_TRIANGLES - || *surface == surfaceType_t::SF_VBO_MESH ) - { - srfGeneric_t *gen = ( srfGeneric_t * ) surface; - - VectorCopy( gen->bounds[ 0 ], worldBounds[ 0 ] ); - VectorCopy( gen->bounds[ 1 ], worldBounds[ 1 ] ); - } - else if ( *surface == surfaceType_t::SF_MDV ) - { - goto skipInteraction; - } - else - { - goto skipInteraction; - } - - // use the frustum planes to cut off shadow casters beyond the split frustum - for ( i = 0; i < 6; i++ ) - { - clipPlane = &frustum[ i ]; - - // we can have shadow casters outside the initial computed light view frustum - if ( i == Util::ordinal(frustumBits_t::FRUSTUM_NEAR) && shadowCasters ) - { - continue; - } - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], clipPlane ); - - if ( r == 2 ) - { - goto skipInteraction; - } - } - - if ( shadowCasters && (ia->type & IA_SHADOW) ) - { - numCasters++; - } - - for ( j = 0; j < 8; j++ ) - { - point[ 0 ] = worldBounds[ j & 1 ][ 0 ]; - point[ 1 ] = worldBounds[( j >> 1 ) & 1 ][ 1 ]; - point[ 2 ] = worldBounds[( j >> 2 ) & 1 ][ 2 ]; - point[ 3 ] = 1; - - MatrixTransform4( lightViewProjectionMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, bounds[ 0 ], bounds[ 1 ] ); - } - -skipInteraction: - - if ( !ia->next ) - { - // this is the last interaction of the current light - break; - } - else - { - // just continue - ia = ia->next; - iaCount++; - } - } - - return numCasters; -} - -static interaction_t *IterateLights( const interaction_t *prev ) -{ - if ( !prev && backEnd.viewParms.numInteractions > 0 ) - { - return backEnd.viewParms.interactions; - } - - if ( backEnd.viewParms.numInteractions <= 0 ) - { - return nullptr; - } - - const interaction_t *next = prev; - const interaction_t *last = &backEnd.viewParms.interactions[ backEnd.viewParms.numInteractions - 1 ]; - - while ( next <= last && next->light == prev->light ) - { - next++; - } - - if ( next > last ) - { - next = nullptr; - } - - return ( interaction_t * ) next; -} - -static void RB_SetupLightAttenuationForEntity( trRefLight_t *light, const trRefEntity_t *entity ) -{ - matrix_t modelToLight; - - // transform light origin into model space for u_LightOrigin parameter - if ( entity != &tr.worldEntity ) - { - vec3_t tmp; - VectorSubtract( light->origin, backEnd.orientation.origin, tmp ); - light->transformed[ 0 ] = DotProduct( tmp, backEnd.orientation.axis[ 0 ] ); - light->transformed[ 1 ] = DotProduct( tmp, backEnd.orientation.axis[ 1 ] ); - light->transformed[ 2 ] = DotProduct( tmp, backEnd.orientation.axis[ 2 ] ); - } - else - { - VectorCopy( light->origin, light->transformed ); - } - - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight ); - - // build the attenuation matrix using the entity transform - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - - MatrixCopy( light->attenuationMatrix, light->shadowMatrices[ 0 ] ); - break; - } - - case refLightType_t::RL_PROJ: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.0 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5f, 0.5f, 1.0f / std::min( light->falloffLength, 1.0f ) ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - - MatrixCopy( light->attenuationMatrix, light->shadowMatrices[ 0 ] ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - MatrixSetupTranslation( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // bias - MatrixMultiplyScale( light->attenuationMatrix, 0.5, 0.5, 0.5 ); // scale - MatrixMultiply2( light->attenuationMatrix, light->projectionMatrix ); - MatrixMultiply2( light->attenuationMatrix, modelToLight ); - break; - } - - case refLightType_t::RL_MAX_REF_LIGHT_TYPE: - { - //Nothing for right now... - break; - } - } -} - -/* -================= -RB_RenderInteractions -================= -*/ -static void RB_RenderInteractions() -{ - shader_t *shader, *oldShader; - trRefEntity_t *entity, *oldEntity; - trRefLight_t *light; - const interaction_t *ia; - const interaction_t *iaFirst; - bool depthRange, oldDepthRange; - surfaceType_t *surface; - int startTime = 0, endTime = 0; - - GLIMP_LOGCOMMENT( "--- RB_RenderInteractions ---" ); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES)) - { - glFinish(); - startTime = ri.Milliseconds(); - } - - // draw everything - oldEntity = nullptr; - oldShader = nullptr; - oldDepthRange = false; - depthRange = false; - iaFirst = nullptr; - - // render interactions - while ( ( iaFirst = IterateLights( iaFirst ) ) ) - { - backEnd.currentLight = light = iaFirst->light; - - // set light scissor to reduce fillrate - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, iaFirst->scissorWidth, iaFirst->scissorHeight ); - - for ( ia = iaFirst; ia; ia = ia->next ) - { - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - - if ( !shader || !shader->interactLight ) - { - // skip this interaction because the surface shader has no ability to interact with light - // this will save texcoords and matrix calculations - continue; - } - - if ( !(ia->type & IA_LIGHT) ) - { - // skip this interaction because the interaction is meant for shadowing only - continue; - } - - GLIMP_LOGCOMMENT( "----- Rendering new light -----" ); - - // Tr3B: this should never happen in the first iteration - if ( entity == oldEntity && shader == oldShader ) - { - // fast path, same as previous - rb_surfaceTable[Util::ordinal(*surface)](surface ); - continue; - } - - // draw the contents of the last shader batch - Tess_End(); - - // begin a new batch - Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, false, -1, 0 ); - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - - if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - // add the triangles for this surface - rb_surfaceTable[Util::ordinal(*surface)](surface ); - oldEntity = entity; - oldShader = shader; - } - - // draw the contents of the last shader batch - Tess_End(); - - // force updates - oldEntity = nullptr; - oldShader = nullptr; - } - - Tess_End(); - - // go back to the world modelview matrix - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - - if ( depthRange ) - { - glDepthRange( 0, 1 ); - } - - // reset scissor - GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, - backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - - GL_CheckErrors(); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardLightingTime += endTime - startTime; - } -} - -static void RB_SetupLightForShadowing( trRefLight_t *light, int index, - bool shadowClip ) -{ - // HACK: bring OpenGL into a safe state or strange FBO update problems will occur - GL_BindNullProgram(); - GL_State( GLS_DEFAULT ); - - GL_Bind( tr.whiteImage ); - int cubeSide = index; - int splitFrustumIndex = index; - interaction_t *ia = light->firstInteraction; - int iaCount = ia - backEnd.viewParms.interactions; - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - float zNear, zFar; - float fovX, fovY; - bool flipX, flipY; - vec3_t angles; - matrix_t rotationMatrix, transformMatrix, viewMatrix; - - GLIMP_LOGCOMMENT( "----- Rendering shadowCube side: %i -----", cubeSide ); - - R_BindFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, - tr.shadowClipCubeFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - else - { - R_AttachFBOTexture2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, - tr.shadowCubeFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - GL_Scissor( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - switch ( cubeSide ) - { - case 0: - { - // view parameters - VectorSet( angles, 0, 0, 90 ); - - // projection parameters - flipX = false; - flipY = false; - break; - } - - case 1: - { - VectorSet( angles, 0, 180, 90 ); - flipX = true; - flipY = true; - break; - } - - case 2: - { - VectorSet( angles, 0, 90, 0 ); - flipX = false; - flipY = false; - break; - } - - case 3: - { - VectorSet( angles, 0, -90, 0 ); - flipX = true; - flipY = true; - break; - } - - case 4: - { - VectorSet( angles, -90, 90, 0 ); - flipX = false; - flipY = false; - break; - } - - case 5: - { - VectorSet( angles, 90, 90, 0 ); - flipX = true; - flipY = true; - break; - } - - default: - { - // shut up compiler - VectorSet( angles, 0, 0, 0 ); - flipX = false; - flipY = false; - break; - } - } - - // Quake -> OpenGL view matrix from light perspective - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, light->origin ); - MatrixAffineInverse( transformMatrix, viewMatrix ); - - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - MatrixMultiply( quakeToOpenGLMatrix, viewMatrix, light->viewMatrix ); - - // OpenGL projection matrix - fovX = 90; - fovY = 90; - - zNear = 1.0; - zFar = light->sphereRadius; - - if ( flipX ) - { - fovX = -fovX; - } - - if ( flipY ) - { - fovY = -fovY; - } - - MatrixPerspectiveProjectionFovXYRH( light->projectionMatrix, fovX, fovY, zNear, zFar ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - break; - } - - case refLightType_t::RL_PROJ: - { - GLIMP_LOGCOMMENT( "--- Rendering projective shadowMap ---" ); - - R_BindFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.shadowClipMapFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - else - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.shadowMapFBOImage[ light->shadowLOD ]->texnum, 0 ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.shadowMapFBO[ light->shadowLOD ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - GL_Scissor( 0, 0, shadowMapResolutions[ light->shadowLOD ], shadowMapResolutions[ light->shadowLOD ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - int j; - vec3_t angles; - vec4_t forward, side, up; - vec3_t lightDirection; - vec3_t viewOrigin, viewDirection; - matrix_t rotationMatrix, transformMatrix, viewMatrix, projectionMatrix, viewProjectionMatrix; - matrix_t cropMatrix; - vec3_t splitFrustumNearCorners[ 4 ]; - vec3_t splitFrustumFarCorners[ 4 ]; - vec3_t splitFrustumBounds[ 2 ]; - vec3_t splitFrustumClipBounds[ 2 ]; - int numCasters; - vec3_t casterBounds[ 2 ]; - vec3_t receiverBounds[ 2 ]; - vec3_t cropBounds[ 2 ]; - vec4_t point; - vec4_t transf; - - GLIMP_LOGCOMMENT( "--- Rendering directional shadowMap ---" ); - - R_BindFBO( tr.sunShadowMapFBO[ splitFrustumIndex ] ); - - if( shadowClip ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.sunShadowClipMapFBOImage[ splitFrustumIndex ]->texnum, 0 ); - } - else if ( !r_evsmPostProcess->integer ) - { - R_AttachFBOTexture2D( GL_TEXTURE_2D, tr.sunShadowMapFBOImage[ splitFrustumIndex ]->texnum, 0 ); - } - else - { - R_AttachFBOTextureDepth( tr.sunShadowMapFBOImage[ splitFrustumIndex ]->texnum ); - } - - if ( checkGLErrors() ) - { - R_CheckFBO( tr.sunShadowMapFBO[ splitFrustumIndex ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, sunShadowMapResolutions[ splitFrustumIndex ], sunShadowMapResolutions[ splitFrustumIndex ] ); - GL_Scissor( 0, 0, sunShadowMapResolutions[ splitFrustumIndex ], sunShadowMapResolutions[ splitFrustumIndex ] ); - - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - VectorCopy( tr.sunDirection, lightDirection ); - - if ( r_parallelShadowSplits->integer ) - { - // original light direction is from surface to light - VectorInverse( lightDirection ); - VectorNormalize( lightDirection ); - - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( backEnd.viewParms.orientation.axis[ 0 ], viewDirection ); - VectorNormalize( viewDirection ); - - // calculate new up dir - CrossProduct( lightDirection, viewDirection, side ); - VectorNormalize( side ); - - CrossProduct( side, lightDirection, up ); - VectorNormalize( up ); - - vectoangles( lightDirection, angles ); - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - AngleVectors( angles, forward, side, up ); - - MatrixLookAtRH( light->viewMatrix, viewOrigin, lightDirection, up ); - - plane_t splitFrustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( backEnd.viewParms.frustums[ 1 + splitFrustumIndex ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 1 + splitFrustumIndex ][ j ].dist; - } - - R_CalcFrustumNearCorners( splitFrustum, splitFrustumNearCorners ); - R_CalcFrustumFarCorners( splitFrustum, splitFrustumFarCorners ); - - if ( GLimp_isLogging() ) - { - vec3_t rayIntersectionNear, rayIntersectionFar; - float zNear, zFar; - - PlaneIntersectRay( viewOrigin, viewDirection, splitFrustum[ FRUSTUM_FAR ], rayIntersectionFar ); - zFar = Distance( viewOrigin, rayIntersectionFar ); - - VectorInverse( viewDirection ); - - PlaneIntersectRay( rayIntersectionFar, viewDirection, splitFrustum[ FRUSTUM_NEAR ], rayIntersectionNear ); - zNear = Distance( viewOrigin, rayIntersectionNear ); - - VectorInverse( viewDirection ); - - GLIMP_LOGCOMMENT( "split frustum %i: near = %5.3f, far = %5.3f", - splitFrustumIndex, zNear, zFar ); - - GLIMP_LOGCOMMENT( "pyramid nearCorners" ); - - for ( auto nearCorner : splitFrustumNearCorners ) - { - GLIMP_LOGCOMMENT( "(%5.3f, %5.3f, %5.3f)", - nearCorner[ 0 ], nearCorner[ 1 ], nearCorner[ 2 ] ); - } - - GLIMP_LOGCOMMENT( "pyramid farCorners" ); - - for ( auto farCorner : splitFrustumFarCorners ) - { - GLIMP_LOGCOMMENT( "(%5.3f, %5.3f, %5.3f)", - farCorner[ 0 ], farCorner[ 1 ], farCorner[ 2 ] ); - } - } - - ClearBounds( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - - for ( auto nearCorner : splitFrustumNearCorners ) - { - AddPointToBounds( nearCorner, splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - AddPointToBounds( farCorner, splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - } - - // - // Scene-Dependent Projection - // - - // find the bounding box of the current split in the light's view space - ClearBounds( cropBounds[ 0 ], cropBounds[ 1 ] ); - - const auto pointsToViewBounds = [&]( vec_t *c ) { - VectorCopy( c, point ); - point[ 3 ] = 1; - MatrixTransform4( light->viewMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, cropBounds[ 0 ], cropBounds[ 1 ] ); - }; - - for ( auto nearCorner : splitFrustumNearCorners ) - { - pointsToViewBounds( nearCorner ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - pointsToViewBounds( farCorner ); - } - - MatrixOrthogonalProjectionRH( projectionMatrix, cropBounds[ 0 ][ 0 ], cropBounds[ 1 ][ 0 ], cropBounds[ 0 ][ 1 ], cropBounds[ 1 ][ 1 ], -cropBounds[ 1 ][ 2 ], -cropBounds[ 0 ][ 2 ] ); - - MatrixMultiply( projectionMatrix, light->viewMatrix, viewProjectionMatrix ); - - numCasters = MergeInteractionBounds( viewProjectionMatrix, ia, iaCount, casterBounds, true ); - MergeInteractionBounds( viewProjectionMatrix, ia, iaCount, receiverBounds, false ); - - // find the bounding box of the current split in the light's clip space - ClearBounds( splitFrustumClipBounds[ 0 ], splitFrustumClipBounds[ 1 ] ); - - const auto pointsToViewProjectionBounds = [&]( vec_t* c ) { - VectorCopy( c, point ); - point[ 3 ] = 1; - - MatrixTransform4( viewProjectionMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, splitFrustumClipBounds[ 0 ], splitFrustumClipBounds[ 1 ] ); - }; - - for ( auto nearCorner : splitFrustumNearCorners ) - { - pointsToViewProjectionBounds( nearCorner ); - } - - for ( auto farCorner : splitFrustumFarCorners ) - { - pointsToViewProjectionBounds( farCorner ); - } - - if ( GLimp_isLogging() ) - { - GLIMP_LOGCOMMENT( "shadow casters = %i", numCasters ); - - GLIMP_LOGCOMMENT( "split frustum light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - splitFrustumClipBounds[ 0 ][ 0 ], splitFrustumClipBounds[ 0 ][ 1 ], splitFrustumClipBounds[ 0 ][ 2 ], - splitFrustumClipBounds[ 1 ][ 0 ], splitFrustumClipBounds[ 1 ][ 1 ], splitFrustumClipBounds[ 1 ][ 2 ] ); - - GLIMP_LOGCOMMENT( "shadow caster light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - casterBounds[ 0 ][ 0 ], casterBounds[ 0 ][ 1 ], casterBounds[ 0 ][ 2 ], - casterBounds[ 1 ][ 0 ], casterBounds[ 1 ][ 1 ], casterBounds[ 1 ][ 2 ] ); - - GLIMP_LOGCOMMENT( "light receiver light space clip bounds (%5.3f, %5.3f, %5.3f) (%5.3f, %5.3f, %5.3f)", - receiverBounds[ 0 ][ 0 ], receiverBounds[ 0 ][ 1 ], receiverBounds[ 0 ][ 2 ], - receiverBounds[ 1 ][ 0 ], receiverBounds[ 1 ][ 1 ], receiverBounds[ 1 ][ 2 ] ); - } - - // scene-dependent bounding volume - cropBounds[ 0 ][ 0 ] = std::max( std::max( casterBounds[ 0 ][ 0 ], receiverBounds[ 0 ][ 0 ] ), splitFrustumClipBounds[ 0 ][ 0 ] ); - cropBounds[ 0 ][ 1 ] = std::max( std::max( casterBounds[ 0 ][ 1 ], receiverBounds[ 0 ][ 1 ] ), splitFrustumClipBounds[ 0 ][ 1 ] ); - - cropBounds[ 1 ][ 0 ] = std::min( std::min( casterBounds[ 1 ][ 0 ], receiverBounds[ 1 ][ 0 ] ), splitFrustumClipBounds[ 1 ][ 0 ] ); - cropBounds[ 1 ][ 1 ] = std::min( std::min( casterBounds[ 1 ][ 1 ], receiverBounds[ 1 ][ 1 ] ), splitFrustumClipBounds[ 1 ][ 1 ] ); - - cropBounds[ 0 ][ 2 ] = std::min( casterBounds[ 0 ][ 2 ], splitFrustumClipBounds[ 0 ][ 2 ] ); - cropBounds[ 1 ][ 2 ] = std::min( receiverBounds[ 1 ][ 2 ], splitFrustumClipBounds[ 1 ][ 2 ] ); - - if ( numCasters == 0 ) - { - VectorCopy( splitFrustumClipBounds[ 0 ], cropBounds[ 0 ] ); - VectorCopy( splitFrustumClipBounds[ 1 ], cropBounds[ 1 ] ); - } - - MatrixCrop( cropMatrix, cropBounds[ 0 ], cropBounds[ 1 ] ); - - MatrixMultiply( cropMatrix, projectionMatrix, light->projectionMatrix ); - - GL_LoadProjectionMatrix( light->projectionMatrix ); - } - else - { - // original light direction is from surface to light - VectorInverse( lightDirection ); - - // Quake -> OpenGL view matrix from light perspective - vectoangles( lightDirection, angles ); - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, backEnd.viewParms.orientation.origin ); - MatrixAffineInverse( transformMatrix, viewMatrix ); - MatrixMultiply( quakeToOpenGLMatrix, viewMatrix, light->viewMatrix ); - - ClearBounds( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ] ); - //BoundsAdd(splitFrustumBounds[0], splitFrustumBounds[1], backEnd.viewParms.visBounds[0], backEnd.viewParms.visBounds[1]); - BoundsAdd( splitFrustumBounds[ 0 ], splitFrustumBounds[ 1 ], light->worldBounds[ 0 ], light->worldBounds[ 1 ] ); - - ClearBounds( cropBounds[ 0 ], cropBounds[ 1 ] ); - - for ( j = 0; j < 8; j++ ) - { - point[ 0 ] = splitFrustumBounds[ j & 1 ][ 0 ]; - point[ 1 ] = splitFrustumBounds[( j >> 1 ) & 1 ][ 1 ]; - point[ 2 ] = splitFrustumBounds[( j >> 2 ) & 1 ][ 2 ]; - point[ 3 ] = 1; - - MatrixTransform4( light->viewMatrix, point, transf ); - transf[ 0 ] /= transf[ 3 ]; - transf[ 1 ] /= transf[ 3 ]; - transf[ 2 ] /= transf[ 3 ]; - - AddPointToBounds( transf, cropBounds[ 0 ], cropBounds[ 1 ] ); - } - - MatrixOrthogonalProjectionRH( light->projectionMatrix, cropBounds[ 0 ][ 0 ], cropBounds[ 1 ][ 0 ], cropBounds[ 0 ][ 1 ], cropBounds[ 1 ][ 1 ], -cropBounds[ 1 ][ 2 ], -cropBounds[ 0 ][ 2 ] ); - GL_LoadProjectionMatrix( light->projectionMatrix ); - } - - break; - } - - default: - break; - } - - GLIMP_LOGCOMMENT( "----- First Shadow Interaction: %i -----", - (int)( light->firstInteraction - backEnd.viewParms.interactions ) ); -} - -static void RB_SetupLightForLighting( trRefLight_t *light ) -{ - GLIMP_LOGCOMMENT( "--- Rendering lighting ---" ); - - GLIMP_LOGCOMMENT( "----- First Light Interaction: %i -----", - (int)( light->firstInteraction - backEnd.viewParms.interactions ) ); - - R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] ); - - // set the window clipping - GL_Viewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - - interaction_t *iaFirst = light->firstInteraction; - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, - iaFirst->scissorWidth, iaFirst->scissorHeight ); - - // restore camera matrices - GL_LoadProjectionMatrix( backEnd.viewParms.projectionMatrix ); - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // reset light view and projection matrices - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - MatrixAffineInverse( light->transformMatrix, light->viewMatrix ); - MatrixSetupScale( light->projectionMatrix, 1.0f / light->l.radius, 1.0f / light->l.radius, - 1.0f / light->l.radius ); - break; - } - - case refLightType_t::RL_DIRECTIONAL: - { - // draw split frustum shadow maps - if ( r_showShadowMaps->integer ) - { - int frustumIndex; - float x, y, w, h; - matrix_t ortho; - vec4_t quadVerts[ 4 ]; - - // set 2D virtual screen size - GL_PushMatrix(); - MatrixOrthogonalProjection( ortho, backEnd.viewParms.viewportX, - backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, - backEnd.viewParms.viewportY, - backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999 ); - GL_LoadProjectionMatrix( ortho ); - - for ( frustumIndex = 0; frustumIndex <= r_parallelShadowSplits->integer; frustumIndex++ ) - { - GL_Cull( cullType_t::CT_TWO_SIDED ); - GL_State( GLS_DEPTHTEST_DISABLE ); - - gl_debugShadowMapShader->BindProgram( 0 ); - - gl_debugShadowMapShader->SetUniform_CurrentMapBindless( - GL_BindToTMU( 0, tr.sunShadowMapFBOImage[frustumIndex] ) - ); - - w = 200; - h = 200; - - x = 205 * frustumIndex; - y = 70; - - Tess_InstantQuad( *gl_debugShadowMapShader, x, y, w, h ); - - { - int j; - vec3_t farCorners[ 4 ]; - vec3_t nearCorners[ 4 ]; - - GL_Viewport( x, y, w, h ); - GL_Scissor( x, y, w, h ); - - GL_PushMatrix(); - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - gl_genericShader->SetUniform_ModelViewProjectionMatrix( light->shadowMatrices[ frustumIndex ] ); - - tess.multiDrawPrimitives = 0; - tess.numIndexes = 0; - tess.numVertexes = 0; - - plane_t splitFrustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( backEnd.viewParms.frustums[ 1 + frustumIndex ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 1 + frustumIndex ][ j ].dist; - } - - R_CalcFrustumNearCorners( splitFrustum, nearCorners ); - R_CalcFrustumFarCorners( splitFrustum, farCorners ); - - // draw outer surfaces - for ( j = 0; j < 4; j++ ) - { - Vector4Set( quadVerts[ 0 ], nearCorners[ j ][ 0 ], nearCorners[ j ][ 1 ], nearCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ j ][ 0 ], farCorners[ j ][ 1 ], farCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[( j + 1 ) % 4 ][ 0 ], farCorners[( j + 1 ) % 4 ][ 1 ], farCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[( j + 1 ) % 4 ][ 0 ], nearCorners[( j + 1 ) % 4 ][ 1 ], nearCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Cyan ); - } - - // draw far cap - Vector4Set( quadVerts[ 0 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Blue ); - - // draw near cap - Vector4Set( quadVerts[ 0 ], nearCorners[ 0 ][ 0 ], nearCorners[ 0 ][ 1 ], nearCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], nearCorners[ 1 ][ 0 ], nearCorners[ 1 ][ 1 ], nearCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], nearCorners[ 2 ][ 0 ], nearCorners[ 2 ][ 1 ], nearCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[ 3 ][ 0 ], nearCorners[ 3 ][ 1 ], nearCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, Color::Green ); - - Tess_UpdateVBOs( ); - GL_VertexAttribsState( ATTR_POSITION | ATTR_COLOR ); - Tess_DrawElements(); - - tess.multiDrawPrimitives = 0; - tess.numIndexes = 0; - tess.numVertexes = 0; - - GL_PopMatrix(); - - GL_Viewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - - GL_Scissor( iaFirst->scissorX, iaFirst->scissorY, - iaFirst->scissorWidth, iaFirst->scissorHeight ); - } - } - - GL_PopMatrix(); - } - } - break; - - default: - break; - } -} - -static void RB_BlurShadowMap( const trRefLight_t *light, int i ) -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - if ( light->l.inverseShadows ) - { - return; - } - - if ( !r_softShadowsPP->integer ) - { - return; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI ) - { - return; - } - - int index; - image_t **images; - FBO_t **fbos; - vec2_t texScale; - - fbos = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? tr.sunShadowMapFBO : tr.shadowMapFBO; - images = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? tr.sunShadowMapFBOImage : tr.shadowMapFBOImage; - index = ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) ? i : light->shadowLOD; - - texScale[ 0 ] = 1.0f / fbos[ index ]->width; - texScale[ 1 ] = 1.0f / fbos[ index ]->height; - - R_BindFBO( fbos[ index ] ); - R_AttachFBOTexture2D( images[ index + MAX_SHADOWMAPS ]->type, images[ index + MAX_SHADOWMAPS ]->texnum, 0 ); - - if ( checkGLErrors() ) - { - R_CheckFBO( fbos[ index ] ); - } - - // set the window clipping - GL_Viewport( 0, 0, fbos[index]->width, fbos[index]->height ); - GL_Scissor( 0, 0, fbos[index]->width, fbos[index]->height ); - - glClear( GL_COLOR_BUFFER_BIT ); - - GL_Cull( cullType_t::CT_TWO_SIDED ); - GL_State( GLS_DEPTHTEST_DISABLE ); - - gl_blurShader->BindProgram( 0 ); - gl_blurShader->SetUniform_DeformMagnitude( 1 ); - gl_blurShader->SetUniform_TexScale( texScale ); - gl_blurShader->SetUniform_Horizontal( true ); - - gl_blurShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, images[index] ) - ); - - Tess_InstantScreenSpaceQuad(); - - R_AttachFBOTexture2D( images[ index ]->type, images[ index ]->texnum, 0 ); - - glClear( GL_COLOR_BUFFER_BIT ); - - gl_blurShader->BindProgram( 0 ); - gl_blurShader->SetUniform_DeformMagnitude( 1 ); - gl_blurShader->SetUniform_TexScale( texScale ); - gl_blurShader->SetUniform_Horizontal( false ); - - gl_blurShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, images[index + MAX_SHADOWMAPS] ) - ); - - Tess_InstantScreenSpaceQuad(); -} - -/* -================= -RB_RenderInteractionsShadowMapped -================= -*/ - -static void RB_RenderInteractionsShadowMapped() -{ - shader_t *shader, *oldShader; - trRefEntity_t *entity, *oldEntity; - trRefLight_t *light; - const interaction_t *ia; - const interaction_t *iaFirst; - surfaceType_t *surface; - bool depthRange, oldDepthRange; - bool alphaTest, oldAlphaTest; - bool shadowClipFound; - - int startTime = 0, endTime = 0; - static const matrix_t bias = { 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 - }; - - DAEMON_ASSERT( glConfig2.shadowMapping ); - - GLIMP_LOGCOMMENT( "--- RB_RenderInteractionsShadowMapped ---" ); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - startTime = ri.Milliseconds(); - } - - // draw everything - oldEntity = nullptr; - oldShader = nullptr; - oldDepthRange = depthRange = false; - oldAlphaTest = alphaTest = false; - - // if we need to clear the FBO color buffers then it should be white - GL_ClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); - - // render each light - iaFirst = nullptr; - - while ( ( iaFirst = IterateLights( iaFirst ) ) ) - { - backEnd.currentLight = light = iaFirst->light; - - // begin shadowing - int numMaps; - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - numMaps = 6; - break; - case refLightType_t::RL_DIRECTIONAL: - numMaps = std::max( r_parallelShadowSplits->integer + 1, 1 ); - break; - default: - numMaps = 1; - break; - } - - const interaction_t *iaLast = iaFirst; - for ( int i = 0; i < numMaps; i++ ) - { - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; - - if ( light->l.noShadows || light->shadowLOD < 0 ) - { - GLIMP_LOGCOMMENT( "----- Skipping shadowCube side: %i -----", i ); - - continue; - } - - RB_SetupLightForShadowing( light, i, false ); - - shadowClipFound = false; - for( ia = iaFirst; ia; ia = ia->next ) - { - iaLast = ia; - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - alphaTest = shader->alphaTest; - - if ( entity->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) - { - continue; - } - - if ( shader->isSky ) - { - continue; - } - - if ( shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( shader->noShadows ) - { - continue; - } - - if ( (ia->type & IA_SHADOWCLIP) ) { - shadowClipFound = true; - } - - if ( !(ia->type & IA_SHADOW) ) - { - continue; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI && !( ia->cubeSideBits & ( 1 << i ) ) ) - { - continue; - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - if ( entity == oldEntity && ( alphaTest ? shader == oldShader : alphaTest == oldAlphaTest ) ) - { - GLIMP_LOGCOMMENT( "----- Batching Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - continue; - } - else - { - // draw the contents of the last shader batch - Tess_End(); - - GLIMP_LOGCOMMENT( "----- Beginning Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // we don't need tangent space calculations here - Tess_Begin( Tess_StageIteratorShadowFill, shader, light->shader, true, -1, 0 ); - } - - break; - } - - default: - break; - } - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForLight( entity, light, &backEnd.orientation ); - - if ( entity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - // set up the transformation matrix - backEnd.orientation = {}; - - backEnd.orientation.axis[ 0 ][ 0 ] = 1; - backEnd.orientation.axis[ 1 ][ 1 ] = 1; - backEnd.orientation.axis[ 2 ][ 2 ] = 1; - VectorCopy( light->l.origin, backEnd.orientation.viewOrigin ); - - MatrixIdentity( backEnd.orientation.transformMatrix ); - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix ); - MatrixCopy( backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix ); - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - break; - } - - default: - break; - } - oldEntity = entity; - oldShader = shader; - oldAlphaTest = alphaTest; - } - - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); - - Tess_End(); - - if( shadowClipFound ) - { - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; - - if ( light->l.noShadows || light->shadowLOD < 0 ) - { - GLIMP_LOGCOMMENT( "----- Skipping shadowCube side: %i -----", i ); - continue; - } - - RB_SetupLightForShadowing( light, i, true ); - - for( ia = iaFirst; ia; ia = ia->next ) - { - iaLast = ia; - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - alphaTest = shader->alphaTest; - - if ( entity->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) ) - { - continue; - } - - if ( shader->isSky ) - { - continue; - } - - if ( shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( shader->noShadows ) - { - continue; - } - - if ( !(ia->type & IA_SHADOWCLIP) ) - { - continue; - } - - if ( light->l.rlType == refLightType_t::RL_OMNI && !( ia->cubeSideBits & ( 1 << i ) ) ) - { - continue; - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - if ( entity == oldEntity && ( alphaTest ? shader == oldShader : alphaTest == oldAlphaTest ) ) - { - GLIMP_LOGCOMMENT( "----- Batching Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - continue; - } - else - { - // draw the contents of the last shader batch - Tess_End(); - - GLIMP_LOGCOMMENT( "----- Beginning Shadow Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // we don't need tangent space calculations here - Tess_Begin( Tess_StageIteratorShadowFill, shader, light->shader, true, -1, 0 ); - } - - break; - } - - default: - break; - } - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForLight( entity, light, &backEnd.orientation ); - - if ( entity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - // set up the transformation matrix - backEnd.orientation = {}; - - backEnd.orientation.axis[ 0 ][ 0 ] = 1; - backEnd.orientation.axis[ 1 ][ 1 ] = 1; - backEnd.orientation.axis[ 2 ][ 2 ] = 1; - VectorCopy( light->l.origin, backEnd.orientation.viewOrigin ); - - MatrixIdentity( backEnd.orientation.transformMatrix ); - MatrixMultiply( light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix ); - MatrixCopy( backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix ); - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - break; - } - - default: - break; - } - oldEntity = entity; - oldShader = shader; - oldAlphaTest = alphaTest; - } - - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); - - Tess_End(); - } - - // set shadow matrix including scale + offset - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - MatrixCopy( bias, light->shadowMatricesBiased[ i ] ); - MatrixMultiply2( light->shadowMatricesBiased[ i ], light->projectionMatrix ); - MatrixMultiply2( light->shadowMatricesBiased[ i ], light->viewMatrix ); - - MatrixMultiply( light->projectionMatrix, light->viewMatrix, light->shadowMatrices[ i ] ); - } - - RB_BlurShadowMap( light, i ); - } - - // begin lighting - RB_SetupLightForLighting( light ); - entity = nullptr; - shader = nullptr; - oldEntity = nullptr; - oldShader = nullptr; - for ( ia = iaFirst; ia; ia = ia->next ) - { - iaLast = ia; - backEnd.currentEntity = entity = ia->entity; - surface = ia->surface; - shader = ia->shader; - alphaTest = shader->alphaTest; - - if ( !shader->interactLight ) - { - continue; - } - - if ( !(ia->type & IA_LIGHT) ) - { - continue; - } - - if ( entity == oldEntity && shader == oldShader ) - { - GLIMP_LOGCOMMENT( "----- Batching Light Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // fast path, same as previous - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - continue; - } - else - { - // draw the contents of the last shader batch - Tess_End(); - - GLIMP_LOGCOMMENT( "----- Beginning Light Interaction: %i -----", - (int)( ia - backEnd.viewParms.interactions ) ); - - // begin a new batch - Tess_Begin( Tess_StageIteratorLighting, shader, light->shader, light->l.inverseShadows, -1, 0 ); - } - - // change the modelview matrix if needed - if ( entity != oldEntity ) - { - depthRange = false; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( entity, &backEnd.viewParms, &backEnd.orientation ); - - if ( entity->e.renderfx & RF_DEPTHHACK ) - { - // hack the depth range to prevent view model from poking into walls - depthRange = true; - } - } - else - { - // set up the transformation matrix - // transform by the camera placement - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - - // change depthrange if needed - if ( oldDepthRange != depthRange ) - { - if ( depthRange ) - { - glDepthRange( 0, 0.3 ); - } - else - { - glDepthRange( 0, 1 ); - } - - oldDepthRange = depthRange; - } - - RB_SetupLightAttenuationForEntity( light, entity ); - } - - // add the triangles for this surface - rb_surfaceTable[ Util::ordinal(*surface) ]( surface ); - oldEntity = entity; - oldShader = shader; - oldAlphaTest = alphaTest; - } - - GLIMP_LOGCOMMENT( "----- Last Interaction: %i -----", - (int)( iaLast - backEnd.viewParms.interactions ) ); - - Tess_End(); - } - - // draw the contents of the last shader batch - Tess_End(); - - // go back to the world modelview matrix - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - - if ( depthRange ) - { - glDepthRange( 0, 1 ); - } - - // reset scissor clamping - GL_Scissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, - backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - - // reset clear color - GL_ClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - - GL_CheckErrors(); - - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardLightingTime += endTime - startTime; - } -} - /* ============= RB_RunVisTests @@ -2697,30 +1103,6 @@ void RB_RenderPostDepthLightTile() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* Do not run lightTile code when the tiled renderer is not used. - - This computation is part of the tiled dynamic lighting renderer, - it's better to not run it and save CPU cycles when such effects - are disabled. - - Disabling this code also make possible to not compile the related - GLSL shaders at all when such effects are disabled. - - Not running the related GLSL shaders also helps older hardware to - run the game, for example the Radeon R300 Arithmetic Logic Unit is - too small to run the related GLSL code even if the shader itself - can be compiled. Such GPU are so old and slow that any kind of - dynamic lighting including the tiled implementation is expected to - be disabled anyway. Saving CPU cycles when a feature is not used is - welcome in any case. - - See https://github.com/DaemonEngine/Daemon/issues/344 */ - - return; - } - if ( !backEnd.refdef.numLights ) { return; } @@ -3183,153 +1565,10 @@ static void RB_RenderDebugUtils() { GLIMP_LOGCOMMENT( "--- RB_RenderDebugUtils ---" ); - if ( r_showLightTransforms->integer || r_showShadowLod->integer ) - { - const interaction_t *ia; - trRefLight_t *light; - vec3_t forward, left, up; - - static const vec3_t minSize = { -2, -2, -2 }; - static const vec3_t maxSize = { 2, 2, 2 }; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - ia = nullptr; - Color::Color lightColor; - while ( ( ia = IterateLights( ia ) ) ) - { - backEnd.currentLight = light = ia->light; - - if ( r_showShadowLod->integer ) - { - if ( light->shadowLOD == 0 ) - { - lightColor = Color::Red; - } - else if ( light->shadowLOD == 1 ) - { - lightColor = Color::Green; - } - else if ( light->shadowLOD == 2 ) - { - lightColor = Color::Blue; - } - else if ( light->shadowLOD == 3 ) - { - lightColor = Color::Yellow; - } - else if ( light->shadowLOD == 4 ) - { - lightColor = Color::Magenta; - } - else if ( light->shadowLOD == 5 ) - { - lightColor = Color::Cyan; - } - else - { - lightColor = Color::MdGrey; - } - } - else - { - lightColor = Color::Blue; - } - - lightColor.SetAlpha( 0.2 ); - - SetUniform_Color( gl_genericShader, lightColor ); - - MatrixToVectorsFLU( matrixIdentity, forward, left, up ); - VectorMA( vec3_origin, 16, forward, forward ); - VectorMA( vec3_origin, 16, left, left ); - VectorMA( vec3_origin, 16, up, up ); - - Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - - { - // set up the transformation matrix - R_RotateLightForViewParms( light, &backEnd.viewParms, &backEnd.orientation ); - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - gl_genericShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - - R_TessLight( light, lightColor ); - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - if ( !VectorCompare( light->l.center, vec3_origin ) ) - { - Tess_AddCube( light->l.center, minSize, maxSize, Color::Yellow ); - } - break; - } - - case refLightType_t::RL_PROJ: - { - // draw light_target - Tess_AddCube( light->l.projTarget, minSize, maxSize, Color::Red ); - Tess_AddCube( light->l.projRight, minSize, maxSize, Color::Green ); - Tess_AddCube( light->l.projUp, minSize, maxSize, Color::Blue ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - Tess_AddCube( light->l.projStart, minSize, maxSize, Color::Yellow ); - } - - if ( !VectorCompare( light->l.projEnd, vec3_origin ) ) - { - Tess_AddCube( light->l.projEnd, minSize, maxSize, Color::Magenta ); - } - break; - } - - default: - break; - } - } - - Tess_End(); - } - - // go back to the world modelview matrix - backEnd.orientation = backEnd.viewParms.world; - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - } - - if ( r_showLightInteractions->integer ) + if ( r_showEntityBounds.Get() ) { + trRefEntity_t *ent; int i; - int cubeSides; - interaction_t *ia; - int iaCount; - trRefLight_t *light; - trRefEntity_t *entity; - surfaceType_t *surface; - Color::Color lightColor; - static const vec3_t mins = { -1, -1, -1 }; static const vec3_t maxs = { 1, 1, 1 }; @@ -3340,128 +1579,23 @@ static void RB_RenderDebugUtils() gl_genericShader->SetDepthFade( false ); gl_genericShader->BindProgram( 0 ); - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - for ( iaCount = 0, ia = &backEnd.viewParms.interactions[ 0 ]; iaCount < backEnd.viewParms.numInteractions; ia++, iaCount++ ) + if ( r_showEntityBounds.Get() == 2 ) { - backEnd.currentEntity = entity = ia->entity; - light = ia->light; - surface = ia->surface; - - if ( entity != &tr.worldEntity ) - { - // set up the transformation matrix - R_RotateEntityForViewParms( backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation ); - } - else - { - backEnd.orientation = backEnd.viewParms.world; - } - - GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix ); - gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - if ( glConfig2.shadowMapping && light->l.rlType == refLightType_t::RL_OMNI ) - { - // count how many cube sides are in use for this interaction - cubeSides = 0; - - for ( i = 0; i < 6; i++ ) - { - if ( ia->cubeSideBits & ( 1 << i ) ) - { - cubeSides++; - } - } - lightColor = Color::Color::Indexed( cubeSides ); - } - else - { - lightColor = Color::MdGrey; - } - - lightColor = Color::White; - - Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - - if ( *surface == surfaceType_t::SF_FACE || *surface == surfaceType_t::SF_GRID || *surface == surfaceType_t::SF_TRIANGLES ) - { - srfGeneric_t *gen; - - gen = ( srfGeneric_t * ) surface; - - if ( *surface == surfaceType_t::SF_FACE ) - { - lightColor = Color::MdGrey; - } - else if ( *surface == surfaceType_t::SF_GRID ) - { - lightColor = Color::Cyan; - } - else if ( *surface == surfaceType_t::SF_TRIANGLES ) - { - lightColor = Color::Magenta; - } - else - { - lightColor = Color::MdGrey; - } - - Tess_AddCube( vec3_origin, gen->bounds[ 0 ], gen->bounds[ 1 ], lightColor ); - - Tess_AddCube( gen->origin, mins, maxs, Color::White ); - } - else if ( *surface == surfaceType_t::SF_VBO_MESH ) - { - srfVBOMesh_t *srf = ( srfVBOMesh_t * ) surface; - Tess_AddCube( vec3_origin, srf->bounds[ 0 ], srf->bounds[ 1 ], lightColor ); - } - else if ( *surface == surfaceType_t::SF_MDV ) - { - Tess_AddCube( vec3_origin, entity->localBounds[ 0 ], entity->localBounds[ 1 ], lightColor ); - } - - Tess_End(); + GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); + glEnable( GL_POLYGON_OFFSET_FILL ); + GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); + } + else + { + GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); } - // go back to the world modelview matrix - backEnd.orientation = backEnd.viewParms.world; - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - } - - if ( r_showEntityTransforms->integer ) - { - trRefEntity_t *ent; - int i; - static const vec3_t mins = { -1, -1, -1 }; - static const vec3_t maxs = { 1, 1, 1 }; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); GL_Cull( cullType_t::CT_TWO_SIDED ); // set uniforms gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX ); - SetUniform_Color( gl_genericShader, Color::Black ); + SetUniform_Color( gl_genericShader, Color::Color(0, 0, 0, 0) ); // bind u_ColorMap gl_genericShader->SetUniform_ColorMapBindless( @@ -3473,13 +1607,13 @@ static void RB_RenderDebugUtils() for ( i = 0; i < backEnd.refdef.numEntities; i++, ent++ ) { - if ( ( ent->e.renderfx & RF_THIRD_PERSON ) && - backEnd.viewParms.portalLevel == 0 ) + if ( ent->e.reType != refEntityType_t::RT_MODEL ) { continue; } - if ( ent->cull == cullResult_t::CULL_OUT ) + if ( ( ent->e.renderfx & RF_THIRD_PERSON ) && + backEnd.viewParms.portalLevel == 0 ) { continue; } @@ -3491,9 +1625,15 @@ static void RB_RenderDebugUtils() Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Blue ); - - Tess_AddCube( vec3_origin, mins, maxs,Color::White ); + if ( r_showEntityBounds.Get() == 2) + { + Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Color(0, 0, 0.5, 0.4) ); + } + else + { + Tess_AddCube( vec3_origin, ent->localBounds[ 0 ], ent->localBounds[ 1 ], Color::Blue ); + Tess_AddCube( vec3_origin, mins, maxs,Color::White ); + } Tess_End(); } @@ -3501,6 +1641,7 @@ static void RB_RenderDebugUtils() // go back to the world modelview matrix backEnd.orientation = backEnd.viewParms.world; GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); + glDisable( GL_POLYGON_OFFSET_FILL ); } if ( r_showSkeleton->integer ) @@ -3721,72 +1862,6 @@ static void RB_RenderDebugUtils() } } - if ( r_showLightScissors->integer ) - { - interaction_t *ia; - int iaCount; - matrix_t ortho; - - gl_genericShader->SetVertexSkinning( false ); - gl_genericShader->SetVertexAnimation( false ); - gl_genericShader->SetTCGenEnvironment( false ); - gl_genericShader->SetTCGenLightmap( false ); - gl_genericShader->SetDepthFade( false ); - gl_genericShader->BindProgram( 0 ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE ); - GL_Cull( cullType_t::CT_TWO_SIDED ); - - // set uniforms - gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); - - // bind u_ColorMap - gl_genericShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); - gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); - - // set 2D virtual screen size - GL_PushMatrix(); - MatrixOrthogonalProjection( ortho, backEnd.viewParms.viewportX, - backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, - backEnd.viewParms.viewportY, - backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999 ); - GL_LoadProjectionMatrix( ortho ); - - for ( iaCount = 0, ia = &backEnd.viewParms.interactions[ 0 ]; iaCount < backEnd.viewParms.numInteractions; ) - { - SetUniform_Color( gl_genericShader, Color::White ); - - Tess_InstantQuad( *gl_genericShader, - ia->scissorX, ia->scissorY, ia->scissorWidth - 1.0f, ia->scissorHeight - 1.0f ); - - if ( !ia->next ) - { - if ( iaCount < ( backEnd.viewParms.numInteractions - 1 ) ) - { - // jump to next interaction and continue - ia++; - iaCount++; - } - else - { - // increase last time to leave for loop - iaCount++; - } - } - else - { - // just continue - ia = ia->next; - iaCount++; - } - } - - GL_PopMatrix(); - } - // GLSL shader isn't built when reflection mapping is disabled. if ( r_showCubeProbes.Get() && glConfig2.reflectionMapping && !( backEnd.refdef.rdflags & ( RDF_NOWORLDMODEL | RDF_NOCUBEMAP ) ) ) @@ -4152,8 +2227,8 @@ static void RB_RenderDebugUtils() plane_t splitFrustum[ 6 ]; for ( j = 0; j < 6; j++ ) { - VectorCopy( backEnd.viewParms.frustums[ 0 ][ j ].normal, splitFrustum[ j ].normal ); - splitFrustum[ j ].dist = backEnd.viewParms.frustums[ 0 ][ j ].dist; + VectorCopy( backEnd.viewParms.frustum[ j ].normal, splitFrustum[ j ].normal ); + splitFrustum[ j ].dist = backEnd.viewParms.frustum[ j ].dist; } // calculate split frustum corner points @@ -4431,10 +2506,8 @@ RB_RenderView */ static void RB_RenderView( bool depthPass ) { - int startTime = 0, endTime = 0; - - GLIMP_LOGCOMMENT( "--- RB_RenderView( %i surfaces, %i interactions ) ---", - backEnd.viewParms.numDrawSurfs, backEnd.viewParms.numInteractions ); + GLIMP_LOGCOMMENT( "--- RB_RenderView( %i surfaces ) ---", + backEnd.viewParms.numDrawSurfs ); GL_CheckErrors(); @@ -4469,12 +2542,6 @@ static void RB_RenderView( bool depthPass ) GL_CheckErrors(); - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - startTime = ri.Milliseconds(); - } - if( depthPass ) { if ( glConfig2.usingMaterialSystem ) { materialSystem.RenderMaterials( shaderSort_t::SS_DEPTH, shaderSort_t::SS_DEPTH, backEnd.viewParms.viewID ); @@ -4514,24 +2581,6 @@ static void RB_RenderView( bool depthPass ) RB_RenderSSAO(); - if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES) ) - { - glFinish(); - endTime = ri.Milliseconds(); - backEnd.pc.c_forwardAmbientTime += endTime - startTime; - } - - if ( glConfig2.shadowMapping ) - { - // render dynamic shadowing and lighting using shadow mapping - RB_RenderInteractionsShadowMapped(); - } - else - { - // render dynamic lighting - RB_RenderInteractions(); - } - // render global fog post process effect RB_RenderGlobalFog(); @@ -5140,24 +3189,20 @@ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ); for( int i = 0, j = 0; i < numLights; i++, j++ ) { - trRefLight_t *light = &refdef.lights[j]; - - while( light->l.inverseShadows ) { - light = &refdef.lights[++j]; - } + refLight_t *light = &refdef.lights[j]; - VectorCopy( light->l.origin, buffer[i].center ); - buffer[i].radius = light->l.radius; - VectorScale( light->l.color, 4.0f * light->l.scale, buffer[i].color ); - buffer[i].type = Util::ordinal( light->l.rlType ); - switch( light->l.rlType ) { + VectorCopy( light->origin, buffer[i].center ); + buffer[i].radius = light->radius; + VectorScale( light->color, 4.0f * light->scale, buffer[i].color ); + buffer[i].type = Util::ordinal( light->rlType ); + switch( light->rlType ) { case refLightType_t::RL_PROJ: - VectorCopy( light->l.projTarget, + VectorCopy( light->projTarget, buffer[i].direction ); - buffer[i].angle = cosf( atan2f( VectorLength( light->l.projUp), VectorLength( light->l.projTarget ) ) ); + buffer[i].angle = cosf( atan2f( VectorLength( light->projUp), VectorLength( light->projTarget ) ) ); break; case refLightType_t::RL_DIRECTIONAL: - VectorCopy( light->l.projTarget, + VectorCopy( light->projTarget, buffer[i].direction ); break; default: diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index b327378de..3cd0c9b9b 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -919,7 +919,7 @@ static void ParseTriangleSurface( dsurface_t* ds, drawVert_t* verts, bspSurface_ // We may have a nodraw surface, because they might still need to be around for movement clipping if ( s_worldData.shaders[LittleLong( ds->shaderNum )].surfaceFlags & SURF_NODRAW ) { - surfaceType_t skipData = surfaceType_t::SF_SKIP; + static surfaceType_t skipData = surfaceType_t::SF_SKIP; surf->data = &skipData; return; } @@ -2721,7 +2721,7 @@ static void R_CreateWorldVBO() { MergeDuplicateVertices( rendererSurfaces, numSurfaces, vboVerts, numVertsInitial, vboIdxs, 3 * numTriangles, numVerts, numIndices ); if ( glConfig2.usingMaterialSystem ) { - OptimiseMapGeometryMaterial( rendererSurfaces, numSurfaces ); + OptimiseMapGeometryMaterial( &s_worldData, rendererSurfaces, numSurfaces, vboVerts, numVerts, vboIdxs, numIndices ); } vertexAttributeSpec_t attrs[]{ @@ -2731,10 +2731,6 @@ static void R_CreateWorldVBO() { { ATTR_INDEX_TEXCOORD, GL_FLOAT, GL_HALF_FLOAT, &vboVerts[0].st, 4, sizeof( *vboVerts ), 0 }, }; - if ( glConfig2.usingGeometryCache ) { - geometryCache.AddMapGeometry( numVerts, numIndices, std::begin( attrs ), std::end( attrs ), vboIdxs ); - } - s_worldData.vbo = R_CreateStaticVBO( "staticWorld_VBO", std::begin( attrs ), std::end( attrs ), numVerts ); s_worldData.ibo = R_CreateStaticIBO2( "staticWorld_IBO", numTriangles, vboIdxs ); @@ -2757,8 +2753,6 @@ static void R_CreateWorldVBO() { // clear data used for sorting surface->viewCount = -1; - surface->lightCount = -1; - surface->interactionBits = 0; } ri.Hunk_FreeTempMemory( rendererSurfaces ); @@ -2980,10 +2974,6 @@ static void R_LoadNodesAndLeafs( lump_t *nodeLump, lump_t *leafLump ) s_worldData.numnodes = numNodes + numLeafs; s_worldData.numDecisionNodes = numNodes; - // ydnar: skybox optimization - s_worldData.numSkyNodes = 0; - s_worldData.skyNodes = (bspNode_t**) ri.Hunk_Alloc( WORLD_MAX_SKY_NODES * sizeof( *s_worldData.skyNodes ), ha_pref::h_low ); - // load nodes for ( i = 0; i < numNodes; i++, in++, out++ ) { diff --git a/src/engine/renderer/tr_cmds.cpp b/src/engine/renderer/tr_cmds.cpp index 6701d16ac..ab9d8a937 100644 --- a/src/engine/renderer/tr_cmds.cpp +++ b/src/engine/renderer/tr_cmds.cpp @@ -46,12 +46,6 @@ void R_PerformanceCounters() backEnd.pc.c_views, backEnd.pc.c_portals, backEnd.pc.c_batches, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes, backEnd.pc.c_indexes / 3 ); - Log::Notice("%i lights %i bout %i pvsout %i interactions", - tr.pc.c_dlights, - tr.pc.c_box_cull_light_out, - tr.pc.c_pvs_cull_light_out, - tr.pc.c_dlightInteractions ); - Log::Notice("%i draws %i vbos %i ibos %i verts %i tris", backEnd.pc.c_drawElements, backEnd.pc.c_vboVertexBuffers, backEnd.pc.c_vboIndexBuffers, @@ -79,26 +73,10 @@ void R_PerformanceCounters() { Log::Notice("viewcluster: %i", tr.visClusters[ tr.visIndex ] ); } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_LIGHTS )) - { - Log::Notice("dlight srf:%i culled:%i", tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled ); - - Log::Notice("dlights:%i interactions:%i", tr.pc.c_dlights, tr.pc.c_dlightInteractions ); - } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADOWCUBE_CULLING )) - { - Log::Notice("omni pyramid tests:%i bin:%i bclip:%i bout:%i", - tr.pc.c_pyramidTests, tr.pc.c_pyramid_cull_ent_in, tr.pc.c_pyramid_cull_ent_clip, tr.pc.c_pyramid_cull_ent_out ); - } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_FOG )) { Log::Notice("fog srf:%i batches:%i", backEnd.pc.c_fogSurfaces, backEnd.pc.c_fogBatches ); } - else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADING_TIMES )) - { - Log::Notice("forward shading times: ambient:%i lighting:%i", backEnd.pc.c_forwardAmbientTime, - backEnd.pc.c_forwardLightingTime ); - } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_NEAR_FAR )) { Log::Notice("zNear: %.0f zFar: %.0f", tr.viewParms.zNear, tr.viewParms.zFar ); @@ -245,8 +223,7 @@ R_AddSetupLightsCmd */ void R_AddSetupLightsCmd() { - if ( !glConfig2.realtimeLighting || - r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( !glConfig2.realtimeLighting ) { return; } diff --git a/src/engine/renderer/tr_fbo.cpp b/src/engine/renderer/tr_fbo.cpp index 28b116c3c..37833e7e4 100644 --- a/src/engine/renderer/tr_fbo.cpp +++ b/src/engine/renderer/tr_fbo.cpp @@ -429,8 +429,7 @@ void R_InitFBOs() R_AttachFBOTexturePackedDepthStencil( tr.currentDepthImage->texnum ); R_CheckFBO( tr.mainFBO[1] ); - if ( glConfig2.realtimeLighting - && r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( glConfig2.realtimeLighting ) { /* It's only required to create frame buffers only used by the tiled dynamic lighting renderer when this feature is enabled. */ @@ -451,55 +450,6 @@ void R_InitFBOs() R_CheckFBO( tr.lighttileFBO ); } - if ( glConfig2.shadowMapping ) - { - // shadowMap FBOs for shadow mapping offscreen rendering - for ( i = 0; i < MAX_SHADOWMAPS; i++ ) - { - width = height = shadowMapResolutions[ i ]; - - tr.shadowMapFBO[ i ] = R_CreateFBO( va( "_shadowMap%d", i ), width, height ); - R_BindFBO( tr.shadowMapFBO[ i ] ); - R_AttachFBOTexture2D( GL_TEXTURE_2D, - tr.shadowMapFBOImage[ i ]->texnum, - 0 ); - - R_CreateFBODepthBuffer( tr.shadowMapFBO[ i ], GL_DEPTH_COMPONENT24 ); - - R_CheckFBO( tr.shadowMapFBO[ i ] ); - } - - // sun requires different resolutions - for ( i = 0; i < MAX_SHADOWMAPS; i++ ) - { - width = height = sunShadowMapResolutions[ i ]; - - tr.sunShadowMapFBO[ i ] = R_CreateFBO( va( "_sunShadowMap%d", i ), width, height ); - R_BindFBO( tr.sunShadowMapFBO[ i ] ); - R_AttachFBOTexture2D( GL_TEXTURE_2D, - tr.sunShadowMapFBOImage[ i ]->texnum, - 0 ); - - R_CreateFBODepthBuffer( tr.sunShadowMapFBO[ i ], GL_DEPTH_COMPONENT24 ); - - if ( glConfig2.shadowingMode == shadowingMode_t::SHADOWING_EVSM32 - && r_evsmPostProcess->integer ) - { - R_AttachFBOTextureDepth( tr.sunShadowMapFBOImage[ i ]->texnum ); - - /* - Since we don't have a color attachment, the framebuffer will be considered incomplete. - Consequently, we must inform the driver that we do not wish to render to the color buffer. - We do this with a call to set the draw-buffer and read-buffer to GL_NONE: - */ - glDrawBuffer( GL_NONE ); - glReadBuffer( GL_NONE ); - } - - R_CheckFBO( tr.sunShadowMapFBO[ i ] ); - } - } - { width = glConfig.vidWidth; height = glConfig.vidHeight; diff --git a/src/engine/renderer/tr_image.cpp b/src/engine/renderer/tr_image.cpp index 60cfafab5..5a694da0c 100644 --- a/src/engine/renderer/tr_image.cpp +++ b/src/engine/renderer/tr_image.cpp @@ -2514,22 +2514,6 @@ static void R_CreateRandomNormalsImage() tr.randomNormalsImage = R_CreateImage( "_randomNormals", ( const byte ** ) &dataPtr, DEFAULT_SIZE, DEFAULT_SIZE, 1, imageParams ); } -static void R_CreateNoFalloffImage() -{ - byte data[ DEFAULT_SIZE ][ DEFAULT_SIZE ][ 4 ]; - // we use a solid white image instead of disabling texturing - memset(data, 255, sizeof(data)); - - byte *dataPtr = &data[0][0][0]; - - imageParams_t imageParams = {}; - imageParams.bits = IF_NOPICMIP; - imageParams.filterType = filterType_t::FT_DEFAULT; - imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - tr.noFalloffImage = R_CreateImage( "_noFalloff", ( const byte ** ) &dataPtr, 8, 8, 1, imageParams ); -} - static void R_CreateContrastRenderFBOImage() { if ( !glConfig2.bloom) @@ -2624,22 +2608,6 @@ static void R_CreateDepthRenderImage() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* Do not create lightTile images when the tiled renderer is not used. - - Those images are part of the tiled dynamic lighting renderer, - it's better to not create them and save memory when such effects - are disabled. - - Some hardware not powerful enough to supported dynamic lighting may - even not support the related formats. - - See https://github.com/DaemonEngine/Daemon/issues/745 */ - - return; - } - { int width = glConfig.vidWidth; int height = glConfig.vidHeight; @@ -2684,156 +2652,6 @@ static void R_CreatePortalRenderImage() tr.portalRenderImage = R_CreateImage( "_portalRender", nullptr, width, height, 1, imageParams ); } -// *INDENT-OFF* -static void R_CreateShadowMapFBOImage() -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - int numFactor = 1; - int format = IF_NOPICMIP; - - // FIXME: We should test if those formats are supported. - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - format |= IF_ONECOMP16F; - break; - case shadowingMode_t::SHADOWING_ESM32: - format |= IF_ONECOMP32F; - break; - case shadowingMode_t::SHADOWING_VSM16: - numFactor = 2; - format |= IF_TWOCOMP16F; - break; - case shadowingMode_t::SHADOWING_VSM32: - numFactor = 2; - format |= IF_TWOCOMP32F; - break; - case shadowingMode_t::SHADOWING_EVSM32: - numFactor = 2; - if ( r_evsmPostProcess->integer ) - { - format |= IF_ONECOMP32F; - } - else - { - format |= IF_RGBA32F; - } - break; - case shadowingMode_t::SHADOWING_NONE: - case shadowingMode_t::SHADOWING_BLOB: - default: - DAEMON_ASSERT( false ); - return; - } - - int numShadowMaps = MAX_SHADOWMAPS; - - if ( r_softShadowsPP->integer ) - { - numShadowMaps *= numFactor; - } - - filterType_t filter = filterType_t::FT_NEAREST; - - if( r_shadowMapLinearFilter->integer ) - { - filter = filterType_t::FT_LINEAR; - } - - imageParams_t imageParams = {}; - imageParams.bits = format; - imageParams.filterType = filter; - imageParams.wrapType = wrapTypeEnum_t::WT_ONE_CLAMP; - - for ( int i = 0; i < numShadowMaps; i++ ) - { - int size = shadowMapResolutions[ i % MAX_SHADOWMAPS ]; - - tr.shadowMapFBOImage[ i ] = R_CreateImage( va( "_shadowMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - tr.shadowClipMapFBOImage[ i ] = R_CreateImage( va( "_shadowClipMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - } - - // sun shadow maps - for ( int i = 0; i < numShadowMaps; i++ ) - { - int size = sunShadowMapResolutions[ i % MAX_SHADOWMAPS ]; - - tr.sunShadowMapFBOImage[ i ] = R_CreateImage( va( "_sunShadowMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - tr.sunShadowClipMapFBOImage[ i ] = R_CreateImage( va( "_sunShadowClipMapFBO%d", i ), nullptr, size, size, 1, imageParams ); - } -} - -// *INDENT-ON* - -// *INDENT-OFF* -static void R_CreateShadowCubeFBOImage() -{ - if ( !glConfig2.shadowMapping ) - { - return; - } - - int format = IF_NOPICMIP; - - // FIXME: We should test if those formats are supported. - switch( glConfig2.shadowingMode ) - { - case shadowingMode_t::SHADOWING_ESM16: - format |= IF_ONECOMP16F; - break; - case shadowingMode_t::SHADOWING_ESM32: - format |= IF_ONECOMP32F; - break; - case shadowingMode_t::SHADOWING_VSM16: - format |= IF_TWOCOMP16F; - break; - case shadowingMode_t::SHADOWING_VSM32: - format |= IF_TWOCOMP32F; - break; - case shadowingMode_t::SHADOWING_EVSM32: - if ( r_evsmPostProcess->integer ) - { - format |= IF_ONECOMP32F; - } - else - { - format |= IF_RGBA32F; - } - break; - case shadowingMode_t::SHADOWING_NONE: - case shadowingMode_t::SHADOWING_BLOB: - default: - DAEMON_ASSERT( false ); - return; - } - - filterType_t filter = filterType_t::FT_NEAREST; - - if ( r_shadowMapLinearFilter->integer ) - { - filter = filterType_t::FT_LINEAR; - } - - imageParams_t imageParams = {}; - imageParams.bits = format; - imageParams.filterType = filter; - imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - for ( int i = 0; i < 5; i++ ) - { - int size = shadowMapResolutions[ i ]; - - tr.shadowCubeFBOImage[ i ] = R_CreateCubeImage( va( "_shadowCubeFBO%d", i ), nullptr, size, size, imageParams ); - tr.shadowClipCubeFBOImage[ i ] = R_CreateCubeImage( va( "_shadowClipCubeFBO%d", i ), nullptr, size, size, imageParams ); - } -} - -// *INDENT-ON* - // *INDENT-OFF* static void R_CreateBlackCubeImage() { @@ -3027,14 +2845,11 @@ void R_CreateBuiltinImages() R_CreateRandomNormalsImage(); R_CreateFogImage(); - R_CreateNoFalloffImage(); R_CreateContrastRenderFBOImage(); R_CreateBloomRenderFBOImages(); R_CreateCurrentRenderImage(); R_CreateDepthRenderImage(); R_CreatePortalRenderImage(); - R_CreateShadowMapFBOImage(); - R_CreateShadowCubeFBOImage(); R_CreateBlackCubeImage(); R_CreateWhiteCubeImage(); R_CreateColorGradeImage(); diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 822cf317b..76c31833b 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -79,18 +79,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_nocull; cvar_t *r_facePlaneCull; cvar_t *r_nocurves; - cvar_t *r_lightScissors; - cvar_t *r_noLightVisCull; - cvar_t *r_noInteractionSort; - Cvar::Range> r_realtimeLightingRenderer( "r_realtimeLightingRenderer", - "renderer for real time lights: 0: legacy, 1: tiled", Cvar::NONE, - Util::ordinal(realtimeLightingRenderer_t::TILED), - Util::ordinal(realtimeLightingRenderer_t::LEGACY), - Util::ordinal(realtimeLightingRenderer_t::TILED) ); Cvar::Cvar r_realtimeLighting( "r_realtimeLighting", "Enable realtime light rendering", Cvar::NONE, true ); Cvar::Range> r_realtimeLightLayers( "r_realtimeLightLayers", "Dynamic light layers per tile, each layer holds 16 lights", Cvar::NONE, 4, 1, MAX_REF_LIGHTS / 16 ); - cvar_t *r_realtimeLightingCastShadows; cvar_t *r_precomputedLighting; Cvar::Cvar r_overbrightDefaultExponent("r_overbrightDefaultExponent", "default map light color shift (multiply by 2^x)", Cvar::NONE, 2); Cvar::Range> r_overbrightBits("r_overbrightBits", "clamp lightmap colors to 2^x", Cvar::NONE, 1, 0, 3); @@ -133,35 +124,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Cvar::Range> r_shadows( "cg_shadows", "shadowing mode", Cvar::NONE, Util::ordinal(shadowingMode_t::SHADOWING_BLOB), Util::ordinal(shadowingMode_t::SHADOWING_NONE), - Util::ordinal(shadowingMode_t::SHADOWING_EVSM32) ); - cvar_t *r_softShadows; - cvar_t *r_softShadowsPP; - cvar_t *r_shadowBlur; - - cvar_t *r_shadowMapSizeUltra; - cvar_t *r_shadowMapSizeVeryHigh; - cvar_t *r_shadowMapSizeHigh; - cvar_t *r_shadowMapSizeMedium; - cvar_t *r_shadowMapSizeLow; - - cvar_t *r_shadowMapSizeSunUltra; - cvar_t *r_shadowMapSizeSunVeryHigh; - cvar_t *r_shadowMapSizeSunHigh; - cvar_t *r_shadowMapSizeSunMedium; - cvar_t *r_shadowMapSizeSunLow; - - cvar_t *r_shadowLodBias; - cvar_t *r_shadowLodScale; - cvar_t *r_noShadowPyramids; - cvar_t *r_cullShadowPyramidFaces; - cvar_t *r_debugShadowMaps; - cvar_t *r_noLightFrustums; - cvar_t *r_shadowMapLinearFilter; - cvar_t *r_lightBleedReduction; - cvar_t *r_overDarkeningFactor; - cvar_t *r_shadowMapDepthScale; - cvar_t *r_parallelShadowSplits; - cvar_t *r_parallelShadowSplitWeight; + Util::ordinal(shadowingMode_t::SHADOWING_BLOB) ); cvar_t *r_mode; cvar_t *r_nobind; @@ -263,14 +226,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_showTris; cvar_t *r_showSky; - cvar_t *r_showShadowLod; - cvar_t *r_showShadowMaps; cvar_t *r_showSkeleton; - cvar_t *r_showEntityTransforms; - cvar_t *r_showLightTransforms; - cvar_t *r_showLightInteractions; - cvar_t *r_showLightScissors; - cvar_t *r_showLightBatches; cvar_t *r_showLightGrid; cvar_t *r_showLightTiles; cvar_t *r_showBatches; @@ -294,7 +250,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Util::ordinal( MaterialDebugMode::NONE ), Util::ordinal( MaterialDebugMode::OPAQUE_TRANSPARENT ) ); Cvar::Cvar r_materialDebug( "r_materialDebug", "Enable material debug SSBO", Cvar::NONE, false ); - cvar_t *r_showParallelShadowSplits; Cvar::Cvar r_profilerRenderSubGroups( "r_profilerRenderSubGroups", "Enable subgroup profiling in rendering shaders", Cvar::CHEAT, false ); Cvar::Range> r_profilerRenderSubGroupsMode( "r_profilerRenderSubGroupsMode", "Red: more wasted lanes, green: less wasted lanes; " @@ -1197,7 +1152,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_customwidth = Cvar_Get( "r_customwidth", "1600", CVAR_LATCH | CVAR_ARCHIVE ); r_customheight = Cvar_Get( "r_customheight", "1024", CVAR_LATCH | CVAR_ARCHIVE ); r_subdivisions = Cvar_Get( "r_subdivisions", "4", CVAR_LATCH ); - r_realtimeLightingCastShadows = Cvar_Get( "r_realtimeLightingCastShadows", "1", 0 ); r_precomputedLighting = Cvar_Get( "r_precomputedLighting", "1", CVAR_CHEAT | CVAR_LATCH ); Cvar::Latch( r_overbrightDefaultExponent ); Cvar::Latch( r_overbrightBits ); @@ -1221,15 +1175,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p // temporary latched variables that can only change over a restart r_singleShader = Cvar_Get( "r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); r_stitchCurves = Cvar_Get( "r_stitchCurves", "1", CVAR_CHEAT | CVAR_LATCH ); - r_debugShadowMaps = Cvar_Get( "r_debugShadowMaps", "0", CVAR_CHEAT | CVAR_LATCH ); - r_shadowMapLinearFilter = Cvar_Get( "r_shadowMapLinearFilter", "1", CVAR_CHEAT | CVAR_LATCH ); - r_lightBleedReduction = Cvar_Get( "r_lightBleedReduction", "0", CVAR_CHEAT | CVAR_LATCH ); - r_overDarkeningFactor = Cvar_Get( "r_overDarkeningFactor", "30.0", CVAR_CHEAT | CVAR_LATCH ); - r_shadowMapDepthScale = Cvar_Get( "r_shadowMapDepthScale", "1.41", CVAR_CHEAT | CVAR_LATCH ); - - r_parallelShadowSplitWeight = Cvar_Get( "r_parallelShadowSplitWeight", "0.9", CVAR_CHEAT ); - r_parallelShadowSplits = Cvar_Get( "r_parallelShadowSplits", "2", CVAR_CHEAT | CVAR_LATCH ); - AssertCvarRange( r_parallelShadowSplits, 0, MAX_SHADOWMAPS - 1, true ); // archived variables that can change at any time r_lodBias = Cvar_Get( "r_lodBias", "0", 0 ); @@ -1265,13 +1210,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_debugSort = Cvar_Get( "r_debugSort", "0", CVAR_CHEAT ); r_nocurves = Cvar_Get( "r_nocurves", "0", CVAR_CHEAT ); - r_lightScissors = Cvar_Get( "r_lightScissors", "1", CVAR_ARCHIVE ); - AssertCvarRange( r_lightScissors, 0, 2, true ); - - r_noLightVisCull = Cvar_Get( "r_noLightVisCull", "0", CVAR_CHEAT ); - r_noInteractionSort = Cvar_Get( "r_noInteractionSort", "0", CVAR_CHEAT ); - Cvar::Latch( r_realtimeLightingRenderer ); Cvar::Latch( r_realtimeLighting ); Cvar::Latch( r_realtimeLightLayers ); Cvar::Latch( r_preferBindlessTextures ); @@ -1327,61 +1266,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_shadows ); - r_softShadows = Cvar_Get( "r_softShadows", "0", CVAR_LATCH ); - AssertCvarRange( r_softShadows, 0, 6, true ); - - r_softShadowsPP = Cvar_Get( "r_softShadowsPP", "0", CVAR_LATCH ); - - r_shadowBlur = Cvar_Get( "r_shadowBlur", "2", CVAR_LATCH ); - - r_shadowMapSizeUltra = Cvar_Get( "r_shadowMapSizeUltra", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeUltra, 32, 2048, true ); - - r_shadowMapSizeVeryHigh = Cvar_Get( "r_shadowMapSizeVeryHigh", "512", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeVeryHigh, 32, 2048, true ); - - r_shadowMapSizeHigh = Cvar_Get( "r_shadowMapSizeHigh", "256", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeHigh, 32, 2048, true ); - - r_shadowMapSizeMedium = Cvar_Get( "r_shadowMapSizeMedium", "128", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeMedium, 32, 2048, true ); - - r_shadowMapSizeLow = Cvar_Get( "r_shadowMapSizeLow", "64", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeLow, 32, 2048, true ); - - shadowMapResolutions[ 0 ] = r_shadowMapSizeUltra->integer; - shadowMapResolutions[ 1 ] = r_shadowMapSizeVeryHigh->integer; - shadowMapResolutions[ 2 ] = r_shadowMapSizeHigh->integer; - shadowMapResolutions[ 3 ] = r_shadowMapSizeMedium->integer; - shadowMapResolutions[ 4 ] = r_shadowMapSizeLow->integer; - - r_shadowMapSizeSunUltra = Cvar_Get( "r_shadowMapSizeSunUltra", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunUltra, 32, 2048, true ); - - r_shadowMapSizeSunVeryHigh = Cvar_Get( "r_shadowMapSizeSunVeryHigh", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunVeryHigh, 512, 2048, true ); - - r_shadowMapSizeSunHigh = Cvar_Get( "r_shadowMapSizeSunHigh", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunHigh, 512, 2048, true ); - - r_shadowMapSizeSunMedium = Cvar_Get( "r_shadowMapSizeSunMedium", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunMedium, 512, 2048, true ); - - r_shadowMapSizeSunLow = Cvar_Get( "r_shadowMapSizeSunLow", "1024", CVAR_LATCH ); - AssertCvarRange( r_shadowMapSizeSunLow, 512, 2048, true ); - - sunShadowMapResolutions[ 0 ] = r_shadowMapSizeSunUltra->integer; - sunShadowMapResolutions[ 1 ] = r_shadowMapSizeSunVeryHigh->integer; - sunShadowMapResolutions[ 2 ] = r_shadowMapSizeSunHigh->integer; - sunShadowMapResolutions[ 3 ] = r_shadowMapSizeSunMedium->integer; - sunShadowMapResolutions[ 4 ] = r_shadowMapSizeSunLow->integer; - - r_shadowLodBias = Cvar_Get( "r_shadowLodBias", "0", CVAR_CHEAT ); - r_shadowLodScale = Cvar_Get( "r_shadowLodScale", "0.8", CVAR_CHEAT ); - r_noShadowPyramids = Cvar_Get( "r_noShadowPyramids", "0", CVAR_CHEAT ); - r_cullShadowPyramidFaces = Cvar_Get( "r_cullShadowPyramidFaces", "0", CVAR_CHEAT ); - r_noLightFrustums = Cvar_Get( "r_noLightFrustums", "1", CVAR_CHEAT ); - r_maxPolys = Cvar_Get( "r_maxpolys", "10000", CVAR_LATCH ); // 600 in vanilla Q3A AssertCvarRange( r_maxPolys, 600, 30000, true ); @@ -1390,14 +1274,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showTris = Cvar_Get( "r_showTris", "0", CVAR_CHEAT ); r_showSky = Cvar_Get( "r_showSky", "0", CVAR_CHEAT ); - r_showShadowLod = Cvar_Get( "r_showShadowLod", "0", CVAR_CHEAT ); - r_showShadowMaps = Cvar_Get( "r_showShadowMaps", "0", CVAR_CHEAT ); r_showSkeleton = Cvar_Get( "r_showSkeleton", "0", CVAR_CHEAT ); - r_showEntityTransforms = Cvar_Get( "r_showEntityTransforms", "0", CVAR_CHEAT ); - r_showLightTransforms = Cvar_Get( "r_showLightTransforms", "0", CVAR_CHEAT ); - r_showLightInteractions = Cvar_Get( "r_showLightInteractions", "0", CVAR_CHEAT ); - r_showLightScissors = Cvar_Get( "r_showLightScissors", "0", CVAR_CHEAT ); - r_showLightBatches = Cvar_Get( "r_showLightBatches", "0", CVAR_CHEAT ); r_showLightGrid = Cvar_Get( "r_showLightGrid", "0", CVAR_CHEAT ); r_showLightTiles = Cvar_Get("r_showLightTiles", "0", CVAR_CHEAT | CVAR_LATCH ); r_showBatches = Cvar_Get( "r_showBatches", "0", CVAR_CHEAT ); @@ -1410,7 +1287,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showBspNodes = Cvar_Get( "r_showBspNodes", "0", CVAR_CHEAT ); Cvar::Latch( r_showGlobalMaterials ); Cvar::Latch( r_materialDebug ); - r_showParallelShadowSplits = Cvar_Get( "r_showParallelShadowSplits", "0", CVAR_CHEAT | CVAR_LATCH ); Cvar::Latch( r_profilerRenderSubGroups ); } @@ -1662,6 +1538,10 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p GLSL_FinishGPUShaders(); } + if ( glConfig2.shadingLanguage420PackAvailable ) { + gl_shaderManager.BindBuffers(); + } + /* TODO: Move this into a loading step and don't render it to the screen For now though do it here to avoid the ugly square rendering appearing on top of the loading screen */ if ( glConfig2.reflectionMappingAvailable ) { diff --git a/src/engine/renderer/tr_light.cpp b/src/engine/renderer/tr_light.cpp index 4316a2e90..b7e074006 100644 --- a/src/engine/renderer/tr_light.cpp +++ b/src/engine/renderer/tr_light.cpp @@ -23,90 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_light.c #include "tr_local.h" -/* -============= -R_AddBrushModelInteractions - -Determine which dynamic lights may effect this bmodel -============= -*/ -void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - bspSurface_t *surf; - bspModel_t *bspModel = nullptr; - model_t *pModel = nullptr; - byte cubeSideBits; - - // cull the entire model if it is outside the view frustum - // and we don't care about proper shadowing - if ( ent->cull == cullResult_t::CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - if ( !iaType ) - { - return; - } - - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - - pModel = R_GetModelByHandle( ent->e.hModel ); - bspModel = pModel->bsp; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // set the light bits in all the surfaces - for (unsigned i = 0; i < bspModel->numSurfaces; i++ ) - { - surf = bspModel->firstSurface + i; - - // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || ( !surf->shader->interactLight && surf->shader->noShadows ) ) - { - continue; - } - - R_AddLightInteraction( light, surf->data, surf->shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } -} - /* ============================================================================= @@ -260,1264 +176,3 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve return true; } -/* -================= -R_SetupLightOrigin -Tr3B - needs finished transformMatrix -================= -*/ -void R_SetupLightOrigin( trRefLight_t *light ) -{ - vec3_t transformed; - - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - if ( !VectorCompare( light->l.center, vec3_origin ) ) - { - MatrixTransformPoint( light->transformMatrix, light->l.center, transformed ); - VectorSubtract( transformed, light->l.origin, light->direction ); - VectorNormalize( light->direction ); - - VectorMA( light->l.origin, 10000, light->direction, light->origin ); - } - else - { - vec3_t down = { 0, 0, 1 }; - - MatrixTransformPoint( light->transformMatrix, down, transformed ); - VectorSubtract( transformed, light->l.origin, light->direction ); - VectorNormalize( light->direction ); - - VectorMA( light->l.origin, 10000, light->direction, light->origin ); - - VectorCopy( light->l.origin, light->origin ); - } - } - else - { - MatrixTransformPoint( light->transformMatrix, light->l.center, light->origin ); - } -} - -/* -================= -R_SetupLightLocalBounds -================= -*/ -void R_SetupLightLocalBounds( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - light->localBounds[ 0 ][ 0 ] = -light->l.radius; - light->localBounds[ 0 ][ 1 ] = -light->l.radius; - light->localBounds[ 0 ][ 2 ] = -light->l.radius; - light->localBounds[ 1 ][ 0 ] = light->l.radius; - light->localBounds[ 1 ][ 1 ] = light->l.radius; - light->localBounds[ 1 ][ 2 ] = light->l.radius; - break; - } - - case refLightType_t::RL_PROJ: - { - int j; - vec3_t farCorners[ 4 ]; - - ClearBounds( light->localBounds[ 0 ], light->localBounds[ 1 ] ); - - // transform frustum from world space to local space - R_CalcFrustumFarCorners( light->localFrustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( light->localFrustum, nearCorners ); - - for ( j = 0; j < 4; j++ ) - { - AddPointToBounds( farCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - AddPointToBounds( nearCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - } - } - else - { - vec3_t top; - const plane_t* frustum = light->localFrustum; - - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - AddPointToBounds( top, light->localBounds[ 0 ], light->localBounds[ 1 ] ); - - for ( j = 0; j < 4; j++ ) - { - AddPointToBounds( farCorners[ j ], light->localBounds[ 0 ], light->localBounds[ 1 ] ); - } - } - - break; - } - - default: - break; - } - - light->sphereRadius = RadiusFromBounds( light->localBounds[ 0 ], light->localBounds[ 1 ] ); -} - -/* -================= -R_SetupLightWorldBounds -Tr3B - needs finished transformMatrix -================= -*/ -void R_SetupLightWorldBounds( trRefLight_t *light ) -{ - MatrixTransformBounds(light->transformMatrix, light->localBounds[0], light->localBounds[1], light->worldBounds[0], light->worldBounds[1]); -} - -/* -================= -R_SetupLightView -================= -*/ -void R_SetupLightView( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_PROJ: - case refLightType_t::RL_DIRECTIONAL: - { - MatrixAffineInverse( light->transformMatrix, light->viewMatrix ); - break; - } - default: - Sys::Drop( "R_SetupLightView: Bad rlType" ); - } -} - -void R_TessLight( const trRefLight_t *light, const Color::Color& color, bool use_default_color ) -{ - int j; - - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - Tess_AddCube( vec3_origin, light->localBounds[ 0 ], light->localBounds[ 1 ], use_default_color ? Color::White : color ); - break; - case refLightType_t::RL_PROJ: - { - vec3_t farCorners[ 4 ]; - vec4_t quadVerts[ 4 ]; - - R_CalcFrustumFarCorners( light->localFrustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( light->localFrustum, nearCorners ); - - // draw outer surfaces - for ( j = 0; j < 4; j++ ) - { - Vector4Set( quadVerts[ 0 ], nearCorners[ j ][ 0 ], nearCorners[ j ][ 1 ], nearCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ j ][ 0 ], farCorners[ j ][ 1 ], farCorners[ j ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[( j + 1 ) % 4 ][ 0 ], farCorners[( j + 1 ) % 4 ][ 1 ], farCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[( j + 1 ) % 4 ][ 0 ], nearCorners[( j + 1 ) % 4 ][ 1 ], nearCorners[( j + 1 ) % 4 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Cyan : color ); - } - - // draw far cap - Vector4Set( quadVerts[ 0 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Red : color ); - - // draw near cap - Vector4Set( quadVerts[ 0 ], nearCorners[ 0 ][ 0 ], nearCorners[ 0 ][ 1 ], nearCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], nearCorners[ 1 ][ 0 ], nearCorners[ 1 ][ 1 ], nearCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], nearCorners[ 2 ][ 0 ], nearCorners[ 2 ][ 1 ], nearCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], nearCorners[ 3 ][ 0 ], nearCorners[ 3 ][ 1 ], nearCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Green : color ); - } - else - { - vec3_t top; - const plane_t* frustum = light->localFrustum; - - // no light_start, just use the top vertex (doesn't need to be mirrored) - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - - // draw pyramid - for ( j = 0; j < 4; j++ ) - { - Color::Color32Bit iColor = use_default_color ? Color::Cyan : color; - - VectorCopy( top, tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - - VectorCopy( farCorners[( j + 1 ) % 4 ], tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - - VectorCopy( farCorners[ j ], tess.verts[ tess.numVertexes ].xyz ); - tess.verts[ tess.numVertexes ].color = iColor; - tess.indexes[ tess.numIndexes++ ] = tess.numVertexes; - tess.numVertexes++; - } - - Vector4Set( quadVerts[ 0 ], farCorners[ 0 ][ 0 ], farCorners[ 0 ][ 1 ], farCorners[ 0 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 1 ], farCorners[ 1 ][ 0 ], farCorners[ 1 ][ 1 ], farCorners[ 1 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 2 ], farCorners[ 2 ][ 0 ], farCorners[ 2 ][ 1 ], farCorners[ 2 ][ 2 ], 1 ); - Vector4Set( quadVerts[ 3 ], farCorners[ 3 ][ 0 ], farCorners[ 3 ][ 1 ], farCorners[ 3 ][ 2 ], 1 ); - Tess_AddQuadStamp2( quadVerts, use_default_color ? Color::Red : color ); - } - } - break; - default: - break; - } -} - -void R_TessLight( const trRefLight_t *light, const Color::Color& color ) -{ - R_TessLight ( light, color, false ); -} - -void R_TessLight( const trRefLight_t *light ) -{ - R_TessLight ( light, Color::Color(), true ); -} - -/* -================= -R_SetupLightFrustum -================= -*/ -void R_SetupLightFrustum( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - int i; - vec3_t planeNormal; - vec3_t planeOrigin; - axis_t axis; - - QuatToAxis( light->l.rotation, axis ); - - for ( i = 0; i < 3; i++ ) - { - VectorMA( light->l.origin, light->l.radius, axis[ i ], planeOrigin ); - VectorNegate( axis[ i ], planeNormal ); - VectorNormalize( planeNormal ); - - VectorCopy( planeNormal, light->frustum[ i ].normal ); - light->frustum[ i ].dist = DotProduct( planeOrigin, planeNormal ); - } - - for ( i = 0; i < 3; i++ ) - { - VectorMA( light->l.origin, -light->l.radius, axis[ i ], planeOrigin ); - VectorCopy( axis[ i ], planeNormal ); - VectorNormalize( planeNormal ); - - VectorCopy( planeNormal, light->frustum[ i + 3 ].normal ); - light->frustum[ i + 3 ].dist = DotProduct( planeOrigin, planeNormal ); - } - - for ( i = 0; i < 6; i++ ) - { - vec_t length, ilength; - - light->frustum[ i ].type = PLANE_NON_AXIAL; - - // normalize - length = VectorLength( light->frustum[ i ].normal ); - - if ( length ) - { - ilength = 1.0f / length; - light->frustum[ i ].normal[ 0 ] *= ilength; - light->frustum[ i ].normal[ 1 ] *= ilength; - light->frustum[ i ].normal[ 2 ] *= ilength; - light->frustum[ i ].dist *= ilength; - } - - SetPlaneSignbits( &light->frustum[ i ] ); - } - - break; - } - - case refLightType_t::RL_PROJ: - { - int i; - - // transform local frustum to world space - plane_t worldFrustum[ 6 ]; - for ( i = 0; i < 6; i++ ) - { - MatrixTransformPlane( light->transformMatrix, light->localFrustum[ i ], worldFrustum[ i ] ); - } - - // normalize all frustum planes - for ( i = 0; i < 6; i++ ) - { - PlaneNormalize( worldFrustum[ i ] ); - - VectorCopy( worldFrustum[ i ].normal, light->frustum[ i ].normal ); - light->frustum[ i ].dist = worldFrustum[ i ].dist; - - light->frustum[ i ].type = PLANE_NON_AXIAL; - - SetPlaneSignbits( &light->frustum[ i ] ); - } - - break; - } - - default: - break; - } -} - -/* -================= -R_SetupLightProjection -================= -*/ -// *INDENT-OFF* -void R_SetupLightProjection( trRefLight_t *light ) -{ - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - case refLightType_t::RL_DIRECTIONAL: - { - MatrixSetupScale( light->projectionMatrix, 1.0f / light->l.radius, 1.0f / light->l.radius, 1.0f / light->l.radius ); - break; - } - - case refLightType_t::RL_PROJ: - { - plane_t lightProject[ 4 ]; - - { - vec3_t right, up, normal; - - float rLen = VectorNormalize2( light->l.projRight, right ); - float uLen = VectorNormalize2( light->l.projUp, up ); - - CrossProduct( up, right, normal ); - VectorNormalize( normal ); - - vec_t dist = DotProduct( light->l.projTarget, normal ); - - if ( dist < 0 ) - { - dist = -dist; - VectorInverse( normal ); - } - - VectorScale( right, ( 0.5f * dist ) / rLen, right ); - VectorScale( up, - ( 0.5f * dist ) / uLen, up ); - - PlaneSet( lightProject[ 0 ], right[ 0 ], right[ 1 ], right[ 2 ], 0 ); - PlaneSet( lightProject[ 1 ], up[ 0 ], up[ 1 ], up[ 2 ], 0 ); - PlaneSet( lightProject[ 2 ], normal[ 0 ], normal[ 1 ], normal[ 2 ], 0 ); - } - - // now offset to center - { - vec3_t targetGlobal; - VectorSet( targetGlobal, - light->l.projTarget[ 0 ], light->l.projTarget[ 1 ], - light->l.projTarget[ 2 ] ); - - { - vec_t a = DotProduct( targetGlobal, lightProject[ 0 ].normal ); - vec_t b = DotProduct( targetGlobal, lightProject[ 2 ].normal ); - vec_t ofs = 0.5 - a / b; - - VectorMA( lightProject[ 0 ].normal, ofs, lightProject[ 2 ].normal, lightProject[ 0 ].normal ); - } - - { - vec_t a = DotProduct( targetGlobal, lightProject[ 1 ].normal ); - vec_t b = DotProduct( targetGlobal, lightProject[ 2 ].normal ); - vec_t ofs = 0.5 - a / b; - - VectorMA( lightProject[ 0 ].normal, ofs, lightProject[ 2 ].normal, lightProject[ 0 ].normal ); - } - } - - { - vec3_t start; - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - VectorCopy( light->l.projStart, start ); - } - else - { - VectorClear( start ); - } - - vec3_t stop; - - if ( !VectorCompare( light->l.projEnd, vec3_origin ) ) - { - VectorCopy( light->l.projEnd, stop ); - } - else - { - VectorCopy( light->l.projTarget, stop ); - } - - // Calculate the falloff vector - vec3_t falloff; - - { - VectorSubtract( stop, start, falloff ); - - vec_t falloffLen = VectorNormalize( falloff ); - light->falloffLength = falloffLen; - - if ( falloffLen <= 0 ) - { - falloffLen = 1; - } - - //FIXME ? - VectorScale( falloff, 1.0f / falloffLen, falloff ); - } - - PlaneSet( lightProject[ 3 ], falloff, -DotProduct( start, falloff ) ); - } - - // we want the planes of s=0, s=q, t=0, and t=q - plane_t *frustum = light->localFrustum; - - frustum[ FRUSTUM_LEFT ] = lightProject[ 0 ]; - - frustum[ FRUSTUM_BOTTOM ] = lightProject[ 1 ]; - - { - vec3_t normal; - VectorSubtract( lightProject[ 2 ].normal, lightProject[ 0 ].normal, normal ); - - PlaneSet( frustum[ FRUSTUM_RIGHT ], normal, 0 ); - } - - { - vec3_t normal; - VectorSubtract( lightProject[ 2 ].normal, lightProject[ 1 ].normal, normal ); - - PlaneSet( frustum[ FRUSTUM_TOP ], normal, 0 ); - } - - { - // we want the planes of s=0 and s=1 for front and rear clipping planes - frustum[ FRUSTUM_NEAR ] = lightProject[ 3 ]; - } - - { - vec3_t normal; - VectorNegate( lightProject[ 3 ].normal, normal ); - vec_t dist = - lightProject[ 3 ].dist - 1.0f; - - PlaneSet( frustum[ FRUSTUM_FAR ], normal, dist ); - } - - { - // calculate the new projection matrix from the frustum planes - float *proj = light->projectionMatrix; - MatrixFromPlanes( proj, frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_BOTTOM ], frustum[ FRUSTUM_TOP ], frustum[ FRUSTUM_NEAR ], frustum[ FRUSTUM_FAR ] ); - - //MatrixMultiply2(proj, newProjection); - - // scale the falloff texture coordinate so that 0.5 is at the apex and 0.0 - // as at the base of the pyramid. - // TODO: I don't like hacking the matrix like this, but all attempts to use - // a transformation seemed to affect too many other things. - //proj[10] *= 0.5f; - } - - // normalise all frustum planes - for ( int i = 0; i < 6; i++ ) - { - PlaneNormalize( frustum[ i ] ); - } - - break; - } - - default: - Sys::Drop( "R_SetupLightProjection: Bad rlType" ); - } -} - -// *INDENT-ON* - -/* -================= -R_AddLightInteraction -================= -*/ -bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_t *surfaceShader, byte cubeSideBits, - interactionType_t iaType ) -{ - int iaIndex; - interaction_t *ia; - - // skip all surfaces that don't matter for lighting only pass - if ( surfaceShader ) - { - if ( surfaceShader->isSky || ( !surfaceShader->interactLight && surfaceShader->noShadows ) ) - { - return false; - } - } - else - { - return false; - } - - // instead of checking for overflow, we just mask the index - // so it wraps around - iaIndex = tr.refdef.numInteractions & INTERACTION_MASK; - ia = &tr.refdef.interactions[ iaIndex ]; - tr.refdef.numInteractions++; - - light->noSort = iaIndex == 0; - - // connect to interaction grid - if ( !light->firstInteraction ) - { - light->firstInteraction = ia; - } - - if ( light->lastInteraction ) - { - light->lastInteraction->next = ia; - } - - light->lastInteraction = ia; - - // update counters - light->numInteractions++; - - if( !(iaType & IA_LIGHT) ) { - light->numShadowOnlyInteractions++; - } - if( !(iaType & (IA_SHADOW | IA_SHADOWCLIP) ) ) { - light->numLightOnlyInteractions++; - } - - ia->next = nullptr; - - ia->type = iaType; - - ia->light = light; - ia->entity = tr.currentEntity; - ia->surface = surface; - ia->shader = surfaceShader; - ia->shaderNum = surfaceShader->sortedIndex; - - ia->cubeSideBits = cubeSideBits; - - ia->scissorX = light->scissor.coords[ 0 ]; - ia->scissorY = light->scissor.coords[ 1 ]; - ia->scissorWidth = light->scissor.coords[ 2 ] - light->scissor.coords[ 0 ]; - ia->scissorHeight = light->scissor.coords[ 3 ] - light->scissor.coords[ 1 ]; - - tr.pc.c_dlightInteractions++; - - return true; -} - -/* -================= -InteractionCompare -compare function for qsort() -================= -*/ -static int InteractionCompare( const void *a, const void *b ) -{ - // shader first - if ( ( ( interaction_t * ) a )->shaderNum < ( ( interaction_t * ) b )->shaderNum ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->shaderNum > ( ( interaction_t * ) b )->shaderNum ) - { - return 1; - } - - // then entity - if ( ( ( interaction_t * ) a )->entity == &tr.worldEntity && ( ( interaction_t * ) b )->entity != &tr.worldEntity ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->entity != &tr.worldEntity && ( ( interaction_t * ) b )->entity == &tr.worldEntity ) - { - return 1; - } - - else if ( ( ( interaction_t * ) a )->entity < ( ( interaction_t * ) b )->entity ) - { - return -1; - } - - else if ( ( ( interaction_t * ) a )->entity > ( ( interaction_t * ) b )->entity ) - { - return 1; - } - - return 0; -} - -/* -================= -R_SortInteractions -================= -*/ -void R_SortInteractions( trRefLight_t *light ) -{ - int i; - int iaFirstIndex; - interaction_t *iaFirst; - interaction_t *ia; - interaction_t *iaLast; - - if ( r_noInteractionSort->integer ) - { - return; - } - - if ( !light->numInteractions || light->noSort ) - { - return; - } - - iaFirst = light->firstInteraction; - iaFirstIndex = light->firstInteraction - tr.refdef.interactions; - - // sort by material etc. for geometry batching in the renderer backend - qsort( iaFirst, light->numInteractions, sizeof( interaction_t ), InteractionCompare ); - - // fix linked list - iaLast = nullptr; - - for ( i = 0; i < light->numInteractions; i++ ) - { - ia = &tr.refdef.interactions[ iaFirstIndex + i ]; - - if ( iaLast ) - { - iaLast->next = ia; - } - - ia->next = nullptr; - - iaLast = ia; - } -} - -/* -================= -R_IntersectRayPlane -================= -*/ -static void R_IntersectRayPlane( const vec3_t v1, const vec3_t v2, cplane_t *plane, vec3_t res ) -{ - vec3_t v; - float sect; - - VectorSubtract( v1, v2, v ); - sect = - ( DotProduct( plane->normal, v1 ) - plane->dist ) / DotProduct( plane->normal, v ); - VectorScale( v, sect, v ); - VectorAdd( v1, v, res ); -} - -/* -================= -R_AddPointToLightScissor -================= -*/ -static void R_AddPointToLightScissor( trRefLight_t *light, const vec3_t world ) -{ - vec4_t eye, clip, normalized, window; - - R_TransformWorldToClip( world, tr.viewParms.world.viewMatrix, tr.viewParms.projectionMatrix, eye, clip ); - R_TransformClipToWindow( clip, &tr.viewParms, normalized, window ); - - light->scissor.coords[ 0 ] = std::min( light->scissor.coords[ 0 ], ( int ) window[ 0 ] ); - light->scissor.coords[ 1 ] = std::min( light->scissor.coords[ 1 ], ( int ) window[ 1 ] ); - light->scissor.coords[ 2 ] = std::max( light->scissor.coords[ 2 ], ( int ) window[ 0 ] ); - light->scissor.coords[ 3 ] = std::max( light->scissor.coords[ 3 ], ( int ) window[ 1 ] ); -} - -static int R_ClipEdgeToPlane( cplane_t plane, const vec3_t in_world1, const vec3_t in_world2, vec3_t out_world1, vec3_t out_world2 ) -{ - vec3_t intersect; - - // check edge to frustrum plane - int side1 = ( ( DotProduct( plane.normal, in_world1 ) - plane.dist ) >= 0.0f ); - int side2 = ( ( DotProduct( plane.normal, in_world2 ) - plane.dist ) >= 0.0f ); - - int sides = side1 | ( side2 << 1 ); - - // edge completely behind plane - if ( !sides ) - { - return 0; - } - - if ( !side1 || !side2 ) - { - R_IntersectRayPlane( in_world1, in_world2, &plane, intersect ); - } - - if ( !side1 ) - { - VectorCopy( intersect, out_world1 ); - VectorCopy( in_world2, out_world2 ); - } - else if ( !side2 ) - { - VectorCopy( in_world1, out_world1 ); - VectorCopy( intersect, out_world2 ); - } - else - { - // edge doesn't intersect plane - VectorCopy( in_world1, out_world1 ); - VectorCopy( in_world2, out_world2 ); - } - - return sides; -} - -/* -================= -R_AddEdgeToLightScissor -================= -*/ -static void R_AddEdgeToLightScissor( trRefLight_t *light, const vec3_t in_world1, const vec3_t in_world2 ) -{ - int i; - cplane_t *frust; - vec3_t clip1, clip2; - - if ( r_lightScissors->integer == 1 ) - { - // only clip against near plane - frust = &tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ]; - int sides = R_ClipEdgeToPlane( *frust, in_world1, in_world2, clip1, clip2 ); - if ( !sides ) - { - return; - } - R_AddPointToLightScissor( light, clip1 ); - R_AddPointToLightScissor( light, clip2 ); - } - else if ( r_lightScissors->integer == 2 ) - { - // clip against all planes - for ( i = 0; i < FRUSTUM_PLANES; i++ ) - { - frust = &tr.viewParms.frustums[ 0 ][ i ]; - - int sides = R_ClipEdgeToPlane( *frust, in_world1, in_world2, clip1, clip2 ); - - if ( !sides ) - { - continue; // edge behind plane - } - - R_AddPointToLightScissor( light, clip1 ); - R_AddPointToLightScissor( light, clip2 ); - } - } -} - -/* -================= -R_SetupLightScissor -Recturns the screen space rectangle taken by the box. - (Clips the box to the near plane to have correct results even if the box intersects the near plane) -Tr3B - recoded from Tenebrae2 -================= -*/ -void R_SetupLightScissor( trRefLight_t *light ) -{ - vec3_t v1, v2; - - light->scissor.coords[ 0 ] = tr.viewParms.viewportX; - light->scissor.coords[ 1 ] = tr.viewParms.viewportY; - light->scissor.coords[ 2 ] = tr.viewParms.viewportX + tr.viewParms.viewportWidth; - light->scissor.coords[ 3 ] = tr.viewParms.viewportY + tr.viewParms.viewportHeight; - - // transform world light corners to eye space -> clip space -> window space - // and extend the light scissor's mins maxs by resulting window coords - light->scissor.coords[ 0 ] = 100000000; - light->scissor.coords[ 1 ] = 100000000; - light->scissor.coords[ 2 ] = -100000000; - light->scissor.coords[ 3 ] = -100000000; - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - { - // top plane - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - // bottom plane - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - // sides - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 1 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 0 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - - VectorSet( v1, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 0 ][ 2 ] ); - VectorSet( v2, light->worldBounds[ 1 ][ 0 ], light->worldBounds[ 0 ][ 1 ], light->worldBounds[ 1 ][ 2 ] ); - R_AddEdgeToLightScissor( light, v1, v2 ); - break; - } - - case refLightType_t::RL_PROJ: - { - int j; - vec3_t farCorners[ 4 ]; - plane_t frustum[ 6 ]; - for ( j = 0; j < 6; j++ ) - { - VectorCopy( light->frustum[ j ].normal, frustum[ j ].normal ); - frustum[ j ].dist = light->frustum[ j ].dist; - } - - R_CalcFrustumFarCorners( frustum, farCorners ); - - if ( !VectorCompare( light->l.projStart, vec3_origin ) ) - { - vec3_t nearCorners[ 4 ]; - - // calculate the vertices defining the top area - R_CalcFrustumNearCorners( frustum, nearCorners ); - - for ( j = 0; j < 4; j++ ) - { - // outer quad - R_AddEdgeToLightScissor( light, nearCorners[ j ], farCorners[ j ] ); - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, farCorners[( j + 1 ) % 4 ], nearCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, nearCorners[( j + 1 ) % 4 ], nearCorners[ j ] ); - - // far cap - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - - // near cap - R_AddEdgeToLightScissor( light, nearCorners[ j ], nearCorners[( j + 1 ) % 4 ] ); - } - } - else - { - vec3_t top; - - // no light_start, just use the top vertex (doesn't need to be mirrored) - PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_RIGHT ], frustum[ FRUSTUM_TOP ], top ); - - for ( j = 0; j < 4; j++ ) - { - R_AddEdgeToLightScissor( light, farCorners[ j ], farCorners[( j + 1 ) % 4 ] ); - R_AddEdgeToLightScissor( light, top, farCorners[ j ] ); - } - } - - break; - } - - default: - break; - } - - light->scissor.coords[ 0 ] = Math::Clamp( light->scissor.coords[ 0 ], tr.viewParms.viewportX, tr.viewParms.viewportX + tr.viewParms.viewportWidth ); - light->scissor.coords[ 2 ] = Math::Clamp( light->scissor.coords[ 2 ], tr.viewParms.viewportX, tr.viewParms.viewportX + tr.viewParms.viewportWidth ); - - light->scissor.coords[ 1 ] = Math::Clamp( light->scissor.coords[ 1 ], tr.viewParms.viewportY, tr.viewParms.viewportY + tr.viewParms.viewportHeight ); - light->scissor.coords[ 3 ] = Math::Clamp( light->scissor.coords[ 3 ], tr.viewParms.viewportY, tr.viewParms.viewportY + tr.viewParms.viewportHeight ); -} - -/* -============= -R_CalcLightCubeSideBits -============= -*/ -// *INDENT-OFF* -byte R_CalcLightCubeSideBits( trRefLight_t *light, vec3_t worldBounds[ 2 ] ) -{ - int i; - int cubeSide; - byte cubeSideBits; - float xMin, xMax, yMin, yMax; - float zNear, zFar; - float fovX, fovY; - vec3_t angles; - matrix_t tmpMatrix, rotationMatrix, transformMatrix, viewMatrix, projectionMatrix, viewProjectionMatrix; - frustum_t frustum; - cplane_t *clipPlane; - int r; - bool anyClip; - bool culled; - - if ( light->l.rlType != refLightType_t::RL_OMNI || !glConfig2.shadowMapping || r_noShadowPyramids->integer ) - { - return CUBESIDE_CLIPALL; - } - - cubeSideBits = 0; - - for ( cubeSide = 0; cubeSide < 6; cubeSide++ ) - { - switch ( cubeSide ) - { - default: // 0 - { - // view parameters - VectorSet( angles, 0, 0, 0 ); - break; - } - - case 1: - { - VectorSet( angles, 0, 180, 0 ); - break; - } - - case 2: - { - VectorSet( angles, 0, 90, 0 ); - break; - } - - case 3: - { - VectorSet( angles, 0, 270, 0 ); - break; - } - - case 4: - { - VectorSet( angles, -90, 0, 0 ); - break; - } - - case 5: - { - VectorSet( angles, 90, 0, 0 ); - break; - } - } - - // Quake -> OpenGL view matrix from light perspective - MatrixFromAngles( rotationMatrix, angles[ PITCH ], angles[ YAW ], angles[ ROLL ] ); - MatrixSetupTransformFromRotation( transformMatrix, rotationMatrix, light->origin ); - MatrixAffineInverse( transformMatrix, tmpMatrix ); - - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - MatrixMultiply( quakeToOpenGLMatrix, tmpMatrix, viewMatrix ); - - // OpenGL projection matrix - fovX = 90; - fovY = 90; - - zNear = 1.0f; - zFar = light->sphereRadius; - - xMax = zNear * tanf( fovX * M_PI / 360.0f ); - xMin = -xMax; - - yMax = zNear * tanf( fovY * M_PI / 360.0f ); - yMin = -yMax; - - MatrixPerspectiveProjection( projectionMatrix, xMin, xMax, yMin, yMax, zNear, zFar ); - - // calculate frustum planes using the modelview projection matrix - MatrixMultiply( projectionMatrix, viewMatrix, viewProjectionMatrix ); - R_SetupFrustum2( frustum, viewProjectionMatrix ); - - // use the frustum planes to cut off shadowmaps beyond the light volume - anyClip = false; - culled = false; - - for ( i = 0; i < 5; i++ ) - { - clipPlane = &frustum[ i ]; - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], clipPlane ); - - if ( r == 2 ) - { - culled = true; - break; - } - - if ( r == 3 ) - { - anyClip = true; - } - } - - if ( !culled ) - { - if ( !anyClip ) - { - // completely inside frustum - tr.pc.c_pyramid_cull_ent_in++; - } - else - { - // partially clipped - tr.pc.c_pyramid_cull_ent_clip++; - } - - cubeSideBits |= ( 1 << cubeSide ); - } - else - { - // completely outside frustum - tr.pc.c_pyramid_cull_ent_out++; - } - } - - tr.pc.c_pyramidTests++; - - return cubeSideBits; -} - -// *INDENT-ON* - -/* -================= -R_SetupLightLOD -================= -*/ -void R_SetupLightLOD( trRefLight_t *light ) -{ - float radius; - float flod, lodscale; - float projectedRadius; - int lod; - int numLods; - - if ( light->l.noShadows ) - { - light->shadowLOD = -1; - return; - } - - numLods = 5; - - // compute projected bounding sphere - // and use that as a criteria for selecting LOD - radius = light->sphereRadius; - - if ( ( projectedRadius = R_ProjectRadius( radius, light->l.origin ) ) != 0 ) - { - lodscale = r_shadowLodScale->value; - - if ( lodscale > 20 ) - { - lodscale = 20; - } - - flod = 1.0f - projectedRadius * lodscale; - } - else - { - // object intersects near view plane, e.g. view weapon - flod = 0; - } - - flod *= numLods; - lod = Q_ftol( flod ); - - if ( lod < 0 ) - { - lod = 0; - } - else if ( lod >= numLods ) - { - //lod = numLods - 1; - } - - lod += r_shadowLodBias->integer; - - if ( lod < 0 ) - { - lod = 0; - } - - if ( lod >= numLods ) - { - // don't draw any shadow - lod = -1; - - //lod = numLods - 1; - } - - // never give ultra quality for point lights - if ( lod == 0 && light->l.rlType == refLightType_t::RL_OMNI ) - { - lod = 1; - } - - light->shadowLOD = lod; -} - -/* -================= -R_SetupLightShader -================= -*/ -void R_SetupLightShader( trRefLight_t *light ) -{ - if ( !light->l.attenuationShader ) - { - switch ( light->l.rlType ) - { - default: - case refLightType_t::RL_OMNI: - light->shader = tr.defaultDynamicLightShader; - break; - - case refLightType_t::RL_PROJ: - light->shader = tr.defaultProjectedLightShader; - break; - } - } - else - { - light->shader = R_GetShaderByHandle( light->l.attenuationShader ); - } -} - -/* -=============== -R_ComputeFinalAttenuation -=============== -*/ -void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ) -{ - matrix_t matrix; - - GLIMP_LOGCOMMENT( "--- R_ComputeFinalAttenuation ---" ); - - RB_CalcTexMatrix( &pStage->bundle[ TB_COLORMAP ], matrix ); - - MatrixMultiply( matrix, light->attenuationMatrix, light->attenuationMatrix2 ); -} - -/* -================= -R_CullLightTriangle - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -cullResult_t R_CullLightWorldBounds( trRefLight_t *light, vec3_t worldBounds[ 2 ] ) -{ - int i; - cplane_t *frust; - bool anyClip; - int r; - - if ( r_nocull->integer ) - { - return cullResult_t::CULL_CLIP; - } - - // check against frustum planes - anyClip = false; - - for ( i = 0; i < 6; i++ ) - { - frust = &light->frustum[ i ]; - - r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], frust ); - - if ( r == 2 ) - { - // completely outside frustum - return cullResult_t::CULL_OUT; - } - - if ( r == 3 ) - { - anyClip = true; - } - } - - if ( !anyClip ) - { - // completely inside frustum - return cullResult_t::CULL_IN; - } - - // partially clipped - return cullResult_t::CULL_CLIP; -} diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 283b80d06..2c29878b9 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -165,7 +165,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define SMP_FRAMES 2 #define MAX_SHADERS ( 1 << 12 ) -#define SHADERS_MASK ( MAX_SHADERS - 1 ) #define MAX_SHADER_TABLES 1024 #define MAX_SHADER_STAGES 16 @@ -175,8 +174,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define MAX_VISCOUNTS 5 #define MAX_VIEWS 10 -#define MAX_SHADOWMAPS 5 - #define MAX_TEXTURE_MIPS 16 #define MAX_TEXTURE_LAYERS 256 @@ -196,9 +193,6 @@ static inline void halfToFloat( const f16vec4_t in, vec4_t out ) #define MAX_DRAWSURFS 0x10000 #define DRAWSURF_MASK ( MAX_DRAWSURFS - 1 ) -#define MAX_INTERACTIONS ( MAX_DRAWSURFS * 8 ) -#define INTERACTION_MASK ( MAX_INTERACTIONS - 1 ) - // 16x16 pixels per tile #define TILE_SHIFT 4 #define TILE_SIZE (1 << TILE_SHIFT) @@ -298,8 +292,6 @@ static inline void glFboSetExt() enum class lightMode_t { FULLBRIGHT, VERTEX, GRID, MAP }; enum class deluxeMode_t { NONE, GRID, MAP }; -enum class realtimeLightingRenderer_t { LEGACY, TILED }; - enum class showCubeProbesMode { DISABLED, GRID, @@ -332,10 +324,7 @@ enum class ssaoMode { RSPEEDS_GENERAL = 1, RSPEEDS_CULLING, RSPEEDS_VIEWCLUSTER, - RSPEEDS_LIGHTS, - RSPEEDS_SHADOWCUBE_CULLING, RSPEEDS_FOG, - RSPEEDS_SHADING_TIMES, RSPEEDS_CHC, RSPEEDS_NEAR_FAR, }; @@ -353,7 +342,6 @@ enum class ssaoMode { }; #define REF_CUBEMAP_SIZE 32 -#define REF_CUBEMAP_STORE_SIZE 1024 #define REF_COLORGRADE_SLOTS 4 #define REF_COLORGRADEMAP_SIZE 16 @@ -389,66 +377,31 @@ enum class ssaoMode { using frustum_t = cplane_t[6]; - enum + // FIXME: it is impossible for the game to create any type besides RL_OMNI + enum class refLightType_t { - CUBESIDE_PX = ( 1 << 0 ), - CUBESIDE_PY = ( 1 << 1 ), - CUBESIDE_PZ = ( 1 << 2 ), - CUBESIDE_NX = ( 1 << 3 ), - CUBESIDE_NY = ( 1 << 4 ), - CUBESIDE_NZ = ( 1 << 5 ), - CUBESIDE_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32 + RL_OMNI, // point light + RL_PROJ, // spot light + RL_DIRECTIONAL, // sun light + + RL_MAX_REF_LIGHT_TYPE }; -// a trRefLight_t has all the information passed in by -// the client game, as well as some locally derived info - struct trRefLight_t + struct refLight_t { - refLight_t l; - - // local - bool additive; // texture detail is lost tho when the lightmap is dark - vec3_t origin; // l.origin + rotated l.center - vec3_t transformed; // origin in local coordinate system - vec3_t direction; // for directional lights (sun) - - matrix_t transformMatrix; // light to world - matrix_t viewMatrix; // object to light - matrix_t projectionMatrix; // light frustum - - float falloffLength; - - matrix_t shadowMatrices[ MAX_SHADOWMAPS ]; - matrix_t shadowMatricesBiased[ MAX_SHADOWMAPS ]; - matrix_t attenuationMatrix; // attenuation * (light view * entity transform) - matrix_t attenuationMatrix2; // attenuation * tcMod matrices - - vec3_t localBounds[ 2 ]; - vec3_t worldBounds[ 2 ]; - float sphereRadius; // calculated from localBounds - - int8_t shadowLOD; // Level of Detail for shadow mapping - - int restrictInteractionFirst; - int restrictInteractionLast; - - frustum_t frustum; - plane_t localFrustum[ 6 ]; - - screenRect_t scissor; + refLightType_t rlType; - struct shader_t *shader; + vec3_t origin; + vec3_t color; // range from 0.0 to 1.0, should be color normalized - struct interaction_t *firstInteraction; + float scale; // r_lightScale if not set - struct interaction_t *lastInteraction; + // omni-directional light specific + float radius; - uint16_t numInteractions; // total interactions - uint16_t numShadowOnlyInteractions; - uint16_t numLightOnlyInteractions; - bool noSort; // don't sort interactions by material - - int visCounts[ MAX_VISCOUNTS ]; // node needs to be traversed if current + // projective light specific + vec3_t projTarget; + vec3_t projUp; }; // a structure matching the GLSL struct shaderLight in std140 layout @@ -471,7 +424,6 @@ enum class ssaoMode { // local float axisLength; // compensate for non-normalized axis - cullResult_t cull; vec3_t localBounds[ 2 ]; vec3_t worldBounds[ 2 ]; }; @@ -967,8 +919,6 @@ enum class ssaoMode { }; #define MAX_SHADER_DEFORMS 3 -#define MAX_SHADER_DEFORM_STEPS 4 -#define MAX_SHADER_DEFORM_PARMS ( MAX_SHADER_DEFORMS * MAX_SHADER_DEFORM_STEPS ) struct deformStage_t { deform_t deformation; // vertex coordinate modification type @@ -1076,10 +1026,6 @@ enum class ssaoMode { ST_COLLAPSE_COLORMAP, ST_COLLAPSE_DIFFUSEMAP, ST_COLLAPSE_REFLECTIONMAP, // color cubemap + normalmap - - // light shader stage types - ST_ATTENUATIONMAP_XY, - ST_ATTENUATIONMAP_Z }; enum class collapseType_t @@ -1128,9 +1074,6 @@ enum class ssaoMode { stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; - bool doShadowFill; - bool doForwardLighting; - textureBundle_t bundle[ MAX_TEXTURE_BUNDLES ]; expression_t ifExp; @@ -1258,7 +1201,6 @@ enum class ssaoMode { SHADER_2D, // surface material: shader is for 2D rendering (like GUI elements) SHADER_3D_DYNAMIC, // surface material: shader is for cGen diffuseLighting lighting SHADER_3D_STATIC, // surface material: pre-lit triangle models - SHADER_LIGHT // light material: attenuation }; struct shader_t @@ -1281,7 +1223,6 @@ enum class ssaoMode { int contentFlags; bool entityMergable; // merge across entites optimizable (smoke, blood) - bool alphaTest; // helps merging shadowmap generating surfaces fogParms_t fogParms; fogPass_t fogPass; // draw a blended pass, possibly with depth test equals @@ -1291,7 +1232,6 @@ enum class ssaoMode { float reliefOffsetBias; // offset the heightmap top relatively to the floor float reliefDepthScale = 1.0f; // per-shader relief depth scale - bool noShadows; bool ambientLight; bool translucent; bool forceOpaque; @@ -1440,8 +1380,7 @@ enum class ssaoMode { trRefEntity_t *entities; int numLights; - int numShaderLights; - trRefLight_t *lights; + refLight_t *lights; int numPolys; struct srfPoly_t *polys; @@ -1449,9 +1388,6 @@ enum class ssaoMode { int numDrawSurfs; struct drawSurf_t *drawSurfs; - int numInteractions; - struct interaction_t *interactions; - byte *pixelTarget; //set this to Non Null to copy to a buffer after scene rendering int pixelTargetWidth; int pixelTargetHeight; @@ -1469,23 +1405,12 @@ enum class ssaoMode { shader_t *shader; }; -//----(SA) modified -#define MAX_PART_MODELS 5 - - struct skinModel_t - { - char type[ MAX_QPATH ]; // md3_lower, md3_lbelt, md3_rbelt, etc. - char model[ MAX_QPATH ]; // lower.md3, belt1.md3, etc. - int hash; - }; - struct skin_t { char name[ MAX_QPATH ]; // game path, including extension int numSurfaces; int numModels; skinSurface_t *surfaces[ MD3_MAX_SURFACES ]; - skinModel_t *models[ MAX_PART_MODELS ]; }; //----(SA) end @@ -1535,10 +1460,7 @@ enum class ssaoMode { matrix_t projectionMatrixNonPortal; // For skybox rendering in portals matrix_t unprojectionMatrix; // transform pixel window space -> world space - float parallelSplitDistances[ MAX_SHADOWMAPS + 1 ]; // distances in camera space - - frustum_t frustums[ MAX_SHADOWMAPS + 1 ]; // first frustum is the default one with complete zNear - zFar range - // and the other ones are for PSSM + frustum_t frustum; vec3_t visBounds[ 2 ]; float zNear; @@ -1547,9 +1469,6 @@ enum class ssaoMode { int numDrawSurfs; struct drawSurf_t *drawSurfs; int firstDrawSurf[ Util::ordinal(shaderSort_t::SS_NUM_SORTS) + 1 ]; - - int numInteractions; - struct interaction_t *interactions; }; /* @@ -1663,35 +1582,6 @@ enum class ssaoMode { } }; - enum interactionType_t - { - IA_LIGHT = 1 << 0, // the received light if not in shadow - IA_SHADOW = 1 << 1, // the surface shadows the light - IA_SHADOWCLIP = 1 << 2, // the surface clips the shadow - - IA_DEFAULT = IA_LIGHT | IA_SHADOW, // lighting and shadowing - IA_DEFAULTCLIP = IA_LIGHT | IA_SHADOWCLIP - }; - -// an interaction is a node between a light and any surface - struct interaction_t - { - interactionType_t type; - - trRefLight_t *light; - - trRefEntity_t *entity; - surfaceType_t *surface; // any of surface*_t - shader_t *shader; - int shaderNum; - - byte cubeSideBits; - - int16_t scissorX, scissorY, scissorWidth, scissorHeight; - - interaction_t *next; - }; - #define MAX_PATCH_SIZE 64 // max dimensions of a patch mesh in map file #define MAX_GRID_SIZE 65 // max dimensions of a grid mesh in memory @@ -1740,17 +1630,16 @@ enum class ssaoMode { // BSP VBO offset int firstIndex; + + int numVerts; + + int numTriangles; + srfTriangle_t* triangles; // ^ Valid in: SF_FACE, SF_GRID, SF_TRIANGLES, SF_VBO_MESH cplane_t plane; // Valid in: SF_FACE, SF_TRIANGLES - int numVerts; // Valid in: SF_FACE, SF_GRID, SF_TRIANGLES, SF_VBO_MESH srfVert_t* verts; // Valid in: SF_FACE, SF_GRID, SF_TRIANGLES - - // v Valid in: SF_FACE, SF_GRID, SF_TRIANGLES - int numTriangles; - srfTriangle_t* triangles; - // ^ Valid in: SF_FACE, SF_GRID, SF_TRIANGLES }; struct srfGridMesh_t : srfGeneric_t { @@ -1824,8 +1713,8 @@ enum class ssaoMode { struct bspSurface_t { int viewCount; // if == tr.viewCount, already added - int lightCount; - int interactionBits; + + int scratch1, scratch2; struct shader_t *shader; @@ -1890,9 +1779,6 @@ enum class ssaoMode { vec3_t maxs; }; -// ydnar: optimization -#define WORLD_MAX_SKY_NODES 32 - struct world_t { char name[ MAX_QPATH ]; // ie: maps/tim_dm2.bsp @@ -1913,9 +1799,6 @@ enum class ssaoMode { int numDecisionNodes; bspNode_t *nodes; - int numSkyNodes; - bspNode_t **skyNodes; // ydnar: don't walk the entire bsp when rendering sky - int numPortals; AABB *portals; @@ -2307,19 +2190,9 @@ enum class ssaoMode { int c_sphere_cull_mdv_in, c_sphere_cull_mdv_clip, c_sphere_cull_mdv_out; int c_box_cull_mdv_in, c_box_cull_mdv_clip, c_box_cull_mdv_out; int c_box_cull_md5_in, c_box_cull_md5_clip, c_box_cull_md5_out; - int c_box_cull_light_in, c_box_cull_light_clip, c_box_cull_light_out; - int c_pvs_cull_light_out; - - int c_pyramidTests; - int c_pyramid_cull_ent_in, c_pyramid_cull_ent_clip, c_pyramid_cull_ent_out; int c_nodes; int c_leafs; - - int c_dlights; - int c_dlightSurfaces; - int c_dlightSurfacesCulled; - int c_dlightInteractions; }; #define FOG_TABLE_SIZE 256 @@ -2387,9 +2260,6 @@ enum class ssaoMode { int c_fogSurfaces; int c_fogBatches; - int c_forwardAmbientTime; - int c_forwardLightingTime; - int c_multiDrawElements; int c_multiDrawPrimitives; int c_multiVboIndexes; @@ -2416,7 +2286,6 @@ enum class ssaoMode { visTestQueries_t visTestQueries[ MAX_VISTESTS ]; bool isHyperspace; trRefEntity_t *currentEntity; - trRefLight_t *currentLight; // only used when lighting interactions bool skyRenderedThisView; // flag for drawing sun bool postDepthLightTileRendered = false; @@ -2536,6 +2405,10 @@ enum class ssaoMode { grid = ( T* ) ri.Hunk_Alloc( size * sizeof( T ), ha_pref::h_low ); } + void Clear() { + memset( grid, 0, size * sizeof( T ) ); + } + struct Iterator { T* ptr; @@ -2551,6 +2424,10 @@ enum class ssaoMode { return ptr; } + ptrdiff_t operator-( const Iterator& other ) const { + return ptr - other.ptr; + } + Iterator& operator++() { ptr++; return *this; @@ -2626,7 +2503,6 @@ enum class ssaoMode { int sceneCount; // incremented every scene int viewCount; // incremented every view (twice a scene if portaled) int viewCountNoReset; // incremented when doing something that visits surfaces and sets their viewCount - int lightCount; // incremented every time a dlight traverses the world // and every R_MarkFragments call int smpFrame; // toggles from 0 to 1 every endFrame @@ -2666,7 +2542,6 @@ enum class ssaoMode { image_t *blueImage; image_t *flatImage; // use this as default normalmap image_t *randomNormalsImage; - image_t *noFalloffImage; image_t *blackCubeImage; image_t *whiteCubeImage; @@ -2679,13 +2554,6 @@ enum class ssaoMode { image_t *lighttileRenderImage; image_t *portalRenderImage; - image_t *shadowMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowCubeFBOImage[ MAX_SHADOWMAPS ]; - image_t *sunShadowMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowClipMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - image_t *shadowClipCubeFBOImage[ MAX_SHADOWMAPS ]; - image_t *sunShadowClipMapFBOImage[ MAX_SHADOWMAPS * 2 ]; - // external images image_t *colorGradeImage; GLuint colorGradePBO; @@ -2698,8 +2566,6 @@ enum class ssaoMode { FBO_t *portalRenderFBO; // holds a copy of the last currentRender that was rendered into a FBO FBO_t *contrastRenderFBO; FBO_t *bloomRenderFBO[ 2 ]; - FBO_t *shadowMapFBO[ MAX_SHADOWMAPS ]; - FBO_t *sunShadowMapFBO[ MAX_SHADOWMAPS ]; // vertex buffer objects VBO_t *lighttileVBO; @@ -2726,9 +2592,6 @@ enum class ssaoMode { trRefEntity_t worldEntity; // point currentEntity at this when rendering world model_t *currentModel; - // render lights - trRefLight_t *currentLight; - // ----------------------------------------- viewParms_t viewParms; @@ -2823,8 +2686,6 @@ enum class ssaoMode { extern const matrix_t quakeToOpenGLMatrix; extern const matrix_t openGLToQuakeMatrix; extern const matrix_t flipZMatrix; - extern int shadowMapResolutions[ 5 ]; - extern int sunShadowMapResolutions[ 5 ]; extern backEndState_t backEnd; extern trGlobals_t tr; @@ -2864,10 +2725,8 @@ enum class ssaoMode { extern cvar_t *r_lightScale; extern Cvar::Cvar r_drawSky; // Controls whether sky should be drawn or cleared. - extern Cvar::Range> r_realtimeLightingRenderer; extern Cvar::Cvar r_realtimeLighting; extern Cvar::Range> r_realtimeLightLayers; - extern cvar_t *r_realtimeLightingCastShadows; extern cvar_t *r_precomputedLighting; extern Cvar::Cvar r_overbrightDefaultExponent; extern Cvar::Range> r_overbrightBits; @@ -2895,9 +2754,6 @@ enum class ssaoMode { extern cvar_t *r_nocull; extern cvar_t *r_facePlaneCull; // enables culling of planar surfaces with back side test extern cvar_t *r_nocurves; - extern cvar_t *r_lightScissors; - extern cvar_t *r_noLightVisCull; - extern cvar_t *r_noInteractionSort; extern cvar_t *r_mode; // video mode extern cvar_t *r_gamma; @@ -2949,34 +2805,6 @@ enum class ssaoMode { extern Cvar::Cvar r_highPrecisionRendering; extern Cvar::Range> r_shadows; - extern cvar_t *r_softShadows; - extern cvar_t *r_softShadowsPP; - extern cvar_t *r_shadowBlur; - - extern cvar_t *r_shadowMapSizeUltra; - extern cvar_t *r_shadowMapSizeVeryHigh; - extern cvar_t *r_shadowMapSizeHigh; - extern cvar_t *r_shadowMapSizeMedium; - extern cvar_t *r_shadowMapSizeLow; - - extern cvar_t *r_shadowMapSizeSunUltra; - extern cvar_t *r_shadowMapSizeSunVeryHigh; - extern cvar_t *r_shadowMapSizeSunHigh; - extern cvar_t *r_shadowMapSizeSunMedium; - extern cvar_t *r_shadowMapSizeSunLow; - - extern cvar_t *r_shadowLodBias; - extern cvar_t *r_shadowLodScale; - extern cvar_t *r_noShadowPyramids; - extern cvar_t *r_cullShadowPyramidFaces; - extern cvar_t *r_debugShadowMaps; - extern cvar_t *r_noLightFrustums; - extern cvar_t *r_shadowMapLinearFilter; - extern cvar_t *r_lightBleedReduction; - extern cvar_t *r_overDarkeningFactor; - extern cvar_t *r_shadowMapDepthScale; - extern cvar_t *r_parallelShadowSplits; - extern cvar_t *r_parallelShadowSplitWeight; extern cvar_t *r_lockpvs; extern cvar_t *r_noportals; @@ -3004,14 +2832,7 @@ enum class ssaoMode { extern cvar_t *r_showTris; // enables wireframe rendering of the world extern cvar_t *r_showSky; // forces sky in front of all surfaces - extern cvar_t *r_showShadowLod; - extern cvar_t *r_showShadowMaps; extern cvar_t *r_showSkeleton; - extern cvar_t *r_showEntityTransforms; - extern cvar_t *r_showLightTransforms; - extern cvar_t *r_showLightInteractions; - extern cvar_t *r_showLightScissors; - extern cvar_t *r_showLightBatches; extern cvar_t *r_showLightGrid; extern cvar_t *r_showLightTiles; extern cvar_t *r_showBatches; @@ -3026,7 +2847,6 @@ enum class ssaoMode { extern cvar_t *r_showBspNodes; extern Cvar::Range> r_showGlobalMaterials; extern Cvar::Cvar r_materialDebug; - extern cvar_t *r_showParallelShadowSplits; extern Cvar::Cvar r_forceRendererTime; @@ -3079,7 +2899,6 @@ inline bool checkGLErrors() void R_RenderPostProcess(); void R_AddMDVSurfaces( trRefEntity_t *e ); - void R_AddMDVInteractions( trRefEntity_t *e, trRefLight_t *light, interactionType_t iaType ); void R_AddPolygonSurfaces(); @@ -3098,8 +2917,6 @@ inline bool checkGLErrors() void R_SetupEntityWorldBounds( trRefEntity_t *ent ); void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); - void R_RotateEntityForLight( const trRefEntity_t *ent, const trRefLight_t *light, orientationr_t *orien ); - void R_RotateLightForViewParms( const trRefLight_t *ent, const viewParms_t *viewParms, orientationr_t *orien ); void R_SetupFrustum2( frustum_t frustum, const matrix_t modelViewProjectionMatrix ); template @@ -3168,10 +2985,8 @@ inline bool checkGLErrors() ==================================================================== */ void GL_Bind( image_t *image ); - void GL_BindNearestCubeMap( int unit, const vec3_t xyz ); void GL_Unbind( image_t *image ); GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ); - void GL_TextureFilter( image_t *image, filterType_t filterType ); void GL_BindProgram( ShaderProgramDescriptor* program ); GLuint64 GL_BindToTMU( int unit, image_t *image ); void GL_BindNullProgram(); @@ -3236,9 +3051,6 @@ inline bool checkGLErrors() bool R_GetModeInfo( int *width, int *height, int mode ); -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516 - const void *RB_TakeScreenshotCmd( const void *data ); - void R_InitSkins(); skin_t *R_GetSkinByHandle( qhandle_t hSkin ); @@ -3460,8 +3272,6 @@ void GLimp_LogComment_( std::string comment ); void Tess_StageIteratorDebug(); void Tess_StageIteratorColor(); void Tess_StageIteratorPortal(); - void Tess_StageIteratorShadowFill(); - void Tess_StageIteratorLighting(); void Tess_StageIteratorSky(); void Tess_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, const Color::Color& color ); @@ -3527,8 +3337,6 @@ void GLimp_LogComment_( std::string comment ); bool R_inPVS( const vec3_t p1, const vec3_t p2 ); bool R_inPVVS( const vec3_t p1, const vec3_t p2 ); - void R_AddWorldInteractions( trRefLight_t *light ); - /* ============================================================ @@ -3537,36 +3345,10 @@ void GLimp_LogComment_( std::string comment ); ============================================================ */ - void R_AddBrushModelInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); float R_InterpolateLightGrid( world_t *w, int from[3], int to[3], float *factors[3], vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); - void R_TessLight( const trRefLight_t *light, const Color::Color& color ); - - void R_SetupLightOrigin( trRefLight_t *light ); - void R_SetupLightLocalBounds( trRefLight_t *light ); - void R_SetupLightWorldBounds( trRefLight_t *light ); - - void R_SetupLightView( trRefLight_t *light ); - void R_SetupLightFrustum( trRefLight_t *light ); - void R_SetupLightProjection( trRefLight_t *light ); - - bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_t *surfaceShader, byte cubeSideBits, - interactionType_t iaType ); - - void R_SortInteractions( trRefLight_t *light ); - - void R_SetupLightScissor( trRefLight_t *light ); - void R_SetupLightLOD( trRefLight_t *light ); - - void R_SetupLightShader( trRefLight_t *light ); - - byte R_CalcLightCubeSideBits( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); - - cullResult_t R_CullLightWorldBounds( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); - - void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ); /* ============================================================ @@ -3668,7 +3450,6 @@ void GLimp_LogComment_( std::string comment ); void RE_ClearScene(); void RE_AddRefEntityToScene( const refEntity_t *ent ); - void RE_AddPolyToSceneQ3A( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num ); void RE_AddPolyToSceneET( qhandle_t hShader, int numVerts, const polyVert_t *verts ); void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ); @@ -3701,10 +3482,8 @@ void GLimp_LogComment_( std::string comment ); skelAnimation_t *R_GetAnimationByHandle( qhandle_t hAnim ); void R_AddMD5Surfaces( trRefEntity_t *ent ); - void R_AddMD5Interactions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); void R_AddIQMSurfaces( trRefEntity_t *ent ); - void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ); int RE_CheckSkeleton( refSkeleton_t *skel, qhandle_t hModel, qhandle_t hAnim ); int RE_BuildSkeleton( refSkeleton_t *skel, qhandle_t anim, int startFrame, int endFrame, float frac, @@ -3931,9 +3710,8 @@ void GLimp_LogComment_( std::string comment ); struct backEndData_t { drawSurf_t drawSurfs[ MAX_DRAWSURFS ]; - interaction_t interactions[ MAX_INTERACTIONS ]; - trRefLight_t lights[ MAX_REF_LIGHTS ]; + refLight_t lights[ MAX_REF_LIGHTS ]; trRefEntity_t entities[ MAX_REF_ENTITIES ]; srfPoly_t *polys; //[MAX_POLYS]; @@ -4001,7 +3779,6 @@ void GLimp_LogComment_( std::string comment ); // video stuff - const void *RB_TakeVideoFrameCmd( const void *data ); void RE_TakeVideoFrame( int width, int height, byte *captureBuffer, byte *encodeBuffer, bool motionJpeg ); // cubemap reflections stuff diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index e6befc7ce..77259a2aa 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -36,9 +36,6 @@ const matrix_t quakeToOpenGLMatrix = 0, 0, 0, 1 }; -int shadowMapResolutions[ 5 ] = { 2048, 1024, 512, 256, 128 }; -int sunShadowMapResolutions[ 5 ] = { 2048, 2048, 1024, 1024, 1024 }; - refimport_t ri; // entities that will have procedurally generated surfaces will just @@ -352,7 +349,7 @@ cullResult_t R_CullBox( vec3_t worldBounds[ 2 ] ) for ( i = 0; i < FRUSTUM_PLANES; i++ ) { - frust = &tr.viewParms.frustums[ 0 ][ i ]; + frust = &tr.viewParms.frustum[ i ]; r = BoxOnPlaneSide( worldBounds[ 0 ], worldBounds[ 1 ], frust ); @@ -429,7 +426,7 @@ cullResult_t R_CullPointAndRadius( vec3_t pt, float radius ) // check against frustum planes for ( i = 0; i < Util::ordinal(frustumBits_t::FRUSTUM_PLANES); i++ ) { - frust = &tr.viewParms.frustums[ 0 ][ i ]; + frust = &tr.viewParms.frustum[ i ]; dist = DotProduct( pt, frust->normal ) - frust->dist; @@ -680,101 +677,6 @@ void R_RotateEntityForViewParms( const trRefEntity_t *ent, const viewParms_t *vi orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ) * axisLength; } -/* -================= -R_RotateEntityForLight - -Generates an orientation for an entity and light -Does NOT produce any GL calls -Called by both the front end and the back end -================= -*/ -void R_RotateEntityForLight( const trRefEntity_t *ent, const trRefLight_t *light, orientationr_t * orientation ) -{ - vec3_t delta; - float axisLength; - - if ( ent->e.reType != refEntityType_t::RT_MODEL ) - { - *orientation = {}; - - orientation ->axis[ 0 ][ 0 ] = 1; - orientation ->axis[ 1 ][ 1 ] = 1; - orientation ->axis[ 2 ][ 2 ] = 1; - - VectorCopy( light->l.origin, orientation ->viewOrigin ); - - MatrixIdentity( orientation ->transformMatrix ); - MatrixMultiply( light->viewMatrix, orientation ->transformMatrix, orientation ->viewMatrix ); - MatrixCopy( orientation ->viewMatrix, orientation ->modelViewMatrix ); - return; - } - - VectorCopy( ent->e.origin, orientation ->origin ); - - VectorCopy( ent->e.axis[ 0 ], orientation ->axis[ 0 ] ); - VectorCopy( ent->e.axis[ 1 ], orientation ->axis[ 1 ] ); - VectorCopy( ent->e.axis[ 2 ], orientation ->axis[ 2 ] ); - - MatrixSetupTransformFromVectorsFLU( orientation ->transformMatrix, orientation ->axis[ 0 ], orientation ->axis[ 1 ], orientation ->axis[ 2 ], orientation ->origin ); - MatrixAffineInverse( orientation ->transformMatrix, orientation ->viewMatrix ); - - MatrixMultiply( light->viewMatrix, orientation ->transformMatrix, orientation ->modelViewMatrix ); - - // calculate the viewer origin in the model's space - // needed for fog, specular, and environment mapping - VectorSubtract( light->l.origin, orientation ->origin, delta ); - - // compensate for scale in the axes if necessary - if ( ent->e.nonNormalizedAxes ) - { - axisLength = VectorLength( ent->e.axis[ 0 ] ); - - if ( !axisLength ) - { - axisLength = 0; - } - else - { - axisLength = 1.0f / axisLength; - } - } - else - { - axisLength = 1.0f; - } - - orientation ->viewOrigin[ 0 ] = DotProduct( delta, orientation ->axis[ 0 ] ) * axisLength; - orientation ->viewOrigin[ 1 ] = DotProduct( delta, orientation ->axis[ 1 ] ) * axisLength; - orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ) * axisLength; -} - -/* -================= -R_RotateLightForViewParms -================= -*/ -void R_RotateLightForViewParms( const trRefLight_t *light, const viewParms_t *viewParms, orientationr_t * orientation ) -{ - vec3_t delta; - - VectorCopy( light->l.origin, orientation ->origin ); - - QuatToAxis( light->l.rotation, orientation ->axis ); - - MatrixSetupTransformFromVectorsFLU( orientation ->transformMatrix, orientation ->axis[ 0 ], orientation ->axis[ 1 ], orientation ->axis[ 2 ], orientation ->origin ); - MatrixAffineInverse( orientation ->transformMatrix, orientation ->viewMatrix ); - MatrixMultiply( viewParms->world.viewMatrix, orientation ->transformMatrix, orientation ->modelViewMatrix ); - - // calculate the viewer origin in the light's space - // needed for fog, specular, and environment mapping - VectorSubtract( viewParms->orientation.origin, orientation ->origin, delta ); - - orientation ->viewOrigin[ 0 ] = DotProduct( delta, orientation ->axis[ 0 ] ); - orientation ->viewOrigin[ 1 ] = DotProduct( delta, orientation ->axis[ 1 ] ); - orientation ->viewOrigin[ 2 ] = DotProduct( delta, orientation ->axis[ 2 ] ); -} - /* ================= R_RotateForViewer @@ -976,11 +878,11 @@ static void R_SetupFrustum() MatrixTransformPlane2(invTransform, plane); - VectorCopy(plane.normal, tr.viewParms.frustums[0][i].normal); - tr.viewParms.frustums[0][i].dist = plane.dist; + VectorCopy(plane.normal, tr.viewParms.frustum[i].normal); + tr.viewParms.frustum[i].dist = plane.dist; - SetPlaneSignbits(&tr.viewParms.frustums[0][i]); - tr.viewParms.frustums[0][i].type = PLANE_NON_AXIAL; + SetPlaneSignbits(&tr.viewParms.frustum[i]); + tr.viewParms.frustum[i].type = PLANE_NON_AXIAL; } } else @@ -989,36 +891,36 @@ static void R_SetupFrustum() xs = sinf( ang ); xc = cosf( ang ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 0 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 0 ].normal, xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustums[ 0 ][ 0 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 0 ].normal ); + VectorMA( tr.viewParms.frustum[ 0 ].normal, xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustum[ 0 ].normal ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 1 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 1 ].normal, -xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustums[ 0 ][ 1 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 1 ].normal ); + VectorMA( tr.viewParms.frustum[ 1 ].normal, -xc, tr.viewParms.orientation.axis[ 1 ], tr.viewParms.frustum[ 1 ].normal ); ang = DEG2RAD( tr.viewParms.fovY * 0.5f ); xs = sinf( ang ); xc = cosf( ang ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 2 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 2 ].normal, xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustums[ 0 ][ 2 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 2 ].normal ); + VectorMA( tr.viewParms.frustum[ 2 ].normal, xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustum[ 2 ].normal ); - VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustums[ 0 ][ 3 ].normal ); - VectorMA( tr.viewParms.frustums[ 0 ][ 3 ].normal, -xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustums[ 0 ][ 3 ].normal ); + VectorScale( tr.viewParms.orientation.axis[ 0 ], xs, tr.viewParms.frustum[ 3 ].normal ); + VectorMA( tr.viewParms.frustum[ 3 ].normal, -xc, tr.viewParms.orientation.axis[ 2 ], tr.viewParms.frustum[ 3 ].normal ); for ( int i = 0; i < 4; i++ ) { - tr.viewParms.frustums[ 0 ][ i ].type = PLANE_NON_AXIAL; - tr.viewParms.frustums[ 0 ][ i ].dist = DotProduct( tr.viewParms.orientation.origin, tr.viewParms.frustums[ 0 ][ i ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ 0 ][ i ] ); + tr.viewParms.frustum[ i ].type = PLANE_NON_AXIAL; + tr.viewParms.frustum[ i ].dist = DotProduct( tr.viewParms.orientation.origin, tr.viewParms.frustum[ i ].normal ); + SetPlaneSignbits( &tr.viewParms.frustum[ i ] ); } // Tr3B: set extra near plane which is required by the dynamic occlusion culling - tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; - VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal ); + tr.viewParms.frustum[ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; + VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustum[ FRUSTUM_NEAR ].normal ); - VectorMA( tr.viewParms.orientation.origin, r_znear->value, tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal, planeOrigin ); - tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ 0 ][ FRUSTUM_NEAR ] ); + VectorMA( tr.viewParms.orientation.origin, r_znear->value, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal, planeOrigin ); + tr.viewParms.frustum[ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustum[ FRUSTUM_NEAR ].normal ); + SetPlaneSignbits( &tr.viewParms.frustum[ FRUSTUM_NEAR ] ); } } @@ -1111,68 +1013,6 @@ void R_CalcFrustumFarCornersUnsafe( const plane_t frustum[ FRUSTUM_FAR + 1 ], ve PlanesGetIntersectionPoint( frustum[ FRUSTUM_LEFT ], frustum[ FRUSTUM_BOTTOM ], frustum[ FRUSTUM_FAR ], corners[ 3 ] ); } -static void CopyPlane( const cplane_t *in, cplane_t *out ) -{ - VectorCopy( in->normal, out->normal ); - out->dist = in->dist; - out->type = in->type; - out->signbits = in->signbits; - out->pad[ 0 ] = in->pad[ 0 ]; - out->pad[ 1 ] = in->pad[ 1 ]; -} - -static void R_SetupSplitFrustums() -{ - int i, j; - float lambda; - float ratio; - vec3_t planeOrigin; - float zNear, zFar; - - lambda = r_parallelShadowSplitWeight->value; - ratio = tr.viewParms.zFar / tr.viewParms.zNear; - - for ( j = 0; j < 5; j++ ) - { - CopyPlane( &tr.viewParms.frustums[ 0 ][ j ], &tr.viewParms.frustums[ 1 ][ j ] ); - } - - for ( i = 1; i <= ( r_parallelShadowSplits->integer + 1 ); i++ ) - { - float si = i / ( float )( r_parallelShadowSplits->integer + 1 ); - - zFar = 1.005f * lambda * ( tr.viewParms.zNear * powf( ratio, si ) ) + ( 1 - lambda ) * ( tr.viewParms.zNear + ( tr.viewParms.zFar - tr.viewParms.zNear ) * si ); - - if ( i <= r_parallelShadowSplits->integer ) - { - tr.viewParms.parallelSplitDistances[ i - 1 ] = zFar; - } - - tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].type = PLANE_NON_AXIAL; - VectorNegate( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].normal ); - - VectorMA( tr.viewParms.orientation.origin, zFar, tr.viewParms.orientation.axis[ 0 ], planeOrigin ); - tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ i ][ FRUSTUM_FAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ i ][ FRUSTUM_FAR ] ); - - if ( i <= ( r_parallelShadowSplits->integer ) ) - { - zNear = zFar - ( zFar * 0.005f ); - tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].type = PLANE_NON_AXIAL; - VectorCopy( tr.viewParms.orientation.axis[ 0 ], tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].normal ); - - VectorMA( tr.viewParms.orientation.origin, zNear, tr.viewParms.orientation.axis[ 0 ], planeOrigin ); - tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].dist = DotProduct( planeOrigin, tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ].normal ); - SetPlaneSignbits( &tr.viewParms.frustums[ i + 1 ][ FRUSTUM_NEAR ] ); - } - - for ( j = 0; j < 4; j++ ) - { - CopyPlane( &tr.viewParms.frustums[ 0 ][ j ], &tr.viewParms.frustums[ i ][ j ] ); - } - } -} - /* ================= R_MirrorPoint @@ -1670,6 +1510,7 @@ static void R_SetupPortalFrustum( const viewParms_t& oldParms, const orientation frustum[FRUSTUM_NEAR].dist = DotProduct(worldNearPlane, newParms.orientation.origin) - worldNearPlane[3]; // calculate new znear for parallel split frustums in this view + // TODO get rid of this? "Parallel split" was a shadow mapping thing plane_t frustumPlanes[FRUSTUM_PLANES]; for (int i = 0; i < FRUSTUM_PLANES; i++) { @@ -1916,20 +1757,6 @@ static void R_SortDrawSurfs() tr.viewParms.numDrawSurfs = MAX_DRAWSURFS; } - // if we overflowed MAX_INTERACTIONS, the interactions - // wrapped around in the buffer and we will be missing - // the first interactions, not the last ones - if ( tr.viewParms.numInteractions > MAX_INTERACTIONS ) - { - interaction_t *ia; - - tr.viewParms.numInteractions = MAX_INTERACTIONS; - - // reset last interaction's next pointer - ia = &tr.viewParms.interactions[ tr.viewParms.numInteractions - 1 ]; - ia->next = nullptr; - } - std::sort( tr.viewParms.drawSurfs, tr.viewParms.drawSurfs + tr.viewParms.numDrawSurfs, []( const drawSurf_t &a, const drawSurf_t &b ) { return a.sort < b.sort; @@ -2104,266 +1931,6 @@ void R_AddEntitySurfaces() } } -/* -============= -R_AddEntityInteractions -============= -*/ -void R_AddEntityInteractions( trRefLight_t *light ) -{ - int i; - trRefEntity_t *ent; - interactionType_t iaType; - - if ( !r_drawentities->integer ) - { - return; - } - - for ( i = 0; i < tr.refdef.numEntities; i++ ) - { - iaType = IA_DEFAULT; - - if ( !glConfig2.shadowMapping || light->l.noShadows ) { - iaType = (interactionType_t) (iaType & (~IA_SHADOW)); - } - - if ( light->restrictInteractionFirst >= 0 && - ( i < light->restrictInteractionFirst || - i > light->restrictInteractionLast ) ) { - iaType = (interactionType_t) (iaType & (~IA_SHADOW)); - } - - if ( light->restrictInteractionFirst >= 0 && - i >= light->restrictInteractionFirst && - i <= light->restrictInteractionLast ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - ent = tr.currentEntity = &tr.refdef.entities[ i ]; - - // - // the weapon model must be handled special -- - // we don't want the hacked weapon position showing in - // mirrors, because the true body position will already be drawn - // - if ( ( ent->e.renderfx & RF_FIRST_PERSON ) && - ( tr.viewParms.portalLevel > 0 || tr.viewParms.isMirror ) ) - { - continue; - } - - // simple generated models, like sprites and beams, are not culled - switch ( ent->e.reType ) - { - case refEntityType_t::RT_PORTALSURFACE: - break; // don't draw anything - - case refEntityType_t::RT_SPRITE: - break; - - case refEntityType_t::RT_MODEL: - tr.currentModel = R_GetModelByHandle( ent->e.hModel ); - - if ( tr.currentModel ) - { - switch ( tr.currentModel->type ) - { - case modtype_t::MOD_MESH: - R_AddMDVInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_MD5: - R_AddMD5Interactions( ent, light, iaType ); - break; - - case modtype_t::MOD_IQM: - R_AddIQMInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_BSP: - R_AddBrushModelInteractions( ent, light, iaType ); - break; - - case modtype_t::MOD_BAD: // null model axis - break; - - default: - Sys::Drop( "R_AddEntityInteractions: Bad modeltype" ); - } - } - - break; - - default: - Sys::Drop( "R_AddEntityInteractions: Bad reType" ); - } - } -} - -/* -============= -R_TransformShadowLight - -check if OMNI shadow light can be turned into PROJ for better shadow map quality -============= -*/ -void R_TransformShadowLight( trRefLight_t *light ) { - int i; - vec3_t mins, maxs, mids; - vec3_t forward, right, up; - float radius; - - if( !light->l.inverseShadows || light->l.rlType != refLightType_t::RL_OMNI || - light->restrictInteractionFirst < 0 ) - return; - - ClearBounds( mins, maxs ); - for( i = light->restrictInteractionFirst; i <= light->restrictInteractionLast; i++ ) { - trRefEntity_t *ent = &tr.refdef.entities[ i ]; - - BoundsAdd(ent->worldBounds[0], ent->worldBounds[1], mins, maxs); - } - - // if light origin is outside BBox of shadow receivers, build - // a projection light on the closest plane of the BBox - VectorAdd( mins, maxs, mids ); - VectorScale( mids, 0.5f, mids ); - radius = Distance( mids, maxs ); - - light->l.rlType = refLightType_t::RL_PROJ; - VectorSubtract( mids, light->l.origin, forward ); - VectorNormalize( forward ); - PerpendicularVector( right, forward ); - CrossProduct( forward, right, up ); - - VectorScale( right, 2.0f * radius, light->l.projRight ); - VectorScale( up, 2.0f * radius, light->l.projUp ); - VectorCopy( vec3_origin, light->l.projStart ); - VectorCopy( vec3_origin, light->l.projEnd ); - VectorScale( forward, light->l.radius, light->l.projTarget ); -} - -/* -============= -R_AddLightInteractions -============= -*/ -void R_AddLightInteractions() -{ - int i; - trRefLight_t *light; - - realtimeLightingRenderer_t realtimeLightingRenderer = realtimeLightingRenderer_t( r_realtimeLightingRenderer.Get() ); - - tr.refdef.numShaderLights = 0; - - for ( i = 0; i < tr.refdef.numLights; i++ ) - { - light = tr.currentLight = &tr.refdef.lights[ i ]; - - if ( !light->l.inverseShadows ) - { - if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) - { - tr.refdef.numShaderLights++; - tr.pc.c_dlights++; - - continue; - } - } - - R_TransformShadowLight( light ); - - // we must set up parts of tr.or for light culling - R_RotateLightForViewParms( light, &tr.viewParms, &tr.orientation ); - - // calc local bounds for culling - { - // set up light transform matrix - MatrixSetupTransformFromQuat( light->transformMatrix, light->l.rotation, light->l.origin ); - - // set up light origin for lighting and shadowing - R_SetupLightOrigin( light ); - - // set up model to light view matrix - R_SetupLightView( light ); - - // set up projection - R_SetupLightProjection( light ); - - // calc local bounds for culling - R_SetupLightLocalBounds( light ); - - // look if we have to draw the light including its interactions - switch ( R_CullLocalBox( light->localBounds ) ) - { - case cullResult_t::CULL_IN: - default: - tr.pc.c_box_cull_light_in++; - break; - - case cullResult_t::CULL_CLIP: - tr.pc.c_box_cull_light_clip++; - break; - - case cullResult_t::CULL_OUT: - // light is not visible so skip other light setup stuff to save speed - tr.pc.c_box_cull_light_out++; - continue; - } - - // setup world bounds for intersection tests - R_SetupLightWorldBounds( light ); - - // setup frustum planes for intersection tests - R_SetupLightFrustum( light ); - - // ignore if not in visible bounds - if ( !BoundsIntersect - ( light->worldBounds[ 0 ], light->worldBounds[ 1 ], tr.viewParms.visBounds[ 0 ], tr.viewParms.visBounds[ 1 ] ) ) - { - continue; - } - } - - // set up view dependent light scissor - R_SetupLightScissor( light ); - - // set up view dependent light Level of Detail - R_SetupLightLOD( light ); - - // look for proper attenuation shader - R_SetupLightShader( light ); - - // setup interactions - light->firstInteraction = nullptr; - light->lastInteraction = nullptr; - - light->numInteractions = 0; - light->numShadowOnlyInteractions = 0; - light->numLightOnlyInteractions = 0; - light->noSort = false; - - R_AddWorldInteractions( light ); - R_AddEntityInteractions( light ); - - if ( light->numInteractions && light->numInteractions != light->numShadowOnlyInteractions ) - { - R_SortInteractions( light ); - - tr.pc.c_dlights++; - } - else - { - // skip all interactions of this light because it caused only shadow volumes - // but no lighting - tr.refdef.numInteractions -= light->numInteractions; - } - } -} - static std::vector botDebugDrawCommands; void RE_SendBotDebugDrawCommands( std::vector commands ) { @@ -2454,7 +2021,6 @@ or a mirror / remote location void R_RenderView( viewParms_t *parms ) { int firstDrawSurf; - int firstInteraction; if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { @@ -2476,7 +2042,6 @@ void R_RenderView( viewParms_t *parms ) tr.viewParms.viewCount = tr.viewCount; // % MAX_VIEWS; firstDrawSurf = tr.refdef.numDrawSurfs; - firstInteraction = tr.refdef.numInteractions; // set viewParms.world R_RotateForViewer(); @@ -2489,7 +2054,7 @@ void R_RenderView( viewParms_t *parms ) if ( glConfig2.usingMaterialSystem && !r_materialSystemSkip.Get() ) { tr.viewParms.viewID = tr.viewCount; - materialSystem.QueueSurfaceCull( tr.viewCount, tr.viewParms.pvsOrigin, (frustum_t*) tr.viewParms.frustums[0] ); + materialSystem.QueueSurfaceCull( tr.viewCount, tr.viewParms.pvsOrigin, (frustum_t*) tr.viewParms.frustum ); materialSystem.AddAutospriteSurfaces(); } else { R_AddWorldSurfaces(); @@ -2508,13 +2073,8 @@ void R_RenderView( viewParms_t *parms ) // set camera frustum planes in world space again, but this time including the far plane tr.orientation = tr.viewParms.world; - // for parallel split shadow mapping - R_SetupSplitFrustums(); - R_AddEntitySurfaces(); - R_AddLightInteractions(); - // Transform the blur vector in view space, FIXME for some we need reason invert its Z component MatrixTransformNormal2( tr.viewParms.world.viewMatrix, tr.refdef.blurVec ); tr.refdef.blurVec[2] *= -1; @@ -2522,9 +2082,6 @@ void R_RenderView( viewParms_t *parms ) tr.viewParms.drawSurfs = tr.refdef.drawSurfs + firstDrawSurf; tr.viewParms.numDrawSurfs = tr.refdef.numDrawSurfs - firstDrawSurf; - tr.viewParms.interactions = tr.refdef.interactions + firstInteraction; - tr.viewParms.numInteractions = tr.refdef.numInteractions - firstInteraction; - R_SortDrawSurfs(); // draw main system development information (surface outlines, etc) diff --git a/src/engine/renderer/tr_mesh.cpp b/src/engine/renderer/tr_mesh.cpp index 294aa0f01..be367a213 100644 --- a/src/engine/renderer/tr_mesh.cpp +++ b/src/engine/renderer/tr_mesh.cpp @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA R_CullMDV ============= */ -static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) +static cullResult_t R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { mdvFrame_t *oldFrame, *newFrame; int i; @@ -59,13 +59,11 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { case cullResult_t::CULL_OUT: tr.pc.c_sphere_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; case cullResult_t::CULL_IN: tr.pc.c_sphere_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_sphere_cull_mdv_clip++; @@ -91,14 +89,12 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) if ( sphereCull == cullResult_t::CULL_OUT ) { tr.pc.c_sphere_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } else if ( sphereCull == cullResult_t::CULL_IN ) { tr.pc.c_sphere_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; } else { @@ -112,19 +108,16 @@ static void R_CullMDV( mdvModel_t *model, trRefEntity_t *ent ) { case cullResult_t::CULL_IN: tr.pc.c_box_cull_mdv_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_mdv_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_mdv_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -296,9 +289,7 @@ void R_AddMDVSurfaces( trRefEntity_t *ent ) // cull the entire model if merged bounding box of both frames // is outside the view frustum. - R_CullMDV( model, ent ); - - if ( ent->cull == CULL_OUT ) + if ( R_CullMDV( model, ent ) == CULL_OUT ) { return; } @@ -343,134 +334,6 @@ void R_AddMDVSurfaces( trRefEntity_t *ent ) } } -/* -================= -R_AddMDVInteractions -================= -*/ -void R_AddMDVInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType ) -{ - mdvModel_t *model = nullptr; - mdvSurface_t *mdvSurface = nullptr; - int lod; - bool personalModel; - byte cubeSideBits; - - // cull the entire model if merged bounding box of both frames - // is outside the view frustum and we don't care about proper shadowing - if ( ent->cull == CULL_OUT ) - { - iaType = (interactionType_t) (iaType & ~IA_LIGHT); - } - - if ( !iaType ) - { - return; - } - - // avoid drawing of certain objects -#if defined( USE_REFENTITY_NOSHADOWID ) - - if ( light->l.inverseShadows ) - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) ) - { - return; - } - } - else - { - if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) ) - { - return; - } - } - -#endif - - // don't add third_person objects if not in a portal - personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && - tr.viewParms.portalLevel == 0; - - // compute LOD - lod = R_ComputeLOD( ent ); - - model = tr.currentModel->mdv[ lod ]; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, ent->worldBounds ) == CULL_OUT ) - { - tr.pc.c_dlightSurfacesCulled += model->numSurfaces; - return; - } - } - - cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds ); - - // generate interactions with all surfaces - if ( r_vboModels.Get() && model->numVBOSurfaces ) - { - // new brute force method: just render everthing with static VBOs - srfVBOMDVMesh_t *vboSurface; - - // static VBOs are fine for lighting and shadow mapping - for ( int i = 0; i < model->numVBOSurfaces; i++ ) - { - vboSurface = model->vboSurfaces[ i ]; - mdvSurface = vboSurface->mdvSurface; - - shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) vboSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } - else - { - int i; - for ( i = 0, mdvSurface = model->surfaces; i < model->numSurfaces; i++, mdvSurface++ ) - { - shader_t *shader = GetMDVSurfaceShader( ent, mdvSurface ); - - // skip all surfaces that don't matter for lighting only pass - if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) ) - { - continue; - } - - // we will add shadows even if the main object isn't visible in the view - - // don't add third_person objects if not viewing through a portal - if ( !personalModel ) - { - R_AddLightInteraction( light, ( surfaceType_t * ) mdvSurface, shader, cubeSideBits, iaType ); - tr.pc.c_dlightSurfaces++; - } - } - } -} - void MarkShaderBuildMDV( const mdvModel_t* model ) { for ( int i = 0; i < model->numVBOSurfaces; i++ ) { srfVBOMDVMesh_t* surface = model->vboSurfaces[i]; diff --git a/src/engine/renderer/tr_model.cpp b/src/engine/renderer/tr_model.cpp index 4bf9c67e3..2f80a8e48 100644 --- a/src/engine/renderer/tr_model.cpp +++ b/src/engine/renderer/tr_model.cpp @@ -147,7 +147,7 @@ qhandle_t RE_RegisterModel( const char *name ) if ( !err ) { - if ( Str::IsIPrefix( "MD5Version", buffer ) ) + if ( Str::IsIPrefix( MD5_IDENTSTRING, buffer ) ) { loaded = R_LoadMD5( mod, buffer.c_str(), name ); } diff --git a/src/engine/renderer/tr_model_iqm.cpp b/src/engine/renderer/tr_model_iqm.cpp index a23d0d56e..d6a9413be 100644 --- a/src/engine/renderer/tr_model_iqm.cpp +++ b/src/engine/renderer/tr_model_iqm.cpp @@ -930,7 +930,7 @@ bool R_LoadIQModel( model_t *mod, const void *buffer, int filesize, R_CullIQM ============= */ -static void R_CullIQM( trRefEntity_t *ent ) { +static cullResult_t R_CullIQM( trRefEntity_t *ent ) { vec3_t localBounds[ 2 ]; float scale = ent->e.skeleton.scale; IQModel_t *model = tr.currentModel->iqm; @@ -962,17 +962,14 @@ static void R_CullIQM( trRefEntity_t *ent ) { { case cullResult_t::CULL_IN: tr.pc.c_box_cull_md5_in++; - ent->cull = cullResult_t::CULL_IN; - return; + return cullResult_t::CULL_IN; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_md5_clip++; - ent->cull = cullResult_t::CULL_CLIP; - return; + return cullResult_t::CULL_CLIP; case cullResult_t::CULL_OUT: default: tr.pc.c_box_cull_md5_out++; - ent->cull = cullResult_t::CULL_OUT; - return; + return cullResult_t::CULL_OUT; } } @@ -999,14 +996,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) { personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && tr.viewParms.portalLevel == 0; - // cull the entire model if merged bounding box of both frames - // is outside the view frustum. - R_CullIQM( ent ); - // HACK: Never cull first-person models, due to issues with a certain model's bounds // A first-person model not in the player's sight seems like something that should not happen in any case - // But R_CullIQM is always called because it sets some fields used by other code - if ( ent->cull == cullResult_t::CULL_OUT && !( ent->e.renderfx & RF_FIRST_PERSON ) ) + if ( !( ent->e.renderfx & RF_FIRST_PERSON ) && R_CullIQM( ent ) == cullResult_t::CULL_OUT ) { return; } diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index 1fbd173a6..5a0c4f115 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -142,8 +142,6 @@ struct glconfig2_t bool colorGrading; bool realtimeLighting; int realtimeLightLayers; - bool shadowMapping; - shadowingMode_t shadowingMode; bool deluxeMapping; bool normalMapping; bool specularMapping; diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 4626d9dae..388d8a16a 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -28,7 +28,6 @@ static Cvar::Cvar r_drawDynamicLights( "r_drawDynamicLights", "render dynamic lights (if realtime lighting is enabled)", Cvar::NONE, true ); static int r_firstSceneDrawSurf; -static int r_firstSceneInteraction; static int r_numLights; static int r_firstSceneLight; @@ -66,7 +65,6 @@ void R_ToggleSmpFrame() backEndData[ tr.smpFrame ]->commands.used = 0; r_firstSceneDrawSurf = 0; - r_firstSceneInteraction = 0; r_numLights = 0; r_firstSceneLight = 0; @@ -287,7 +285,7 @@ ydnar: modified dlight system to support separate radius and intensity */ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensity, float r, float g, float b, qhandle_t, int flags ) { - trRefLight_t *light; + refLight_t *light; if ( !glConfig2.realtimeLighting || !r_drawDynamicLights.Get() ) { @@ -299,12 +297,10 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit return; } - // set last lights restrictInteractionEnd if needed - if ( r_numLights > r_firstSceneLight ) { - light = &backEndData[ tr.smpFrame ]->lights[ r_numLights - 1 ]; - if( light->restrictInteractionFirst >= 0 ) { - light->restrictInteractionLast = r_numEntities - r_firstSceneEntity - 1; - } + if ( flags & REF_INVERSE_DLIGHT ) + { + Log::Warn( "REF_INVERSE_DLIGHT not implemtented" ); + return; } if ( r_numLights >= MAX_REF_LIGHTS ) @@ -319,38 +315,16 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit light = &backEndData[ tr.smpFrame ]->lights[ r_numLights++ ]; - light->l.rlType = refLightType_t::RL_OMNI; - VectorCopy( org, light->l.origin ); - - QuatClear( light->l.rotation ); - VectorClear( light->l.center ); - - // HACK: this will tell the renderer backend to use tr.defaultLightShader - light->l.attenuationShader = 0; - - light->l.radius = radius; + light->rlType = refLightType_t::RL_OMNI; + VectorCopy( org, light->origin ); - light->l.color[ 0 ] = r; - light->l.color[ 1 ] = g; - light->l.color[ 2 ] = b; + light->radius = radius; - light->l.inverseShadows = (flags & REF_INVERSE_DLIGHT) != 0; - light->l.noShadows = !r_realtimeLightingCastShadows->integer && !light->l.inverseShadows; + light->color[ 0 ] = r; + light->color[ 1 ] = g; + light->color[ 2 ] = b; - if( flags & REF_RESTRICT_DLIGHT ) { - light->restrictInteractionFirst = r_numEntities - r_firstSceneEntity; - light->restrictInteractionLast = 0; - } else { - light->restrictInteractionFirst = -1; - light->restrictInteractionLast = -1; - } - - light->additive = true; - - if( light->l.inverseShadows ) - light->l.scale = -intensity; - else - light->l.scale = intensity; + light->scale = intensity; } void RE_AddDynamicLightToSceneQ3A( const vec3_t org, float radius, float r, float g, float b ) @@ -541,7 +515,7 @@ void RE_RenderScene( const refdef_t *fd ) // will force a reset of the visible leafs even if the view hasn't moved tr.refdef.areamaskModified = false; - if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) && !( ( tr.refdef.rdflags & RDF_SKYBOXPORTAL ) && tr.world->numSkyNodes > 0 ) ) + if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) ) { int areaDiff; int i; @@ -572,9 +546,6 @@ void RE_RenderScene( const refdef_t *fd ) tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; tr.refdef.drawSurfs = backEndData[ tr.smpFrame ]->drawSurfs; - tr.refdef.numInteractions = r_firstSceneInteraction; - tr.refdef.interactions = backEndData[ tr.smpFrame ]->interactions; - tr.refdef.numEntities = r_numEntities - r_firstSceneEntity; tr.refdef.entities = &backEndData[ tr.smpFrame ]->entities[ r_firstSceneEntity ]; @@ -662,7 +633,6 @@ void RE_RenderScene( const refdef_t *fd ) // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; - r_firstSceneInteraction = tr.refdef.numInteractions; r_firstSceneEntity = r_numEntities; r_firstSceneLight = r_numLights; r_firstScenePoly = r_numPolys; diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 223303a1d..abb1a2a8d 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -41,30 +41,27 @@ static void EnableAvailableFeatures() if ( glConfig2.realtimeLighting ) { - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - if ( !glConfig2.uniformBufferObjectAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); - glConfig2.realtimeLighting = false; - } + if ( !glConfig2.uniformBufferObjectAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_ARB_uniform_buffer_object is not available." ); + glConfig2.realtimeLighting = false; + } - if ( !glConfig2.textureIntegerAvailable ) { - Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); - glConfig2.realtimeLighting = false; - } + if ( !glConfig2.textureIntegerAvailable ) { + Log::Warn( "Tiled dynamic light renderer disabled because GL_EXT_texture_integer is not available." ); + glConfig2.realtimeLighting = false; + } - if ( glConfig2.max3DTextureSize == 0 ) - { - Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); - glConfig2.realtimeLighting = false; - } + if ( glConfig2.max3DTextureSize == 0 ) + { + Log::Warn( "Tiled dynamic light renderer disabled because of missing 3D texture support." ); + glConfig2.realtimeLighting = false; + } - // See below about ALU instructions on ATI R300 and Intel GMA 3. - if ( !glConfig2.glCoreProfile && glConfig2.maxAluInstructions < 128 ) - { - Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig2.maxAluInstructions ); - glConfig2.realtimeLighting = false; - } + // See below about ALU instructions on ATI R300 and Intel GMA 3. + if ( !glConfig2.glCoreProfile && glConfig2.maxAluInstructions < 128 ) + { + Log::Warn( "Tiled dynamic light rendered disabled because GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB is too small: %d", glConfig2.maxAluInstructions ); + glConfig2.realtimeLighting = false; } } @@ -91,18 +88,6 @@ static void EnableAvailableFeatures() } } - glConfig2.shadowingMode = shadowingMode_t( r_shadows.Get() ); - glConfig2.shadowMapping = glConfig2.shadowingMode >= shadowingMode_t::SHADOWING_ESM16; - - if ( glConfig2.shadowMapping ) - { - if ( !glConfig2.textureFloatAvailable ) - { - Log::Warn( "Shadow mapping disabled because ARB_texture_float is not available." ); - glConfig2.shadowMapping = false; - } - } - glConfig2.deluxeMapping = r_deluxeMapping->integer; glConfig2.normalMapping = r_normalMapping->integer; glConfig2.specularMapping = r_specularMapping->integer; @@ -174,7 +159,6 @@ static void EnableAvailableFeatures() if ( !glConfig2.glCoreProfile && glConfig2.maxTexIndirections < 16 ) { static const std::pair indirectFeatures[] = { - { &glConfig2.shadowMapping, "Shadow mapping" }, { &glConfig2.bloom, "Bloom" }, { &glConfig2.motionBlur, "Motion blur" }, }; @@ -255,45 +239,13 @@ static void GLSL_InitGPUShadersOrError() if ( glConfig2.realtimeLighting ) { - realtimeLightingRenderer_t realtimeLightingRenderer = realtimeLightingRenderer_t( r_realtimeLightingRenderer.Get() ); - - switch( realtimeLightingRenderer ) - { - case realtimeLightingRenderer_t::LEGACY: - // projective lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); - - // omni-directional specular bump mapping ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_omniXYZ ); - - // directional sun lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_directionalSun ); - break; - case realtimeLightingRenderer_t::TILED: - gl_shaderManager.LoadShader( gl_depthtile1Shader ); - gl_shaderManager.LoadShader( gl_depthtile2Shader ); - gl_shaderManager.LoadShader( gl_lighttileShader ); - - gl_depthtile1Shader->MarkProgramForBuilding( 0 ); - gl_depthtile2Shader->MarkProgramForBuilding( 0 ); - gl_lighttileShader->MarkProgramForBuilding( 0 ); - DAEMON_FALLTHROUGH; - default: - /* Dynamic shadowing code also needs this shader. - This code is not well known, so there may be a bug, - but commit a09f03bc8e775d83ac5e057593eff4e88cdea7eb mentions this: - - > Use conventional shadow mapping code for inverse lights. - > This re-enables shadows for players in the tiled renderer. - > -- @gimhael + gl_shaderManager.LoadShader( gl_depthtile1Shader ); + gl_shaderManager.LoadShader( gl_depthtile2Shader ); + gl_shaderManager.LoadShader( gl_lighttileShader ); - See also https://github.com/DaemonEngine/Daemon/pull/606#pullrequestreview-912402293 */ - if ( glConfig2.shadowMapping ) - { - // projective lighting ( Doom3 style ) - gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); - } - } + gl_depthtile1Shader->MarkProgramForBuilding( 0 ); + gl_depthtile2Shader->MarkProgramForBuilding( 0 ); + gl_lighttileShader->MarkProgramForBuilding( 0 ); } if ( glConfig2.reflectionMappingAvailable ) @@ -380,7 +332,7 @@ static void GLSL_InitGPUShadersOrError() gl_cameraEffectsShader->MarkProgramForBuilding( 0 ); - if ( glConfig2.bloom || glConfig2.shadowMapping ) + if ( glConfig2.bloom ) { // gaussian blur gl_shaderManager.LoadShader( gl_blurShader ); @@ -388,15 +340,6 @@ static void GLSL_InitGPUShadersOrError() gl_blurShader->MarkProgramForBuilding( 0 ); } - if ( glConfig2.shadowMapping ) - { - // shadowmap distance compression - gl_shaderManager.LoadShader( gl_shadowFillShader ); - - // debug utils - gl_shaderManager.LoadShader( gl_debugShadowMapShader ); - } - if ( r_liquidMapping->integer != 0 ) { gl_shaderManager.LoadShader( gl_liquidShader ); @@ -517,10 +460,6 @@ void GLSL_ShutdownGPUShaders() gl_processSurfacesShader = nullptr; gl_lightMappingShader = nullptr; gl_lightMappingShaderMaterial = nullptr; - gl_forwardLightingShader_omniXYZ = nullptr; - gl_forwardLightingShader_projXYZ = nullptr; - gl_forwardLightingShader_directionalSun = nullptr; - gl_shadowFillShader = nullptr; gl_reflectionShader = nullptr; gl_reflectionShaderMaterial = nullptr; gl_skyboxShader = nullptr; @@ -536,7 +475,6 @@ void GLSL_ShutdownGPUShaders() gl_contrastShader = nullptr; gl_cameraEffectsShader = nullptr; gl_blurShader = nullptr; - gl_debugShadowMapShader = nullptr; gl_liquidShader = nullptr; gl_liquidShaderMaterial = nullptr; gl_motionblurShader = nullptr; @@ -689,7 +627,7 @@ static void DrawTris() // u_AlphaThreshold gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - if ( r_showBatches->integer || r_showLightBatches->integer ) + if ( r_showBatches->integer ) { SetUniform_Color( gl_genericShader, Color::Color::Indexed( backEnd.pc.c_batches % 8 ) ); } @@ -931,7 +869,6 @@ void Render_generic3D( shaderStage_t *pStage ) { // calculate the environment texcoords in object space gl_genericShader->SetUniform_ViewOrigin( backEnd.orientation.viewOrigin ); - gl_genericShader->SetUniform_ViewUp( backEnd.orientation.axis[ 2 ] ); } // u_AlphaThreshold @@ -1101,12 +1038,11 @@ void Render_lightMapping( shaderStage_t *pStage ) gl_lightMappingShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - if ( glConfig2.realtimeLighting && - r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + if ( glConfig2.realtimeLighting ) { gl_lightMappingShader->SetUniform_numLights( tr.refdef.numLights ); - if ( backEnd.refdef.numShaderLights > 0 ) + if ( backEnd.refdef.numLights > 0 ) { gl_lightMappingShader->SetUniformBlock_Lights( tr.dlightUBO ); @@ -1287,845 +1223,213 @@ void Render_lightMapping( shaderStage_t *pStage ) GL_CheckErrors(); } -static void Render_shadowFill( shaderStage_t *pStage ) +void Render_reflection_CB( shaderStage_t *pStage ) { - uint32_t stateBits; - - GLIMP_LOGCOMMENT( "--- Render_shadowFill ---" ); - - // remove blend modes - stateBits = pStage->stateBits; - stateBits &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); - - GL_State( stateBits ); - - gl_shadowFillShader->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_shadowFillShader->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_shadowFillShader->SetMacro_LIGHT_DIRECTIONAL( backEnd.currentLight->l.rlType == refLightType_t::RL_DIRECTIONAL ); - - gl_shadowFillShader->BindProgram( pStage->deformIndex ); - - gl_shadowFillShader->SetRequiredVertexPointers(); + GLIMP_LOGCOMMENT( "--- Render_reflection_CB ---" ); - if ( r_debugShadowMaps->integer ) - { - SetUniform_Color( gl_shadowFillShader, Color::Color::Indexed( backEnd.pc.c_batches % 8 ) ); - } + GL_State( pStage->stateBits ); - // u_AlphaThreshold - gl_shadowFillShader->SetUniform_AlphaTest( pStage->stateBits ); + // choose right shader program ---------------------------------- + ProcessShaderReflection( pStage ); + gl_reflectionShader->BindProgram( pStage->deformIndex ); + // end choose right shader program ------------------------------ - if ( backEnd.currentLight->l.rlType != refLightType_t::RL_DIRECTIONAL ) - { - gl_shadowFillShader->SetUniform_LightOrigin( backEnd.currentLight->origin ); - gl_shadowFillShader->SetUniform_LightRadius( backEnd.currentLight->sphereRadius ); - } + gl_reflectionShader->SetUniform_ViewOrigin( backEnd.viewParms.orientation.origin ); // in world space - gl_shadowFillShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_shadowFillShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); + gl_reflectionShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); + gl_reflectionShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); // u_Bones if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) { - gl_shadowFillShader->SetUniform_Bones( tess.numBones, tess.bones ); + gl_reflectionShader->SetUniform_Bones( tess.numBones, tess.bones ); } // u_VertexInterpolation if ( tess.vboVertexAnimation ) { - gl_shadowFillShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); + gl_reflectionShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); } - // u_DeformGen - gl_shadowFillShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - // bind u_ColorMap - if ( ( pStage->stateBits & GLS_ATEST_BITS ) != 0 ) - { - gl_shadowFillShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) - ); - gl_shadowFillShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_COLORMAP ] ); - } - else - { - gl_shadowFillShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, tr.whiteImage ) - ); + vec3_t position; + if ( backEnd.currentEntity && ( backEnd.currentEntity != &tr.worldEntity ) ) { + VectorCopy( backEnd.currentEntity->e.origin, position ); + } else { + // FIXME position + VectorCopy( backEnd.viewParms.orientation.origin, position ); } - Tess_DrawElements(); - - GL_CheckErrors(); -} - -static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, - shaderStage_t *attenuationXYStage, - shaderStage_t *attenuationZStage, trRefLight_t *light ) -{ - vec3_t viewOrigin; - vec3_t lightOrigin; - float shadowTexelSize; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_omni ---" ); - - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_omniXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_omniXYZ->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_forwardLightingShader_omniXYZ->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); - - gl_forwardLightingShader_omniXYZ->SetReliefMapping( pStage->enableReliefMapping ); - - gl_forwardLightingShader_omniXYZ->SetShadowing( shadowCompare ); - - gl_forwardLightingShader_omniXYZ->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ + cubemapProbe_t* probes[ 1 ]; + vec4_t trilerp; + R_GetNearestCubeMaps( position, probes, trilerp, 1 ); - // now we are ready to set the shader program uniforms + gl_reflectionShader->SetUniform_ColorMapCubeBindless( + GL_BindToTMU( 0, probes[0]->cubemap ) + ); - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); + // bind u_NormalMap + gl_reflectionShader->SetUniform_NormalMapBindless( + GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) + ); - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_omniXYZ, rgbGen, alphaGen ); + // bind u_NormalScale + if ( pStage->enableNormalMapping ) + { + vec3_t normalScale; + SetNormalScale( pStage, normalScale ); - // u_Color - SetUniform_Color( gl_forwardLightingShader_omniXYZ, tess.svars.color ); + gl_reflectionShader->SetUniform_NormalScale( normalScale ); + } - // u_AlphaThreshold - gl_forwardLightingShader_omniXYZ->SetUniform_AlphaTest( pStage->stateBits ); + gl_reflectionShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_NORMALMAP ] ); - // bind u_HeightMap + // bind u_HeightMap u_depthScale u_reliefOffsetBias if ( pStage->enableReliefMapping ) { float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); depthScale *= tess.surfaceShader->reliefDepthScale; - gl_forwardLightingShader_omniXYZ->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_omniXYZ->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); + gl_reflectionShader->SetUniform_ReliefDepthScale( depthScale ); + gl_reflectionShader->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap if ( !pStage->hasHeightMapInNormalMap ) { - gl_forwardLightingShader_omniXYZ->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) + gl_reflectionShader->SetUniform_HeightMapBindless( + GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) ); } } - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( light->origin, lightOrigin ); - Color::Color lightColor = tess.svars.color; + gl_reflectionShader->SetRequiredVertexPointers(); - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / shadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } + Tess_DrawElements(); - gl_forwardLightingShader_omniXYZ->SetUniform_ViewOrigin( viewOrigin ); + GL_CheckErrors(); +} - gl_forwardLightingShader_omniXYZ->SetUniform_LightOrigin( lightOrigin ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_omniXYZ->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); +void Render_skybox( shaderStage_t *pStage ) +{ + GLIMP_LOGCOMMENT( "--- Render_skybox ---" ); - GL_CheckErrors(); + GL_State( pStage->stateBits ); - if ( shadowCompare ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowBlur( r_shadowBlur->value ); - } + gl_skyboxShader->BindProgram( pStage->deformIndex ); - GL_CheckErrors(); + gl_skyboxShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - gl_forwardLightingShader_omniXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_omniXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); + // bind u_ColorMap + gl_skyboxShader->SetUniform_ColorMapCubeBindless( + GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) + ); - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_Bones( tess.numBones, tess.bones ); - } + // u_AlphaThreshold + gl_skyboxShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } + gl_skyboxShader->SetRequiredVertexPointers(); - gl_forwardLightingShader_omniXYZ->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); + Tess_DrawElements(); GL_CheckErrors(); +} - // bind u_DiffuseMap - gl_forwardLightingShader_omniXYZ->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); +void Render_screen( shaderStage_t *pStage ) +{ + GLIMP_LOGCOMMENT( "--- Render_screen ---" ); - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_omniXYZ->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } + GL_State( pStage->stateBits ); - // bind u_NormalMap - gl_forwardLightingShader_omniXYZ->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); + gl_screenShader->BindProgram( pStage->deformIndex ); - // bind u_NormalScale - if ( pStage->enableNormalMapping ) { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_omniXYZ->SetUniform_NormalScale( normalScale ); + GL_VertexAttribsState( ATTR_POSITION ); + glVertexAttrib4fv( ATTR_INDEX_COLOR, tess.svars.color.ToArray() ); } - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); + gl_screenShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); + + // bind u_CurrentMap + gl_screenShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); - gl_forwardLightingShader_omniXYZ->SetUniform_SpecularExponent( minSpec, maxSpec ); + Tess_DrawElements(); - // bind u_MaterialMap - gl_forwardLightingShader_omniXYZ->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - } + GL_CheckErrors(); +} + +/* This doesn't render the portal itself but the texture +blended to it to fade it with distance. */ +void Render_portal( shaderStage_t *pStage ) +{ + GLIMP_LOGCOMMENT( "--- Render_portal ---" ); - // bind u_AttenuationMapXY - gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapXYBindless( - BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP]) ); + GL_State( pStage->stateBits ); - // bind u_AttenuationMapZ - gl_forwardLightingShader_omniXYZ->SetUniform_AttenuationMapZBindless( - BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); + // enable shader, set arrays + gl_portalShader->BindProgram( pStage->deformIndex ); - // bind u_ShadowMap - if ( shadowCompare ) { - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowMapBindless( - GL_BindToTMU( 5, tr.shadowCubeFBOImage[light->shadowLOD] ) ); - gl_forwardLightingShader_omniXYZ->SetUniform_ShadowClipMapBindless( - GL_BindToTMU( 7, tr.shadowClipCubeFBOImage[light->shadowLOD] ) ); + GL_VertexAttribsState( ATTR_POSITION | ATTR_TEXCOORD ); + glVertexAttrib4fv( ATTR_INDEX_COLOR, tess.svars.color.ToArray() ); } - // bind u_RandomMap - gl_forwardLightingShader_omniXYZ->SetUniform_RandomMapBindless( - GL_BindToTMU( 6, tr.randomNormalsImage ) - ); + gl_portalShader->SetUniform_InversePortalRange( 1 / tess.surfaceShader->portalRange ); - gl_forwardLightingShader_omniXYZ->SetRequiredVertexPointers(); + gl_portalShader->SetUniform_ModelViewMatrix( glState.modelViewMatrix[ glState.stackIndex ] ); + gl_portalShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); + + // bind u_CurrentMap + gl_portalShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); Tess_DrawElements(); GL_CheckErrors(); } -static void Render_forwardLighting_DBS_proj( shaderStage_t *pStage, - shaderStage_t *attenuationXYStage, - shaderStage_t *attenuationZStage, trRefLight_t *light ) +void Render_heatHaze( shaderStage_t *pStage ) { - vec3_t viewOrigin; - vec3_t lightOrigin; - float shadowTexelSize; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_proj ---" ); - - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_projXYZ->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_projXYZ->SetVertexAnimation( tess.vboVertexAnimation ); + uint32_t stateBits; + float deformMagnitude; - gl_forwardLightingShader_projXYZ->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); + GLIMP_LOGCOMMENT( "--- Render_heatHaze ---" ); - gl_forwardLightingShader_projXYZ->SetReliefMapping( pStage->enableReliefMapping ); + // remove alpha test + stateBits = pStage->stateBits; + stateBits &= ~GLS_ATEST_BITS; + stateBits &= ~GLS_DEPTHMASK_TRUE; - gl_forwardLightingShader_projXYZ->SetShadowing( shadowCompare ); + GL_State( stateBits ); - gl_forwardLightingShader_projXYZ->BindProgram( pStage->deformIndex ); + // choose right shader program ---------------------------------- + ProcessShaderHeatHaze( pStage ); + gl_heatHazeShader->BindProgram( pStage->deformIndex ); // end choose right shader program ------------------------------ - // now we are ready to set the shader program uniforms - - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); + // set uniforms - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_projXYZ, rgbGen, alphaGen ); + deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); + gl_heatHazeShader->SetUniform_DeformMagnitude( deformMagnitude ); - // u_Color - SetUniform_Color( gl_forwardLightingShader_projXYZ, tess.svars.color ); + gl_heatHazeShader->SetUniform_ModelViewMatrixTranspose( glState.modelViewMatrix[ glState.stackIndex ] ); + gl_heatHazeShader->SetUniform_ProjectionMatrixTranspose( glState.projectionMatrix[ glState.stackIndex ] ); + gl_heatHazeShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - // u_AlphaThreshold - gl_forwardLightingShader_projXYZ->SetUniform_AlphaTest( pStage->stateBits ); + // u_Bones + if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) + { + gl_heatHazeShader->SetUniform_Bones( tess.numBones, tess.bones ); + } - // bind u_HeightMap - if ( pStage->enableReliefMapping ) + // u_VertexInterpolation + if ( tess.vboVertexAnimation ) { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; + gl_heatHazeShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); + } - gl_forwardLightingShader_projXYZ->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_projXYZ->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_forwardLightingShader_projXYZ->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - VectorCopy( light->origin, lightOrigin ); - Color::Color lightColor = tess.svars.color; - - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / shadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } - - gl_forwardLightingShader_projXYZ->SetUniform_ViewOrigin( viewOrigin ); - - gl_forwardLightingShader_projXYZ->SetUniform_LightOrigin( lightOrigin ); - gl_forwardLightingShader_projXYZ->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_projXYZ->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_projXYZ->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_projXYZ->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); - - GL_CheckErrors(); - - if ( shadowCompare ) - { - gl_forwardLightingShader_projXYZ->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowBlur( r_shadowBlur->value ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowMatrix( light->shadowMatrices ); - } - - GL_CheckErrors(); - - gl_forwardLightingShader_projXYZ->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_projXYZ->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_projXYZ->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_projXYZ->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_forwardLightingShader_projXYZ->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - GL_CheckErrors(); - - // bind u_DiffuseMap - gl_forwardLightingShader_projXYZ->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_projXYZ->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } - - // bind u_NormalMap - gl_forwardLightingShader_projXYZ->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_projXYZ->SetUniform_NormalScale( normalScale ); - } - - // bind u_MaterialMap - gl_forwardLightingShader_projXYZ->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - - gl_forwardLightingShader_projXYZ->SetUniform_SpecularExponent( minSpec, maxSpec ); - } - - // bind u_AttenuationMapXY - gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapXYBindless( - BindAnimatedImage( 3, &attenuationXYStage->bundle[TB_COLORMAP] ) ); - - // bind u_AttenuationMapZ - gl_forwardLightingShader_projXYZ->SetUniform_AttenuationMapZBindless( - BindAnimatedImage( 4, &attenuationZStage->bundle[TB_COLORMAP] ) ); - - // bind u_ShadowMap - if ( shadowCompare ) - { - gl_forwardLightingShader_projXYZ->SetUniform_ShadowMap0Bindless( - GL_BindToTMU( 5, tr.shadowMapFBOImage[light->shadowLOD] ) - ); - gl_forwardLightingShader_projXYZ->SetUniform_ShadowClipMap0Bindless( - GL_BindToTMU( 7, tr.shadowClipMapFBOImage[light->shadowLOD] ) - ); - } - - // bind u_RandomMap - gl_forwardLightingShader_projXYZ->SetUniform_RandomMapBindless( - GL_BindToTMU( 6, tr.randomNormalsImage ) - ); - - gl_forwardLightingShader_projXYZ->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -static void Render_forwardLighting_DBS_directional( shaderStage_t *pStage, trRefLight_t *light ) -{ - vec3_t viewOrigin; - vec3_t lightDirection; - float shadowTexelSize; - - GLIMP_LOGCOMMENT( "--- Render_forwardLighting_DBS_directional ---" ); - - bool shadowCompare = ( glConfig2.shadowMapping && !light->l.noShadows && light->shadowLOD >= 0 ); - - // choose right shader program ---------------------------------- - gl_forwardLightingShader_directionalSun->SetVertexSkinning( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ); - gl_forwardLightingShader_directionalSun->SetVertexAnimation( tess.vboVertexAnimation ); - - gl_forwardLightingShader_directionalSun->SetHeightMapInNormalMap( pStage->hasHeightMapInNormalMap ); - - gl_forwardLightingShader_directionalSun->SetReliefMapping( pStage->enableReliefMapping ); - - gl_forwardLightingShader_directionalSun->SetShadowing( shadowCompare ); - - gl_forwardLightingShader_directionalSun->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - // now we are ready to set the shader program uniforms - - // u_ColorModulate - colorGen_t rgbGen = SetRgbGen( pStage ); - alphaGen_t alphaGen = SetAlphaGen( pStage ); - - SetUniform_ColorModulateColorGen( gl_forwardLightingShader_directionalSun, rgbGen, alphaGen ); - - // u_Color - SetUniform_Color( gl_forwardLightingShader_directionalSun, tess.svars.color ); - - // u_AlphaThreshold - gl_forwardLightingShader_directionalSun->SetUniform_AlphaTest( pStage->stateBits ); - - // bind u_HeightMap - if ( pStage->enableReliefMapping ) - { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; - - gl_forwardLightingShader_directionalSun->SetUniform_ReliefDepthScale( depthScale ); - gl_forwardLightingShader_directionalSun->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_forwardLightingShader_directionalSun->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - // set uniforms - VectorCopy( backEnd.viewParms.orientation.origin, viewOrigin ); - - VectorCopy( tr.sunDirection, lightDirection ); - - Color::Color lightColor = tess.svars.color; - - if ( shadowCompare ) - { - shadowTexelSize = 1.0f / sunShadowMapResolutions[ light->shadowLOD ]; - } - else - { - shadowTexelSize = 1.0f; - } - - gl_forwardLightingShader_directionalSun->SetUniform_ViewOrigin( viewOrigin ); - - gl_forwardLightingShader_directionalSun->SetUniform_LightDir( lightDirection ); - gl_forwardLightingShader_directionalSun->SetUniform_LightColor( lightColor.ToArray() ); - gl_forwardLightingShader_directionalSun->SetUniform_LightRadius( light->sphereRadius ); - gl_forwardLightingShader_directionalSun->SetUniform_LightScale( light->l.scale ); - gl_forwardLightingShader_directionalSun->SetUniform_LightAttenuationMatrix( light->attenuationMatrix2 ); - - GL_CheckErrors(); - - if ( shadowCompare ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMatrix( light->shadowMatricesBiased ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowParallelSplitDistances( backEnd.viewParms.parallelSplitDistances ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowTexelSize( shadowTexelSize ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowBlur( r_shadowBlur->value ); - } - - GL_CheckErrors(); - - gl_forwardLightingShader_directionalSun->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_forwardLightingShader_directionalSun->SetUniform_ViewMatrix( backEnd.viewParms.world.viewMatrix ); - gl_forwardLightingShader_directionalSun->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_forwardLightingShader_directionalSun->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_forwardLightingShader_directionalSun->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - gl_forwardLightingShader_directionalSun->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - - GL_CheckErrors(); - - // bind u_DiffuseMap - gl_forwardLightingShader_directionalSun->SetUniform_DiffuseMapBindless( - GL_BindToTMU( 0, pStage->bundle[TB_DIFFUSEMAP].image[0] ) - ); - - if ( pStage->type != stageType_t::ST_LIGHTMAP ) - { - gl_forwardLightingShader_directionalSun->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_DIFFUSEMAP ] ); - } - - // bind u_NormalMap - gl_forwardLightingShader_directionalSun->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_forwardLightingShader_directionalSun->SetUniform_NormalScale( normalScale ); - } - - // bind u_MaterialMap - gl_forwardLightingShader_directionalSun->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - - // FIXME: physical mapping is not implemented. - if ( pStage->enableSpecularMapping ) - { - float minSpec = RB_EvalExpression( &pStage->specularExponentMin, r_specularExponentMin->value ); - float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); - gl_forwardLightingShader_directionalSun->SetUniform_SpecularExponent( minSpec, maxSpec ); - } - - // bind u_ShadowMap - if ( shadowCompare ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap0Bindless( - GL_BindToTMU( 5, tr.sunShadowMapFBOImage[ 0 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap0Bindless( - GL_BindToTMU( 10, tr.sunShadowClipMapFBOImage[ 0 ] ) - ); - - if ( r_parallelShadowSplits->integer >= 1 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap1Bindless( - GL_BindToTMU( 6, tr.sunShadowMapFBOImage[ 1 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap1Bindless( - GL_BindToTMU( 11, tr.sunShadowClipMapFBOImage[ 1 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 2 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap2Bindless( - GL_BindToTMU( 7, tr.sunShadowMapFBOImage[ 2 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap2Bindless( - GL_BindToTMU( 12, tr.sunShadowClipMapFBOImage[ 2 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 3 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap3Bindless( - GL_BindToTMU( 8, tr.sunShadowMapFBOImage[ 3 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap3Bindless( - GL_BindToTMU( 13, tr.sunShadowClipMapFBOImage[ 3 ] ) - ); - } - - if ( r_parallelShadowSplits->integer >= 4 ) - { - gl_forwardLightingShader_directionalSun->SetUniform_ShadowMap4Bindless( - GL_BindToTMU( 9, tr.sunShadowMapFBOImage[ 4 ] ) - ); - gl_forwardLightingShader_directionalSun->SetUniform_ShadowClipMap4Bindless( - GL_BindToTMU( 14, tr.sunShadowClipMapFBOImage[ 4 ] ) - ); - } - } - - gl_forwardLightingShader_directionalSun->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -void Render_reflection_CB( shaderStage_t *pStage ) -{ - GLIMP_LOGCOMMENT( "--- Render_reflection_CB ---" ); - - GL_State( pStage->stateBits ); - - // choose right shader program ---------------------------------- - ProcessShaderReflection( pStage ); - gl_reflectionShader->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - gl_reflectionShader->SetUniform_ViewOrigin( backEnd.viewParms.orientation.origin ); // in world space - - gl_reflectionShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - gl_reflectionShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_reflectionShader->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_reflectionShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - vec3_t position; - if ( backEnd.currentEntity && ( backEnd.currentEntity != &tr.worldEntity ) ) { - VectorCopy( backEnd.currentEntity->e.origin, position ); - } else { - // FIXME position - VectorCopy( backEnd.viewParms.orientation.origin, position ); - } - - cubemapProbe_t* probes[ 1 ]; - vec4_t trilerp; - R_GetNearestCubeMaps( position, probes, trilerp, 1 ); - - gl_reflectionShader->SetUniform_ColorMapCubeBindless( - GL_BindToTMU( 0, probes[0]->cubemap ) - ); - - // bind u_NormalMap - gl_reflectionShader->SetUniform_NormalMapBindless( - GL_BindToTMU( 1, pStage->bundle[TB_NORMALMAP].image[0] ) - ); - - // bind u_NormalScale - if ( pStage->enableNormalMapping ) - { - vec3_t normalScale; - SetNormalScale( pStage, normalScale ); - - gl_reflectionShader->SetUniform_NormalScale( normalScale ); - } - - gl_reflectionShader->SetUniform_TextureMatrix( tess.svars.texMatrices[ TB_NORMALMAP ] ); - - // bind u_HeightMap u_depthScale u_reliefOffsetBias - if ( pStage->enableReliefMapping ) - { - float depthScale = RB_EvalExpression( &pStage->depthScaleExp, r_reliefDepthScale->value ); - depthScale *= tess.surfaceShader->reliefDepthScale; - - gl_reflectionShader->SetUniform_ReliefDepthScale( depthScale ); - gl_reflectionShader->SetUniform_ReliefOffsetBias( tess.surfaceShader->reliefOffsetBias ); - - // FIXME: if there is both, embedded heightmap in normalmap is used instead of standalone heightmap - if ( !pStage->hasHeightMapInNormalMap ) - { - gl_reflectionShader->SetUniform_HeightMapBindless( - GL_BindToTMU( 15, pStage->bundle[TB_HEIGHTMAP].image[0] ) - ); - } - } - - gl_reflectionShader->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -void Render_skybox( shaderStage_t *pStage ) -{ - GLIMP_LOGCOMMENT( "--- Render_skybox ---" ); - - GL_State( pStage->stateBits ); - - gl_skyboxShader->BindProgram( pStage->deformIndex ); - - gl_skyboxShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // bind u_ColorMap - gl_skyboxShader->SetUniform_ColorMapCubeBindless( - GL_BindToTMU( 0, pStage->bundle[TB_COLORMAP].image[0] ) - ); - - // u_AlphaThreshold - gl_skyboxShader->SetUniform_AlphaTest( GLS_ATEST_NONE ); - - gl_skyboxShader->SetRequiredVertexPointers(); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -void Render_screen( shaderStage_t *pStage ) -{ - GLIMP_LOGCOMMENT( "--- Render_screen ---" ); - - GL_State( pStage->stateBits ); - - gl_screenShader->BindProgram( pStage->deformIndex ); - - { - GL_VertexAttribsState( ATTR_POSITION ); - glVertexAttrib4fv( ATTR_INDEX_COLOR, tess.svars.color.ToArray() ); - } - - gl_screenShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // bind u_CurrentMap - gl_screenShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -/* This doesn't render the portal itself but the texture -blended to it to fade it with distance. */ -void Render_portal( shaderStage_t *pStage ) -{ - GLIMP_LOGCOMMENT( "--- Render_portal ---" ); - - GL_State( pStage->stateBits ); - - // enable shader, set arrays - gl_portalShader->BindProgram( pStage->deformIndex ); - - { - GL_VertexAttribsState( ATTR_POSITION | ATTR_TEXCOORD ); - glVertexAttrib4fv( ATTR_INDEX_COLOR, tess.svars.color.ToArray() ); - } - - gl_portalShader->SetUniform_InversePortalRange( 1 / tess.surfaceShader->portalRange ); - - gl_portalShader->SetUniform_ModelViewMatrix( glState.modelViewMatrix[ glState.stackIndex ] ); - gl_portalShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // bind u_CurrentMap - gl_portalShader->SetUniform_CurrentMapBindless( BindAnimatedImage( 0, &pStage->bundle[TB_COLORMAP] ) ); - - Tess_DrawElements(); - - GL_CheckErrors(); -} - -void Render_heatHaze( shaderStage_t *pStage ) -{ - uint32_t stateBits; - float deformMagnitude; - - GLIMP_LOGCOMMENT( "--- Render_heatHaze ---" ); - - // remove alpha test - stateBits = pStage->stateBits; - stateBits &= ~GLS_ATEST_BITS; - stateBits &= ~GLS_DEPTHMASK_TRUE; - - GL_State( stateBits ); - - // choose right shader program ---------------------------------- - ProcessShaderHeatHaze( pStage ); - gl_heatHazeShader->BindProgram( pStage->deformIndex ); - // end choose right shader program ------------------------------ - - // set uniforms - - deformMagnitude = RB_EvalExpression( &pStage->deformMagnitudeExp, 1.0 ); - gl_heatHazeShader->SetUniform_DeformMagnitude( deformMagnitude ); - - gl_heatHazeShader->SetUniform_ModelViewMatrixTranspose( glState.modelViewMatrix[ glState.stackIndex ] ); - gl_heatHazeShader->SetUniform_ProjectionMatrixTranspose( glState.projectionMatrix[ glState.stackIndex ] ); - gl_heatHazeShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - - // u_Bones - if ( glConfig2.vboVertexSkinningAvailable && tess.vboVertexSkinning ) - { - gl_heatHazeShader->SetUniform_Bones( tess.numBones, tess.bones ); - } - - // u_VertexInterpolation - if ( tess.vboVertexAnimation ) - { - gl_heatHazeShader->SetUniform_VertexInterpolation( glState.vertexAttribsInterpolation ); - } - - // u_DeformGen - if ( tess.surfaceShader->numDeforms ) - { - gl_heatHazeShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); - } + // u_DeformGen + if ( tess.surfaceShader->numDeforms ) + { + gl_heatHazeShader->SetUniform_Time( backEnd.refdef.floatTime - backEnd.currentEntity->e.shaderTime ); + } // draw to background image R_BindFBO( tr.mainFBO[ 1 - backEnd.currentMainFBO ] ); @@ -2398,12 +1702,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color = Color::Adapt( backEnd.currentLight->l.color ); - tess.svars.color.Clamp(); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color = backEnd.currentEntity->e.shaderRGBA; tess.svars.color.Clamp(); @@ -2418,13 +1717,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_ONE_MINUS_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetRed( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 0 ], 0.0f, 1.0f ) ); - tess.svars.color.SetGreen( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 1 ], 0.0f, 1.0f ) ); - tess.svars.color.SetBlue( 1.0 - Math::Clamp( backEnd.currentLight->l.color[ 2 ], 0.0f, 1.0f ) ); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color = backEnd.currentEntity->e.shaderRGBA; tess.svars.color.Clamp(); @@ -2474,13 +1767,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case colorGen_t::CGEN_CUSTOM_RGBs: { - if ( backEnd.currentLight ) - { - red = Math::Clamp( RB_EvalExpression( &pStage->redExp, backEnd.currentLight->l.color[ 0 ] ), 0.0f, 1.0f ); - green = Math::Clamp( RB_EvalExpression( &pStage->greenExp, backEnd.currentLight->l.color[ 1 ] ), 0.0f, 1.0f ); - blue = Math::Clamp( RB_EvalExpression( &pStage->blueExp, backEnd.currentLight->l.color[ 2 ] ), 0.0f, 1.0f ); - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { red = Math::Clamp( RB_EvalExpression( &pStage->redExp, backEnd.currentEntity->e.shaderRGBA.Red() * ( 1.0 / 255.0 ) ), 0.0f, 1.0f ); @@ -2531,11 +1818,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case alphaGen_t::AGEN_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetAlpha( 1.0 ); // FIXME ? - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color.SetAlpha( Math::Clamp( backEnd.currentEntity->e.shaderRGBA.Alpha() * ( 1.0 / 255.0 ), 0.0, 1.0 ) ); } @@ -2549,11 +1832,7 @@ void Tess_ComputeColor( shaderStage_t *pStage ) case alphaGen_t::AGEN_ONE_MINUS_ENTITY: { - if ( backEnd.currentLight ) - { - tess.svars.color.SetAlpha( 0.0 ); // FIXME ? - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { tess.svars.color.SetAlpha( 1.0 - Math::Clamp( backEnd.currentEntity->e.shaderRGBA.Alpha() * ( 1.0 / 255.0 ), 0.0, 1.0 ) ); } @@ -2729,164 +2008,6 @@ void Tess_StageIteratorPortal() { } } -void Tess_StageIteratorShadowFill() -{ - GLIMP_LOGCOMMENT( "--- Tess_StageIteratorShadowFill( %s, %i vertices, %i triangles ) ---", - tess.surfaceShader->name, tess.numVertexes, tess.numIndexes / 3 ); - - GL_CheckErrors(); - - if ( tess.surfaceShader->autoSpriteMode != 0 ) - { - Tess_AutospriteDeform( tess.surfaceShader->autoSpriteMode ); - } - - if ( !glState.currentVBO || !glState.currentIBO || glState.currentVBO == tess.vbo || glState.currentIBO == tess.ibo ) - { - Tess_UpdateVBOs( ); - } - - // set face culling appropriately - if( backEnd.currentEntity->e.renderfx & RF_SWAPCULL ) - GL_Cull( ReverseCull( tess.surfaceShader->cullType ) ); - else - GL_Cull( tess.surfaceShader->cullType ); - - // set polygon offset if necessary - if ( tess.surfaceShader->polygonOffset ) - { - glEnable( GL_POLYGON_OFFSET_FILL ); - GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // call shader function - for ( shaderStage_t *pStage = tess.surfaceStages; pStage < tess.surfaceLastStage; pStage++ ) - { - if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeTexMatrices( pStage ); - - if ( pStage->doShadowFill ) - { - Render_shadowFill( pStage ); - } - } - - // reset polygon offset - glDisable( GL_POLYGON_OFFSET_FILL ); -} - -void Tess_StageIteratorLighting() -{ - trRefLight_t *light; - - GLIMP_LOGCOMMENT( "--- Tess_StageIteratorLighting( %s, %s, %i vertices, %i triangles ) ---", - tess.surfaceShader->name, tess.lightShader->name, tess.numVertexes, tess.numIndexes / 3 ); - - GL_CheckErrors(); - - light = backEnd.currentLight; - - if ( tess.surfaceShader->autoSpriteMode != 0 ) - { - Tess_AutospriteDeform( tess.surfaceShader->autoSpriteMode ); - } - - if ( !glState.currentVBO || !glState.currentIBO || glState.currentVBO == tess.vbo || glState.currentIBO == tess.ibo ) - { - Tess_UpdateVBOs( ); - } - - // set OpenGL state for lighting - if ( light->l.inverseShadows ) - { - GL_State( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ); - } - else - { - if ( tess.surfaceShader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - } - else - { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - } - - // set face culling appropriately - if( backEnd.currentEntity->e.renderfx & RF_SWAPCULL ) - GL_Cull( ReverseCull( tess.surfaceShader->cullType ) ); - else - GL_Cull( tess.surfaceShader->cullType ); - - // set polygon offset if necessary - if ( tess.surfaceShader->polygonOffset ) - { - glEnable( GL_POLYGON_OFFSET_FILL ); - GL_PolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // call shader function - shaderStage_t *attenuationZStage = &tess.lightShader->stages[ 0 ]; - - for ( shaderStage_t *pStage = tess.surfaceStages; pStage < tess.surfaceLastStage; pStage++ ) - { - if ( !RB_EvalExpression( &pStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeTexMatrices( pStage ); - - for ( shaderStage_t *attenuationXYStage = tess.lightShader->stages; - attenuationXYStage < tess.lightShader->lastStage; - attenuationXYStage++ ) - { - if ( attenuationXYStage->type != stageType_t::ST_ATTENUATIONMAP_XY ) - { - continue; - } - - if ( !RB_EvalExpression( &attenuationXYStage->ifExp, 1.0 ) ) - { - continue; - } - - Tess_ComputeColor( attenuationXYStage ); - R_ComputeFinalAttenuation( attenuationXYStage, light ); - - if ( pStage->doForwardLighting ) - { - switch( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - Render_forwardLighting_DBS_omni( pStage, attenuationXYStage, attenuationZStage, light ); - break; - case refLightType_t::RL_PROJ: - Render_forwardLighting_DBS_proj( pStage, attenuationXYStage, attenuationZStage, light ); - break; - case refLightType_t::RL_DIRECTIONAL: - Render_forwardLighting_DBS_directional( pStage, light ); - break; - default: - ASSERT_UNREACHABLE(); - break; - }; - } - } - } - - // reset polygon offset - if ( tess.surfaceShader->polygonOffset ) - { - glDisable( GL_POLYGON_OFFSET_FILL ); - } -} - void Tess_Clear() { tess.vboVertexSkinning = false; @@ -2942,12 +2063,11 @@ void Tess_End() // call off to shader specific tess end function tess.stageIteratorFunc(); - if ( tess.stageIteratorFunc != Tess_StageIteratorShadowFill && - tess.stageIteratorFunc != Tess_StageIteratorDebug && + if ( tess.stageIteratorFunc != Tess_StageIteratorDebug && tess.stageIteratorFunc != Tess_StageIteratorDummy ) { // draw debugging stuff - if ( r_showTris->integer || r_showBatches->integer || ( r_showLightBatches->integer && ( tess.stageIteratorFunc == Tess_StageIteratorLighting ) ) ) + if ( r_showTris->integer || r_showBatches->integer ) { // Skybox triangle rendering is done in Tess_StageIteratorSky() if ( tess.stageIteratorFunc != Tess_StageIteratorSky ) { diff --git a/src/engine/renderer/tr_shade_calc.cpp b/src/engine/renderer/tr_shade_calc.cpp index 5afa74112..6329c71f0 100644 --- a/src/engine/renderer/tr_shade_calc.cpp +++ b/src/engine/renderer/tr_shade_calc.cpp @@ -99,12 +99,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM0: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 0 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Red() * inv255; } @@ -116,12 +111,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM1: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 1 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Green() * inv255; } @@ -133,12 +123,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM2: - if ( backEnd.currentLight ) - { - value = backEnd.currentLight->l.color[ 2 ]; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Blue() * inv255; } @@ -150,12 +135,7 @@ static float GetOpValue( const expOperation_t *op ) break; case opcode_t::OP_PARM3: - if ( backEnd.currentLight ) - { - value = 1.0; - break; - } - else if ( backEnd.currentEntity ) + if ( backEnd.currentEntity ) { value = backEnd.currentEntity->e.shaderRGBA.Alpha() * inv255; } diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index e20f707d5..518c4021e 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -1781,23 +1781,6 @@ static void ParseReflectionStageBlended( shaderStage_t *stage, const char **text ParseReflectionMap( stage, text, TB_COLORMAP ); } -static void ParseLightFalloffImage( shaderStage_t *stage, const char **text ) -{ - char buffer[ 1024 ] = ""; - - stage->active = true; - stage->type = stageType_t::ST_ATTENUATIONMAP_Z; - stage->rgbGen = colorGen_t::CGEN_IDENTITY; - stage->stateBits = GLS_DEFAULT; - stage->overrideWrapType = true; - stage->wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - if ( ParseMap( text, buffer, sizeof( buffer ) ) ) - { - LoadMap( stage, buffer, stageType_t::ST_COLORMAP ); - } -} - static bool HasNormalFormat( shaderStage_t *stage ) { return stage->normalFormat[ 0 ]; @@ -2142,8 +2125,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) else if ( !Q_stricmp( token, "portalMap" ) ) else if ( !Q_stricmp( token, "heathazeMap" ) ) else if ( !Q_stricmp( token, "liquidMap" ) ) - else if ( !Q_stricmp( token, "attenuationMapXY" ) ) - else if ( !Q_stricmp( token, "attenuationMapZ" ) ) */ // lightmap // What is the use case for this? @@ -2647,14 +2628,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) stage->type = stageType_t::ST_LIQUIDMAP; SetNormalFormat( stage, dxNormalFormat ); } - else if ( !Q_stricmp( token, "attenuationMapXY" ) ) - { - stage->type = stageType_t::ST_ATTENUATIONMAP_XY; - } - else if ( !Q_stricmp( token, "attenuationMapZ" ) ) - { - stage->type = stageType_t::ST_ATTENUATIONMAP_Z; - } else { Log::Warn("unknown stage parameter '%s' in shader '%s'", token, shader.name ); @@ -3266,12 +3239,6 @@ static bool ParseStage( shaderStage_t *stage, const char **text ) depthMaskBits = GLS_DEPTHMASK_TRUE; } - // tell shader if this stage has an alpha test - if ( atestBits & GLS_ATEST_BITS ) - { - shader.alphaTest = true; - } - // check that depthFade and depthWrite are mutually exclusive if ( depthMaskBits && stage->hasDepthFade ) { Log::Warn( "depth fade conflicts with depth mask in shader '%s'", shader.name ); @@ -4130,7 +4097,6 @@ static bool ParseShader( const char *_text ) // noShadows else if ( !Q_stricmp( token, "noShadows" ) ) { - shader.noShadows = true; continue; } // translucent @@ -4645,13 +4611,6 @@ static bool ParseShader( const char *_text ) } continue; } - // lightFalloffImage - else if ( !Q_stricmp( token, "lightFalloffImage" ) ) - { - ParseLightFalloffImage( &stages[ s ], text ); - s++; - continue; - } // Doom 3 DECAL_MACRO else if ( !Q_stricmp( token, "DECAL_MACRO" ) ) { @@ -5215,11 +5174,6 @@ static void FinishStages() lightStageFound = true; break; - case stageType_t::ST_ATTENUATIONMAP_XY: - case stageType_t::ST_ATTENUATIONMAP_Z: - stage->active = ( glConfig2.realtimeLighting && r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::LEGACY ) ); - break; - default: break; } @@ -5362,10 +5316,6 @@ static void SetStagesRenderers() surfaceDataUpdater_t surfaceDataUpdater; stageShaderBinder_t shaderBinder; stageMaterialProcessor_t materialProcessor; - - // Per-stage configuration. - bool doShadowFill; - bool doForwardLighting; }; for ( size_t s = 0; s < numStages; s++ ) @@ -5375,18 +5325,14 @@ static void SetStagesRenderers() stageRendererOptions_t stageRendererOptions = { &Render_NONE, &MarkShaderBuildNONE, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, false, }; - bool opaqueOrLess = shader.sort <= Util::ordinal(shaderSort_t::SS_OPAQUE); - switch ( stage->type ) { case stageType_t::ST_COLORMAP: stageRendererOptions = { &Render_generic, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - opaqueOrLess, false, }; break; case stageType_t::ST_STYLELIGHTMAP: @@ -5394,7 +5340,6 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_generic3D, &MarkShaderBuildGeneric3D, &UpdateSurfaceDataGeneric3D, &BindShaderGeneric3D, &ProcessMaterialGeneric3D, - true, false, }; break; case stageType_t::ST_LIGHTMAP: @@ -5403,14 +5348,12 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - true, true, }; break; case stageType_t::ST_COLLAPSE_COLORMAP: stageRendererOptions = { &Render_lightMapping, &MarkShaderBuildLightMapping, &UpdateSurfaceDataLightMapping, &BindShaderLightMapping, &ProcessMaterialLightMapping, - true, false, }; break; case stageType_t::ST_REFLECTIONMAP: @@ -5418,21 +5361,18 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_reflection_CB, &MarkShaderBuildReflection, &UpdateSurfaceDataReflection, &BindShaderReflection, &ProcessMaterialReflection, - false, false, }; break; case stageType_t::ST_SKYBOXMAP: stageRendererOptions = { &Render_skybox, &MarkShaderBuildSkybox, &UpdateSurfaceDataSkybox, &BindShaderSkybox, &ProcessMaterialSkybox, - false, false, }; break; case stageType_t::ST_SCREENMAP: stageRendererOptions = { &Render_screen, &MarkShaderBuildScreen, &UpdateSurfaceDataScreen, &BindShaderScreen, &ProcessMaterialScreen, - false, false, }; break; case stageType_t::ST_PORTALMAP: @@ -5441,36 +5381,24 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_portal, &MarkShaderBuildPortal, &UpdateSurfaceDataNONE, &BindShaderNONE, &ProcessMaterialNONE, - false, false, }; break; case stageType_t::ST_HEATHAZEMAP: stageRendererOptions = { &Render_heatHaze, &MarkShaderBuildHeatHaze, &UpdateSurfaceDataHeatHaze, &BindShaderHeatHaze, &ProcessMaterialHeatHaze, - false, false, }; break; case stageType_t::ST_LIQUIDMAP: stageRendererOptions = { &Render_liquid, &MarkShaderBuildLiquid, &UpdateSurfaceDataLiquid, &BindShaderLiquid, &ProcessMaterialLiquid, - false, false, }; break; case stageType_t::ST_FOGMAP: stageRendererOptions = { &Render_fog, &MarkShaderBuildFog, &UpdateSurfaceDataFog, &BindShaderFog, &ProcessMaterialFog, - false, false, - }; - break; - case stageType_t::ST_ATTENUATIONMAP_XY: - case stageType_t::ST_ATTENUATIONMAP_Z: - stageRendererOptions = { - &Render_NOP, &MarkShaderBuildNOP, - &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - false, true, }; break; default: @@ -5479,7 +5407,6 @@ static void SetStagesRenderers() stageRendererOptions = { &Render_NOP, &MarkShaderBuildNOP, &UpdateSurfaceDataNOP, &BindShaderNOP, &ProcessMaterialNOP, - false, false, }; break; } @@ -5491,9 +5418,6 @@ static void SetStagesRenderers() stage->shaderBinder = stageRendererOptions.shaderBinder; stage->materialProcessor = stageRendererOptions.materialProcessor; - stage->doShadowFill = stageRendererOptions.doShadowFill; - stage->doForwardLighting = stageRendererOptions.doForwardLighting; - // Disable stages that have no renderer yet. if ( stage->colorRenderer == &Render_NONE ) { @@ -5678,8 +5602,6 @@ static void ValidateStage( shaderStage_t *pStage ) { stageType_t::ST_STYLECOLORMAP, { true, true, false, "style color map" } }, { stageType_t::ST_COLLAPSE_COLORMAP, { true, true, true, "collapsed color map" } }, { stageType_t::ST_COLLAPSE_DIFFUSEMAP, { true, true, true, "collapsed diffuseMap" } }, - { stageType_t::ST_ATTENUATIONMAP_XY, { true, true, false, "attenuationMapXY" } }, - { stageType_t::ST_ATTENUATIONMAP_Z, { true, true, false, "attenuationMapZ" } }, // TODO: Document the remaining stage types. }; @@ -5835,40 +5757,6 @@ static shader_t *FinishShader() shader.portalRange = r_portalDefaultRange.Get(); } - // all light materials need at least one z attenuation stage as first stage - if ( shader.type == shaderType_t::SHADER_LIGHT ) - { - if ( stages[ 0 ].type != stageType_t::ST_ATTENUATIONMAP_Z ) - { - // move up subsequent stages - memmove( &stages[ 1 ], &stages[ 0 ], sizeof( stages[ 0 ] ) * ( MAX_SHADER_STAGES - 1 ) ); - - stages[ 0 ].active = true; - stages[ 0 ].type = stageType_t::ST_ATTENUATIONMAP_Z; - stages[ 0 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 0 ].stateBits = GLS_DEFAULT; - stages[ 0 ].overrideWrapType = true; - stages[ 0 ].wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP; - - const char *squarelight1a = "lights/squarelight1a"; - Log::Debug( "loading '%s' image as shader", squarelight1a ); - LoadMap( &stages[ 0 ], squarelight1a, stageType_t::ST_COLORMAP ); - } - - // force following shader stages to be xy attenuation stages - for ( int i = 1; i < MAX_SHADER_STAGES; i++ ) - { - shaderStage_t *pStage = &stages[ i ]; - - if ( !pStage->active ) - { - break; - } - - pStage->type = stageType_t::ST_ATTENUATIONMAP_XY; - } - } - numStages = MAX_SHADER_STAGES; GroupActiveStages(); @@ -5911,15 +5799,6 @@ static shader_t *FinishShader() shader.sort = DetermineShaderSort(); - // HACK: allow alpha tested surfaces to create shadowmaps - if ( glConfig2.shadowMapping ) - { - if ( shader.noShadows && shader.alphaTest ) - { - shader.noShadows = false; - } - } - if ( shader.sort <= Util::ordinal( shaderSort_t::SS_OPAQUE ) ) { shader.fogPass = fogPass_t::FP_EQUAL; } else if ( shader.contentFlags & CONTENTS_FOG ) { @@ -6360,22 +6239,6 @@ shader_t *R_FindShader( const char *name, shaderType_t type, int flags ) break; } - case shaderType_t::SHADER_LIGHT: - { - stages[ 0 ].type = stageType_t::ST_ATTENUATIONMAP_Z; - stages[ 0 ].bundle[ 0 ].image[ 0 ] = tr.noFalloffImage; // FIXME should be attenuationZImage - stages[ 0 ].active = true; - stages[ 0 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 0 ].stateBits = GLS_DEFAULT; - - stages[ 1 ].type = stageType_t::ST_ATTENUATIONMAP_XY; - stages[ 1 ].bundle[ 0 ].image[ 0 ] = image; - stages[ 1 ].active = true; - stages[ 1 ].rgbGen = colorGen_t::CGEN_IDENTITY; - stages[ 1 ].stateBits = GLS_DEFAULT; - break; - } - default: break; } @@ -6455,9 +6318,7 @@ qhandle_t RE_RegisterShader( const char *name, int flags ) return 0; } - sh = R_FindShader( name, - (flags & RSF_LIGHT_ATTENUATION) ? shaderType_t::SHADER_LIGHT : shaderType_t::SHADER_2D, - flags ); + sh = R_FindShader( name, shaderType_t::SHADER_2D, flags ); // we want to return 0 if the shader failed to // load for some reason, but R_FindShader should @@ -6515,7 +6376,6 @@ class ListShadersCmd : public Cmd::StaticCmd { shaderType_t::SHADER_2D, "2D" }, { shaderType_t::SHADER_3D_DYNAMIC, "3D_DYNAMIC" }, { shaderType_t::SHADER_3D_STATIC, "3D_STATIC" }, - { shaderType_t::SHADER_LIGHT, "LIGHT" }, }; static const std::unordered_map shaderSortName = { @@ -6565,8 +6425,6 @@ class ListShadersCmd : public Cmd::StaticCmd { stageType_t::ST_COLLAPSE_COLORMAP, "COLLAPSE_COLORMAP" }, { stageType_t::ST_COLLAPSE_DIFFUSEMAP, "COLLAPSE_DIFFUSEMAP" }, { stageType_t::ST_COLLAPSE_REFLECTIONMAP, "COLLAPSE_REFLECTIONMAP" }, - { stageType_t::ST_ATTENUATIONMAP_XY, "ATTENUATIONMAP_XY" }, - { stageType_t::ST_ATTENUATIONMAP_Z, "ATTENUATIONMAP_XZ" }, }; const char *prefix = args.Argc() > 1 ? args.Argv( 1 ).c_str() : nullptr; @@ -6576,7 +6434,6 @@ class ListShadersCmd : public Cmd::StaticCmd std::string shaderType = "shaderType"; std::string shaderSort = "shaderSort"; std::string stageType = "stageType"; - std::string interactLight = "interactLight"; std::string stageNumber = "stageNumber"; std::string shaderName = "shaderName"; @@ -6588,7 +6445,6 @@ class ListShadersCmd : public Cmd::StaticCmd size_t shaderTypeLen = shaderType.length(); size_t shaderSortLen = shaderSort.length(); size_t stageTypeLen = stageType.length(); - size_t interactLightLen = interactLight.length(); // Value size for ( const auto& kv : shaderTypeName ) @@ -6615,7 +6471,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << stageNumber << ":" << shaderName; std::string lineSeparator( lineStream.str().length(), '-' ); @@ -6657,7 +6512,6 @@ class ListShadersCmd : public Cmd::StaticCmd shaderSort = shaderSortName.at( (shaderSort_t) shader->sort ); } - interactLight = shader->interactLight ? "INTERACTLIGHT" : ""; shaderName = shader->name; shaderName += shader->defaultShader ? " (DEFAULTED)" : ""; @@ -6671,7 +6525,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << "-:" << shaderName; Print( lineStream.str() ); @@ -6704,7 +6557,6 @@ class ListShadersCmd : public Cmd::StaticCmd lineStream << std::setw(shaderTypeLen) << shaderType << separator; lineStream << std::setw(shaderSortLen) << shaderSort << separator; lineStream << std::setw(stageTypeLen) << stageType << separator; - lineStream << std::setw(interactLightLen) << interactLight << separator; lineStream << j << ":" << shaderName; Print( lineStream.str() ); @@ -7029,15 +6881,6 @@ static void CreateInternalShaders() tr.fogLEShader = FinishShader(); } -static void CreateExternalShaders() -{ - Log::Debug("----- CreateExternalShaders -----" ); - - tr.defaultPointLightShader = R_FindShader( "lights/defaultPointLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); - tr.defaultProjectedLightShader = R_FindShader( "lights/defaultProjectedLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); - tr.defaultDynamicLightShader = R_FindShader( "lights/defaultDynamicLight", shaderType_t::SHADER_LIGHT, RSF_DEFAULT ); -} - /* ================== R_InitShaders @@ -7055,8 +6898,6 @@ void R_InitShaders() CreateInternalShaders(); ScanAndLoadShaderFiles(); - - CreateExternalShaders(); } /* diff --git a/src/engine/renderer/tr_skin.cpp b/src/engine/renderer/tr_skin.cpp index 2f3afbf11..171bc38ee 100644 --- a/src/engine/renderer/tr_skin.cpp +++ b/src/engine/renderer/tr_skin.cpp @@ -165,7 +165,6 @@ qhandle_t RE_RegisterSkin( const char *name ) qhandle_t hSkin; skin_t *skin; skinSurface_t *surf; - skinModel_t *model; //----(SA) added const char *text_p; const char *token; char surfName[ MAX_QPATH ]; @@ -226,7 +225,6 @@ qhandle_t RE_RegisterSkin( const char *name ) tr.skins[ hSkin ] = skin; Q_strncpyz( skin->name, name, sizeof( skin->name ) ); skin->numSurfaces = 0; - skin->numModels = 0; //----(SA) added //----(SA) end @@ -256,22 +254,6 @@ qhandle_t RE_RegisterSkin( const char *name ) continue; } - if ( !Q_strnicmp( token, "md3_", 4 ) ) - { - // this is specifying a model - model = skin->models[ skin->numModels ] = (skinModel_t*) ri.Hunk_Alloc( sizeof( *skin->models[ 0 ] ), ha_pref::h_low ); - Q_strncpyz( model->type, token, sizeof( model->type ) ); - model->hash = Com_HashKey( model->type, sizeof( model->type ) ); - - // get the model name - token = CommaParse( &text_p ); - - Q_strncpyz( model->model, token, sizeof( model->model ) ); - - skin->numModels++; - continue; - } - // parse the shader name token = CommaParse( &text_p ); diff --git a/src/engine/renderer/tr_types.h b/src/engine/renderer/tr_types.h index e00a2cd01..e6a56639c 100644 --- a/src/engine/renderer/tr_types.h +++ b/src/engine/renderer/tr_types.h @@ -45,6 +45,8 @@ Maryland 20850 USA. #define bool DO_NOT_USE_BOOL_IN_IPC_MESSAGE_TYPES using bool8_t = uint8_t; +// TODO(0.56): Remove all shadow stuff in here? + // XreaL BEGIN #define MAX_REF_LIGHTS 1024 #define MAX_REF_ENTITIES 1023 // can't be increased without changing drawsurf bit packing @@ -52,7 +54,6 @@ using bool8_t = uint8_t; #define MAX_WEIGHTS 4 // GPU vertex skinning limit, never change this without rewriting many GLSL shaders // XreaL END -#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces #define MAX_ENTITIES MAX_REF_ENTITIES // RB: for compatibility // renderfx flags @@ -93,6 +94,7 @@ using bool8_t = uint8_t; #define GL_INDEX_TYPE GL_UNSIGNED_INT using glIndex_t = unsigned int; +// TODO(0.56): drop RSF_LIGHT_ATTENUATION enum RegisterShaderFlags_t { RSF_DEFAULT = BIT( 0 ), RSF_2D = BIT( 1 ), @@ -131,11 +133,6 @@ enum class refEntityType_t RT_MAX_REF_ENTITY_TYPE }; -// XreaL BEGIN - -// RB: defining any of the following macros would break the compatibility to old ET mods -//#define USE_REFENTITY_NOSHADOWID 1 - // RB: having bone names for each refEntity_t takes several MiBs // in backEndData_t so only use it for debugging and development // enabling this will show the bone names with r_showSkeleton 1 @@ -204,11 +201,6 @@ struct refEntity_t float radius; float rotation; -#if defined( USE_REFENTITY_NOSHADOWID ) - // extra light interaction information - short noShadowID; -#endif - int altShaderIndex; // KEEP SKELETON AT THE END OF THE STRUCTURE @@ -220,52 +212,6 @@ struct refEntity_t // ================================================================================================ -// XreaL BEGIN - -enum class refLightType_t -{ - RL_OMNI, // point light - RL_PROJ, // spot light - RL_DIRECTIONAL, // sun light - - RL_MAX_REF_LIGHT_TYPE -}; - -struct refLight_t -{ - refLightType_t rlType; -// int lightfx; - - qhandle_t attenuationShader; - - vec3_t origin; - quat_t rotation; - vec3_t center; - vec3_t color; // range from 0.0 to 1.0, should be color normalized - - float scale; // r_lightScale if not set - - // omni-directional light specific - float radius; - - // projective light specific - vec3_t projTarget; - vec3_t projRight; - vec3_t projUp; - vec3_t projStart; - vec3_t projEnd; - - bool8_t noShadows; - short noShadowID; // don't cast shadows of all entities with this id - - bool8_t inverseShadows; // don't cast light and draw shadows by darken the scene - // this is useful for drawing player shadows with shadow mapping -}; - -// XreaL END - -// ================================================================================================ - struct refdef_t { int x, y, width, height; diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index b355ca37a..a452b1a78 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "Material.h" #include "GeometryCache.h" +#include "GLMemory.h" // interleaved data: position, colour, qtangent, texcoord // -> struct shaderVertex_t in tr_local.h @@ -662,18 +663,6 @@ static void R_InitTileVBO() return; } - if ( r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - /* This computation is part of the tiled dynamic lighting renderer, - it's better to not run it and save CPU cycles when such effects - are disabled. - - There is no need to create vertex buffers that are only used by the - tiled dynamic lighting renderer when this feature is disabled. */ - - return; - } - R_SyncRenderThread(); int x, y, w, h; @@ -773,6 +762,10 @@ void R_InitVBOs() geometryCache.InitGLBuffers(); } + if ( glConfig2.directStateAccessAvailable && glConfig2.uniformBufferObjectAvailable ) { + stagingBuffer.InitGLBuffer(); + } + GL_CheckErrors(); } @@ -845,6 +838,10 @@ void R_ShutdownVBOs() geometryCache.FreeGLBuffers(); } + if ( glConfig2.directStateAccessAvailable && glConfig2.uniformBufferObjectAvailable ) { + stagingBuffer.FreeGLBuffer(); + } + tess.verts = tess.vertsBuffer = nullptr; tess.indexes = tess.indexesBuffer = nullptr; } diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index 43b746845..a8bac11e4 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -125,136 +125,6 @@ static bool R_CullSurface( surfaceType_t *surface, shader_t *shader, int planeBi return false; } -static bool R_CullLightSurface( surfaceType_t *surface, shader_t *shader, trRefLight_t *light, byte *cubeSideBits ) -{ - srfGeneric_t *gen; - float d; - - // allow culling to be disabled - if ( r_nocull->integer ) - { - return false; - } - - // ydnar: made surface culling generic, inline with q3map2 surface classification - if ( *surface == surfaceType_t::SF_GRID && r_nocurves->integer ) - { - return true; - } - - if ( *surface != surfaceType_t::SF_FACE && *surface != surfaceType_t::SF_TRIANGLES && *surface != surfaceType_t::SF_VBO_MESH && *surface != surfaceType_t::SF_GRID ) - { - return true; - } - - gen = ( srfGeneric_t * ) surface; - - // do a quick AABB cull - if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], gen->bounds[ 0 ], gen->bounds[ 1 ] ) ) - { - return true; - } - - // do a more expensive and precise light frustum cull - if ( !r_noLightFrustums->integer ) - { - if ( R_CullLightWorldBounds( light, gen->bounds ) == CULL_OUT ) - { - return true; - } - } - - // plane cull - if ( *surface == surfaceType_t::SF_FACE && r_facePlaneCull->integer ) - { - srfGeneric_t* srf = ( srfGeneric_t* ) gen; - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - d = DotProduct( tr.sunDirection, srf->plane.normal ); - } - else - { - d = DotProduct( light->origin, srf->plane.normal ) - srf->plane.dist; - } - // don't cull exactly on the plane, because there are levels of rounding - // through the BSP, ICD, and hardware that may cause pixel gaps if an - // epsilon isn't allowed here - if ( shader->cullType == CT_FRONT_SIDED ) - { - if ( d < -8.0f ) - { - return true; - } - } - else if ( shader->cullType == CT_BACK_SIDED ) - { - if ( d > 8.0f ) - { - return true; - } - } - } - - if ( r_cullShadowPyramidFaces->integer ) - { - *cubeSideBits = R_CalcLightCubeSideBits( light, gen->bounds ); - } - - return false; -} - -/* -====================== -R_AddInteractionSurface -====================== -*/ -static void R_AddInteractionSurface( bspSurface_t *surf, trRefLight_t *light, int interactionBits ) -{ - byte cubeSideBits = CUBESIDE_CLIPALL; - bool firstAddition = false; - int bits; - - if ( surf->lightCount != tr.lightCount ) - { - surf->interactionBits = 0; - surf->lightCount = tr.lightCount; - firstAddition = true; - } - - // only add interactions we haven't already added - bits = interactionBits & ~surf->interactionBits; - - if ( !bits ) - { - // already added these interactions - return; - } - - surf->interactionBits |= bits; - - // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || ( !surf->shader->interactLight && surf->shader->noShadows ) ) - { - return; - } - - if ( R_CullLightSurface( surf->data, surf->shader, light, &cubeSideBits ) ) - { - if ( firstAddition ) - { - tr.pc.c_dlightSurfacesCulled++; - } - return; - } - - R_AddLightInteraction( light, surf->data, surf->shader, cubeSideBits, ( interactionType_t ) bits ); - - if ( firstAddition ) - { - tr.pc.c_dlightSurfaces++; - } -} - /* ====================== R_AddWorldSurface @@ -315,9 +185,7 @@ void R_AddBSPModelSurfaces( trRefEntity_t *ent ) VectorAdd( ent->worldBounds[ 0 ], ent->worldBounds[ 1 ], boundsCenter ); VectorScale( boundsCenter, 0.5f, boundsCenter ); - ent->cull = R_CullBox( ent->worldBounds ); - - if ( ent->cull == CULL_OUT ) + if ( R_CullBox( ent->worldBounds ) == CULL_OUT ) { return; } @@ -427,7 +295,7 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits ) { if ( planeBits & ( 1 << i ) ) { - r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustums[ 0 ][ i ] ); + r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustum[ i ] ); if ( r == 2 ) { @@ -468,110 +336,6 @@ static void R_RecursiveWorldNode( bspNode_t *node, int planeBits ) } } -/* -================ -R_RecursiveInteractionNode -================ -*/ -static void R_RecursiveInteractionNode( bspNode_t *node, trRefLight_t *light, int planeBits, int interactionBits ) -{ - int i; - int r; - - do - { - // surfaces that arn't potentially visible may still cast shadows - // but we don't bother lighting them since there will be no visible effect - if ( node->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) - { - interactionBits &= ~IA_LIGHT; - } - - // if the bounding volume is outside the frustum, nothing - // inside can be visible OPTIMIZE: don't do this all the way to leafs? - - // Tr3B - even surfaces that belong to nodes that are outside of the view frustum - // can cast shadows into the view frustum - if ( !r_nocull->integer ) - { - for ( i = 0; i < FRUSTUM_PLANES; i++ ) - { - if ( planeBits & ( 1 << i ) ) - { - r = BoxOnPlaneSide( node->mins, node->maxs, &tr.viewParms.frustums[ 0 ][ i ] ); - - if ( r == 2 ) - { - // this node cannot be lighted, but may cast shadows - interactionBits &= ~IA_LIGHT; - break; - } - - if ( r == 1 ) - { - planeBits &= ~( 1 << i ); // all descendants will also be in front - } - } - } - } - - // don't waste time on nodes with no interactions - if ( !interactionBits ) - { - return; - } - - if ( node->contents != -1 ) - { - break; - } - - // node is just a decision point, so go down both sides - // since we don't care about sort orders, just go positive to negative - r = BoxOnPlaneSide( light->worldBounds[ 0 ], light->worldBounds[ 1 ], node->plane ); - - switch ( r ) - { - case 1: - node = node->children[ 0 ]; - break; - - case 2: - node = node->children[ 1 ]; - break; - - case 3: - default: - // recurse down the children, front side first - R_RecursiveInteractionNode( node->children[ 0 ], light, planeBits, interactionBits ); - - // tail recurse - node = node->children[ 1 ]; - break; - } - } - while ( true ); - - { - // leaf node, so add mark surfaces - int c; - bspSurface_t *surf, **mark; - - // add the individual surfaces - mark = tr.world->markSurfaces + node->firstMarkSurface; - c = node->numMarkSurfaces; - - while ( c-- ) - { - // the surface may have already been added if it - // spans multiple leafs - surf = *mark; - R_AddInteractionSurface( surf, light, interactionBits ); - mark++; - } - } -} - /* =============== R_PointInLeaf @@ -794,20 +558,6 @@ static void R_MarkLeaves() continue; } - // ydnar: don't want to walk the entire bsp to add skybox surfaces - if ( tr.refdef.rdflags & RDF_SKYBOXPORTAL ) - { - // this only happens once, as game/cgame know the origin of the skybox - // this also means the skybox portal cannot move, as this list is calculated once and never again - if ( tr.world->numSkyNodes < WORLD_MAX_SKY_NODES ) - { - tr.world->skyNodes[ tr.world->numSkyNodes++ ] = leaf; - } - - R_AddLeafSurfaces( leaf, FRUSTUM_CLIPALL ); - continue; - } - parent = leaf; do @@ -846,65 +596,12 @@ void R_AddWorldSurfaces() // clear out the visible min/max ClearBounds( tr.viewParms.visBounds[ 0 ], tr.viewParms.visBounds[ 1 ] ); - // render sky or world? - if ( tr.refdef.rdflags & RDF_SKYBOXPORTAL && tr.world->numSkyNodes > 0 ) - { - int i; - bspNode_t **node; - - for ( i = 0, node = tr.world->skyNodes; i < tr.world->numSkyNodes; i++, node++ ) - { - R_AddLeafSurfaces( *node, FRUSTUM_CLIPALL ); - } - } - else - { - // determine which leaves are in the PVS / areamask - R_MarkLeaves(); - - // clear traversal list - backEndData[ tr.smpFrame ]->traversalLength = 0; - - // update visbounds and add surfaces that weren't cached with VBOs - R_RecursiveWorldNode( tr.world->nodes, FRUSTUM_CLIPALL ); - } -} - -/* -============= -R_AddWorldInteractions -============= -*/ -void R_AddWorldInteractions( trRefLight_t *light ) -{ - int interactionBits; + // determine which leaves are in the PVS / areamask + R_MarkLeaves(); - if ( !r_drawworld->integer ) - { - return; - } - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) - { - return; - } - - tr.currentEntity = &tr.worldEntity; - - // perform frustum culling and add all the potentially visible surfaces - tr.lightCount++; - - interactionBits = IA_DEFAULT; - - if ( light->restrictInteractionFirst >= 0 ) - { - interactionBits = IA_DEFAULTCLIP; - } - - if ( !glConfig2.shadowMapping || light->l.noShadows ) - { - interactionBits &= IA_LIGHT; - } + // clear traversal list + backEndData[ tr.smpFrame ]->traversalLength = 0; - R_RecursiveInteractionNode( tr.world->nodes, light, FRUSTUM_CLIPALL, interactionBits ); + // update visbounds and add surfaces that weren't cached with VBOs + R_RecursiveWorldNode( tr.world->nodes, FRUSTUM_CLIPALL ); }