Restored original vanilla renderer and renamed current to rd-gles

This commit is contained in:
Simon 2022-11-30 17:59:40 +00:00
parent cd9026c927
commit 399e803068
73 changed files with 64120 additions and 5333 deletions

View file

@ -23,7 +23,7 @@ LOCAL_STATIC_LIBRARIES := sigc libzip libpng libminizip
LOCAL_SHARED_LIBRARIES := vrapi gl4es
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(TOP_DIR)/JKVR $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(SUPPORT_LIBS)/minizip/include $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(TOP_DIR)/JKVR $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(SUPPORT_LIBS)/minizip/include $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
#############################################################################

View file

@ -23,7 +23,7 @@ LOCAL_STATIC_LIBRARIES := sigc libzip libpng libminizip
LOCAL_SHARED_LIBRARIES := vrapi gl4es
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(TOP_DIR)/JKVR $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(SUPPORT_LIBS)/minizip/include $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(TOP_DIR)/JKVR $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(SUPPORT_LIBS)/minizip/include $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
#############################################################################

View file

@ -18,7 +18,7 @@ LOCAL_LDLIBS += -llog -lz
#LOCAL_STATIC_LIBRARIES := s-setup lz
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(TOP_DIR)/SupportLibs/openal/include $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK3_CODE_PATH)/game $(TOP_DIR)/SupportLibs/openal/include $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
JK3_SRC = \
code/game/AI_Animal.cpp \

View file

@ -18,7 +18,7 @@ LOCAL_LDLIBS += -llog -lz
#LOCAL_STATIC_LIBRARIES := s-setup lz
LOCAL_SHARED_LIBRARIES :=
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK2_CODE_PATH)/game $(TOP_DIR)/SupportLibs/openal/include $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(TOP_DIR) $(GL4ES_PATH) $(GL4ES_PATH)/include $(JK2_CODE_PATH)/game $(TOP_DIR)/SupportLibs/openal/include $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
JK2_SRC = \
codeJK2/game/AI_Atst.cpp \

View file

@ -18,45 +18,45 @@ LOCAL_LDLIBS += -lGLESv3 -landroid -lEGL -ldl -llog
LOCAL_STATIC_LIBRARIES := libpng libjpeg
LOCAL_SHARED_LIBRARIES := gl4es
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(SUPPORT_LIBS)/libpng $(TOP_DIR) $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(SUPPORT_LIBS)/libpng $(TOP_DIR) $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
JK3_SRC = \
${JK3_CODE_PATH}/rd-vanilla/G2_API.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_bolts.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_bones.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_misc.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_surfaces.cpp \
${JK3_CODE_PATH}/rd-gles/G2_API.cpp \
${JK3_CODE_PATH}/rd-gles/G2_bolts.cpp \
${JK3_CODE_PATH}/rd-gles/G2_bones.cpp \
${JK3_CODE_PATH}/rd-gles/G2_misc.cpp \
${JK3_CODE_PATH}/rd-gles/G2_surfaces.cpp \
${JK3_CODE_PATH}/qcommon/matcomp.cpp \
${JK3_CODE_PATH}/qcommon/q_shared.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_arb.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_backend.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_bsp.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_cmds.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_curve.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_draw.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_ghoul2.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_image.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_init.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_light.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_main.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_marks.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_mesh.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_model.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_quicksprite.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_scene.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shade.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shade_calc.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shader.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shadows.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_skin.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_sky.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_stl.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_subs.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_surface.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_surfacesprites.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_world.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_WorldEffects.cpp \
${JK3_CODE_PATH}/rd-gles/tr_arb.cpp \
${JK3_CODE_PATH}/rd-gles/tr_backend.cpp \
${JK3_CODE_PATH}/rd-gles/tr_bsp.cpp \
${JK3_CODE_PATH}/rd-gles/tr_cmds.cpp \
${JK3_CODE_PATH}/rd-gles/tr_curve.cpp \
${JK3_CODE_PATH}/rd-gles/tr_draw.cpp \
${JK3_CODE_PATH}/rd-gles/tr_ghoul2.cpp \
${JK3_CODE_PATH}/rd-gles/tr_image.cpp \
${JK3_CODE_PATH}/rd-gles/tr_init.cpp \
${JK3_CODE_PATH}/rd-gles/tr_light.cpp \
${JK3_CODE_PATH}/rd-gles/tr_main.cpp \
${JK3_CODE_PATH}/rd-gles/tr_marks.cpp \
${JK3_CODE_PATH}/rd-gles/tr_mesh.cpp \
${JK3_CODE_PATH}/rd-gles/tr_model.cpp \
${JK3_CODE_PATH}/rd-gles/tr_quicksprite.cpp \
${JK3_CODE_PATH}/rd-gles/tr_scene.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shade.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shade_calc.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shader.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shadows.cpp \
${JK3_CODE_PATH}/rd-gles/tr_skin.cpp \
${JK3_CODE_PATH}/rd-gles/tr_sky.cpp \
${JK3_CODE_PATH}/rd-gles/tr_stl.cpp \
${JK3_CODE_PATH}/rd-gles/tr_subs.cpp \
${JK3_CODE_PATH}/rd-gles/tr_surface.cpp \
${JK3_CODE_PATH}/rd-gles/tr_surfacesprites.cpp \
${JK3_CODE_PATH}/rd-gles/tr_world.cpp \
${JK3_CODE_PATH}/rd-gles/tr_WorldEffects.cpp \
${JK3_CODE_PATH}/rd-common/tr_font.cpp \
${JK3_CODE_PATH}/rd-common/tr_image_load.cpp \
${JK3_CODE_PATH}/rd-common/tr_image_jpg.cpp \

View file

@ -18,45 +18,45 @@ LOCAL_LDLIBS += -lGLESv3 -landroid -lEGL -ldl -llog
LOCAL_STATIC_LIBRARIES := libpng libjpeg
LOCAL_SHARED_LIBRARIES := gl4es
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(SUPPORT_LIBS)/libpng $(TOP_DIR) $(JK3_CODE_PATH)/rd-vanilla $(JK3_CODE_PATH)/rd-common
LOCAL_C_INCLUDES := $(JK3_BASE_C_INCLUDES) $(SUPPORT_LIBS)/libpng $(TOP_DIR) $(JK3_CODE_PATH)/rd-gles $(JK3_CODE_PATH)/rd-common
JK3_SRC = \
${JK3_CODE_PATH}/rd-vanilla/G2_API.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_bolts.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_bones.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_misc.cpp \
${JK3_CODE_PATH}/rd-vanilla/G2_surfaces.cpp \
${JK3_CODE_PATH}/rd-gles/G2_API.cpp \
${JK3_CODE_PATH}/rd-gles/G2_bolts.cpp \
${JK3_CODE_PATH}/rd-gles/G2_bones.cpp \
${JK3_CODE_PATH}/rd-gles/G2_misc.cpp \
${JK3_CODE_PATH}/rd-gles/G2_surfaces.cpp \
${JK3_CODE_PATH}/qcommon/matcomp.cpp \
${JK3_CODE_PATH}/qcommon/q_shared.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_arb.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_backend.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_bsp.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_cmds.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_curve.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_draw.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_ghoul2.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_image.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_init.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_light.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_main.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_marks.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_mesh.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_model.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_quicksprite.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_scene.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shade.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shade_calc.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shader.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_shadows.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_skin.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_sky.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_stl.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_subs.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_surface.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_surfacesprites.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_world.cpp \
${JK3_CODE_PATH}/rd-vanilla/tr_WorldEffects.cpp \
${JK3_CODE_PATH}/rd-gles/tr_arb.cpp \
${JK3_CODE_PATH}/rd-gles/tr_backend.cpp \
${JK3_CODE_PATH}/rd-gles/tr_bsp.cpp \
${JK3_CODE_PATH}/rd-gles/tr_cmds.cpp \
${JK3_CODE_PATH}/rd-gles/tr_curve.cpp \
${JK3_CODE_PATH}/rd-gles/tr_draw.cpp \
${JK3_CODE_PATH}/rd-gles/tr_ghoul2.cpp \
${JK3_CODE_PATH}/rd-gles/tr_image.cpp \
${JK3_CODE_PATH}/rd-gles/tr_init.cpp \
${JK3_CODE_PATH}/rd-gles/tr_light.cpp \
${JK3_CODE_PATH}/rd-gles/tr_main.cpp \
${JK3_CODE_PATH}/rd-gles/tr_marks.cpp \
${JK3_CODE_PATH}/rd-gles/tr_mesh.cpp \
${JK3_CODE_PATH}/rd-gles/tr_model.cpp \
${JK3_CODE_PATH}/rd-gles/tr_quicksprite.cpp \
${JK3_CODE_PATH}/rd-gles/tr_scene.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shade.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shade_calc.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shader.cpp \
${JK3_CODE_PATH}/rd-gles/tr_shadows.cpp \
${JK3_CODE_PATH}/rd-gles/tr_skin.cpp \
${JK3_CODE_PATH}/rd-gles/tr_sky.cpp \
${JK3_CODE_PATH}/rd-gles/tr_stl.cpp \
${JK3_CODE_PATH}/rd-gles/tr_subs.cpp \
${JK3_CODE_PATH}/rd-gles/tr_surface.cpp \
${JK3_CODE_PATH}/rd-gles/tr_surfacesprites.cpp \
${JK3_CODE_PATH}/rd-gles/tr_world.cpp \
${JK3_CODE_PATH}/rd-gles/tr_WorldEffects.cpp \
${JK3_CODE_PATH}/rd-common/tr_font.cpp \
${JK3_CODE_PATH}/rd-common/tr_image_load.cpp \
${JK3_CODE_PATH}/rd-common/tr_image_jpg.cpp \

View file

@ -24,7 +24,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#if !defined(G2_H_INC)
#define G2_H_INC
#include "rd-vanilla/tr_local.h"
#include "tr_local.h"
class CMiniHeap;

View file

@ -0,0 +1,203 @@
#============================================================================
# Copyright (C) 2013 - 2018, OpenJK contributors
#
# This file is part of the OpenJK source code.
#
# OpenJK is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#============================================================================
# Make sure the user is not executing this script directly
if(NOT InOpenJK)
message(FATAL_ERROR "Use the top-level cmake script!")
endif(NOT InOpenJK)
if(BuildSPRdVanilla OR BuildJK2SPRdVanilla)
set(SPRDVanillaRendererIncludeDirectories ${SPDir})
set(SPRDVanillaRendererIncludeDirectories
${SharedDir}
${SPRDVanillaRendererIncludeDirectories}
"${SPDir}/rd-vanilla"
"${GSLIncludeDirectory}"
)
# Modular Renderer crap (let's hope this works..)
# Defines
set(SPRDVanillaDefines ${SharedDefines} "RENDERER" "_JK2EXE")
# Files
# GHOUL 2
set(SPRDVanillaG2Files
"${SPDir}/ghoul2/G2.h"
"${SPDir}/ghoul2/ghoul2_gore.h"
"${SPDir}/rd-vanilla/G2_API.cpp"
"${SPDir}/rd-vanilla/G2_bolts.cpp"
"${SPDir}/rd-vanilla/G2_bones.cpp"
"${SPDir}/rd-vanilla/G2_misc.cpp"
"${SPDir}/rd-vanilla/G2_surfaces.cpp"
)
source_group("ghoul2" FILES ${SPRDVanillaG2Files})
set(SPRDVanillaFiles ${SPRDVanillaFiles} ${SPRDVanillaG2Files})
# Transparently use either bundled or system jpeg.
list(APPEND SPRDVanillaRendererIncludeDirectories ${JPEG_INCLUDE_DIR})
list(APPEND SPRDVanillaRendererLibraries ${JPEG_LIBRARIES})
# Transparently use either bundled or system libpng. Order is important --
# libpng used zlib, so it must come before it on the linker command line.
list(APPEND SPRDVanillaRendererIncludeDirectories ${PNG_INCLUDE_DIRS})
list(APPEND SPRDVanillaRendererLibraries ${PNG_LIBRARIES})
# Transparently use either bundled or system zlib.
list(APPEND SPRDVanillaRendererIncludeDirectories ${ZLIB_INCLUDE_DIR})
list(APPEND SPRDVanillaRendererLibraries ${ZLIB_LIBRARIES})
# Transparently use our bundled minizip.
list(APPEND SPRDVanillaRendererIncludeDirectories ${MINIZIP_INCLUDE_DIRS})
list(APPEND SPRDVanillaRendererLibraries ${MINIZIP_LIBRARIES})
# Transparantly make use of all renderer directories
list(APPEND SPRDVanillaRendererIncludeDirectories "${SPDir}/rd-common")
list(APPEND SPRDVanillaRendererIncludeDirectories "${SPDir}/rd-vanilla")
# Misc files
set(SPRDVanillaCommonFiles
"${SPDir}/qcommon/matcomp.cpp"
"${SPDir}/qcommon/q_shared.cpp"
"${SPDir}/qcommon/q_shared.h"
"${SPDir}/qcommon/ojk_i_saved_game.h"
"${SPDir}/qcommon/ojk_saved_game_class_archivers.h"
"${SPDir}/qcommon/ojk_saved_game_helper.h"
"${SPDir}/qcommon/ojk_saved_game_helper_fwd.h"
"${SPDir}/qcommon/ojk_scope_guard.h"
${SharedCommonFiles}
)
source_group("common" FILES ${SPRDVanillaCommonFiles})
set(SPRDVanillaFiles ${SPRDVanillaFiles} ${SPRDVanillaCommonFiles})
# Misc files
set(SPRDVanillaCommonSafeFiles
${SharedCommonSafeFiles}
)
source_group("common/safe" FILES ${SPRDVanillaCommonSafeFiles})
set(SPRDVanillaFiles ${SPRDVanillaFiles} ${SPRDVanillaCommonSafeFiles})
# main files
set(SPRDVanillaMainFiles
"${SPDir}/rd-vanilla/glext.h"
"${SPDir}/rd-vanilla/qgl.h"
"${SPDir}/rd-vanilla/tr_arb.cpp"
"${SPDir}/rd-vanilla/tr_backend.cpp"
"${SPDir}/rd-vanilla/tr_bsp.cpp"
"${SPDir}/rd-vanilla/tr_cmds.cpp"
"${SPDir}/rd-vanilla/tr_curve.cpp"
"${SPDir}/rd-vanilla/tr_draw.cpp"
"${SPDir}/rd-vanilla/tr_ghoul2.cpp"
"${SPDir}/rd-vanilla/tr_image.cpp"
"${SPDir}/rd-vanilla/tr_init.cpp"
"${SPDir}/rd-vanilla/tr_light.cpp"
"${SPDir}/rd-vanilla/tr_local.h"
"${SPDir}/rd-vanilla/tr_main.cpp"
"${SPDir}/rd-vanilla/tr_marks.cpp"
"${SPDir}/rd-vanilla/tr_mesh.cpp"
"${SPDir}/rd-vanilla/tr_model.cpp"
"${SPDir}/rd-vanilla/tr_quicksprite.cpp"
"${SPDir}/rd-vanilla/tr_quicksprite.h"
"${SPDir}/rd-vanilla/tr_scene.cpp"
"${SPDir}/rd-vanilla/tr_shade.cpp"
"${SPDir}/rd-vanilla/tr_shade_calc.cpp"
"${SPDir}/rd-vanilla/tr_shader.cpp"
"${SPDir}/rd-vanilla/tr_shadows.cpp"
"${SPDir}/rd-vanilla/tr_skin.cpp"
"${SPDir}/rd-vanilla/tr_sky.cpp"
"${SPDir}/rd-vanilla/tr_stl.cpp"
"${SPDir}/rd-vanilla/tr_stl.h"
"${SPDir}/rd-vanilla/tr_subs.cpp"
"${SPDir}/rd-vanilla/tr_surface.cpp"
"${SPDir}/rd-vanilla/tr_surfacesprites.cpp"
"${SPDir}/rd-vanilla/tr_world.cpp"
"${SPDir}/rd-vanilla/tr_WorldEffects.cpp"
"${SPDir}/rd-vanilla/tr_WorldEffects.h"
)
source_group("renderer" FILES ${SPRDVanillaMainFiles})
set(SPRDVanillaFiles ${SPRDVanillaFiles} ${SPRDVanillaMainFiles})
set(SPRDVanillaRdCommonFiles
"${SPDir}/rd-common/mdx_format.h"
"${SPDir}/rd-common/tr_common.h"
"${SPDir}/rd-common/tr_font.cpp"
"${SPDir}/rd-common/tr_font.h"
"${SPDir}/rd-common/tr_image_load.cpp"
"${SPDir}/rd-common/tr_image_jpg.cpp"
"${SPDir}/rd-common/tr_image_tga.cpp"
"${SPDir}/rd-common/tr_image_png.cpp"
"${SPDir}/rd-common/tr_noise.cpp"
"${SPDir}/rd-common/tr_public.h"
"${SPDir}/rd-common/tr_types.h")
source_group("rd-common" FILES ${SPRDVanillaRdCommonFiles})
set(SPRDVanillaFiles ${SPRDVanillaFiles} ${SPRDVanillaRdCommonFiles})
find_package(OpenGL REQUIRED)
set(SPRDVanillaRendererIncludeDirectories ${SPRDVanillaRendererIncludeDirectories} ${OPENGL_INCLUDE_DIR})
set(SPRDVanillaRendererLibraries ${SPRDVanillaRendererLibraries} ${OPENGL_LIBRARIES})
set(SPRDVanillaRendererIncludeDirectories ${SPRDVanillaRendererIncludeDirectories} ${OpenJKLibDir})
function(add_sp_renderer_project ProjectName Label EngineName InstallDir Component)
add_library(${ProjectName} SHARED ${SPRDVanillaFiles})
if(NOT MSVC)
# remove "lib" prefix for .so/.dylib files
set_target_properties(${ProjectName} PROPERTIES PREFIX "")
endif()
if(WIN32)
install(TARGETS ${ProjectName}
RUNTIME
DESTINATION ${InstallDir}
COMPONENT ${Component})
else(WIN32)
if(MakeApplicationBundles AND (BuildSPEngine OR BuildJK2SPEngine))
install(TARGETS ${ProjectName}
LIBRARY
DESTINATION "${InstallDir}/${EngineName}.app/Contents/MacOS/"
COMPONENT ${Component})
else()
install(TARGETS ${ProjectName}
LIBRARY
DESTINATION ${InstallDir}
COMPONENT ${Component})
endif()
endif()
set_target_properties(${ProjectName} PROPERTIES COMPILE_DEFINITIONS "${SPRDVanillaDefines}")
# Hide symbols not explicitly marked public.
set_property(TARGET ${ProjectName} APPEND PROPERTY COMPILE_OPTIONS ${OPENJK_VISIBILITY_FLAGS})
set_target_properties(${ProjectName} PROPERTIES INCLUDE_DIRECTORIES "${SPRDVanillaRendererIncludeDirectories}")
set_target_properties(${ProjectName} PROPERTIES PROJECT_LABEL ${Label})
target_link_libraries(${ProjectName} ${SPRDVanillaRendererLibraries})
endfunction(add_sp_renderer_project)
if(BuildSPRdVanilla)
add_sp_renderer_project(${SPRDVanillaRenderer} "SP Vanilla Renderer" ${SPEngine} ${JKAInstallDir} ${JKASPClientComponent})
endif(BuildSPRdVanilla)
if(BuildJK2SPRdVanilla)
set(SPRDVanillaDefines ${SPRDVanillaDefines} "JK2_MODE")
add_sp_renderer_project(${JK2SPVanillaRenderer} "JK2 SP Vanilla Renderer" ${JK2SPEngine} ${JK2InstallDir} ${JK2SPClientComponent})
endif(BuildJK2SPRdVanilla)
endif(BuildSPRdVanilla OR BuildJK2SPRdVanilla)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,265 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#ifndef __Q_SHARED_H
#include "../qcommon/q_shared.h"
#endif
#if !defined(TR_LOCAL_H)
#include "tr_local.h"
#endif
#if !defined(G2_H_INC)
#include "../ghoul2/G2.h"
#endif
#define G2_MODEL_OK(g) ((g)&&(g)->mValid&&(g)->aHeader&&(g)->currentModel&&(g)->animModel)
//=====================================================================================================================
// Bolt List handling routines - so entities can attach themselves to any part of the model in question
// Given a bone number, see if that bone is already in our bone list
int G2_Find_Bolt_Bone_Num(boltInfo_v &bltlist, const int boneNum)
{
// look through entire list
for(size_t i=0; i<bltlist.size(); i++)
{
if (bltlist[i].boneNumber == boneNum)
{
return i;
}
}
// didn't find it
return -1;
}
// Given a bone number, see if that surface is already in our surfacelist list
int G2_Find_Bolt_Surface_Num(boltInfo_v &bltlist, const int surfaceNum, const int flags)
{
// look through entire list
for(size_t i=0; i<bltlist.size(); i++)
{
if ((bltlist[i].surfaceNumber == surfaceNum) && ((bltlist[i].surfaceType & flags) == flags))
{
return i;
}
}
// didn't find it
return -1;
}
//=========================================================================================
//// Public Bolt Routines
int G2_Add_Bolt_Surf_Num(CGhoul2Info *ghlInfo, boltInfo_v &bltlist, surfaceInfo_v &slist, const int surfNum)
{
assert(ghlInfo&&ghlInfo->mValid);
boltInfo_t tempBolt;
assert(surfNum>=0&&surfNum<(int)slist.size());
// ensure surface num is valid
if (surfNum >= (int)slist.size())
{
return -1;
}
// look through entire list - see if it's already there first
for(size_t i=0; i<bltlist.size(); i++)
{
// already there??
if (bltlist[i].surfaceNumber == surfNum)
{
// increment the usage count
bltlist[i].boltUsed++;
return i;
}
}
// we have a surface
// look through entire list - see if it's already there first
for(size_t i=0; i<bltlist.size(); i++)
{
// if this surface entry has info in it, bounce over it
if (bltlist[i].boneNumber == -1 && bltlist[i].surfaceNumber == -1)
{
// if we found an entry that had a -1 for the bone / surface number, then we hit a surface / bone slot that was empty
bltlist[i].surfaceNumber = surfNum;
bltlist[i].surfaceType = G2SURFACEFLAG_GENERATED;
bltlist[i].boltUsed = 1;
return i;
}
}
// ok, we didn't find an existing surface of that name, or an empty slot. Lets add an entry
tempBolt.surfaceNumber = surfNum;
tempBolt.surfaceType = G2SURFACEFLAG_GENERATED;
tempBolt.boneNumber = -1;
tempBolt.boltUsed = 1;
bltlist.push_back(tempBolt);
return bltlist.size()-1;
}
void G2_Bolt_Not_Found(const char *boneName,const char *modName);
int G2_Add_Bolt(CGhoul2Info *ghlInfo, boltInfo_v &bltlist, surfaceInfo_v &slist, const char *boneName)
{
assert(ghlInfo&&ghlInfo->mValid);
int surfNum = -1;
mdxaSkel_t *skel;
mdxaSkelOffsets_t *offsets;
boltInfo_t tempBolt;
uint32_t flags;
assert(G2_MODEL_OK(ghlInfo));
// first up, we'll search for that which this bolt names in all the surfaces
surfNum = G2_IsSurfaceLegal(ghlInfo->currentModel, boneName, &flags);
// did we find it as a surface?
if (surfNum != -1)
{
// look through entire list - see if it's already there first
for(size_t i=0; i<bltlist.size(); i++)
{
// already there??
if (bltlist[i].surfaceNumber == surfNum)
{
// increment the usage count
bltlist[i].boltUsed++;
return i;
}
}
// look through entire list - see if we can re-use one
for(size_t i=0; i<bltlist.size(); i++)
{
// if this surface entry has info in it, bounce over it
if (bltlist[i].boneNumber == -1 && bltlist[i].surfaceNumber == -1)
{
// if we found an entry that had a -1 for the bone / surface number, then we hit a surface / bone slot that was empty
bltlist[i].surfaceNumber = surfNum;
bltlist[i].boltUsed = 1;
bltlist[i].surfaceType = 0;
return i;
}
}
// ok, we didn't find an existing surface of that name, or an empty slot. Lets add an entry
tempBolt.surfaceNumber = surfNum;
tempBolt.boneNumber = -1;
tempBolt.boltUsed = 1;
tempBolt.surfaceType = 0;
bltlist.push_back(tempBolt);
return bltlist.size()-1;
}
// no, check to see if it's a bone then
offsets = (mdxaSkelOffsets_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t));
int x;
// walk the entire list of bones in the gla file for this model and see if any match the name of the bone we want to find
for (x=0; x< ghlInfo->aHeader->numBones; x++)
{
skel = (mdxaSkel_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t) + offsets->offsets[x]);
// if name is the same, we found it
if (!Q_stricmp(skel->name, boneName))
{
break;
}
}
// check to see we did actually make a match with a bone in the model
if (x == ghlInfo->aHeader->numBones)
{
// didn't find it? Error
//assert(0&&x == mod_a->mdxa->numBones);
#if _DEBUG
G2_Bolt_Not_Found(boneName,ghlInfo->mFileName);
#endif
return -1;
}
// look through entire list - see if it's already there first
for(size_t i=0; i<bltlist.size(); i++)
{
// already there??
if (bltlist[i].boneNumber == x)
{
// increment the usage count
bltlist[i].boltUsed++;
return i;
}
}
// look through entire list - see if we can re-use it
for(size_t i=0; i<bltlist.size(); i++)
{
// if this bone entry has info in it, bounce over it
if (bltlist[i].boneNumber == -1 && bltlist[i].surfaceNumber == -1)
{
// if we found an entry that had a -1 for the bonenumber, then we hit a bone slot that was empty
bltlist[i].boneNumber = x;
bltlist[i].boltUsed = 1;
bltlist[i].surfaceType = 0;
return i;
}
}
// ok, we didn't find an existing bone of that name, or an empty slot. Lets add an entry
tempBolt.boneNumber = x;
tempBolt.surfaceNumber = -1;
tempBolt.boltUsed = 1;
tempBolt.surfaceType = 0;
bltlist.push_back(tempBolt);
return bltlist.size()-1;
}
// Given a model handle, and a bone name, we want to remove this bone from the bone override list
qboolean G2_Remove_Bolt (boltInfo_v &bltlist, int index)
{
assert(index>=0&&index<(int)bltlist.size());
// did we find it?
if (index != -1)
{
bltlist[index].boltUsed--;
if (!bltlist[index].boltUsed)
{
// set this bone to not used
bltlist[index].boneNumber = -1;
bltlist[index].surfaceNumber = -1;
}
return qtrue;
}
return qfalse;
}
// set the bolt list to all unused so the bone transformation routine ignores it.
void G2_Init_Bolt_List(boltInfo_v &bltlist)
{
bltlist.clear();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,443 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#ifndef __Q_SHARED_H
#include "../qcommon/q_shared.h"
#endif
#if !defined(TR_LOCAL_H)
#include "tr_local.h"
#endif
#if !defined(G2_H_INC)
#include "../ghoul2/G2.h"
#endif
#define G2_MODEL_OK(g) ((g)&&(g)->mValid&&(g)->aHeader&&(g)->currentModel&&(g)->animModel)
class CQuickOverride
{
int mOverride[512];
int mAt[512];
int mCurrentTouch;
public:
CQuickOverride()
{
mCurrentTouch=1;
int i;
for (i=0;i<512;i++)
{
mOverride[i]=0;
}
}
void Invalidate()
{
mCurrentTouch++;
}
void Set(int index,int pos)
{
if (index==10000)
{
return;
}
assert(index>=0&&index<512);
mOverride[index]=mCurrentTouch;
mAt[index]=pos;
}
int Test(int index)
{
assert(index>=0&&index<512);
if (mOverride[index]!=mCurrentTouch)
{
return -1;
}
else
{
return mAt[index];
}
}
};
static CQuickOverride QuickOverride;
// find a particular surface in the surface override list
const surfaceInfo_t *G2_FindOverrideSurface(int surfaceNum,const surfaceInfo_v &surfaceList)
{
if (surfaceNum<0)
{
// starting a new lookup
QuickOverride.Invalidate();
for(size_t i=0; i<surfaceList.size(); i++)
{
if (surfaceList[i].surface>=0)
{
QuickOverride.Set(surfaceList[i].surface,i);
}
}
return NULL;
}
int idx=QuickOverride.Test(surfaceNum);
if (idx<0)
{
if (surfaceNum==10000)
{
for(size_t i=0; i<surfaceList.size(); i++)
{
if (surfaceList[i].surface == surfaceNum)
{
return &surfaceList[i];
}
}
}
#if _DEBUG
// look through entire list
size_t i;
for(i=0; i<surfaceList.size(); i++)
{
if (surfaceList[i].surface == surfaceNum)
{
break;
}
}
// didn't find it.
assert(i==surfaceList.size()); // our quickoverride is not working right
#endif
return NULL;
}
assert(idx>=0&&idx<(int)surfaceList.size());
assert(surfaceList[idx].surface == surfaceNum);
return &surfaceList[idx];
}
// given a surface name, lets see if it's legal in the model
int G2_IsSurfaceLegal(const model_s *mod_m, const char *surfaceName, uint32_t *flags)
{
assert(mod_m);
assert(mod_m->mdxm);
// damn include file dependancies
mdxmSurfHierarchy_t *surf;
surf = (mdxmSurfHierarchy_t *) ( (byte *)mod_m->mdxm + mod_m->mdxm->ofsSurfHierarchy );
for ( int i = 0 ; i < mod_m->mdxm->numSurfaces ; i++)
{
if (!Q_stricmp(surfaceName, surf->name))
{
*flags = surf->flags;
return i;
}
// find the next surface
surf = (mdxmSurfHierarchy_t *)( (byte *)surf + (intptr_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surf->numChildren ] ));
}
return -1;
}
/************************************************************************************************
* G2_FindSurface
* find a surface in a ghoul2 surface override list based on it's name
*
* Input
* filename of model, surface list of model instance, name of surface, int to be filled in
* with the index of this surface (defaults to NULL)
*
* Output
* pointer to surface if successful, false otherwise
*
************************************************************************************************/
const mdxmSurface_t *G2_FindSurface(CGhoul2Info *ghlInfo, surfaceInfo_v &slist, const char *surfaceName,
int *surfIndex/*NULL*/)
{
int i = 0;
// find the model we want
assert(G2_MODEL_OK(ghlInfo));
const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)ghlInfo->currentModel->mdxm + sizeof(mdxmHeader_t));
// first find if we already have this surface in the list
for (i = slist.size() - 1; i >= 0; i--)
{
if ((slist[i].surface != 10000) && (slist[i].surface != -1))
{
const mdxmSurface_t *surf = (mdxmSurface_t *)G2_FindSurface(ghlInfo->currentModel, slist[i].surface, 0);
// back track and get the surfinfo struct for this surface
const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]);
// are these the droids we're looking for?
if (!Q_stricmp (surfInfo->name, surfaceName))
{
// yup
if (surfIndex)
{
*surfIndex = i;
}
return surf;
}
}
}
// didn't find it
if (surfIndex)
{
*surfIndex = -1;
}
return 0;
}
// set a named surface offFlags - if it doesn't find a surface with this name in the list then it will add one.
qboolean G2_SetSurfaceOnOff (CGhoul2Info *ghlInfo, const char *surfaceName, const int offFlags)
{
int surfIndex = -1;
surfaceInfo_t temp_slist_entry;
// find the model we want
// first find if we already have this surface in the list
const mdxmSurface_t *surf = G2_FindSurface(ghlInfo, ghlInfo->mSlist, surfaceName, &surfIndex);
if (surf)
{
// set descendants value
// slist[surfIndex].offFlags = offFlags;
// seems to me that we shouldn't overwrite the other flags.
// the only bit we really care about in the incoming flags is the off bit
ghlInfo->mSlist[surfIndex].offFlags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS);
ghlInfo->mSlist[surfIndex].offFlags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS);
return qtrue;
}
else
{
// ok, not in the list already - in that case, lets verify this surface exists in the model mesh
uint32_t flags;
int surfaceNum = G2_IsSurfaceLegal(ghlInfo->currentModel, surfaceName, &flags);
if (surfaceNum != -1)
{
uint32_t newflags = flags;
// the only bit we really care about in the incoming flags is the off bit
newflags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS);
newflags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS);
if (newflags != flags)
{ // insert here then because it changed, no need to add an override otherwise
temp_slist_entry.offFlags = newflags;
temp_slist_entry.surface = surfaceNum;
ghlInfo->mSlist.push_back(temp_slist_entry);
}
return qtrue;
}
}
return qfalse;
}
void G2_FindRecursiveSurface(const model_t *currentModel, int surfaceNum, surfaceInfo_v &rootList, int *activeSurfaces)
{
assert(currentModel);
assert(currentModel->mdxm);
int i;
const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(currentModel, surfaceNum, 0);
const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->mdxm + sizeof(mdxmHeader_t));
const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]);
// see if we have an override surface in the surface list
const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootList);
// really, we should use the default flags for this surface unless it's been overriden
int offFlags = surfInfo->flags;
// set the off flags if we have some
if (surfOverride)
{
offFlags = surfOverride->offFlags;
}
// if this surface is not off, indicate as such in the active surface list
if (!(offFlags & G2SURFACEFLAG_OFF))
{
activeSurfaces[surfaceNum] = 1;
}
else
// if we are turning off all descendants, then stop this recursion now
if (offFlags & G2SURFACEFLAG_NODESCENDANTS)
{
return;
}
// now recursively call for the children
for (i=0; i< surfInfo->numChildren; i++)
{
surfaceNum = surfInfo->childIndexes[i];
G2_FindRecursiveSurface(currentModel, surfaceNum, rootList, activeSurfaces);
}
}
qboolean G2_SetRootSurface( CGhoul2Info_v &ghoul2, const int modelIndex, const char *surfaceName)
{
int surf;
uint32_t flags;
assert(modelIndex>=0&&modelIndex<ghoul2.size());
assert(ghoul2[modelIndex].currentModel);
assert(ghoul2[modelIndex].currentModel->mdxm);
// first find if we already have this surface in the list
surf = G2_IsSurfaceLegal(ghoul2[modelIndex].currentModel, surfaceName, &flags);
if (surf != -1)
{
ghoul2[modelIndex].mSurfaceRoot = surf;
return qtrue;
}
assert(0);
return qfalse;
}
extern int G2_DecideTraceLod(CGhoul2Info &ghoul2, int useLod);
int G2_AddSurface(CGhoul2Info *ghoul2, int surfaceNumber, int polyNumber, float BarycentricI, float BarycentricJ, int lod )
{
lod = G2_DecideTraceLod(*ghoul2, lod);
// first up, see if we have a free one already set up - look only from the end of the constant surfaces onwards
size_t i;
for (i=0; i<ghoul2->mSlist.size(); i++)
{
// is the surface count -1? That would indicate it's free
if (ghoul2->mSlist[i].surface == -1)
{
break;
}
}
if (i==ghoul2->mSlist.size())
{
ghoul2->mSlist.push_back(surfaceInfo_t());
}
ghoul2->mSlist[i].offFlags = G2SURFACEFLAG_GENERATED;
ghoul2->mSlist[i].surface = 10000; // no model will ever have 10000 surfaces
ghoul2->mSlist[i].genBarycentricI = BarycentricI;
ghoul2->mSlist[i].genBarycentricJ = BarycentricJ;
ghoul2->mSlist[i].genPolySurfaceIndex = ((polyNumber & 0xffff) << 16) | (surfaceNumber & 0xffff);
ghoul2->mSlist[i].genLod = lod;
return i;
}
qboolean G2_RemoveSurface(surfaceInfo_v &slist, const int index)
{
if (index != -1)
{
slist[index].surface = -1;
return qtrue;
}
assert(0);
return qfalse;
}
int G2_GetParentSurface(CGhoul2Info *ghlInfo, const int index)
{
assert(ghlInfo->currentModel);
assert(ghlInfo->currentModel->mdxm);
const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)ghlInfo->currentModel->mdxm + sizeof(mdxmHeader_t));
// walk each surface and see if this index is listed in it's children
const mdxmSurface_t *surf = (mdxmSurface_t *)G2_FindSurface(ghlInfo->currentModel, index, 0);
const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]);
return surfInfo->parentIndex;
}
int G2_GetSurfaceIndex(CGhoul2Info *ghlInfo, const char *surfaceName)
{
uint32_t flags;
assert(ghlInfo->currentModel);
return G2_IsSurfaceLegal(ghlInfo->currentModel, surfaceName, &flags);
}
int G2_IsSurfaceRendered(CGhoul2Info *ghlInfo, const char *surfaceName, surfaceInfo_v &slist)
{
uint32_t flags = 0u;//, surfFlags = 0;
int surfIndex = 0;
assert(ghlInfo->currentModel);
assert(ghlInfo->currentModel->mdxm);
if (!ghlInfo->currentModel->mdxm)
{
return -1;
}
// now travel up the skeleton to see if any of it's ancestors have a 'no descendants' turned on
// find the original surface in the surface list
int surfNum = G2_IsSurfaceLegal(ghlInfo->currentModel, surfaceName, &flags);
if ( surfNum != -1 )
{//must be legal
const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)ghlInfo->currentModel->mdxm + sizeof(mdxmHeader_t));
const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]);
surfNum = surfInfo->parentIndex;
// walk the surface hierarchy up until we hit the root
while (surfNum != -1)
{
const mdxmSurface_t *parentSurf;
uint32_t parentFlags = 0u;
const mdxmSurfHierarchy_t *parentSurfInfo;
parentSurfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]);
// find the original surface in the surface list
//G2 was bug, above comment was accurate, but we don't want the original flags, we want the parent flags
G2_IsSurfaceLegal(ghlInfo->currentModel, parentSurfInfo->name, &parentFlags);
// now see if we already have overriden this surface in the slist
parentSurf = G2_FindSurface(ghlInfo, slist, parentSurfInfo->name, &surfIndex);
if (parentSurf)
{
// set descendants value
parentFlags = slist[surfIndex].offFlags;
}
// now we have the parent flags, lets see if any have the 'no descendants' flag set
if (parentFlags & G2SURFACEFLAG_NODESCENDANTS)
{
flags |= G2SURFACEFLAG_OFF;
break;
}
// set up scan of next parent
surfNum = parentSurfInfo->parentIndex;
}
}
else
{
return -1;
}
if ( flags == 0 )
{//it's not being overridden by a parent
// now see if we already have overriden this surface in the slist
const mdxmSurface_t *surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex);
if (surf)
{
// set descendants value
flags = slist[surfIndex].offFlags;
}
// ok, at this point in flags we have what this surface is set to, and the index of the surface itself
}
return flags;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,794 @@
/*
** QGL.H
*/
#ifndef __QGL_H__
#define __QGL_H__
#if defined( __LINT__ )
#include <GL/gl.h>
#elif defined( _WIN32 )
#pragma warning (disable: 4201)
#pragma warning (disable: 4214)
#pragma warning (disable: 4514)
#pragma warning (disable: 4032)
#pragma warning (disable: 4201)
#pragma warning (disable: 4214)
#include <windows.h>
#include <gl/gl.h>
#elif defined( __APPLE__ ) && defined( __MACH__ )
#include <MesaGL/gl.h>
#elif defined( __linux__ )
#ifdef HAVE_GLES
#include <GLES/gl.h>
#include <EGL/egl.h>
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#else
#include <GL/gl.h>
#include <GL/glx.h>
#endif
//#include <GL/glxew.h>
//#include <GL/fxmesa.h> //LAvaPort
#else
#include <gl.h>
#endif
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef WINAPI
#define WINAPI
#endif
#ifdef HAVE_GLES
#define GLdouble GLfloat
extern void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
extern void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
extern void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
extern void ( APIENTRY * qglPointParameterfEXT)( GLenum, GLfloat);
extern void ( APIENTRY * qglPointParameterfvEXT)( GLenum, GLfloat const *);
extern void (* qglLockArraysEXT) (GLint first, GLsizei count);
extern void (* qglUnlockArraysEXT) (void);
extern void myglClear(GLbitfield mask);
extern void myglTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void myglDrawBuffer(GLenum mode);
extern void myglViewport(GLint x, GLint y, GLsizei width, GLsizei height);
extern void myglScissor(GLint x, GLint y, GLsizei width, GLsizei height);
#else
//===========================================================================
/*
** multitexture extension definitions
*/
#define GL_ACTIVE_TEXTURE_ARB 0x84E0
#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
#define GL_MAX_ACTIVE_TEXTURES_ARB 0x84E2
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1
#define GL_TEXTURE2_ARB 0x84C2
#define GL_TEXTURE3_ARB 0x84C3
#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
typedef void (APIENTRY * PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
typedef void (APIENTRY * PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
typedef void (APIENTRY * PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
typedef void (APIENTRY * PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target);
typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target);
// Steps to adding a new extension:
// - Add the typedef and function pointer externs here.
// - Define the function pointer in tr_init.cpp and possibly add a cvar to track your ext status.
// - Load the extension in win_glimp.cpp.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Register Combiner extension definitions. - AReis
/***********************************************************************************************************/
// NOTE: These are obviously not all the regcom flags. I'm only including the ones I use (to reduce code clutter), so
// if you need any of the other flags, just add them.
#define GL_REGISTER_COMBINERS_NV 0x8522
#define GL_COMBINER0_NV 0x8550
#define GL_COMBINER1_NV 0x8551
#define GL_COMBINER2_NV 0x8552
#define GL_COMBINER3_NV 0x8553
#define GL_COMBINER4_NV 0x8554
#define GL_COMBINER5_NV 0x8555
#define GL_COMBINER6_NV 0x8556
#define GL_COMBINER7_NV 0x8557
#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
#define GL_VARIABLE_A_NV 0x8523
#define GL_VARIABLE_B_NV 0x8524
#define GL_VARIABLE_C_NV 0x8525
#define GL_VARIABLE_D_NV 0x8526
#define GL_VARIABLE_E_NV 0x8527
#define GL_VARIABLE_F_NV 0x8528
#define GL_VARIABLE_G_NV 0x8529
#define GL_DISCARD_NV 0x8530
#define GL_CONSTANT_COLOR0_NV 0x852A
#define GL_CONSTANT_COLOR1_NV 0x852B
#define GL_SPARE0_NV 0x852E
#define GL_SPARE1_NV 0x852F
#define GL_UNSIGNED_IDENTITY_NV 0x8536
#define GL_UNSIGNED_INVERT_NV 0x8537
#endif //HAVE_GLES
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERFVNV) (GLenum pname,const GLfloat *params);
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERIVNV) (GLenum pname,const GLint *params);
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERFNV) (GLenum pname,GLfloat param);
typedef void (APIENTRY *PFNGLCOMBINERPARAMETERINV) (GLenum pname,GLint param);
typedef void (APIENTRY *PFNGLCOMBINERINPUTNV) (GLenum stage,GLenum portion,GLenum variable,GLenum input,GLenum mapping,
GLenum componentUsage);
typedef void (APIENTRY *PFNGLCOMBINEROUTPUTNV) (GLenum stage,GLenum portion,GLenum abOutput,GLenum cdOutput,GLenum sumOutput,
GLenum scale, GLenum bias,GLboolean abDotProduct,GLboolean cdDotProduct,
GLboolean muxSum);
typedef void (APIENTRY *PFNGLFINALCOMBINERINPUTNV) (GLenum variable,GLenum input,GLenum mapping,GLenum componentUsage);
typedef void (APIENTRY *PFNGLGETCOMBINERINPUTPARAMETERFVNV) (GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLfloat *params);
typedef void (APIENTRY *PFNGLGETCOMBINERINPUTPARAMETERIVNV) (GLenum stage,GLenum portion,GLenum variable,GLenum pname,GLint *params);
typedef void (APIENTRY *PFNGLGETCOMBINEROUTPUTPARAMETERFVNV) (GLenum stage,GLenum portion,GLenum pname,GLfloat *params);
typedef void (APIENTRY *PFNGLGETCOMBINEROUTPUTPARAMETERIVNV) (GLenum stage,GLenum portion,GLenum pname,GLint *params);
typedef void (APIENTRY *PFNGLGETFINALCOMBINERINPUTPARAMETERFVNV) (GLenum variable,GLenum pname,GLfloat *params);
typedef void (APIENTRY *PFNGLGETFINALCOMBINERINPUTPARAMETERIVNV) (GLenum variable,GLenum pname,GLfloat *params);
/***********************************************************************************************************/
// Declare Register Combiners function pointers.
extern PFNGLCOMBINERPARAMETERFVNV qglCombinerParameterfvNV;
extern PFNGLCOMBINERPARAMETERIVNV qglCombinerParameterivNV;
extern PFNGLCOMBINERPARAMETERFNV qglCombinerParameterfNV;
extern PFNGLCOMBINERPARAMETERINV qglCombinerParameteriNV;
extern PFNGLCOMBINERINPUTNV qglCombinerInputNV;
extern PFNGLCOMBINEROUTPUTNV qglCombinerOutputNV;
extern PFNGLFINALCOMBINERINPUTNV qglFinalCombinerInputNV;
extern PFNGLGETCOMBINERINPUTPARAMETERFVNV qglGetCombinerInputParameterfvNV;
extern PFNGLGETCOMBINERINPUTPARAMETERIVNV qglGetCombinerInputParameterivNV;
extern PFNGLGETCOMBINEROUTPUTPARAMETERFVNV qglGetCombinerOutputParameterfvNV;
extern PFNGLGETCOMBINEROUTPUTPARAMETERIVNV qglGetCombinerOutputParameterivNV;
extern PFNGLGETFINALCOMBINERINPUTPARAMETERFVNV qglGetFinalCombinerInputParameterfvNV;
extern PFNGLGETFINALCOMBINERINPUTPARAMETERIVNV qglGetFinalCombinerInputParameterivNV;
#ifndef HAVE_GLES
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Format extension definitions. - AReis
/***********************************************************************************************************/
#ifdef _WINDOWS
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
/***********************************************************************************************************/
// Declare Pixel Format function pointers.
extern PFNWGLGETPIXELFORMATATTRIBIVARBPROC qwglGetPixelFormatAttribivARB;
extern PFNWGLGETPIXELFORMATATTRIBFVARBPROC qwglGetPixelFormatAttribfvARB;
extern PFNWGLCHOOSEPIXELFORMATARBPROC qwglChoosePixelFormatARB;
#endif
#ifdef LINUX
typedef GLXFBConfig* ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
typedef XVisualInfo* ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
extern PFNGLXCHOOSEFBCONFIGPROC qglXChooseFBConfig;
extern PFNGLXCREATENEWCONTEXTPROC qglXCreateNewContext;
extern PFNGLXGETFBCONFIGATTRIBPROC qglXGetFBConfigAttrib;
extern PFNGLXGETVISUALFROMFBCONFIGPROC qglXGetVisualFromFBConfig;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pixel Buffer extension definitions. - AReis
/***********************************************************************************************************/
#ifdef _WINDOWS
DECLARE_HANDLE(HPBUFFERARB);
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
#define WGL_PBUFFER_WIDTH_ARB 0x2034
#define WGL_PBUFFER_HEIGHT_ARB 0x2035
#define WGL_RED_BITS_ARB 0x2015
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_BLUE_BITS_ARB 0x2019
typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
/***********************************************************************************************************/
// Declare Pixel Buffer function pointers.
extern PFNWGLCREATEPBUFFERARBPROC qwglCreatePbufferARB;
extern PFNWGLGETPBUFFERDCARBPROC qwglGetPbufferDCARB;
extern PFNWGLRELEASEPBUFFERDCARBPROC qwglReleasePbufferDCARB;
extern PFNWGLDESTROYPBUFFERARBPROC qwglDestroyPbufferARB;
extern PFNWGLQUERYPBUFFERARBPROC qwglQueryPbufferARB;
#endif
#ifdef _LINUX
typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
extern PFNGLXCREATEPBUFFERPROC qglXCreatePbufferARB;
extern PFNGLXDESTROYPBUFFERPROC qglXDestroyPbufferARB;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Render-Texture extension definitions. - AReis
/***********************************************************************************************************/
#ifdef _WINDOWS
#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
#define WGL_TEXTURE_FORMAT_ARB 0x2072
#define WGL_TEXTURE_TARGET_ARB 0x2073
#define WGL_TEXTURE_RGB_ARB 0x2075
#define WGL_TEXTURE_RGBA_ARB 0x2076
#define WGL_TEXTURE_2D_ARB 0x207A
#define WGL_FRONT_LEFT_ARB 0x2083
typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int * piAttribList);
/***********************************************************************************************************/
// Declare Render-Texture function pointers.
extern PFNWGLBINDTEXIMAGEARBPROC qwglBindTexImageARB;
extern PFNWGLRELEASETEXIMAGEARBPROC qwglReleaseTexImageARB;
extern PFNWGLSETPBUFFERATTRIBARBPROC qwglSetPbufferAttribARB;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Vertex and Fragment Program extension definitions. - AReis
/***********************************************************************************************************/
#ifndef GL_ARB_fragment_program
#define GL_FRAGMENT_PROGRAM_ARB 0x8804
#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
#endif
// NOTE: These are obviously not all the vertex program flags (have you seen how many there actually are!). I'm
// only including the ones I use (to reduce code clutter), so if you need any of the other flags, just add them.
#define GL_VERTEX_PROGRAM_ARB 0x8620
#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
#endif //HAVE_GLES
typedef void (APIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string);
typedef void (APIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
typedef void (APIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
typedef void (APIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
typedef void (APIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string);
typedef GLboolean (APIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program);
/***********************************************************************************************************/
// Declare Vertex and Fragment Program function pointers.
extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
extern PFNGLBINDPROGRAMARBPROC qglBindProgramARB;
extern PFNGLDELETEPROGRAMSARBPROC qglDeleteProgramsARB;
extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
extern PFNGLPROGRAMENVPARAMETER4DARBPROC qglProgramEnvParameter4dARB;
extern PFNGLPROGRAMENVPARAMETER4DVARBPROC qglProgramEnvParameter4dvARB;
extern PFNGLPROGRAMENVPARAMETER4FARBPROC qglProgramEnvParameter4fARB;
extern PFNGLPROGRAMENVPARAMETER4FVARBPROC qglProgramEnvParameter4fvARB;
extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC qglProgramLocalParameter4dARB;
extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC qglProgramLocalParameter4dvARB;
extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC qglProgramLocalParameter4fARB;
extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB;
extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC qglGetProgramEnvParameterdvARB;
extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC qglGetProgramEnvParameterfvARB;
extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC qglGetProgramLocalParameterdvARB;
extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC qglGetProgramLocalParameterfvARB;
extern PFNGLGETPROGRAMIVARBPROC qglGetProgramivARB;
extern PFNGLGETPROGRAMSTRINGARBPROC qglGetProgramStringARB;
extern PFNGLISPROGRAMARBPROC qglIsProgramARB;
extern void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
#ifndef HAVE_GLES
/*
** extension constants
*/
// S3TC compression constants
#define GL_RGB_S3TC 0x83A0
#define GL_RGB4_S3TC 0x83A1
// extensions will be function pointers on all platforms
extern void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
extern void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
extern void ( APIENTRY * qglLockArraysEXT) (GLint, GLint);
extern void ( APIENTRY * qglUnlockArraysEXT) (void);
extern void ( APIENTRY * qglPointParameterfEXT)( GLenum, GLfloat);
extern void ( APIENTRY * qglPointParameterfvEXT)( GLenum, GLfloat *);
#endif //HAVE_GLES
// Added 10/23/02 by Aurelio Reis.
extern void ( APIENTRY * qglPointParameteriNV)( GLenum, GLint);
extern void ( APIENTRY * qglPointParameterivNV)( GLenum, const GLint *);
//===========================================================================
// non-windows systems will just redefine qgl* to gl*
#if (!defined( _WIN32 ) && !defined( __linux__ )) || defined(HAVE_GLES)
#include "qgl_linked.h"
#else
// windows systems use a function pointer for each call so we can load minidrivers
extern void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
extern void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
extern GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
extern void ( APIENTRY * qglArrayElement )(GLint i);
extern void ( APIENTRY * qglBegin )(GLenum mode);
extern void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
extern void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
extern void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
extern void ( APIENTRY * qglCallList )(GLuint list);
extern void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
extern void ( APIENTRY * qglClear )(GLbitfield mask);
extern void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
extern void ( APIENTRY * qglClearDepth )(GLclampd depth);
extern void ( APIENTRY * qglClearIndex )(GLfloat c);
extern void ( APIENTRY * qglClearStencil )(GLint s);
extern void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
extern void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
extern void ( APIENTRY * qglColor3bv )(const GLbyte *v);
extern void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
extern void ( APIENTRY * qglColor3dv )(const GLdouble *v);
extern void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
extern void ( APIENTRY * qglColor3fv )(const GLfloat *v);
extern void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
extern void ( APIENTRY * qglColor3iv )(const GLint *v);
extern void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
extern void ( APIENTRY * qglColor3sv )(const GLshort *v);
extern void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
extern void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
extern void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
extern void ( APIENTRY * qglColor3uiv )(const GLuint *v);
extern void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
extern void ( APIENTRY * qglColor3usv )(const GLushort *v);
extern void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
extern void ( APIENTRY * qglColor4bv )(const GLbyte *v);
extern void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
extern void ( APIENTRY * qglColor4dv )(const GLdouble *v);
extern void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void ( APIENTRY * qglColor4fv )(const GLfloat *v);
extern void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
extern void ( APIENTRY * qglColor4iv )(const GLint *v);
extern void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
extern void ( APIENTRY * qglColor4sv )(const GLshort *v);
extern void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
extern void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
extern void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
extern void ( APIENTRY * qglColor4uiv )(const GLuint *v);
extern void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
extern void ( APIENTRY * qglColor4usv )(const GLushort *v);
extern void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
extern void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
extern void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
extern void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
extern void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
extern void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
extern void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
extern void ( APIENTRY * qglCullFace )(GLenum mode);
extern void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
extern void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
extern void ( APIENTRY * qglDepthFunc )(GLenum func);
extern void ( APIENTRY * qglDepthMask )(GLboolean flag);
extern void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
extern void ( APIENTRY * qglDisable )(GLenum cap);
extern void ( APIENTRY * qglDisableClientState )(GLenum array);
extern void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
extern void ( APIENTRY * qglDrawBuffer )(GLenum mode);
extern void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
extern void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
extern void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
extern void ( APIENTRY * qglEnable )(GLenum cap);
extern void ( APIENTRY * qglEnableClientState )(GLenum array);
extern void ( APIENTRY * qglEnd )(void);
extern void ( APIENTRY * qglEndList )(void);
extern void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
extern void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
extern void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
extern void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
extern void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
extern void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
extern void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
extern void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
extern void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
extern void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
extern void ( APIENTRY * qglEvalPoint1 )(GLint i);
extern void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
extern void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
extern void ( APIENTRY * qglFinish )(void);
extern void ( APIENTRY * qglFlush )(void);
extern void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
extern void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
extern void ( APIENTRY * qglFrontFace )(GLenum mode);
extern void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern GLuint ( APIENTRY * qglGenLists )(GLsizei range);
extern void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
extern void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
extern void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
extern void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
extern GLenum ( APIENTRY * qglGetError )(void);
extern void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
extern void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
extern void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
extern void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
extern void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
extern void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
extern void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
extern void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
extern const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
extern void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
extern void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
extern void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
extern void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
extern void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
extern void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
extern void ( APIENTRY * qglIndexMask )(GLuint mask);
extern void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglIndexd )(GLdouble c);
extern void ( APIENTRY * qglIndexdv )(const GLdouble *c);
extern void ( APIENTRY * qglIndexf )(GLfloat c);
extern void ( APIENTRY * qglIndexfv )(const GLfloat *c);
extern void ( APIENTRY * qglIndexi )(GLint c);
extern void ( APIENTRY * qglIndexiv )(const GLint *c);
extern void ( APIENTRY * qglIndexs )(GLshort c);
extern void ( APIENTRY * qglIndexsv )(const GLshort *c);
extern void ( APIENTRY * qglIndexub )(GLubyte c);
extern void ( APIENTRY * qglIndexubv )(const GLubyte *c);
extern void ( APIENTRY * qglInitNames )(void);
extern void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
extern GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
extern GLboolean ( APIENTRY * qglIsList )(GLuint l);
extern GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
extern void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
extern void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
extern void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
extern void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
extern void ( APIENTRY * qglLineWidth )(GLfloat width);
extern void ( APIENTRY * qglListBase )(GLuint base);
extern void ( APIENTRY * qglLoadIdentity )(void);
extern void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
extern void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
extern void ( APIENTRY * qglLoadName )(GLuint name);
extern void ( APIENTRY * qglLogicOp )(GLenum opcode);
extern void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
extern void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
extern void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
extern void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
extern void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
extern void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
extern void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
extern void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
extern void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
extern void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglMatrixMode )(GLenum mode);
extern void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
extern void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
extern void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
extern void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
extern void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
extern void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
extern void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
extern void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
extern void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
extern void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
extern void ( APIENTRY * qglNormal3iv )(const GLint *v);
extern void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
extern void ( APIENTRY * qglNormal3sv )(const GLshort *v);
extern void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern void ( APIENTRY * qglPassThrough )(GLfloat token);
extern void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
extern void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
extern void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
extern void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
extern void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
extern void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
extern void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
extern void ( APIENTRY * qglPointSize )(GLfloat size);
extern void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
extern void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
extern void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
extern void ( APIENTRY * qglPopAttrib )(void);
extern void ( APIENTRY * qglPopClientAttrib )(void);
extern void ( APIENTRY * qglPopMatrix )(void);
extern void ( APIENTRY * qglPopName )(void);
extern void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
extern void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
extern void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
extern void ( APIENTRY * qglPushMatrix )(void);
extern void ( APIENTRY * qglPushName )(GLuint name);
extern void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
extern void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
extern void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
extern void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
extern void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
extern void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
extern void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
extern void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
extern void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
extern void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
extern void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
extern void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
extern void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
extern void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
extern void ( APIENTRY * qglReadBuffer )(GLenum mode);
extern void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
extern void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
extern void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
extern void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
extern void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
extern void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
extern void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
extern void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
extern void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
extern GLint ( APIENTRY * qglRenderMode )(GLenum mode);
extern void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
extern void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
extern void ( APIENTRY * qglShadeModel )(GLenum mode);
extern void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
extern void ( APIENTRY * qglStencilMask )(GLuint mask);
extern void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
extern void ( APIENTRY * qglTexCoord1d )(GLdouble s);
extern void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord1f )(GLfloat s);
extern void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord1i )(GLint s);
extern void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord1s )(GLshort s);
extern void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
extern void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
extern void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
extern void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
extern void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
extern void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
extern void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
extern void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
extern void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
extern void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
extern void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
extern void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
extern void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
extern void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
extern void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
extern void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
extern void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
extern void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
extern void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
extern void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
extern void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
extern void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
extern void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
extern void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
extern void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
extern void ( APIENTRY * qglVertex2iv )(const GLint *v);
extern void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
extern void ( APIENTRY * qglVertex2sv )(const GLshort *v);
extern void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
extern void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
extern void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
extern void ( APIENTRY * qglVertex3iv )(const GLint *v);
extern void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
extern void ( APIENTRY * qglVertex3sv )(const GLshort *v);
extern void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
extern void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
extern void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
extern void ( APIENTRY * qglVertex4iv )(const GLint *v);
extern void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
extern void ( APIENTRY * qglVertex4sv )(const GLshort *v);
extern void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
#if defined( _WIN32 )
extern BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
extern BOOL ( WINAPI * qwglDeleteContext)(HGLRC);
extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
extern HDC ( WINAPI * qwglGetCurrentDC)(VOID);
extern PROC ( WINAPI * qwglGetProcAddress)(LPCSTR);
extern BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
extern BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
extern BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
extern BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
FLOAT, int, LPGLYPHMETRICSFLOAT);
extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
LPLAYERPLANEDESCRIPTOR);
extern int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
CONST COLORREF *);
extern int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
COLORREF *);
extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
#endif // _WIN32
#if defined( __linux__ )
//FX Mesa Functions
//extern fxMesaContext (*qfxMesaCreateContext)(GLuint win, GrScreenResolution_t, GrScreenRefresh_t, const GLint attribList[]);
//extern fxMesaContext (*qfxMesaCreateBestContext)(GLuint win, GLint width, GLint height, const GLint attribList[]);
//extern void (*qfxMesaDestroyContext)(fxMesaContext ctx);
//extern void (*qfxMesaMakeCurrent)(fxMesaContext ctx);
//extern fxMesaContext (*qfxMesaGetCurrentContext)(void);
//extern void (*qfxMesaSwapBuffers)(void);
//GLX Functions
extern XVisualInfo * (*qglXChooseVisual)( Display *dpy, int screen, int *attribList );
extern GLXContext (*qglXCreateContext)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct );
extern void (*qglXDestroyContext)( Display *dpy, GLXContext ctx );
extern Bool (*qglXMakeCurrent)( Display *dpy, GLXDrawable drawable, GLXContext ctx);
extern void (*qglXCopyContext)( Display *dpy, GLXContext src, GLXContext dst, GLuint mask );
extern void (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
extern Bool (*qglXSwapIntervalEXT) (int interval);
#endif //HAVE_GLES
#endif // __linux__
#endif // _WIN32 && __linux__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
////////////////////////////////////////////////////////////////////////////////////////
// RAVEN SOFTWARE - STAR WARS: JK II
// (c) 2002 Activision
//
// World Effects
//
////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#if !defined __TR_WORLDEFFECTS_H
#define __TR_WORLDEFFECTS_H
#include "../qcommon/q_shared.h" // For Vec3_t
////////////////////////////////////////////////////////////////////////////////////////
// Supported Commands
////////////////////////////////////////////////////////////////////////////////////////
void R_AddWeatherZone(vec3_t mins, vec3_t maxs);
void R_InitWorldEffects(void);
void R_ShutdownWorldEffects(void);
void RB_RenderWorldEffects(void);
void R_WorldEffectCommand(const char *command);
void R_WorldEffect_f(void);
////////////////////////////////////////////////////////////////////////////////////////
// Exported Functionality
////////////////////////////////////////////////////////////////////////////////////////
bool R_GetWindVector(vec3_t windVector, vec3_t atpoint);
bool R_GetWindSpeed(float &windSpeed, vec3_t atpoint);
bool R_GetWindGusting(vec3_t atpoint);
bool R_IsOutside(vec3_t pos);
float R_IsOutsideCausingPain(vec3_t pos);
float R_GetChanceOfSaberFizz();
bool R_IsShaking(vec3_t pos);
bool R_SetTempGlobalFogColor(vec3_t color);
bool R_IsRaining();
bool R_IsPuffing();
#endif // __TR_WORLDEFFECTS_H

View file

@ -0,0 +1,194 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_glow.c -- this file deals with the arb shaders for dynamic glow
#include "tr_local.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Vertex and Pixel Shader definitions. - AReis
/***********************************************************************************************************/
// This vertex shader basically passes through most values and calculates no lighting. The only
// unusual thing it does is add the inputed texel offsets to all four texture units (this allows
// nearest neighbor pixel peeking).
const unsigned char g_strGlowVShaderARB[] =
{
"!!ARBvp1.0\
\
# Input.\n\
ATTRIB iPos = vertex.position;\
ATTRIB iColor = vertex.color;\
ATTRIB iTex0 = vertex.texcoord[0];\
ATTRIB iTex1 = vertex.texcoord[1];\
ATTRIB iTex2 = vertex.texcoord[2];\
ATTRIB iTex3 = vertex.texcoord[3];\
\
# Output.\n\
OUTPUT oPos = result.position;\
OUTPUT oColor = result.color;\
OUTPUT oTex0 = result.texcoord[0];\
OUTPUT oTex1 = result.texcoord[1];\
OUTPUT oTex2 = result.texcoord[2];\
OUTPUT oTex3 = result.texcoord[3];\
\
# Constants.\n\
PARAM ModelViewProj[4]= { state.matrix.mvp };\
PARAM TexelOffset0 = program.env[0];\
PARAM TexelOffset1 = program.env[1];\
PARAM TexelOffset2 = program.env[2];\
PARAM TexelOffset3 = program.env[3];\
\
# Main.\n\
DP4 oPos.x, ModelViewProj[0], iPos;\
DP4 oPos.y, ModelViewProj[1], iPos;\
DP4 oPos.z, ModelViewProj[2], iPos;\
DP4 oPos.w, ModelViewProj[3], iPos;\
MOV oColor, iColor;\
# Notice the optimization of using one texture coord instead of all four.\n\
ADD oTex0, iTex0, TexelOffset0;\
ADD oTex1, iTex0, TexelOffset1;\
ADD oTex2, iTex0, TexelOffset2;\
ADD oTex3, iTex0, TexelOffset3;\
\
END"
};
// This Pixel Shader loads four texture units and adds them all together (with a modifier
// multiplied to each in the process). The final output is r0 = t0 + t1 + t2 + t3.
const unsigned char g_strGlowPShaderARB[] =
{
"!!ARBfp1.0\
\
# Input.\n\
ATTRIB iColor = fragment.color.primary;\
\
# Output.\n\
OUTPUT oColor = result.color;\
\
# Constants.\n\
PARAM Weight = program.env[0];\
TEMP t0;\
TEMP t1;\
TEMP t2;\
TEMP t3;\
TEMP r0;\
\
# Main.\n\
TEX t0, fragment.texcoord[0], texture[0], RECT;\
TEX t1, fragment.texcoord[1], texture[1], RECT;\
TEX t2, fragment.texcoord[2], texture[2], RECT;\
TEX t3, fragment.texcoord[3], texture[3], RECT;\
\
MUL r0, t0, Weight;\
MAD r0, t1, Weight, r0;\
MAD r0, t2, Weight, r0;\
MAD r0, t3, Weight, r0;\
\
MOV oColor, r0;\
\
END"
};
/***********************************************************************************************************/
#ifndef HAVE_GLES
#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
void ARB_InitGlowShaders(void) {
// Allocate and Load the global 'Glow' Vertex Program. - AReis
if ( qglGenProgramsARB )
{
qglGenProgramsARB( 1, &tr.glowVShader );
qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, tr.glowVShader );
qglProgramStringARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, ( GLsizei ) strlen( ( char * ) g_strGlowVShaderARB ), g_strGlowVShaderARB );
// const GLubyte *strErr = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
int iErrPos = 0;
qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &iErrPos );
assert( iErrPos == -1 );
}
// NOTE: I make an assumption here. If you have (current) nvidia hardware, you obviously support register combiners instead of fragment
// programs, so use those. The problem with this is that nv30 WILL support fragment shaders, breaking this logic. The good thing is that
// if you always ask for regcoms before fragment shaders, you'll always just use regcoms (problem solved... for now). - AReis
// Load Pixel Shaders (either regcoms or fragprogs).
if ( qglCombinerParameteriNV )
{
// The purpose of this regcom is to blend all the pixels together from the 4 texture units, but with their
// texture coordinates offset by 1 (or more) texels, effectively letting us blend adjoining pixels. The weight is
// used to either strengthen or weaken the pixel intensity. The more it diffuses (the higher the radius of the glow),
// the higher the intensity should be for a noticable effect.
// Regcom result is: ( tex1 * fBlurWeight ) + ( tex2 * fBlurWeight ) + ( tex2 * fBlurWeight ) + ( tex2 * fBlurWeight )
// VV guys, this is the pixel shader you would use instead :-)
/*
// c0 is the blur weight.
ps 1.1
tex t0
tex t1
tex t2
tex t3
mul r0, c0, t0;
madd r0, c0, t1, r0;
madd r0, c0, t2, r0;
madd r0, c0, t3, r0;
*/
tr.glowPShader = qglGenLists( 1 );
qglNewList( tr.glowPShader, GL_COMPILE );
qglCombinerParameteriNV( GL_NUM_GENERAL_COMBINERS_NV, 2 );
// spare0 = fBlend * tex0 + fBlend * tex1.
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerOutputNV( GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// spare1 = fBlend * tex2 + fBlend * tex3.
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE2_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE3_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerInputNV( GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglCombinerOutputNV( GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE1_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// ( A * B ) + ( ( 1 - A ) * C ) + D = ( spare0 * 1 ) + ( ( 1 - spare0 ) * 0 ) + spare1 == spare0 + spare1.
qglFinalCombinerInputNV( GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglFinalCombinerInputNV( GL_VARIABLE_D_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
qglEndList();
}
else if ( qglGenProgramsARB )
{
qglGenProgramsARB( 1, &tr.glowPShader );
qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, tr.glowPShader );
qglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, ( GLsizei ) strlen( ( char * ) g_strGlowPShaderARB ), g_strGlowPShaderARB );
// const GLubyte *strErr = qglGetString( GL_PROGRAM_ERROR_STRING_ARB );
int iErrPos = 0;
qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &iErrPos );
assert( iErrPos == -1 );
}
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,531 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#include "tr_local.h"
/*
=====================
R_PerformanceCounters
=====================
*/
void R_PerformanceCounters( void ) {
if ( !r_speeds->integer ) {
// clear the counters even if we aren't printing
memset( &tr.pc, 0, sizeof( tr.pc ) );
memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
return;
}
if (r_speeds->integer == 1) {
const float texSize = R_SumOfUsedImages( qfalse )/(8*1048576.0f)*(r_texturebits->integer?r_texturebits->integer:glConfig.colorBits);
ri.Printf (PRINT_ALL, "%i/%i shdrs/srfs %i leafs %i vrts %i/%i tris %.2fMB tex %.2f dc\n",
backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
texSize, backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
} else if (r_speeds->integer == 2) {
ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,
tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,
tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
} else if (r_speeds->integer == 3) {
ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
} else if (r_speeds->integer == 4) {
if ( backEnd.pc.c_dlightVertexes ) {
ri.Printf (PRINT_ALL, "dlight srf:%i culled:%i verts:%i tris:%i\n",
tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
}
}
else if (r_speeds->integer == 5 )
{
ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
}
else if (r_speeds->integer == 6 )
{
ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
}
else if (r_speeds->integer == 7) {
const float texSize = R_SumOfUsedImages(qtrue) / (1048576.0f);
const float backBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.colorBits / (8.0f * 1024*1024);
const float depthBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.depthBits / (8.0f * 1024*1024);
const float stencilBuff= glConfig.vidWidth * glConfig.vidHeight * glConfig.stencilBits / (8.0f * 1024*1024);
ri.Printf (PRINT_ALL, "Tex MB %.2f + buffers %.2f MB = Total %.2fMB\n",
texSize, backBuff*2+depthBuff+stencilBuff, texSize+backBuff*2+depthBuff+stencilBuff);
}
memset( &tr.pc, 0, sizeof( tr.pc ) );
memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
}
/*
====================
R_IssueRenderCommands
====================
*/
void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
renderCommandList_t *cmdList;
cmdList = &backEndData->commands;
// add an end-of-list command
byteAlias_t *ba = (byteAlias_t *)&cmdList->cmds[cmdList->used];
ba->ui = RC_END_OF_LIST;
// clear it out, in case this is a sync and not a buffer flip
cmdList->used = 0;
// at this point, the back end thread is idle, so it is ok
// to look at it's performance counters
if ( runPerformanceCounters ) {
R_PerformanceCounters();
}
// actually start the commands going
if ( !r_skipBackEnd->integer ) {
// let it start on the new batch
RB_ExecuteRenderCommands( cmdList->cmds );
}
}
/*
====================
R_IssuePendingRenderCommands
Issue any pending commands and wait for them to complete.
====================
*/
void R_IssuePendingRenderCommands( void ) {
if ( !tr.registered ) {
return;
}
R_IssueRenderCommands( qfalse );
}
/*
============
R_GetCommandBufferReserved
make sure there is enough command space
============
*/
static void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) {
renderCommandList_t *cmdList;
cmdList = &backEndData->commands;
bytes = PAD(bytes, sizeof(void *));
// always leave room for the end of list command
if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) {
if ( bytes > MAX_RENDER_COMMANDS - (int)sizeof( int ) ) {
ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
}
// if we run out of room, just start dropping commands
return NULL;
}
cmdList->used += bytes;
return cmdList->cmds + cmdList->used - bytes;
}
/*
============
R_GetCommandBuffer
make sure there is enough command space
============
*/
static void *R_GetCommandBuffer( int bytes ) {
return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) );
}
/*
=============
R_AddDrawSurfCmd
=============
*/
void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
drawSurfsCommand_t *cmd;
cmd = (drawSurfsCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_DRAW_SURFS;
cmd->drawSurfs = drawSurfs;
cmd->numDrawSurfs = numDrawSurfs;
cmd->refdef = tr.refdef;
cmd->viewParms = tr.viewParms;
}
/*
=============
RE_SetColor
Passing NULL will set the color to white
=============
*/
void RE_SetColor( const float *rgba ) {
setColorCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (setColorCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_SET_COLOR;
if ( !rgba ) {
rgba = colorWhite;
}
cmd->color[0] = rgba[0];
cmd->color[1] = rgba[1];
cmd->color[2] = rgba[2];
cmd->color[3] = rgba[3];
}
/*
=============
RE_StretchPic
=============
*/
void RE_StretchPic ( float x, float y, float w, float h,
float s1, float t1, float s2, float t2, qhandle_t hShader ) {
stretchPicCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (stretchPicCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_STRETCH_PIC;
cmd->shader = R_GetShaderByHandle( hShader );
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
cmd->s1 = s1;
cmd->t1 = t1;
cmd->s2 = s2;
cmd->t2 = t2;
}
/*
=============
RE_RotatePic
=============
*/
void RE_RotatePic ( float x, float y, float w, float h,
float s1, float t1, float s2, float t2,float a, qhandle_t hShader ) {
rotatePicCommand_t *cmd;
if (!tr.registered) {
return;
}
cmd = (rotatePicCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_ROTATE_PIC;
cmd->shader = R_GetShaderByHandle( hShader );
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
cmd->s1 = s1;
cmd->t1 = t1;
cmd->s2 = s2;
cmd->t2 = t2;
cmd->a = a;
}
/*
=============
RE_RotatePic2
=============
*/
void RE_RotatePic2 ( float x, float y, float w, float h,
float s1, float t1, float s2, float t2,float a, qhandle_t hShader ) {
rotatePicCommand_t *cmd;
if (!tr.registered) {
return;
}
cmd = (rotatePicCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_ROTATE_PIC2;
cmd->shader = R_GetShaderByHandle( hShader );
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
cmd->s1 = s1;
cmd->t1 = t1;
cmd->s2 = s2;
cmd->t2 = t2;
cmd->a = a;
}
void RE_LAGoggles( void )
{
tr.refdef.rdflags |= (RDF_doLAGoggles|RDF_doFullbright);
tr.refdef.doLAGoggles = qtrue;
jk_fog_t *fog = &tr.world->fogs[tr.world->numfogs];
fog->parms.color[0] = 0.75f;
fog->parms.color[1] = 0.42f + Q_flrand(0.0f, 1.0f) * 0.025f;
fog->parms.color[2] = 0.07f;
fog->parms.depthForOpaque = 10000;
fog->colorInt = ColorBytes4(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f);
fog->tcScale = 2.0f / ( fog->parms.depthForOpaque * (1.0f + cos( tr.refdef.floatTime) * 0.1f));
}
void RE_RenderWorldEffects(void)
{
setModeCommand_t *cmd;
if (!tr.registered) {
return;
}
cmd = (setModeCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_WORLD_EFFECTS;
}
/*
=============
RE_Scissor
=============
*/
void RE_Scissor ( float x, float y, float w, float h)
{
scissorCommand_t *cmd;
if (!tr.registered) {
return;
}
cmd = (scissorCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_SCISSOR;
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
}
/*
====================
RE_BeginFrame
If running in stereo, RE_BeginFrame will be called twice
for each RE_EndFrame
====================
*/
void RE_BeginFrame( stereoFrame_t stereoFrame ) {
drawBufferCommand_t *cmd = NULL;
if ( !tr.registered ) {
return;
}
glState.finishCalled = qfalse;
tr.frameCount++;
tr.frameSceneNum = 0;
//
// do overdraw measurement
//
#ifndef HAVE_GLES
if ( r_measureOverdraw->integer )
{
if ( glConfig.stencilBits < 4 )
{
ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
ri.Cvar_Set( "r_measureOverdraw", "0" );
r_measureOverdraw->modified = qfalse;
}
else if ( r_shadows->integer == 2 )
{
ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
ri.Cvar_Set( "r_measureOverdraw", "0" );
r_measureOverdraw->modified = qfalse;
}
else
{
R_IssuePendingRenderCommands();
qglEnable( GL_STENCIL_TEST );
qglStencilMask( ~0U );
qglClearStencil( 0U );
qglStencilFunc( GL_ALWAYS, 0U, ~0U );
qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
}
r_measureOverdraw->modified = qfalse;
}
else
{
// this is only reached if it was on and is now off
if ( r_measureOverdraw->modified ) {
R_IssuePendingRenderCommands();
qglDisable( GL_STENCIL_TEST );
r_measureOverdraw->modified = qfalse;
}
}
#endif
//
// texturemode stuff
//
if ( r_textureMode->modified || r_ext_texture_filter_anisotropic->modified) {
R_IssuePendingRenderCommands();
GL_TextureMode( r_textureMode->string );
r_textureMode->modified = qfalse;
r_ext_texture_filter_anisotropic->modified = qfalse;
}
//
// gamma stuff
//
if ( r_gamma->modified ) {
r_gamma->modified = qfalse;
R_IssuePendingRenderCommands();
R_SetColorMappings();
}
// check for errors
if ( !r_ignoreGLErrors->integer ) {
int err;
R_IssuePendingRenderCommands();
if ( ( err = qglGetError() ) != GL_NO_ERROR ) {
Com_Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err );
}
}
//
// draw buffer stuff
//
cmd = (drawBufferCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) );
if ( !cmd ) {
return;
}
cmd->commandId = RC_DRAW_BUFFER;
{
if ( stereoFrame == STEREO_LEFT ) {
cmd->buffer = (int)0;
} else if ( stereoFrame == STEREO_RIGHT ) {
cmd->buffer = (int)1;
} else {
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
}
}
}
/*
=============
RE_EndFrame
Returns the number of msec spent in the back end
=============
*/
void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
swapBuffersCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (swapBuffersCommand_t*)R_GetCommandBuffer(sizeof(*cmd));
if (!cmd) {
return;
}
cmd->commandId = RC_FLUSH;
R_IssueRenderCommands( qfalse );
// use the other buffers next frame, because another CPU
// may still be rendering into the current ones
R_InitNextFrame();
if (frontEndMsec) {
*frontEndMsec = tr.frontEndMsec;
}
tr.frontEndMsec = 0;
if (backEndMsec) {
*backEndMsec = backEnd.pc.msec;
}
backEnd.pc.msec = 0;
for(int i=0;i<MAX_LIGHT_STYLES;i++)
{
styleUpdated[i] = false;
}
}
void RE_SubmitStereoFrame( ) {
swapBuffersCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (swapBuffersCommand_t*)R_GetCommandBuffer(sizeof(*cmd));
if (!cmd) {
return;
}
cmd->commandId = RC_SWAP_BUFFERS;
R_IssueRenderCommands( qtrue );
}

View file

@ -0,0 +1,485 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#include "tr_common.h"
#include "tr_local.h"
/*
This file does all of the processing necessary to turn a raw grid of points
read from the map file into a srfGridMesh_t ready for rendering.
The level of detail solution is direction independent, based only on subdivided
distance from the true curve.
Only a single entry point:
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
*/
/*
============
LerpDrawVert
============
*/
static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
int k;
out->xyz[0] = 0.5 * (a->xyz[0] + b->xyz[0]);
out->xyz[1] = 0.5 * (a->xyz[1] + b->xyz[1]);
out->xyz[2] = 0.5 * (a->xyz[2] + b->xyz[2]);
out->st[0] = 0.5 * (a->st[0] + b->st[0]);
out->st[1] = 0.5 * (a->st[1] + b->st[1]);
out->normal[0] = 0.5 * (a->normal[0] + b->normal[0]);
out->normal[1] = 0.5 * (a->normal[1] + b->normal[1]);
out->normal[2] = 0.5 * (a->normal[2] + b->normal[2]);
for(k=0;k<MAXLIGHTMAPS;k++)
{
out->lightmap[k][0] = 0.5 * (a->lightmap[k][0] + b->lightmap[k][0]);
out->lightmap[k][1] = 0.5 * (a->lightmap[k][1] + b->lightmap[k][1]);
out->color[k][0] = (a->color[k][0] + b->color[k][0]) >> 1;
out->color[k][1] = (a->color[k][1] + b->color[k][1]) >> 1;
out->color[k][2] = (a->color[k][2] + b->color[k][2]) >> 1;
out->color[k][3] = (a->color[k][3] + b->color[k][3]) >> 1;
}
}
/*
============
Transpose
============
*/
static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j;
drawVert_t temp;
if ( width > height ) {
for ( i = 0 ; i < height ; i++ ) {
for ( j = i + 1 ; j < width ; j++ ) {
if ( j < height ) {
// swap the value
temp = ctrl[j][i];
ctrl[j][i] = ctrl[i][j];
ctrl[i][j] = temp;
} else {
// just copy
ctrl[j][i] = ctrl[i][j];
}
}
}
} else {
for ( i = 0 ; i < width ; i++ ) {
for ( j = i + 1 ; j < height ; j++ ) {
if ( j < width ) {
// swap the value
temp = ctrl[i][j];
ctrl[i][j] = ctrl[j][i];
ctrl[j][i] = temp;
} else {
// just copy
ctrl[i][j] = ctrl[j][i];
}
}
}
}
}
/*
=================
MakeMeshNormals
Handles all the complicated wrapping and degenerate cases
=================
*/
static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j, k, dist;
vec3_t normal;
vec3_t sum;
int count;
vec3_t base;
vec3_t delta;
int x, y;
drawVert_t *dv;
vec3_t around[8], temp;
qboolean good[8];
qboolean wrapWidth, wrapHeight;
float len;
static int neighbors[8][2] = {
{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
};
wrapWidth = qfalse;
for ( i = 0 ; i < height ; i++ ) {
VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 ) {
break;
}
}
if ( i == height ) {
wrapWidth = qtrue;
}
wrapHeight = qfalse;
for ( i = 0 ; i < width ; i++ ) {
VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 ) {
break;
}
}
if ( i == width) {
wrapHeight = qtrue;
}
for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) {
count = 0;
dv = &ctrl[j][i];
VectorCopy( dv->xyz, base );
for ( k = 0 ; k < 8 ; k++ ) {
VectorClear( around[k] );
good[k] = qfalse;
for ( dist = 1 ; dist <= 3 ; dist++ ) {
x = i + neighbors[k][0] * dist;
y = j + neighbors[k][1] * dist;
if ( wrapWidth ) {
if ( x < 0 ) {
x = width - 1 + x;
} else if ( x >= width ) {
x = 1 + x - width;
}
}
if ( wrapHeight ) {
if ( y < 0 ) {
y = height - 1 + y;
} else if ( y >= height ) {
y = 1 + y - height;
}
}
if ( x < 0 || x >= width || y < 0 || y >= height ) {
break; // edge of patch
}
VectorSubtract( ctrl[y][x].xyz, base, temp );
if ( VectorNormalize2( temp, temp ) == 0 ) {
continue; // degenerate edge, get more dist
} else {
good[k] = qtrue;
VectorCopy( temp, around[k] );
break; // good edge
}
}
}
VectorClear( sum );
for ( k = 0 ; k < 8 ; k++ ) {
if ( !good[k] || !good[(k+1)&7] ) {
continue; // didn't get two points
}
CrossProduct( around[(k+1)&7], around[k], normal );
if ( VectorNormalize2( normal, normal ) == 0 ) {
continue;
}
VectorAdd( normal, sum, sum );
count++;
}
if ( count == 0 ) {
//printf("bad normal\n");
count = 1;
}
VectorNormalize2( sum, dv->normal );
}
}
}
/*
============
InvertCtrl
============
*/
static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
int i, j;
drawVert_t temp;
for ( i = 0 ; i < height ; i++ ) {
for ( j = 0 ; j < width/2 ; j++ ) {
temp = ctrl[i][j];
ctrl[i][j] = ctrl[i][width-1-j];
ctrl[i][width-1-j] = temp;
}
}
}
/*
=================
InvertErrorTable
=================
*/
static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
int i;
float copy[2][MAX_GRID_SIZE];
memcpy( copy, errorTable, sizeof( copy ) );
for ( i = 0 ; i < width ; i++ ) {
errorTable[1][i] = copy[0][i]; //[width-1-i];
}
for ( i = 0 ; i < height ; i++ ) {
errorTable[0][i] = copy[1][height-1-i];
}
}
/*
==================
PutPointsOnCurve
==================
*/
static void PutPointsOnCurve( drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
int width, int height ) {
int i, j;
drawVert_t prev, next;
for ( i = 0 ; i < width ; i++ ) {
for ( j = 1 ; j < height ; j += 2 ) {
LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev );
LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next );
LerpDrawVert( &prev, &next, &ctrl[j][i] );
}
}
for ( j = 0 ; j < height ; j++ ) {
for ( i = 1 ; i < width ; i += 2 ) {
LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev );
LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next );
LerpDrawVert( &prev, &next, &ctrl[j][i] );
}
}
}
/*
=================
R_SubdividePatchToGrid
=================
*/
srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
int i, j, k, l;
drawVert_t prev, next, mid;
float len, maxLen;
int dir;
int t;
drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
float errorTable[2][MAX_GRID_SIZE];
srfGridMesh_t *grid;
drawVert_t *vert;
vec3_t tmpVec;
for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) {
ctrl[j][i] = points[j*width+i];
}
}
for ( dir = 0 ; dir < 2 ; dir++ ) {
for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
errorTable[dir][j] = 0;
}
// horizontal subdivisions
for ( j = 0 ; j + 2 < width ; j += 2 ) {
// check subdivided midpoints against control points
maxLen = 0;
for ( i = 0 ; i < height ; i++ ) {
vec3_t midxyz;
vec3_t dir;
vec3_t projected;
float d;
// calculate the point on the curve
for ( l = 0 ; l < 3 ; l++ ) {
midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
+ ctrl[i][j+2].xyz[l] ) * 0.25;
}
// see how far off the line it is
// using dist-from-line will not account for internal
// texture warping, but it gives a lot less polygons than
// dist-from-midpoint
VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir );
VectorNormalize( dir );
d = DotProduct( midxyz, dir );
VectorScale( dir, d, projected );
VectorSubtract( midxyz, projected, midxyz);
len = VectorLength( midxyz );
if ( len > maxLen ) {
maxLen = len;
}
}
// if all the points are on the lines, remove the entire columns
if ( maxLen < 0.1 ) {
errorTable[dir][j+1] = 999;
continue;
}
// see if we want to insert subdivided columns
if ( width + 2 > MAX_GRID_SIZE ) {
errorTable[dir][j+1] = 1.0/maxLen;
continue; // can't subdivide any more
}
if ( maxLen <= r_subdivisions->value ) {
errorTable[dir][j+1] = 1.0/maxLen;
continue; // didn't need subdivision
}
errorTable[dir][j+2] = 1.0/maxLen;
// insert two columns and replace the peak
width += 2;
for ( i = 0 ; i < height ; i++ ) {
LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev );
LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next );
LerpDrawVert( &prev, &next, &mid );
for ( k = width - 1 ; k > j + 3 ; k-- ) {
ctrl[i][k] = ctrl[i][k-2];
}
ctrl[i][j + 1] = prev;
ctrl[i][j + 2] = mid;
ctrl[i][j + 3] = next;
}
// back up and recheck this set again, it may need more subdivision
j -= 2;
}
Transpose( width, height, ctrl );
t = width;
width = height;
height = t;
}
// put all the aproximating points on the curve
PutPointsOnCurve( ctrl, width, height );
// cull out any rows or columns that are colinear
for ( i = 1 ; i < width-1 ; i++ ) {
if ( errorTable[0][i] != 999 ) {
continue;
}
for ( j = i+1 ; j < width ; j++ ) {
for ( k = 0 ; k < height ; k++ ) {
ctrl[k][j-1] = ctrl[k][j];
}
errorTable[0][j-1] = errorTable[0][j];
}
width--;
}
for ( i = 1 ; i < height-1 ; i++ ) {
if ( errorTable[1][i] != 999 ) {
continue;
}
for ( j = i+1 ; j < height ; j++ ) {
for ( k = 0 ; k < width ; k++ ) {
ctrl[j-1][k] = ctrl[j][k];
}
errorTable[1][j-1] = errorTable[1][j];
}
height--;
}
#if 1
// flip for longest tristrips as an optimization
// the results should be visually identical with or
// without this step
if ( height > width ) {
Transpose( width, height, ctrl );
InvertErrorTable( errorTable, width, height );
t = width;
width = height;
height = t;
InvertCtrl( width, height, ctrl );
}
#endif
// calculate normals
MakeMeshNormals( width, height, ctrl );
// copy the results out to a grid
grid = (struct srfGridMesh_s *) R_Hunk_Alloc( (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid ), qtrue );
grid->widthLodError = (float *) R_Hunk_Alloc( width * 4, qfalse );
memcpy( grid->widthLodError, errorTable[0], width * 4 );
grid->heightLodError = (float *) R_Hunk_Alloc( height * 4, qfalse );
memcpy( grid->heightLodError, errorTable[1], height * 4 );
grid->width = width;
grid->height = height;
grid->surfaceType = SF_GRID;
ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
for ( i = 0 ; i < width ; i++ ) {
for ( j = 0 ; j < height ; j++ ) {
vert = &grid->verts[j*width+i];
*vert = ctrl[j][i];
AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
}
}
// compute local origin and bounds
VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
grid->meshRadius = VectorLength( tmpVec );
VectorCopy( grid->localOrigin, grid->lodOrigin );
grid->lodRadius = grid->meshRadius;
return grid;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,520 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_light.c
#include "../server/exe_headers.h"
#include "tr_local.h"
#define DLIGHT_AT_RADIUS 16
// at the edge of a dlight's influence, this amount of light will be added
#define DLIGHT_MINIMUM_RADIUS 16
// never calculate a range less than this to prevent huge light numbers
/*
===============
R_TransformDlights
Transforms the origins of an array of dlights.
Used by both the front end (for DlightBmodel) and
the back end (before doing the lighting calculation)
===============
*/
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *ori) {
int i;
vec3_t temp;
for ( i = 0 ; i < count ; i++, dl++ ) {
VectorSubtract( dl->origin, ori->origin, temp );
dl->transformed[0] = DotProduct( temp, ori->axis[0] );
dl->transformed[1] = DotProduct( temp, ori->axis[1] );
dl->transformed[2] = DotProduct( temp, ori->axis[2] );
}
}
/*
=============
R_DlightBmodel
Determine which dynamic lights may effect this bmodel
=============
*/
void R_DlightBmodel( bmodel_t *bmodel, qboolean NoLight ) {
int i, j;
dlight_t *dl;
int mask;
msurface_t *surf;
// transform all the lights
R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.ori );
mask = 0;
if (!NoLight)
{
for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) {
dl = &tr.refdef.dlights[i];
// see if the point is close enough to the bounds to matter
for ( j = 0 ; j < 3 ; j++ ) {
if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) {
break;
}
if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) {
break;
}
}
if ( j < 3 ) {
continue;
}
// we need to check this light
mask |= 1 << i;
}
}
tr.currentEntity->needDlights = (qboolean)(mask != 0);
tr.currentEntity->dlightBits = mask;
// set the dlight bits in all the surfaces
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
surf = bmodel->firstSurface + i;
if ( *surf->data == SF_FACE ) {
((srfSurfaceFace_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_GRID ) {
((srfGridMesh_t *)surf->data)->dlightBits = mask;
} else if ( *surf->data == SF_TRIANGLES ) {
((srfTriangles_t *)surf->data)->dlightBits = mask;
}
}
}
/*
=============================================================================
LIGHT SAMPLING
=============================================================================
*/
extern cvar_t *r_ambientScale;
extern cvar_t *r_directedScale;
extern cvar_t *r_debugLight;
/*
=================
R_SetupEntityLightingGrid
=================
*/
static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
vec3_t lightOrigin;
int pos[3];
int i, j;
float frac[3];
int gridStep[3];
vec3_t direction;
float totalFactor;
unsigned short *startGridPos;
if (r_fullbright->integer || (tr.refdef.rdflags & RDF_doLAGoggles) )
{
ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[2] = 255.0;
ent->directedLight[0] = ent->directedLight[1] = ent->directedLight[2] = 255.0;
VectorCopy( tr.sunDirection, ent->lightDir );
return;
}
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
// seperate lightOrigins are needed so an object that is
// sinking into the ground can still be lit, and so
// multi-part models can be lit identically
VectorCopy( ent->e.lightingOrigin, lightOrigin );
} else {
VectorCopy( ent->e.origin, lightOrigin );
}
#define ACCURATE_LIGHTGRID_SAMPLING 1
#if ACCURATE_LIGHTGRID_SAMPLING
vec3_t startLightOrigin;
VectorCopy( lightOrigin, startLightOrigin );
#endif
VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin );
for ( i = 0 ; i < 3 ; i++ ) {
float v;
v = lightOrigin[i]*tr.world->lightGridInverseSize[i];
pos[i] = floor( v );
frac[i] = v - pos[i];
if ( pos[i] < 0 ) {
pos[i] = 0;
} else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) {
pos[i] = tr.world->lightGridBounds[i] - 1;
}
}
VectorClear( ent->ambientLight );
VectorClear( ent->directedLight );
VectorClear( direction );
// trilerp the light value
gridStep[0] = 1;
gridStep[1] = tr.world->lightGridBounds[0];
gridStep[2] = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
startGridPos = tr.world->lightGridArray + pos[0] * gridStep[0]
+ pos[1] * gridStep[1] + pos[2] * gridStep[2];
#if ACCURATE_LIGHTGRID_SAMPLING
vec3_t startGridOrg;
VectorCopy( tr.world->lightGridOrigin, startGridOrg );
startGridOrg[0] += pos[0] * tr.world->lightGridSize[0];
startGridOrg[1] += pos[1] * tr.world->lightGridSize[1];
startGridOrg[2] += pos[2] * tr.world->lightGridSize[2];
#endif
totalFactor = 0;
for ( i = 0 ; i < 8 ; i++ ) {
float factor;
mgrid_t *data;
unsigned short *gridPos;
int lat, lng;
vec3_t normal;
#if ACCURATE_LIGHTGRID_SAMPLING
vec3_t gridOrg;
VectorCopy( startGridOrg, gridOrg );
#endif
factor = 1.0;
gridPos = startGridPos;
for ( j = 0 ; j < 3 ; j++ ) {
if ( i & (1<<j) ) {
factor *= frac[j];
gridPos += gridStep[j];
#if ACCURATE_LIGHTGRID_SAMPLING
gridOrg[j] += tr.world->lightGridSize[j];
#endif
} else {
factor *= (1.0 - frac[j]);
}
}
if (gridPos >= tr.world->lightGridArray + tr.world->numGridArrayElements)
{//we've gone off the array somehow
continue;
}
data = tr.world->lightGridData + *gridPos;
if ( data->styles[0] == LS_NONE )
{
continue; // ignore samples in walls
}
#if 0
if ( !SV_inPVS( startLightOrigin, gridOrg ) )
{
continue;
}
#endif
totalFactor += factor;
for(j=0;j<MAXLIGHTMAPS;j++)
{
if (data->styles[j] != LS_NONE)
{
const byte style= data->styles[j];
ent->ambientLight[0] += factor * data->ambientLight[j][0] * styleColors[style][0] / 255.0f;
ent->ambientLight[1] += factor * data->ambientLight[j][1] * styleColors[style][1] / 255.0f;
ent->ambientLight[2] += factor * data->ambientLight[j][2] * styleColors[style][2] / 255.0f;
ent->directedLight[0] += factor * data->directLight[j][0] * styleColors[style][0] / 255.0f;
ent->directedLight[1] += factor * data->directLight[j][1] * styleColors[style][1] / 255.0f;
ent->directedLight[2] += factor * data->directLight[j][2] * styleColors[style][2] / 255.0f;
}
else
{
break;
}
}
lat = data->latLong[1];
lng = data->latLong[0];
lat *= (FUNCTABLE_SIZE/256);
lng *= (FUNCTABLE_SIZE/256);
// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )
normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
VectorMA( direction, factor, normal, direction );
#if ACCURATE_LIGHTGRID_SAMPLING
if ( r_debugLight->integer && ent->e.hModel == -1 )
{
//draw
refEntity_t refEnt;
refEnt.hModel = 0;
refEnt.ghoul2 = NULL;
refEnt.renderfx = 0;
VectorCopy( gridOrg, refEnt.origin );
vectoangles( normal, refEnt.angles );
AnglesToAxis( refEnt.angles, refEnt.axis );
refEnt.reType = RT_MODEL;
RE_AddRefEntityToScene( &refEnt );
refEnt.renderfx = RF_DEPTHHACK;
refEnt.reType = RT_SPRITE;
refEnt.customShader = RE_RegisterShader( "gfx/misc/debugAmbient" );
refEnt.shaderRGBA[0] = data->ambientLight[0][0];
refEnt.shaderRGBA[1] = data->ambientLight[0][1];
refEnt.shaderRGBA[2] = data->ambientLight[0][2];
refEnt.shaderRGBA[3] = 255;
refEnt.radius = factor*50+2.0f; // maybe always give it a minimum size?
refEnt.rotation = 0; // don't let the sprite wobble around
RE_AddRefEntityToScene( &refEnt );
refEnt.reType = RT_LINE;
refEnt.customShader = RE_RegisterShader( "gfx/misc/debugArrow" );
refEnt.shaderRGBA[0] = data->directLight[0][0];
refEnt.shaderRGBA[1] = data->directLight[0][1];
refEnt.shaderRGBA[2] = data->directLight[0][2];
refEnt.shaderRGBA[3] = 255;
VectorCopy( refEnt.origin, refEnt.oldorigin );
VectorMA( gridOrg, (factor*-255) - 2.0f, normal, refEnt.origin ); // maybe always give it a minimum length
refEnt.radius = 1.5f;
RE_AddRefEntityToScene( &refEnt );
}
#endif
}
if ( totalFactor > 0 && totalFactor < 0.99 )
{
totalFactor = 1.0 / totalFactor;
VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
VectorScale( ent->directedLight, totalFactor, ent->directedLight );
}
VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );
VectorNormalize2( direction, ent->lightDir );
}
/*
===============
LogLight
===============
*/
static void LogLight( trRefEntity_t *ent ) {
int max1, max2;
/*
if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) {
return;
}
*/
max1 = VectorLength( ent->ambientLight );
/*
max1 = ent->ambientLight[0];
if ( ent->ambientLight[1] > max1 ) {
max1 = ent->ambientLight[1];
} else if ( ent->ambientLight[2] > max1 ) {
max1 = ent->ambientLight[2];
}
*/
max2 = VectorLength( ent->directedLight );
/*
max2 = ent->directedLight[0];
if ( ent->directedLight[1] > max2 ) {
max2 = ent->directedLight[1];
} else if ( ent->directedLight[2] > max2 ) {
max2 = ent->directedLight[2];
}
*/
ri.Printf( PRINT_ALL, "amb:%i dir:%i direction: (%4.2f, %4.2f, %4.2f)\n", max1, max2, ent->lightDir[0], ent->lightDir[1], ent->lightDir[2] );
}
/*
=================
R_SetupEntityLighting
Calculates all the lighting values that will be used
by the Calc_* functions
=================
*/
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
int i;
dlight_t *dl;
float power;
vec3_t dir;
float d;
vec3_t lightDir;
vec3_t lightOrigin;
// lighting calculations
if ( ent->lightingCalculated ) {
return;
}
ent->lightingCalculated = qtrue;
//
// trace a sample point down to find ambient light
//
if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
// seperate lightOrigins are needed so an object that is
// sinking into the ground can still be lit, and so
// multi-part models can be lit identically
VectorCopy( ent->e.lightingOrigin, lightOrigin );
} else {
VectorCopy( ent->e.origin, lightOrigin );
}
// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
if ( !(refdef->rdflags & RDF_NOWORLDMODEL )
&& tr.world->lightGridData ) {
R_SetupEntityLightingGrid( ent );
} else {
ent->ambientLight[0] = ent->ambientLight[1] =
ent->ambientLight[2] = tr.identityLight * 150;
ent->directedLight[0] = ent->directedLight[1] =
ent->directedLight[2] = tr.identityLight * 150;
VectorCopy( tr.sunDirection, ent->lightDir );
}
// bonus items and view weapons have a fixed minimum add
if ( ent->e.renderfx & RF_MORELIGHT ) {
ent->ambientLight[0] += tr.identityLight * 96;
ent->ambientLight[1] += tr.identityLight * 96;
ent->ambientLight[2] += tr.identityLight * 96;
}
else {
// give everything a minimum light add
ent->ambientLight[0] += tr.identityLight * 32;
ent->ambientLight[1] += tr.identityLight * 32;
ent->ambientLight[2] += tr.identityLight * 32;
}
//
// modify the light by dynamic lights
//
d = VectorLength( ent->directedLight );
VectorScale( ent->lightDir, d, lightDir );
for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
dl = &refdef->dlights[i];
VectorSubtract( dl->origin, lightOrigin, dir );
d = VectorNormalize( dir );
power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
if ( d < DLIGHT_MINIMUM_RADIUS ) {
d = DLIGHT_MINIMUM_RADIUS;
}
d = power / ( d * d );
VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
VectorMA( lightDir, d, dir, lightDir );
}
// clamp ambient
for ( i = 0 ; i < 3 ; i++ ) {
if ( ent->ambientLight[i] > tr.identityLightByte ) {
ent->ambientLight[i] = tr.identityLightByte;
}
}
if ( r_debugLight->integer ) {
LogLight( ent );
}
// save out the byte packet version
((byte *)&ent->ambientLightInt)[0] = Q_ftol( ent->ambientLight[0] );
((byte *)&ent->ambientLightInt)[1] = Q_ftol( ent->ambientLight[1] );
((byte *)&ent->ambientLightInt)[2] = Q_ftol( ent->ambientLight[2] );
((byte *)&ent->ambientLightInt)[3] = 0xff;
// transform the direction to local space
VectorNormalize( lightDir );
ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
}
//pass in origin
qboolean RE_GetLighting( const vec3_t origin, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir) {
trRefEntity_t tr_ent;
if ( !tr.world || !tr.world->lightGridData) {
ambientLight[0] = ambientLight[1] = ambientLight[2] = 255.0;
directedLight[0] = directedLight[1] = directedLight[2] = 255.0;
VectorCopy( tr.sunDirection, lightDir );
return qfalse;
}
memset (&tr_ent, 0, sizeof(tr_ent) );
if ( ambientLight[0] == 666 )
{//HAX0R
tr_ent.e.hModel = -1;
}
VectorCopy (origin, tr_ent.e.origin);
R_SetupEntityLightingGrid( &tr_ent );
VectorCopy ( tr_ent.ambientLight, ambientLight);
VectorCopy ( tr_ent.directedLight, directedLight);
VectorCopy ( tr_ent.lightDir, lightDir);
return qtrue;
}
/*
=================
R_LightForPoint
=================
*/
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
{
trRefEntity_t ent;
// bk010103 - this segfaults with -nolight maps
if ( tr.world->lightGridData == NULL )
return qfalse;
memset(&ent, 0, sizeof(ent));
VectorCopy( point, ent.e.origin );
R_SetupEntityLightingGrid( &ent );
VectorCopy(ent.ambientLight, ambientLight);
VectorCopy(ent.directedLight, directedLight);
VectorCopy(ent.lightDir, lightDir);
return qtrue;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,471 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_marks.c -- polygon projection on the world polygons
#include "../server/exe_headers.h"
#include "tr_local.h"
#define MAX_VERTS_ON_POLY 64
#define MARKER_OFFSET 0 // 1
/*
=============
R_ChopPolyBehindPlane
Out must have space for two more vertexes than in
=============
*/
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY],
int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],
vec3_t normal, vec_t dist, vec_t epsilon) {
float dists[MAX_VERTS_ON_POLY+4] = { 0 };
int sides[MAX_VERTS_ON_POLY+4] = { 0 };
int counts[3];
float dot;
int i, j;
float *p1, *p2, *clip;
float d;
// don't clip if it might overflow
if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) {
*numOutPoints = 0;
return;
}
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for ( i = 0 ; i < numInPoints ; i++ ) {
dot = DotProduct( inPoints[i], normal );
dot -= dist;
dists[i] = dot;
if ( dot > epsilon ) {
sides[i] = SIDE_FRONT;
} else if ( dot < -epsilon ) {
sides[i] = SIDE_BACK;
} else {
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*numOutPoints = 0;
if ( !counts[0] ) {
return;
}
if ( !counts[1] ) {
*numOutPoints = numInPoints;
memcpy( outPoints, inPoints, numInPoints * sizeof(vec3_t) );
return;
}
for ( i = 0 ; i < numInPoints ; i++ ) {
p1 = inPoints[i];
clip = outPoints[ *numOutPoints ];
if ( sides[i] == SIDE_ON ) {
VectorCopy( p1, clip );
(*numOutPoints)++;
continue;
}
if ( sides[i] == SIDE_FRONT ) {
VectorCopy( p1, clip );
(*numOutPoints)++;
clip = outPoints[ *numOutPoints ];
}
if ( sides[i+1] == SIDE_ON || sides[i+1] == sides[i] ) {
continue;
}
// generate a split point
p2 = inPoints[ (i+1) % numInPoints ];
d = dists[i] - dists[i+1];
if ( d == 0 ) {
dot = 0;
} else {
dot = dists[i] / d;
}
// clip xyz
for (j=0 ; j<3 ; j++) {
clip[j] = p1[j] + dot * ( p2[j] - p1[j] );
}
(*numOutPoints)++;
}
}
/*
=================
R_BoxSurfaces_r
=================
*/
void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {
int s, c;
msurface_t *surf, **mark;
// do the tail recursion in a loop
while ( node->contents == -1 ) {
s = BoxOnPlaneSide( mins, maxs, node->plane );
if (s == 1) {
node = node->children[0];
} else if (s == 2) {
node = node->children[1];
} else {
R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
node = node->children[1];
}
}
// add the individual surfaces
mark = node->firstmarksurface;
c = node->nummarksurfaces;
while (c--) {
//
if (*listlength >= listsize) break;
//
surf = *mark;
// check if the surface has NOIMPACT or NOMARKS set
if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
|| ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
surf->viewCount = tr.viewCount;
}
// extra check for surfaces to avoid list overflows
else if (*(surf->data) == SF_FACE) {
// the face plane should go through the box
s = BoxOnPlaneSide( mins, maxs, &(( srfSurfaceFace_t * ) surf->data)->plane );
if (s == 1 || s == 2) {
surf->viewCount = tr.viewCount;
} else if (DotProduct((( srfSurfaceFace_t * ) surf->data)->plane.normal, dir) > -0.5) {
// don't add faces that make sharp angles with the projection direction
surf->viewCount = tr.viewCount;
}
}
else if (*(surfaceType_t *) (surf->data) != SF_GRID
&& *(surfaceType_t *) (surf->data) != SF_TRIANGLES )
{
surf->viewCount = tr.viewCount;
}
// check the viewCount because the surface may have
// already been added if it spans multiple leafs
if (surf->viewCount != tr.viewCount) {
surf->viewCount = tr.viewCount;
list[*listlength] = (surfaceType_t *) surf->data;
(*listlength)++;
}
mark++;
}
}
/*
=================
R_AddMarkFragments
=================
*/
void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY],
int numPlanes, vec3_t *normals, float *dists,
int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t *fragmentBuffer,
int *returnedPoints, int *returnedFragments,
vec3_t mins, vec3_t maxs) {
int pingPong, i;
markFragment_t *mf;
// chop the surface by all the bounding planes of the to be projected polygon
pingPong = 0;
for ( i = 0 ; i < numPlanes ; i++ ) {
R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong],
&numClipPoints, clipPoints[!pingPong],
normals[i], dists[i], 0.5 );
pingPong ^= 1;
if ( numClipPoints == 0 ) {
break;
}
}
// completely clipped away?
if ( numClipPoints == 0 ) {
return;
}
// add this fragment to the returned list
if ( numClipPoints + (*returnedPoints) > maxPoints ) {
return; // not enough space for this polygon
}
/*
// all the clip points should be within the bounding box
for ( i = 0 ; i < numClipPoints ; i++ ) {
int j;
for ( j = 0 ; j < 3 ; j++ ) {
if (clipPoints[pingPong][i][j] < mins[j] - 0.5) break;
if (clipPoints[pingPong][i][j] > maxs[j] + 0.5) break;
}
if (j < 3) break;
}
if (i < numClipPoints) return;
*/
mf = fragmentBuffer + (*returnedFragments);
mf->firstPoint = (*returnedPoints);
mf->numPoints = numClipPoints;
memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) );
(*returnedPoints) += numClipPoints;
(*returnedFragments)++;
}
/*
=================
R_MarkFragments
=================
*/
int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
int numsurfaces, numPlanes;
int i, j, k, m, n;
surfaceType_t *surfaces[64];
vec3_t mins, maxs;
int returnedFragments;
int returnedPoints;
vec3_t normals[MAX_VERTS_ON_POLY+2];
float dists[MAX_VERTS_ON_POLY+2];
vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
vec3_t normal;
vec3_t projectionDir;
vec3_t v1, v2;
//increment view count for double check prevention
tr.viewCount++;
//
VectorNormalize2( projection, projectionDir );
// find all the brushes that are to be considered
ClearBounds( mins, maxs );
for ( i = 0 ; i < numPoints ; i++ ) {
vec3_t temp;
AddPointToBounds( points[i], mins, maxs );
VectorAdd( points[i], projection, temp );
AddPointToBounds( temp, mins, maxs );
// make sure we get all the leafs (also the one(s) in front of the hit surface)
VectorMA( points[i], -20, projectionDir, temp );
AddPointToBounds( temp, mins, maxs );
}
if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY;
// create the bounding planes for the to be projected polygon
for ( i = 0 ; i < numPoints ; i++ ) {
VectorSubtract(points[(i+1)%numPoints], points[i], v1);
VectorAdd(points[i], projection, v2);
VectorSubtract(points[i], v2, v2);
CrossProduct(v1, v2, normals[i]);
VectorNormalizeFast(normals[i]);
dists[i] = DotProduct(normals[i], points[i]);
}
// add near and far clipping planes for projection
VectorCopy(projectionDir, normals[numPoints]);
dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
VectorCopy(projectionDir, normals[numPoints+1]);
VectorInverse(normals[numPoints+1]);
dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20;
numPlanes = numPoints + 2;
numsurfaces = 0;
R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir);
//assert(numsurfaces <= 64);
//assert(numsurfaces != 64);
returnedPoints = 0;
returnedFragments = 0;
for ( i = 0 ; i < numsurfaces ; i++ ) {
if (*surfaces[i] == SF_GRID) {
const srfGridMesh_t * const cv = (srfGridMesh_t *) surfaces[i];
for ( m = 0 ; m < cv->height - 1 ; m++ ) {
for ( n = 0 ; n < cv->width - 1 ; n++ ) {
// We triangulate the grid and chop all triangles within
// the bounding planes of the to be projected polygon.
// LOD is not taken into account, not such a big deal though.
//
// It's probably much nicer to chop the grid itself and deal
// with this grid as a normal SF_GRID surface so LOD will
// be applied. However the LOD of that chopped grid must
// be synced with the LOD of the original curve.
// One way to do this; the chopped grid shares vertices with
// the original curve. When LOD is applied to the original
// curve the unused vertices are flagged. Now the chopped curve
// should skip the flagged vertices. This still leaves the
// problems with the vertices at the chopped grid edges.
//
// To avoid issues when LOD applied to "hollow curves" (like
// the ones around many jump pads) we now just add a 2 unit
// offset to the triangle vertices.
// The offset is added in the vertex normal vector direction
// so all triangles will still fit together.
// The 2 unit offset should avoid pretty much all LOD problems.
const int numClipPoints = 3;
const drawVert_t * const dv = cv->verts + m * cv->width + n;
VectorCopy(dv[0].xyz, clipPoints[0][0]);
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
VectorCopy(dv[1].xyz, clipPoints[0][2]);
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
// check the normal of this triangle
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
CrossProduct(v1, v2, normal);
VectorNormalizeFast(normal);
if (DotProduct(normal, projectionDir) < -0.1) {
// add the fragments of this triangle
R_AddMarkFragments(numClipPoints, clipPoints,
numPlanes, normals, dists,
maxPoints, pointBuffer,
maxFragments, fragmentBuffer,
&returnedPoints, &returnedFragments, mins, maxs);
if ( returnedFragments == maxFragments ) {
return returnedFragments; // not enough space for more fragments
}
}
VectorCopy(dv[1].xyz, clipPoints[0][0]);
VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
// check the normal of this triangle
VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
CrossProduct(v1, v2, normal);
VectorNormalizeFast(normal);
if (DotProduct(normal, projectionDir) < -0.05) {
// add the fragments of this triangle
R_AddMarkFragments(numClipPoints, clipPoints,
numPlanes, normals, dists,
maxPoints, pointBuffer,
maxFragments, fragmentBuffer,
&returnedPoints, &returnedFragments, mins, maxs);
if ( returnedFragments == maxFragments ) {
return returnedFragments; // not enough space for more fragments
}
}
}
}
}
else if (*surfaces[i] == SF_FACE) {
const srfSurfaceFace_t * const surf = ( srfSurfaceFace_t * ) surfaces[i];
// check the normal of this face
if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
continue;
}
const int * const indexes = (int *)( (byte *)surf + surf->ofsIndices );
for ( k = 0 ; k < surf->numIndices ; k += 3 ) {
for ( j = 0 ; j < 3 ; j++ ) {
const float * const v = surf->points[0] + VERTEXSIZE * indexes[k+j];
VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] );
}
// add the fragments of this face
R_AddMarkFragments( 3 , clipPoints,
numPlanes, normals, dists,
maxPoints, pointBuffer,
maxFragments, fragmentBuffer,
&returnedPoints, &returnedFragments, mins, maxs);
if ( returnedFragments == maxFragments ) {
return returnedFragments; // not enough space for more fragments
}
}
continue;
}
else if (*surfaces[i] == SF_TRIANGLES)
{
const srfTriangles_t * const surf = ( srfTriangles_t * ) surfaces[i];
for ( k = 0 ; k < surf->numIndexes ; k += 3 )
{
int i1=surf->indexes[k];
int i2=surf->indexes[k+1];
int i3=surf->indexes[k+2];
VectorSubtract(surf->verts[i1].xyz,surf->verts[i2].xyz, v1);
VectorSubtract(surf->verts[i3].xyz,surf->verts[i2].xyz, v2);
CrossProduct(v1, v2, normal);
VectorNormalizeFast(normal);
// check the normal of this triangle
if (DotProduct(normal, projectionDir) < -0.1)
{
VectorMA(surf->verts[i1].xyz, MARKER_OFFSET, normal, clipPoints[0][0]);
VectorMA(surf->verts[i2].xyz, MARKER_OFFSET, normal, clipPoints[0][1]);
VectorMA(surf->verts[i3].xyz, MARKER_OFFSET, normal, clipPoints[0][2]);
// add the fragments of this triangle
R_AddMarkFragments( 3 , clipPoints,
numPlanes, normals, dists,
maxPoints, pointBuffer,
maxFragments, fragmentBuffer,
&returnedPoints, &returnedFragments, mins, maxs);
if ( returnedFragments == maxFragments )
{
return returnedFragments; // not enough space for more fragments
}
}
}
}
else {
// ignore all other world surfaces
// might be cool to also project polygons on a triangle soup
// however this will probably create huge amounts of extra polys
// even more than the projection onto curves
continue;
}
}
return returnedFragments;
}

View file

@ -0,0 +1,437 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_mesh.c: triangle model functions
#include "../server/exe_headers.h"
#include "tr_local.h"
#include "qcommon/matcomp.h"
float ProjectRadius( float r, vec3_t location )
{
float pr;
float dist;
float c;
vec3_t p;
float width;
float depth;
c = DotProduct( tr.viewParms.ori.axis[0], tr.viewParms.ori.origin );
dist = DotProduct( tr.viewParms.ori.axis[0], location ) - c;
if ( dist <= 0 )
return 0;
p[0] = 0;
p[1] = Q_fabs( r );
p[2] = -dist;
width = p[0] * tr.viewParms.projectionMatrix[1] +
p[1] * tr.viewParms.projectionMatrix[5] +
p[2] * tr.viewParms.projectionMatrix[9] +
tr.viewParms.projectionMatrix[13];
depth = p[0] * tr.viewParms.projectionMatrix[3] +
p[1] * tr.viewParms.projectionMatrix[7] +
p[2] * tr.viewParms.projectionMatrix[11] +
tr.viewParms.projectionMatrix[15];
pr = width / depth;
if ( pr > 1.0f )
pr = 1.0f;
return pr;
}
/*
=============
R_CullModel
=============
*/
static int R_CullModel( md3Header_t *header, trRefEntity_t *ent ) {
vec3_t bounds[2];
md3Frame_t *oldFrame, *newFrame;
int i;
// compute frame pointers
newFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
oldFrame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.oldframe;
// cull bounding sphere ONLY if this is not an upscaled entity
if ( !ent->e.nonNormalizedAxes )
{
if ( ent->e.frame == ent->e.oldframe )
{
switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
{
case CULL_OUT:
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
case CULL_IN:
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_sphere_cull_md3_clip++;
break;
}
}
else
{
int sphereCull, sphereCullB;
sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
if ( newFrame == oldFrame ) {
sphereCullB = sphereCull;
} else {
sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
}
if ( sphereCull == sphereCullB )
{
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_md3_out++;
return CULL_OUT;
}
else if ( sphereCull == CULL_IN )
{
tr.pc.c_sphere_cull_md3_in++;
return CULL_IN;
}
else
{
tr.pc.c_sphere_cull_md3_clip++;
}
}
}
}
// calculate a bounding box in the current coordinate system
for (i = 0 ; i < 3 ; i++) {
bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
}
switch ( R_CullLocalBox( bounds ) )
{
case CULL_IN:
tr.pc.c_box_cull_md3_in++;
return CULL_IN;
case CULL_CLIP:
tr.pc.c_box_cull_md3_clip++;
return CULL_CLIP;
case CULL_OUT:
default:
tr.pc.c_box_cull_md3_out++;
return CULL_OUT;
}
}
/*
=================
RE_GetModelBounds
Returns the bounds of the current model
(qhandle_t)hModel and (int)frame need to be set
=================
*/
void RE_GetModelBounds(refEntity_t *refEnt, vec3_t bounds1, vec3_t bounds2)
{
md3Frame_t *frame;
md3Header_t *header;
model_t *model;
assert(refEnt);
model = R_GetModelByHandle( refEnt->hModel );
assert(model);
header = model->md3[0];
assert(header);
frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + refEnt->frame;
assert(frame);
VectorCopy(frame->bounds[0], bounds1);
VectorCopy(frame->bounds[1], bounds2);
}
/*
=================
R_ComputeLOD
=================
*/
static int R_ComputeLOD( trRefEntity_t *ent ) {
float radius;
float flod;
float projectedRadius;
int lod;
if ( tr.currentModel->numLods < 2 )
{ // model has only 1 LOD level, skip computations and bias
return(0);
}
// multiple LODs exist, so compute projected bounding sphere
// and use that as a criteria for selecting LOD
// if ( tr.currentModel->md3[0] )
{ //normal md3
md3Frame_t *frame;
frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
frame += ent->e.frame;
radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
}
if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
{
flod = 1.0f - projectedRadius * r_lodscale->value;
flod *= tr.currentModel->numLods;
}
else
{ // object intersects near view plane, e.g. view weapon
flod = 0;
}
lod = Q_ftol( flod );
if ( lod < 0 ) {
lod = 0;
} else if ( lod >= tr.currentModel->numLods ) {
lod = tr.currentModel->numLods - 1;
}
lod += r_lodbias->integer;
if ( lod >= tr.currentModel->numLods )
lod = tr.currentModel->numLods - 1;
if ( lod < 0 )
lod = 0;
return lod;
}
/*
=================
R_ComputeFogNum
=================
*/
static int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
int i;
jk_fog_t *fog;
md3Frame_t *md3Frame;
vec3_t localOrigin;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
}
if ( tr.refdef.doLAGoggles )
{
return tr.world->numfogs;
}
// FIXME: non-normalized axis issues
md3Frame = ( md3Frame_t * ) ( ( byte * ) header + header->ofsFrames ) + ent->e.frame;
VectorAdd( ent->e.origin, md3Frame->localOrigin, localOrigin );
int partialFog = 0;
for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
fog = &tr.world->fogs[i];
if ( localOrigin[0] - md3Frame->radius >= fog->bounds[0][0]
&& localOrigin[0] + md3Frame->radius <= fog->bounds[1][0]
&& localOrigin[1] - md3Frame->radius >= fog->bounds[0][1]
&& localOrigin[1] + md3Frame->radius <= fog->bounds[1][1]
&& localOrigin[2] - md3Frame->radius >= fog->bounds[0][2]
&& localOrigin[2] + md3Frame->radius <= fog->bounds[1][2] )
{//totally inside it
return i;
break;
}
if ( ( localOrigin[0] - md3Frame->radius >= fog->bounds[0][0] && localOrigin[1] - md3Frame->radius >= fog->bounds[0][1] && localOrigin[2] - md3Frame->radius >= fog->bounds[0][2] &&
localOrigin[0] - md3Frame->radius <= fog->bounds[1][0] && localOrigin[1] - md3Frame->radius <= fog->bounds[1][1] && localOrigin[2] - md3Frame->radius <= fog->bounds[1][2]) ||
( localOrigin[0] + md3Frame->radius >= fog->bounds[0][0] && localOrigin[1] + md3Frame->radius >= fog->bounds[0][1] && localOrigin[2] + md3Frame->radius >= fog->bounds[0][2] &&
localOrigin[0] + md3Frame->radius <= fog->bounds[1][0] && localOrigin[1] + md3Frame->radius <= fog->bounds[1][1] && localOrigin[2] + md3Frame->radius <= fog->bounds[1][2] ) )
{//partially inside it
if ( tr.refdef.fogIndex == i || R_FogParmsMatch( tr.refdef.fogIndex, i ) )
{//take new one only if it's the same one that the viewpoint is in
return i;
break;
}
else if ( !partialFog )
{//first partialFog
partialFog = i;
}
}
}
//if all else fails, return the first partialFog
return partialFog;
}
/*
=================
R_AddMD3Surfaces
=================
*/
void R_AddMD3Surfaces( trRefEntity_t *ent ) {
int i;
md3Header_t *header = 0;
md3Surface_t *surface = 0;
md3Shader_t *md3Shader = 0;
jk_shader_t *shader = 0;
jk_shader_t *main_shader = 0;
int cull;
int lod;
int fogNum;
qboolean personalModel;
// don't add third_person objects if not in a portal
personalModel = (qboolean)((ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal);
if ( ent->e.renderfx & RF_CAP_FRAMES) {
if (ent->e.frame > tr.currentModel->md3[0]->numFrames-1)
ent->e.frame = tr.currentModel->md3[0]->numFrames-1;
if (ent->e.oldframe > tr.currentModel->md3[0]->numFrames-1)
ent->e.oldframe = tr.currentModel->md3[0]->numFrames-1;
}
else if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
ent->e.frame %= tr.currentModel->md3[0]->numFrames;
ent->e.oldframe %= tr.currentModel->md3[0]->numFrames;
}
//
// Validate the frames so there is no chance of a crash.
// This will write directly into the entity structure, so
// when the surfaces are rendered, they don't need to be
// range checked again.
//
if ( (ent->e.frame >= tr.currentModel->md3[0]->numFrames)
|| (ent->e.frame < 0)
|| (ent->e.oldframe >= tr.currentModel->md3[0]->numFrames)
|| (ent->e.oldframe < 0) )
{
ri.Printf (PRINT_ALL, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
ent->e.oldframe, ent->e.frame,
tr.currentModel->name );
ent->e.frame = 0;
ent->e.oldframe = 0;
}
//
// compute LOD
//
lod = R_ComputeLOD( ent );
header = tr.currentModel->md3[lod];
//
// cull the entire model if merged bounding box of both frames
// is outside the view frustum.
//
cull = R_CullModel ( header, ent );
if ( cull == CULL_OUT ) {
return;
}
//
// set up lighting now that we know we aren't culled
//
if ( !personalModel || r_shadows->integer > 1 ) {
R_SetupEntityLighting( &tr.refdef, ent );
}
//
// see if we are in a fog volume
//
fogNum = R_ComputeFogNum( header, ent );
//
// draw all surfaces
//
main_shader = R_GetShaderByHandle( ent->e.customShader );
surface = (md3Surface_t *)( (byte *)header + header->ofsSurfaces );
for ( i = 0 ; i < header->numSurfaces ; i++ ) {
if ( ent->e.customShader ) {// a little more efficient
shader = main_shader;
} else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
skin_t *skin;
int j;
skin = R_GetSkinByHandle( ent->e.customSkin );
// match the surface name to something in the skin file
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
shader = skin->surfaces[j]->shader;
break;
}
}
} else if ( surface->numShaders <= 0 ) {
shader = tr.defaultShader;
} else {
md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
md3Shader += ent->e.skinNum % surface->numShaders;
shader = tr.shaders[ md3Shader->shaderIndex ];
}
// we will add shadows even if the main object isn't visible in the view
// stencil shadows can't do personal models unless I polyhedron clip
if ( !personalModel
&& r_shadows->integer == 2
&& fogNum == 0
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (surfaceType_t *)surface, tr.shadowShader, 0, qfalse );
}
// projection shadows work fine with personal models
if ( r_shadows->integer == 3
&& fogNum == 0
&& (ent->e.renderfx & RF_SHADOW_PLANE )
&& shader->sort == SS_OPAQUE ) {
R_AddDrawSurf( (surfaceType_t *)surface, tr.projectionShadowShader, 0, qfalse );
}
// don't add third_person objects if not viewing through a portal
if ( !personalModel ) {
R_AddDrawSurf( (surfaceType_t *)surface, shader, fogNum, qfalse );
}
surface = (md3Surface_t *)( (byte *)surface + surface->ofsEnd );
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,305 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_QuickSprite.cpp: implementation of the CQuickSpriteSystem class.
//
//////////////////////////////////////////////////////////////////////
#include "../server/exe_headers.h"
#include "tr_quicksprite.h"
extern void R_BindAnimatedImage( const textureBundle_t *bundle );
//////////////////////////////////////////////////////////////////////
// Singleton System
//////////////////////////////////////////////////////////////////////
CQuickSpriteSystem SQuickSprite;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQuickSpriteSystem::CQuickSpriteSystem() :
mTexBundle(NULL),
mGLStateBits(0),
mFogIndex(-1),
mUseFog(qfalse),
mNextVert(0)
{
int i;
memset( mVerts, 0, sizeof( mVerts ) );
memset( mFogTextureCoords, 0, sizeof( mFogTextureCoords ) );
memset( mColors, 0, sizeof( mColors ) );
for (i = 0; i < SHADER_MAX_VERTEXES; i += 4)
{
// Bottom right
mTextureCoords[i + 0][0] = 1.0;
mTextureCoords[i + 0][1] = 1.0;
// Top right
mTextureCoords[i + 1][0] = 1.0;
mTextureCoords[i + 1][1] = 0.0;
// Top left
mTextureCoords[i + 2][0] = 0.0;
mTextureCoords[i + 2][1] = 0.0;
// Bottom left
mTextureCoords[i + 3][0] = 0.0;
mTextureCoords[i + 3][1] = 1.0;
}
}
CQuickSpriteSystem::~CQuickSpriteSystem(void)
{
}
void CQuickSpriteSystem::Flush(void)
{
if (mNextVert==0)
{
return;
}
/*
if (mUseFog && r_drawfog->integer == 2 &&
mFogIndex == tr.world->globalFog)
{ //enable hardware fog when we draw this thing if applicable -rww
jk_fog_t *fog = tr.world->fogs + mFogIndex;
qglFogf(GL_FOG_MODE, GL_EXP2);
qglFogf(GL_FOG_DENSITY, logtestExp2 / fog->parms.depthForOpaque);
qglFogfv(GL_FOG_COLOR, fog->parms.color);
qglEnable(GL_FOG);
}
*/
//this should not be needed, since I just wait to disable fog for the surface til after surface sprites are done
//
// render the main pass
//
R_BindAnimatedImage( mTexBundle );
GL_State(mGLStateBits);
//
// set arrays and lock
//
#ifdef HAVE_GLES
unsigned short indexes[(mNextVert/2)*3];
int idx;
// split TRIANGLE_FAN in 2 TRIANGLES
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
qglEnableClientState( GL_COLOR_ARRAY);
/*for (int i=0; i<mNextVert; i+=4) {
qglTexCoordPointer(2, GL_FLOAT, 0, mTextureCoords+i);
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors+i );
qglVertexPointer (3, GL_FLOAT, 16, mVerts+i);
qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}*/
qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords );
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors );
qglVertexPointer (3, GL_FLOAT, 16, mVerts);
idx = 0;
for (int i=0; i<mNextVert; i+=4) {
// Triangle 1
indexes[idx+0]=i;
indexes[idx+1]=i+1;
indexes[idx+2]=i+2;
idx+=3;
// Triangle 2
indexes[idx+0]=i;
indexes[idx+1]=i+2;
indexes[idx+2]=i+3;
idx+=3;
}
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords );
qglEnableClientState( GL_COLOR_ARRAY);
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors );
qglVertexPointer (3, GL_FLOAT, 16, mVerts);
if ( qglLockArraysEXT )
{
qglLockArraysEXT(0, mNextVert);
GLimp_LogComment( "glLockArraysEXT\n" );
}
qglDrawArrays(GL_QUADS, 0, mNextVert);
#endif
backEnd.pc.c_vertexes += mNextVert;
backEnd.pc.c_indexes += mNextVert;
backEnd.pc.c_totalIndexes += mNextVert;
#ifdef JK2_MODE
if (mUseFog)
#else
//only for software fog pass (global soft/volumetric) -rww
if (mUseFog && (r_drawfog->integer != 2 || mFogIndex != tr.world->globalFog))
#endif
{
jk_fog_t *fog = tr.world->fogs + mFogIndex;
//
// render the fog pass
//
GL_Bind( tr.fogImage );
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
//
// set arrays and lock
//
#ifdef HAVE_GLES
qglDisableClientState( GL_COLOR_ARRAY );
qglColor4ubv((GLubyte *)&fog->colorInt);
/*for (int i=0; i<mNextVert; i+=4) {
qglTexCoordPointer(2, GL_FLOAT, 0, mFogTextureCoords+i);
qglVertexPointer (3, GL_FLOAT, 16, mVerts+i);
qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}*/
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
qglTexCoordPointer( 2, GL_FLOAT, 0, mFogTextureCoords);
// qglEnableClientState( GL_TEXTURE_COORD_ARRAY); // Done above
qglDisableClientState( GL_COLOR_ARRAY );
qglColor4ubv((GLubyte *)&fog->colorInt);
// qglVertexPointer (3, GL_FLOAT, 16, mVerts); // Done above
qglDrawArrays(GL_QUADS, 0, mNextVert);
#endif
// Second pass from fog
backEnd.pc.c_totalIndexes += mNextVert;
}
//
// unlock arrays
//
if (qglUnlockArraysEXT)
{
qglUnlockArraysEXT();
GLimp_LogComment( "glUnlockArraysEXT\n" );
}
mNextVert=0;
}
void CQuickSpriteSystem::StartGroup(textureBundle_t *bundle, uint32_t glbits, int fogIndex )
{
mNextVert = 0;
mTexBundle = bundle;
mGLStateBits = glbits;
if (fogIndex != -1)
{
mUseFog = qtrue;
mFogIndex = fogIndex;
}
else
{
mUseFog = qfalse;
}
int cullingOn;
qglGetIntegerv(GL_CULL_FACE,&cullingOn);
if(cullingOn)
{
mTurnCullBackOn=qtrue;
}
else
{
mTurnCullBackOn=qfalse;
}
qglDisable(GL_CULL_FACE);
}
void CQuickSpriteSystem::EndGroup(void)
{
Flush();
qglColor4ub(255,255,255,255);
if(mTurnCullBackOn)
{
qglEnable(GL_CULL_FACE);
}
}
void CQuickSpriteSystem::Add(float *pointdata, color4ub_t color, vec2_t fog)
{
float *curcoord;
float *curfogtexcoord;
uint32_t *curcolor;
if (mNextVert>SHADER_MAX_VERTEXES-4)
{
Flush();
}
curcoord = mVerts[mNextVert];
// This is 16*sizeof(float) because, pointdata comes from a float[16]
memcpy(curcoord, pointdata, 16*sizeof(float));
// Set up color
curcolor = &mColors[mNextVert];
*curcolor++ = *(uint32_t *)color;
*curcolor++ = *(uint32_t *)color;
*curcolor++ = *(uint32_t *)color;
*curcolor++ = *(uint32_t *)color;
if (fog)
{
curfogtexcoord = &mFogTextureCoords[mNextVert][0];
*curfogtexcoord++ = fog[0];
*curfogtexcoord++ = fog[1];
*curfogtexcoord++ = fog[0];
*curfogtexcoord++ = fog[1];
*curfogtexcoord++ = fog[0];
*curfogtexcoord++ = fog[1];
*curfogtexcoord++ = fog[0];
*curfogtexcoord++ = fog[1];
mUseFog=qtrue;
}
else
{
mUseFog=qfalse;
}
mNextVert+=4;
}

View file

@ -0,0 +1,58 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "tr_local.h"
// tr_QuickSprite.h: interface for the CQuickSprite class.
//
//////////////////////////////////////////////////////////////////////
#pragma once
class CQuickSpriteSystem
{
private:
textureBundle_t *mTexBundle;
uint32_t mGLStateBits;
int mFogIndex;
qboolean mUseFog;
vec4_t mVerts[SHADER_MAX_VERTEXES];
vec2_t mTextureCoords[SHADER_MAX_VERTEXES]; // Ideally this would be static, cause it never changes
vec2_t mFogTextureCoords[SHADER_MAX_VERTEXES];
uint32_t mColors[SHADER_MAX_VERTEXES];
int mNextVert;
qboolean mTurnCullBackOn;
void Flush(void);
public:
CQuickSpriteSystem(void);
~CQuickSpriteSystem(void);
void StartGroup(textureBundle_t *bundle, uint32_t glbits, int fogIndex = -1);
void EndGroup(void);
void Add(float *pointdata, color4ub_t color, vec2_t fog=NULL);
};
extern CQuickSpriteSystem SQuickSprite;

View file

@ -0,0 +1,421 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#include "tr_local.h"
#include <JKVR/VrClientInfo.h>
int r_firstSceneDrawSurf;
int r_numdlights;
int r_firstSceneDlight;
int r_numentities;
int r_firstSceneEntity;
int r_numpolys;
int r_firstScenePoly;
int r_numpolyverts;
int skyboxportal;
int drawskyboxportal;
int hasskybox; // Used to indicate whether the BSP contains a skybox (if not, then use fog colour if applicable)
/*
====================
R_InitNextFrame
====================
*/
void R_InitNextFrame( void ) {
backEndData->commands.used = 0;
r_firstSceneDrawSurf = 0;
r_numdlights = 0;
r_firstSceneDlight = 0;
r_numentities = 0;
r_firstSceneEntity = 0;
r_numpolys = 0;
r_firstScenePoly = 0;
r_numpolyverts = 0;
}
/*
====================
RE_ClearScene
====================
*/
void RE_ClearScene( void ) {
r_firstSceneDlight = r_numdlights;
r_firstSceneEntity = r_numentities;
r_firstScenePoly = r_numpolys;
tr.refdef.rdflags &= ~(RDF_doLAGoggles|RDF_doFullbright); //probably not needed since it gets copied over in RE_RenderScene
tr.refdef.doLAGoggles = qfalse;
}
/*
===========================================================================
DISCRETE POLYS
===========================================================================
*/
/*
=====================
R_AddPolygonSurfaces
Adds all the scene's polys into this view's drawsurf list
=====================
*/
void R_AddPolygonSurfaces( void ) {
int i;
jk_shader_t *sh;
srfPoly_t *poly;
tr.currentEntityNum = REFENTITYNUM_WORLD;
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
sh = R_GetShaderByHandle( poly->hShader );
R_AddDrawSurf( ( surfaceType_t * )poly, sh, poly->fogIndex, qfalse );
}
}
/*
=====================
RE_AddPolyToScene
=====================
*/
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) {
srfPoly_t *poly;
int i;
int fogIndex = 0;
jk_fog_t *fog;
vec3_t bounds[2];
if ( !tr.registered ) {
return;
}
if ( !hShader ) {
#ifndef FINAL_BUILD
Com_DPrintf( S_COLOR_YELLOW"WARNING: RE_AddPolyToScene: NULL poly shader\n");
#endif
return;
}
if ( r_numpolyverts + numVerts >= MAX_POLYVERTS || r_numpolys >= MAX_POLYS ) {
/*
NOTE TTimo this was initially a PRINT_WARNING
but it happens a lot with high fighting scenes and particles
since we don't plan on changing the const and making for room for those effects
simply cut this message to developer only
*/
ri.Printf( PRINT_DEVELOPER, S_COLOR_YELLOW "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
return;
}
poly = &backEndData->polys[r_numpolys];
poly->surfaceType = SF_POLY;
poly->hShader = hShader;
poly->numVerts = numVerts;
poly->verts = &backEndData->polyVerts[r_numpolyverts];
memcpy( poly->verts, verts, numVerts * sizeof( *verts ) );
r_numpolys++;
r_numpolyverts += numVerts;
// see if it is in a fog volume
if ( !tr.world || tr.world->numfogs == 1) {
fogIndex = 0;
} else {
// find which fog volume the poly is in
VectorCopy( poly->verts[0].xyz, bounds[0] );
VectorCopy( poly->verts[0].xyz, bounds[1] );
for ( i = 1 ; i < poly->numVerts ; i++ ) {
AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
}
for ( int fI = 1 ; fI < tr.world->numfogs ; fI++ ) {
fog = &tr.world->fogs[fI];
if ( bounds[0][0] >= fog->bounds[0][0]
&& bounds[0][1] >= fog->bounds[0][1]
&& bounds[0][2] >= fog->bounds[0][2]
&& bounds[1][0] <= fog->bounds[1][0]
&& bounds[1][1] <= fog->bounds[1][1]
&& bounds[1][2] <= fog->bounds[1][2] )
{//completely in this one
fogIndex = fI;
break;
}
else if ( ( bounds[0][0] >= fog->bounds[0][0] && bounds[0][1] >= fog->bounds[0][1] && bounds[0][2] >= fog->bounds[0][2] &&
bounds[0][0] <= fog->bounds[1][0] && bounds[0][1] <= fog->bounds[1][1] && bounds[0][2] <= fog->bounds[1][2]) ||
( bounds[1][0] >= fog->bounds[0][0] && bounds[1][1] >= fog->bounds[0][1] && bounds[1][2] >= fog->bounds[0][2] &&
bounds[1][0] <= fog->bounds[1][0] && bounds[1][1] <= fog->bounds[1][1] && bounds[1][2] <= fog->bounds[1][2] ) )
{//partially in this one
if ( tr.refdef.fogIndex == fI || R_FogParmsMatch( tr.refdef.fogIndex, fI ) )
{//take new one only if it's the same one that the viewpoint is in
fogIndex = fI;
break;
}
else if ( !fogIndex )
{//didn't find one yet, so use this one
fogIndex = fI;
}
}
}
}
poly->fogIndex = fogIndex;
}
//=================================================================================
/*
=====================
RE_AddRefEntityToScene
=====================
*/
void RE_AddRefEntityToScene( const refEntity_t *ent ) {
if ( !tr.registered ) {
return;
}
if ( r_numentities >= MAX_REFENTITIES ) {
#ifndef FINAL_BUILD
ri.Printf( PRINT_WARNING, "WARNING: RE_AddRefEntityToScene: too many entities\n");
#endif
return;
}
if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
Com_Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
}
backEndData->entities[r_numentities].e = *ent;
backEndData->entities[r_numentities].lightingCalculated = qfalse;
r_numentities++;
}
/*
=====================
RE_AddLightToScene
=====================
*/
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
dlight_t *dl;
if ( !tr.registered ) {
return;
}
if ( r_numdlights >= MAX_DLIGHTS ) {
return;
}
if ( intensity <= 0 ) {
return;
}
dl = &backEndData->dlights[r_numdlights++];
VectorCopy (org, dl->origin);
dl->radius = intensity;
dl->color[0] = r;
dl->color[1] = g;
dl->color[2] = b;
}
/*
@@@@@@@@@@@@@@@@@@@@@
RE_RenderScene
Draw a 3D view into a part of the window, then return
to 2D drawing.
Rendering a scene may require multiple views to be rendered
to handle mirrors,
@@@@@@@@@@@@@@@@@@@@@
*/
extern int recursivePortalCount;
void RE_RenderScene( const refdef_t *fd ) {
viewParms_t parms;
int startTime;
static int lastTime = 0;
if ( !tr.registered ) {
return;
}
GLimp_LogComment( "====== RE_RenderScene =====\n" );
if ( r_norefresh->integer ) {
return;
}
startTime = ri.Milliseconds();
if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
Com_Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
}
// memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
tr.refdef.x = fd->x;
tr.refdef.y = fd->y;
tr.refdef.width = fd->width;
tr.refdef.height = fd->height;
tr.refdef.fov_x = fd->fov_x;
tr.refdef.fov_y = fd->fov_y;
memset( &parms, 0, sizeof( parms ) );
VectorCopy( fd->viewaxis[0], parms.ori.axis[0] );
VectorCopy( fd->viewaxis[1], parms.ori.axis[1] );
VectorCopy( fd->viewaxis[2], parms.ori.axis[2] );
VectorCopy( fd->vieworg, tr.refdef.vieworg );
VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
tr.refdef.time = fd->time;
tr.refdef.frametime = fd->time - lastTime;
tr.refdef.rdflags = fd->rdflags;
// Ignore my last there. This actually breaks the rest of the game as well, causing massive issues.
// We need to figure out what's going on in fd->rdflags first :S .. I'm half-tempted to just revert
// back to JK2 and use a qbool for it --eez
if (fd->rdflags & RDF_SKYBOXPORTAL)
{
skyboxportal = 1;
}
else
{
// cdr - only change last time for the real render, not the portal
lastTime = fd->time;
}
if (fd->rdflags & RDF_DRAWSKYBOX)
{
drawskyboxportal = 1;
}
else
{
drawskyboxportal = 0;
}
// copy the areamask data over and note if it has changed, which
// will force a reset of the visible leafs even if the view hasn't moved
tr.refdef.areamaskModified = qfalse;
if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
int areaDiff;
int i;
// compare the area bits
areaDiff = 0;
for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
}
if ( areaDiff ) {
// a door just opened or something
tr.refdef.areamaskModified = qtrue;
}
}
// derived info
tr.refdef.floatTime = tr.refdef.time * 0.001;
tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
tr.refdef.drawSurfs = backEndData->drawSurfs;
tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
tr.refdef.polys = &backEndData->polys[r_firstScenePoly];
// turn off dynamic lighting globally by clearing all the
// dlights if it needs to be disabled or if vertex lighting is enabled
if ( r_dynamiclight->integer == 0 ||
r_vertexLight->integer == 1 ) {
tr.refdef.num_dlights = 0;
}
// a single frame may have multiple scenes draw inside it --
// a 3D game view, 3D status bar renderings, 3D menus, etc.
// They need to be distinguished by the light flare code, because
// the visibility state for a given surface may be different in
// each scene / view.
tr.frameSceneNum++;
tr.sceneCount++;
// setup view parms for the initial view
//
// set up viewport
// The refdef takes 0-at-the-top y coordinates, so
// convert to GL's 0-at-the-bottom space
//
parms.viewportX = tr.refdef.x;
parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
parms.viewportWidth = tr.refdef.width;
parms.viewportHeight = tr.refdef.height;
parms.isPortal = qfalse;
parms.fovX = tr.refdef.fov_x;
parms.fovY = tr.refdef.fov_y;
VectorCopy( fd->vieworg, parms.ori.origin );
// VectorCopy( fd->viewaxis[0], parms.ori.axis[0] );
// VectorCopy( fd->viewaxis[1], parms.ori.axis[1] );
// VectorCopy( fd->viewaxis[2], parms.ori.axis[2] );
VectorCopy( fd->vieworg, parms.pvsOrigin );
recursivePortalCount = 0;
R_RenderView( &parms );
// the next scene rendered in this frame will tack on after this one
r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
r_firstSceneEntity = r_numentities;
r_firstSceneDlight = r_numdlights;
r_firstScenePoly = r_numpolys;
tr.frontEndMsec += ri.Milliseconds() - startTime;
RE_RenderWorldEffects();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,881 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#include "tr_local.h"
/*
for a projection shadow:
point[x] += light vector * ( z - shadow plane )
point[y] +=
point[z] = shadow plane
1 0 light[x] / light[z]
*/
#define _STENCIL_REVERSE
typedef struct {
int i2;
int facing;
} edgeDef_t;
#define MAX_EDGE_DEFS 32
static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
static int numEdgeDefs[SHADER_MAX_VERTEXES];
static int facing[SHADER_MAX_INDEXES/3];
static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
#ifdef HAVE_GLES
static unsigned short indexes[6 * MAX_EDGE_DEFS * SHADER_MAX_VERTEXES + SHADER_MAX_INDEXES * 2];
static int idx = 0;
#endif
void R_AddEdgeDef( int i1, int i2, int facing ) {
int c;
c = numEdgeDefs[ i1 ];
if ( c == MAX_EDGE_DEFS ) {
return; // overflow
}
edgeDefs[ i1 ][ c ].i2 = i2;
edgeDefs[ i1 ][ c ].facing = facing;
numEdgeDefs[ i1 ]++;
}
void R_RenderShadowEdges( void ) {
int i;
int c;
int j;
int i2;
#if 0
int c_edges, c_rejected;
int c2, k;
int hit[2];
#endif
#ifdef _STENCIL_REVERSE
int numTris;
int o1, o2, o3;
#endif
// an edge is NOT a silhouette edge if its face doesn't face the light,
// or if it has a reverse paired edge that also faces the light.
// A well behaved polyhedron would have exactly two faces for each edge,
// but lots of models have dangling edges or overfanned edges
#if 0
c_edges = 0;
c_rejected = 0;
#endif
#ifdef HAVE_GLES
idx = 0;
#endif
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
c = numEdgeDefs[ i ];
for ( j = 0 ; j < c ; j++ ) {
if ( !edgeDefs[ i ][ j ].facing ) {
continue;
}
//with this system we can still get edges shared by more than 2 tris which
//produces artifacts including seeing the shadow through walls. So for now
//we are going to render all edges even though it is a tiny bit slower. -rww
#if 1
i2 = edgeDefs[ i ][ j ].i2;
#ifdef HAVE_GLES
// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRIANGLE_STRIP call
// even if it seems less efficiant, it's faster on the PANDORA
indexes[idx++] = i;
indexes[idx++] = i + tess.numVertexes;
indexes[idx++] = i2;
indexes[idx++] = i2;
indexes[idx++] = i + tess.numVertexes;
indexes[idx++] = i2 + tess.numVertexes;
#else
qglBegin( GL_TRIANGLE_STRIP );
qglVertex3fv( tess.xyz[ i ] );
qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
qglVertex3fv( tess.xyz[ i2 ] );
qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
qglEnd();
#endif
#else
hit[0] = 0;
hit[1] = 0;
i2 = edgeDefs[ i ][ j ].i2;
c2 = numEdgeDefs[ i2 ];
for ( k = 0 ; k < c2 ; k++ ) {
if ( edgeDefs[ i2 ][ k ].i2 == i ) {
hit[ edgeDefs[ i2 ][ k ].facing ]++;
}
}
// if it doesn't share the edge with another front facing
// triangle, it is a sil edge
if (hit[1] != 1)
{
qglBegin( GL_TRIANGLE_STRIP );
qglVertex3fv( tess.xyz[ i ] );
qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
qglVertex3fv( tess.xyz[ i2 ] );
qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
qglEnd();
c_edges++;
} else {
c_rejected++;
}
#endif
}
}
#ifdef _STENCIL_REVERSE
//Carmack Reverse<tm> method requires that volumes
//be capped properly -rww
numTris = tess.numIndexes / 3;
for ( i = 0 ; i < numTris ; i++ )
{
if ( !facing[i] )
{
continue;
}
o1 = tess.indexes[ i*3 + 0 ];
o2 = tess.indexes[ i*3 + 1 ];
o3 = tess.indexes[ i*3 + 2 ];
#ifdef HAVE_GLES
indexes[idx++]=o1;
indexes[idx++]=o2;
indexes[idx++]=o3;
indexes[idx++]=o3 + tess.numVertexes;
indexes[idx++]=o2 + tess.numVertexes;
indexes[idx++]=o1 + tess.numVertexes;
#else
qglBegin(GL_TRIANGLES);
qglVertex3fv(tess.xyz[o1]);
qglVertex3fv(tess.xyz[o2]);
qglVertex3fv(tess.xyz[o3]);
qglEnd();
qglBegin(GL_TRIANGLES);
qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
qglEnd();
#endif
}
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#endif
#endif
}
//#define _DEBUG_STENCIL_SHADOWS
/*
=================
RB_ShadowTessEnd
triangleFromEdge[ v1 ][ v2 ]
set triangle from edge( v1, v2, tri )
if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
}
=================
*/
void RB_DoShadowTessEnd( vec3_t lightPos );
void RB_ShadowTessEnd( void )
{
#if 0
if (backEnd.currentEntity &&
(backEnd.currentEntity->directedLight[0] ||
backEnd.currentEntity->directedLight[1] ||
backEnd.currentEntity->directedLight[2]))
{ //an ent that has its light set for it
RB_DoShadowTessEnd(NULL);
return;
}
// if (!tess.dlightBits)
// {
// return;
// }
int i = 0;
dlight_t *dl;
R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.ori );
/* while (i < tr.refdef.num_dlights)
{
if (tess.dlightBits & (1 << i))
{
dl = &tr.refdef.dlights[i];
RB_DoShadowTessEnd(dl->transformed);
}
i++;
}
*/
dl = &tr.refdef.dlights[0];
RB_DoShadowTessEnd(dl->transformed);
#else //old ents-only way
RB_DoShadowTessEnd(NULL);
#endif
}
void RB_DoShadowTessEnd( vec3_t lightPos )
{
int i;
int numTris;
vec3_t lightDir;
// we can only do this if we have enough space in the vertex buffers
if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
return;
}
if ( glConfig.stencilBits < 4 ) {
return;
}
#if 1 //controlled method - try to keep shadows in range so they don't show through so much -rww
vec3_t worldxyz;
vec3_t entLight;
float groundDist;
VectorCopy( backEnd.currentEntity->lightDir, entLight );
entLight[2] = 0.0f;
VectorNormalize(entLight);
//Oh well, just cast them straight down no matter what onto the ground plane.
//This presets no chance of screwups and still looks better than a stupid
//shader blob.
VectorSet(lightDir, entLight[0]*0.3f, entLight[1]*0.3f, 1.0f);
// project vertexes away from light direction
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
//add or.origin to vert xyz to end up with world oriented coord, then figure
//out the ground pos for the vert to project the shadow volume to
VectorAdd(tess.xyz[i], backEnd.ori.origin, worldxyz);
groundDist = worldxyz[2] - backEnd.currentEntity->e.shadowPlane;
groundDist += 16.0f; //fudge factor
VectorMA( tess.xyz[i], -groundDist, lightDir, tess.xyz[i+tess.numVertexes] );
}
#else
if (lightPos)
{
for ( i = 0 ; i < tess.numVertexes ; i++ )
{
tess.xyz[i+tess.numVertexes][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f);
tess.xyz[i+tess.numVertexes][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f);
tess.xyz[i+tess.numVertexes][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f);
}
}
else
{
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
// project vertexes away from light direction
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] );
}
}
#endif
// decide which triangles face the light
memset( numEdgeDefs, 0, 4 * tess.numVertexes );
numTris = tess.numIndexes / 3;
for ( i = 0 ; i < numTris ; i++ ) {
int i1, i2, i3;
vec3_t d1, d2, normal;
float *v1, *v2, *v3;
float d;
i1 = tess.indexes[ i*3 + 0 ];
i2 = tess.indexes[ i*3 + 1 ];
i3 = tess.indexes[ i*3 + 2 ];
v1 = tess.xyz[ i1 ];
v2 = tess.xyz[ i2 ];
v3 = tess.xyz[ i3 ];
if (!lightPos)
{
VectorSubtract( v2, v1, d1 );
VectorSubtract( v3, v1, d2 );
CrossProduct( d1, d2, normal );
d = DotProduct( normal, lightDir );
}
else
{
float planeEq[4];
planeEq[0] = v1[1]*(v2[2]-v3[2]) + v2[1]*(v3[2]-v1[2]) + v3[1]*(v1[2]-v2[2]);
planeEq[1] = v1[2]*(v2[0]-v3[0]) + v2[2]*(v3[0]-v1[0]) + v3[2]*(v1[0]-v2[0]);
planeEq[2] = v1[0]*(v2[1]-v3[1]) + v2[0]*(v3[1]-v1[1]) + v3[0]*(v1[1]-v2[1]);
planeEq[3] = -( v1[0]*( v2[1]*v3[2] - v3[1]*v2[2] ) +
v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) +
v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) );
d = planeEq[0]*lightPos[0]+
planeEq[1]*lightPos[1]+
planeEq[2]*lightPos[2]+
planeEq[3];
}
if ( d > 0 ) {
facing[ i ] = 1;
} else {
facing[ i ] = 0;
}
// create the edges
R_AddEdgeDef( i1, i2, facing[ i ] );
R_AddEdgeDef( i2, i3, facing[ i ] );
R_AddEdgeDef( i3, i1, facing[ i ] );
}
GL_Bind( tr.whiteImage );
//qglEnable( GL_CULL_FACE );
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
#ifndef _DEBUG_STENCIL_SHADOWS
qglColor3f( 0.2f, 0.2f, 0.2f );
// don't write to the color buffer
qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
qglEnable( GL_STENCIL_TEST );
qglStencilFunc( GL_ALWAYS, 1, 255 );
#else
qglColor3f( 1.0f, 0.0f, 0.0f );
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//qglDisable(GL_DEPTH_TEST);
#endif
#ifdef HAVE_GLES
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
qglVertexPointer (3, GL_FLOAT, 16, tess.xyz);
#endif
#ifdef _STENCIL_REVERSE
qglDepthFunc(GL_LESS);
//now using the Carmack Reverse<tm> -rww
if ( backEnd.viewParms.isMirror ) {
//qglCullFace( GL_BACK );
GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
R_RenderShadowEdges();
//qglCullFace( GL_FRONT );
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
} else {
//qglCullFace( GL_FRONT );
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
R_RenderShadowEdges();
//qglCullFace( GL_BACK );
GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
}
qglDepthFunc(GL_LEQUAL);
#else
// mirrors have the culling order reversed
if ( backEnd.viewParms.isMirror ) {
qglCullFace( GL_FRONT );
qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
R_RenderShadowEdges();
qglCullFace( GL_BACK );
qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
} else {
qglCullFace( GL_BACK );
qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
R_RenderShadowEdges();
qglCullFace( GL_FRONT );
qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
}
#endif
// reenable writing to the color buffer
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
#ifdef HAVE_GLES
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
#endif
#ifdef _DEBUG_STENCIL_SHADOWS
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
}
/*
=================
RB_ShadowFinish
Darken everything that is is a shadow volume.
We have to delay this until everything has been shadowed,
because otherwise shadows from different body parts would
overlap and double darken.
=================
*/
void RB_ShadowFinish( void ) {
if ( r_shadows->integer != 2 ) {
return;
}
if ( glConfig.stencilBits < 4 ) {
return;
}
#ifdef _DEBUG_STENCIL_SHADOWS
return;
#endif
qglEnable( GL_STENCIL_TEST );
qglStencilFunc( GL_NOTEQUAL, 0, 255 );
qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
bool planeZeroBack = false;
if (qglIsEnabled(GL_CLIP_PLANE0))
{
planeZeroBack = true;
qglDisable (GL_CLIP_PLANE0);
}
GL_Cull(CT_TWO_SIDED);
//qglDisable (GL_CULL_FACE);
GL_Bind( tr.whiteImage );
qglPushMatrix();
qglLoadIdentity ();
// qglColor3f( 0.6f, 0.6f, 0.6f );
// GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
// qglColor3f( 1, 0, 0 );
// GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f );
//GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
#ifdef HAVE_GLES
GLfloat vtx[] = {
-100, 100, -10,
100, 100, -10,
100, -100, -10,
-100, -100, -10
};
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
qglVertexPointer ( 3, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
#else
qglBegin( GL_QUADS );
qglVertex3f( -100, 100, -10 );
qglVertex3f( 100, 100, -10 );
qglVertex3f( 100, -100, -10 );
qglVertex3f( -100, -100, -10 );
qglEnd ();
#endif
qglColor4f(1,1,1,1);
qglDisable( GL_STENCIL_TEST );
if (planeZeroBack)
{
qglEnable (GL_CLIP_PLANE0);
}
qglPopMatrix();
}
/*
=================
RB_ProjectionShadowDeform
=================
*/
void RB_ProjectionShadowDeform( void ) {
float *xyz;
int i;
float h;
vec3_t ground;
vec3_t light;
float groundDist;
float d;
vec3_t lightDir;
xyz = ( float * ) tess.xyz;
ground[0] = backEnd.ori.axis[0][2];
ground[1] = backEnd.ori.axis[1][2];
ground[2] = backEnd.ori.axis[2][2];
groundDist = backEnd.ori.origin[2] - backEnd.currentEntity->e.shadowPlane;
VectorCopy( backEnd.currentEntity->lightDir, lightDir );
d = DotProduct( lightDir, ground );
// don't let the shadows get too long or go negative
if ( d < 0.5 ) {
VectorMA( lightDir, (0.5 - d), ground, lightDir );
d = DotProduct( lightDir, ground );
}
d = 1.0 / d;
light[0] = lightDir[0] * d;
light[1] = lightDir[1] * d;
light[2] = lightDir[2] * d;
for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
h = DotProduct( xyz, ground ) + groundDist;
xyz[0] -= light[0] * h;
xyz[1] -= light[1] * h;
xyz[2] -= light[2] * h;
}
}
//update tr.screenImage
void RB_CaptureScreenImage(void)
{
int radX = 2048;
int radY = 2048;
int x = glConfig.vidWidth/2;
int y = glConfig.vidHeight/2;
int cX, cY;
GL_Bind( tr.screenImage );
//using this method, we could pixel-filter the texture and all sorts of crazy stuff.
//but, it is slow as hell.
/*
static byte *tmp = NULL;
if (!tmp)
{
tmp = (byte *)R_Malloc((sizeof(byte)*4)*(glConfig.vidWidth*glConfig.vidHeight), TAG_ICARUS, qtrue);
}
qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmp);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp);
*/
if (radX > glConfig.maxTextureSize)
{
radX = glConfig.maxTextureSize;
}
if (radY > glConfig.maxTextureSize)
{
radY = glConfig.maxTextureSize;
}
while (glConfig.vidWidth < radX)
{
radX /= 2;
}
while (glConfig.vidHeight < radY)
{
radY /= 2;
}
cX = x-(radX/2);
cY = y-(radY/2);
if (cX+radX > glConfig.vidWidth)
{ //would it go off screen?
cX = glConfig.vidWidth-radX;
}
else if (cX < 0)
{ //cap it off at 0
cX = 0;
}
if (cY+radY > glConfig.vidHeight)
{ //would it go off screen?
cY = glConfig.vidHeight-radY;
}
else if (cY < 0)
{ //cap it off at 0
cY = 0;
}
#ifdef HAVE_GLES
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cX, cY, radX, radY, 0);
#else
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, cX, cY, radX, radY, 0);
#endif
}
//yeah.. not really shadow-related.. but it's stencil-related. -rww
float tr_distortionAlpha = 1.0f; //opaque
float tr_distortionStretch = 0.0f; //no stretch override
qboolean tr_distortionPrePost = qfalse; //capture before postrender phase?
qboolean tr_distortionNegate = qfalse; //negative blend mode
void RB_DistortionFill(void)
{
float alpha = tr_distortionAlpha;
float spost = 0.0f;
float spost2 = 0.0f;
if ( glConfig.stencilBits < 4 )
{
return;
}
//ok, cap the stupid thing now I guess
if (!tr_distortionPrePost)
{
RB_CaptureScreenImage();
}
qglEnable(GL_STENCIL_TEST);
qglStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglDisable (GL_CLIP_PLANE0);
GL_Cull( CT_TWO_SIDED );
//reset the view matrices and go into ortho mode
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglLoadIdentity();
qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1);
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
qglLoadIdentity();
if (tr_distortionStretch)
{ //override
spost = tr_distortionStretch;
spost2 = tr_distortionStretch;
}
else
{ //do slow stretchy effect
spost = sin(tr.refdef.time*0.0005f);
if (spost < 0.0f)
{
spost = -spost;
}
spost *= 0.2f;
spost2 = sin(tr.refdef.time*0.0005f);
if (spost2 < 0.0f)
{
spost2 = -spost2;
}
spost2 *= 0.08f;
}
if (alpha != 1.0f)
{ //blend
GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
}
else
{ //be sure to reset the draw state
GL_State(0);
}
#ifdef HAVE_GLES
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
GLfloat tex[] = {
0+spost2, 1-spost,
0+spost2, 0+spost,
1-spost2, 0+spost,
1-spost2, 1-spost
};
GLfloat vtx[] = {
0, 0,
0, glConfig.vidHeight,
glConfig.vidWidth, glConfig.vidHeight,
glConfig.vidWidth, 0
};
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
/* if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );*/
#else
qglBegin(GL_QUADS);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglEnd();
#endif
if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f)
{ //no overrides
if (tr_distortionNegate)
{ //probably the crazy alternate saber trail
alpha = 0.8f;
GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
}
else
{
alpha = 0.5f;
GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA);
}
spost = sin(tr.refdef.time*0.0008f);
if (spost < 0.0f)
{
spost = -spost;
}
spost *= 0.08f;
spost2 = sin(tr.refdef.time*0.0008f);
if (spost2 < 0.0f)
{
spost2 = -spost2;
}
spost2 *= 0.2f;
#ifdef HAVE_GLES
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
/* GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );*/
GLfloat tex[] = {
0+spost2, 1-spost,
0+spost2, 0+spost,
1-spost2, 0+spost,
1-spost2, 1-spost
};
GLfloat vtx[] = {
0, 0,
0, glConfig.vidHeight,
glConfig.vidWidth, glConfig.vidHeight,
glConfig.vidWidth, 0
};
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
#else
qglBegin(GL_QUADS);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglEnd();
#endif
}
#ifdef HAVE_GLES
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
//pop the view matrices back
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
qglDisable( GL_STENCIL_TEST );
}

View file

@ -0,0 +1,485 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "tr_local.h"
#include <map>
#include "../qcommon/sstring.h"
/*
============================================================================
SKINS
============================================================================
*/
/*
==================
CommaParse
This is unfortunate, but the skin files aren't
compatible with our normal parsing rules.
==================
*/
static char *CommaParse( char **data_p ) {
int c = 0, len;
char *data;
static char com_token[MAX_TOKEN_CHARS];
data = *data_p;
len = 0;
com_token[0] = 0;
// make sure incoming data is valid
if ( !data ) {
*data_p = NULL;
return com_token;
}
while ( 1 ) {
// skip whitespace
while( (c = *(const unsigned char* /*eurofix*/)data) <= ' ') {
if( !c ) {
break;
}
data++;
}
c = *data;
// skip double slash comments
if ( c == '/' && data[1] == '/' )
{
while (*data && *data != '\n')
data++;
}
// skip /* */ comments
else if ( c=='/' && data[1] == '*' )
{
while ( *data && ( *data != '*' || data[1] != '/' ) )
{
data++;
}
if ( *data )
{
data += 2;
}
}
else
{
break;
}
}
if ( c == 0 ) {
return "";
}
// handle quoted strings
if (c == '\"')
{
data++;
while (1)
{
c = *data++;
if (c=='\"' || !c)
{
com_token[len] = 0;
*data_p = ( char * ) data;
return com_token;
}
if (len < MAX_TOKEN_CHARS - 1)
{
com_token[len] = c;
len++;
}
}
}
// parse a regular word
do
{
if (len < MAX_TOKEN_CHARS - 1)
{
com_token[len] = c;
len++;
}
data++;
c = *data;
} while (c>32 && c != ',' );
com_token[len] = 0;
*data_p = ( char * ) data;
return com_token;
}
/*
class CStringComparator
{
public:
bool operator()(const char *s1, const char *s2) const { return(stricmp(s1, s2) < 0); }
};
*/
typedef std::map<sstring_t,char * /*, CStringComparator*/ > AnimationCFGs_t;
AnimationCFGs_t AnimationCFGs;
// I added this function for development purposes (and it's VM-safe) so we don't have problems
// with our use of cached models but uncached animation.cfg files (so frame sequences are out of sync
// if someone rebuild the model while you're ingame and you change levels)...
//
// Usage: call with psDest == NULL for a size enquire (for malloc),
// then with NZ ptr for it to copy to your supplied buffer...
//
int RE_GetAnimationCFG(const char *psCFGFilename, char *psDest, int iDestSize)
{
char *psText = NULL;
AnimationCFGs_t::iterator it = AnimationCFGs.find(psCFGFilename);
if (it != AnimationCFGs.end())
{
psText = (*it).second;
}
else
{
// not found, so load it...
//
fileHandle_t f;
int iLen = ri.FS_FOpenFileRead( psCFGFilename, &f, qfalse );
if (iLen <= 0)
{
return 0;
}
psText = (char *) R_Malloc( iLen+1, TAG_ANIMATION_CFG, qfalse );
ri.FS_Read( psText, iLen, f );
psText[iLen] = '\0';
ri.FS_FCloseFile( f );
AnimationCFGs[psCFGFilename] = psText;
}
if (psText) // sanity, but should always be NZ
{
if (psDest)
{
Q_strncpyz(psDest,psText,iDestSize);
}
return strlen(psText);
}
return 0;
}
// only called from devmapbsp, devmapall, or ...
//
void RE_AnimationCFGs_DeleteAll(void)
{
for (AnimationCFGs_t::iterator it = AnimationCFGs.begin(); it != AnimationCFGs.end(); ++it)
{
char *psText = (*it).second;
R_Free(psText);
}
AnimationCFGs.clear();
}
/*
===============
RE_SplitSkins
input = skinname, possibly being a macro for three skins
return= true if three part skins found
output= qualified names to three skins if return is true, undefined if false
===============
*/
bool RE_SplitSkins(const char *INname, char *skinhead, char *skintorso, char *skinlower)
{ //INname= "models/players/jedi_tf/|head01_skin1|torso01|lower01";
if (strchr(INname, '|'))
{
char name[MAX_QPATH];
strcpy(name, INname);
char *p = strchr(name, '|');
*p=0;
p++;
//fill in the base path
strcpy (skinhead, name);
strcpy (skintorso, name);
strcpy (skinlower, name);
//now get the the individual files
//advance to second
char *p2 = strchr(p, '|');
if (!p2)
{
return false;
}
*p2=0;
p2++;
strcat (skinhead, p);
strcat (skinhead, ".skin");
//advance to third
p = strchr(p2, '|');
if (!p)
{
return false;
}
*p=0;
p++;
strcat (skintorso,p2);
strcat (skintorso, ".skin");
strcat (skinlower,p);
strcat (skinlower, ".skin");
return true;
}
return false;
}
// given a name, go get the skin we want and return
qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin)
{
skin_t *skin;
skinSurface_t *surf;
char *text, *text_p;
char *token;
char surfName[MAX_QPATH];
// load and parse the skin file
ri.FS_ReadFile( name, (void **)&text );
if ( !text ) {
ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) failed to load!\n", name );
return 0;
}
assert (tr.skins[hSkin]); //should already be setup, but might be an 3part append
skin = tr.skins[hSkin];
text_p = text;
while ( text_p && *text_p ) {
// get surface name
token = CommaParse( &text_p );
Q_strncpyz( surfName, token, sizeof( surfName ) );
if ( !token[0] ) {
break;
}
// lowercase the surface name so skin compares are faster
Q_strlwr( surfName );
if ( *text_p == ',' ) {
text_p++;
}
if ( !strncmp( token, "tag_", 4 ) ) { //these aren't in there, but just in case you load an id style one...
continue;
}
// parse the shader name
token = CommaParse( &text_p );
#ifndef JK2_MODE
if ( !strcmp( &surfName[strlen(surfName)-4], "_off") )
{
if ( !strcmp( token ,"*off" ) )
{
continue; //don't need these double offs
}
surfName[strlen(surfName)-4] = 0; //remove the "_off"
}
#endif
if ( (unsigned)skin->numSurfaces >= ARRAY_LEN( skin->surfaces ) )
{
assert( ARRAY_LEN( skin->surfaces ) > (unsigned)skin->numSurfaces );
ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) more than %u surfaces!\n", name, (unsigned int)ARRAY_LEN(skin->surfaces) );
break;
}
surf = skin->surfaces[ skin->numSurfaces ] = (skinSurface_t *) R_Hunk_Alloc( sizeof( *skin->surfaces[0] ), qtrue );
Q_strncpyz( surf->name, surfName, sizeof( surf->name ) );
surf->shader = R_FindShader( token, lightmapsNone, stylesDefault, qtrue );
skin->numSurfaces++;
}
ri.FS_FreeFile( text );
// never let a skin have 0 shaders
if ( skin->numSurfaces == 0 ) {
return 0; // use default skin
}
return hSkin;
}
/*
===============
RE_RegisterSkin
===============
*/
qhandle_t RE_RegisterSkin( const char *name) {
qhandle_t hSkin;
skin_t *skin;
// if (!cls.cgameStarted && !cls.uiStarted)
// {
//rww - added uiStarted exception because we want ghoul2 models in the menus.
// gwg well we need our skins to set surfaces on and off, so we gotta get em
//return 1; // cope with Ghoul2's calling-the-renderer-before-its-even-started hackery, must be any NZ amount here to trigger configstring setting
// }
if (!tr.numSkins)
{
R_InitSkins(); //make sure we have numSkins set to at least one.
}
if ( !name || !name[0] ) {
Com_Printf( "Empty name passed to RE_RegisterSkin\n" );
return 0;
}
if ( strlen( name ) >= MAX_QPATH ) {
Com_Printf( "Skin name exceeds MAX_QPATH\n" );
return 0;
}
// see if the skin is already loaded
for ( hSkin = 1; hSkin < tr.numSkins ; hSkin++ ) {
skin = tr.skins[hSkin];
if ( !Q_stricmp( skin->name, name ) ) {
if( skin->numSurfaces == 0 ) {
return 0; // default skin
}
return hSkin;
}
}
if ( tr.numSkins == MAX_SKINS ) {
ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name );
return 0;
}
// allocate a new skin
tr.numSkins++;
skin = (skin_t*) R_Hunk_Alloc( sizeof( skin_t ), qtrue );
tr.skins[hSkin] = skin;
Q_strncpyz( skin->name, name, sizeof( skin->name ) ); //always make one so it won't search for it again
// If not a .skin file, load as a single shader - then return
if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) {
#ifdef JK2_MODE
skin->numSurfaces = 1;
skin->surfaces[0] = (skinSurface_t *) R_Hunk_Alloc( sizeof(skin->surfaces[0]), qtrue );
skin->surfaces[0]->shader = R_FindShader( name, lightmapsNone, stylesDefault, qtrue );
return hSkin;
#endif
/* skin->numSurfaces = 1;
skin->surfaces[0] = (skinSurface_t *) R_Hunk_Alloc( sizeof(skin->surfaces[0]), qtrue );
skin->surfaces[0]->shader = R_FindShader( name, lightmapsNone, stylesDefault, qtrue );
return hSkin;
*/
}
char skinhead[MAX_QPATH]={0};
char skintorso[MAX_QPATH]={0};
char skinlower[MAX_QPATH]={0};
if ( RE_SplitSkins(name, (char*)&skinhead, (char*)&skintorso, (char*)&skinlower ) )
{//three part
hSkin = RE_RegisterIndividualSkin(skinhead, hSkin);
if (hSkin && strcmp(skinhead, skintorso))
{
hSkin = RE_RegisterIndividualSkin(skintorso, hSkin);
}
if (hSkin && strcmp(skinhead, skinlower) && strcmp(skintorso, skinlower))
{
hSkin = RE_RegisterIndividualSkin(skinlower, hSkin);
}
}
else
{//single skin
hSkin = RE_RegisterIndividualSkin(name, hSkin);
}
return(hSkin);
}
/*
===============
R_InitSkins
===============
*/
void R_InitSkins( void ) {
skin_t *skin;
tr.numSkins = 1;
// make the default skin have all default shaders
skin = tr.skins[0] = (skin_t*) R_Hunk_Alloc( sizeof( skin_t ), qtrue );
Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name ) );
skin->numSurfaces = 1;
skin->surfaces[0] = (skinSurface_t *) R_Hunk_Alloc( sizeof( *skin->surfaces[0] ), qtrue );
skin->surfaces[0]->shader = tr.defaultShader;
}
/*
===============
R_GetSkinByHandle
===============
*/
skin_t *R_GetSkinByHandle( qhandle_t hSkin ) {
if ( hSkin < 1 || hSkin >= tr.numSkins ) {
return tr.skins[0];
}
return tr.skins[ hSkin ];
}
/*
===============
R_SkinList_f
===============
*/
void R_SkinList_f (void) {
int i, j;
skin_t *skin;
ri.Printf (PRINT_ALL, "------------------\n");
for ( i = 0 ; i < tr.numSkins ; i++ ) {
skin = tr.skins[i];
ri.Printf( PRINT_ALL, "%3i:%s\n", i, skin->name );
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
ri.Printf( PRINT_ALL, " %s = %s\n",
skin->surfaces[j]->name, skin->surfaces[j]->shader->name );
}
}
ri.Printf (PRINT_ALL, "------------------\n");
}

View file

@ -0,0 +1,892 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// tr_sky.c
#include "../server/exe_headers.h"
#include "tr_local.h"
#define SKY_SUBDIVISIONS 8
#define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2)
static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
/*
===================================================================================
POLYGON TO BOX SIDE PROJECTION
===================================================================================
*/
static vec3_t sky_clip[6] =
{
{1,1,0},
{1,-1,0},
{0,-1,1},
{0,1,1},
{1,0,1},
{-1,0,1}
};
static float sky_mins[2][6], sky_maxs[2][6];
static float sky_min, sky_max;
/*
================
AddSkyPolygon
================
*/
static void AddSkyPolygon (int nump, vec3_t vecs)
{
int i,j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
// s = [0]/[2], t = [1]/[2]
static int vec_to_st[6][3] =
{
{-2,3,1},
{2,3,-1},
{1,3,2},
{-1,3,-2},
{-2,-1,3},
{-2,1,-3}
// {-1,2,3},
// {1,2,-3}
};
// decide which face it maps to
VectorCopy (vec3_origin, v);
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
{
VectorAdd (vp, v, v);
}
av[0] = fabs(v[0]);
av[1] = fabs(v[1]);
av[2] = fabs(v[2]);
if (av[0] > av[1] && av[0] > av[2])
{
if (v[0] < 0)
axis = 1;
else
axis = 0;
}
else if (av[1] > av[2] && av[1] > av[0])
{
if (v[1] < 0)
axis = 3;
else
axis = 2;
}
else
{
if (v[2] < 0)
axis = 5;
else
axis = 4;
}
// project new texture coords
for (i=0 ; i<nump ; i++, vecs+=3)
{
j = vec_to_st[axis][2];
if (j > 0)
dv = vecs[j - 1];
else
dv = -vecs[-j - 1];
if (dv < 0.001)
continue; // don't divide by zero
j = vec_to_st[axis][0];
if (j < 0)
s = -vecs[-j -1] / dv;
else
s = vecs[j-1] / dv;
j = vec_to_st[axis][1];
if (j < 0)
t = -vecs[-j -1] / dv;
else
t = vecs[j-1] / dv;
if (s < sky_mins[0][axis])
sky_mins[0][axis] = s;
if (t < sky_mins[1][axis])
sky_mins[1][axis] = t;
if (s > sky_maxs[0][axis])
sky_maxs[0][axis] = s;
if (t > sky_maxs[1][axis])
sky_maxs[1][axis] = t;
}
}
#define ON_EPSILON 0.1f // point on plane side epsilon
#define MAX_CLIP_VERTS 64
/*
================
ClipSkyPolygon
================
*/
static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS];
int sides[MAX_CLIP_VERTS];
vec3_t newv[2][MAX_CLIP_VERTS];
int newc[2];
int i, j;
if (nump > MAX_CLIP_VERTS-2)
Com_Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
if (stage == 6)
{ // fully clipped, so draw it
AddSkyPolygon (nump, vecs);
return;
}
front = back = qfalse;
norm = sky_clip[stage];
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
d = DotProduct (v, norm);
if (d > ON_EPSILON)
{
front = qtrue;
sides[i] = SIDE_FRONT;
}
else if (d < -ON_EPSILON)
{
back = qtrue;
sides[i] = SIDE_BACK;
}
else
sides[i] = SIDE_ON;
dists[i] = d;
}
if (!front || !back)
{ // not clipped
ClipSkyPolygon (nump, vecs, stage+1);
return;
}
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy (vecs, (vecs+(i*3)) );
newc[0] = newc[1] = 0;
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
switch (sides[i])
{
case SIDE_FRONT:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
break;
case SIDE_BACK:
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
case SIDE_ON:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
}
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
d = dists[i] / (dists[i] - dists[i+1]);
for (j=0 ; j<3 ; j++)
{
e = v[j] + d*(v[j+3] - v[j]);
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
// continue
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
/*
==============
ClearSkyBox
==============
*/
static void ClearSkyBox (void) {
int i;
for (i=0 ; i<6 ; i++) {
sky_mins[0][i] = sky_mins[1][i] = MAX_WORLD_COORD; //9999;
sky_maxs[0][i] = sky_maxs[1][i] = MIN_WORLD_COORD; //-9999;
}
}
/*
================
RB_ClipSkyPolygons
================
*/
void RB_ClipSkyPolygons( shaderCommands_t *input )
{
vec3_t p[5]; // need one extra point for clipping
int i, j;
ClearSkyBox();
for ( i = 0; i < input->numIndexes; i += 3 )
{
for (j = 0 ; j < 3 ; j++)
{
VectorSubtract( input->xyz[input->indexes[i+j]],
backEnd.viewParms.ori.origin,
p[j] );
}
ClipSkyPolygon( 3, p[0], 0 );
}
}
/*
===================================================================================
CLOUD VERTEX GENERATION
===================================================================================
*/
/*
** MakeSkyVec
**
** Parms: s, t range from -1 to 1
*/
static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ )
{
// 1 = s, 2 = t, 3 = 2048
static int st_to_vec[6][3] =
{
{3,-1,2},
{-3,1,2},
{1,3,2},
{-1,-3,2},
{-2,-1,3}, // 0 degrees yaw, look straight up
{2,-1,-3} // look straight down
};
vec3_t b;
int j, k;
float boxSize;
boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
b[0] = s*boxSize;
b[1] = t*boxSize;
b[2] = boxSize;
for (j=0 ; j<3 ; j++)
{
k = st_to_vec[axis][j];
if (k < 0)
{
outXYZ[j] = -b[-k - 1];
}
else
{
outXYZ[j] = b[k - 1];
}
}
// avoid bilerp seam
s = (s+1)*0.5;
t = (t+1)*0.5;
if (s < sky_min)
{
s = sky_min;
}
else if (s > sky_max)
{
s = sky_max;
}
if (t < sky_min)
{
t = sky_min;
}
else if (t > sky_max)
{
t = sky_max;
}
t = 1.0 - t;
if ( outSt )
{
outSt[0] = s;
outSt[1] = t;
}
}
static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
{
int s, t;
GL_Bind( image );
#ifdef HAVE_GLES
GLfloat vtx[3*1024]; // arbitrary sized
GLfloat tex[2*1024];
int idx;
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
#ifdef HAVE_GLES
idx=0;
#else
qglBegin( GL_TRIANGLE_STRIP );
#endif
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
#ifdef HAVE_GLES
memcpy(tex+idx*2, s_skyTexCoords[t][s], sizeof(GLfloat)*2);
memcpy(vtx+idx*3, s_skyPoints[t][s], sizeof(GLfloat)*3);
idx++;
memcpy(tex+idx*2, s_skyTexCoords[t+1][s], sizeof(GLfloat)*2);
memcpy(vtx+idx*3, s_skyPoints[t+1][s], sizeof(GLfloat)*3);
idx++;
#else
qglTexCoord2fv( s_skyTexCoords[t][s] );
qglVertex3fv( s_skyPoints[t][s] );
qglTexCoord2fv( s_skyTexCoords[t+1][s] );
qglVertex3fv( s_skyPoints[t+1][s] );
#endif
}
#ifdef HAVE_GLES
qglVertexPointer (3, GL_FLOAT, 0, vtx);
qglTexCoordPointer(2, GL_FLOAT, 0, tex);
qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx);
#else
qglEnd();
#endif
}
#ifdef HAVE_GLES
if (glcol)
qglEnableClientState(GL_COLOR_ARRAY);
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
}
static void DrawSkyBox( jk_shader_t *shader )
{
int i;
sky_min = 0.0f;
sky_max = 1.0f;
memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
for (i=0 ; i<6 ; i++)
{
int sky_mins_subd[2], sky_maxs_subd[2];
int s, t;
sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
( sky_mins[1][i] >= sky_maxs[1][i] ) )
{
continue;
}
sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS;
sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS;
sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS;
sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS;
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS )
sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
//
// iterate through the subdivisions
//
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
i,
s_skyTexCoords[t][s],
s_skyPoints[t][s] );
}
}
DrawSkySide( shader->sky->outerbox[i],
sky_mins_subd,
sky_maxs_subd );
}
}
static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
{
int s, t;
int vertexStart = tess.numVertexes;
int tHeight, sWidth;
tHeight = maxs[1] - mins[1] + 1;
sWidth = maxs[0] - mins[0] + 1;
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
VectorAdd( s_skyPoints[t][s], backEnd.viewParms.ori.origin, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
tess.numVertexes++;
if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
{
Com_Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()\n" );
}
}
}
// only add indexes for one pass, otherwise it would draw multiple times for each pass
if ( addIndexes ) {
for ( t = 0; t < tHeight-1; t++ )
{
for ( s = 0; s < sWidth-1; s++ )
{
tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth );
tess.numIndexes++;
tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
tess.numIndexes++;
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
tess.numIndexes++;
tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
tess.numIndexes++;
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth );
tess.numIndexes++;
tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
tess.numIndexes++;
}
}
}
}
static void FillCloudBox( const jk_shader_t *shader, int stage )
{
int i;
for ( i =0; i < 6; i++ )
{
int sky_mins_subd[2], sky_maxs_subd[2];
int s, t;
float MIN_T;
if ( 1 ) // FIXME? shader->sky->fullClouds )
{
MIN_T = -HALF_SKY_SUBDIVISIONS;
// still don't want to draw the bottom, even if fullClouds
if ( i == 5 )
continue;
}
else
{
switch( i )
{
case 0:
case 1:
case 2:
case 3:
MIN_T = -1;
break;
case 5:
// don't draw clouds beneath you
continue;
case 4: // top
default:
MIN_T = -HALF_SKY_SUBDIVISIONS;
break;
}
}
sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
( sky_mins[1][i] >= sky_maxs[1][i] ) )
{
continue;
}
sky_mins_subd[0] = Q_ftol( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS );
sky_mins_subd[1] = Q_ftol( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS );
sky_maxs_subd[0] = Q_ftol( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS );
sky_maxs_subd[1] = Q_ftol( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS );
if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
if ( sky_mins_subd[1] < MIN_T )
sky_mins_subd[1] = MIN_T;
else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
if ( sky_maxs_subd[1] < MIN_T )
sky_maxs_subd[1] = MIN_T;
else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
//
// iterate through the subdivisions
//
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
i,
NULL,
s_skyPoints[t][s] );
s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
}
}
// only add indexes for first stage
FillCloudySkySide( sky_mins_subd, sky_maxs_subd, (qboolean)( stage == 0 ) );
}
}
/*
** R_BuildCloudData
*/
void R_BuildCloudData( shaderCommands_t *input )
{
int i;
assert( input->shader->sky );
sky_min = 1.0 / 256.0f; // FIXME: not correct?
sky_max = 255.0 / 256.0f;
// set up for drawing
tess.numIndexes = 0;
tess.numVertexes = 0;
if ( input->shader->sky->cloudHeight )
{
for ( i = 0; i < input->shader->numUnfoggedPasses; i++ )
{
FillCloudBox( input->shader, i );
}
}
}
/*
** R_InitSkyTexCoords
** Called when a sky shader is parsed
*/
#define SQR( a ) ((a)*(a))
void R_InitSkyTexCoords( float heightCloud )
{
int i, s, t;
float radiusWorld = MAX_WORLD_COORD;
float p;
float sRad, tRad;
vec3_t skyVec;
vec3_t v;
// init zfar so MakeSkyVec works even though
// a world hasn't been bounded
backEnd.viewParms.zFar = 1024;
for ( i = 0; i < 6; i++ )
{
for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
{
for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
{
// compute vector from view origin to sky side integral point
MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
i,
NULL,
skyVec );
// compute parametric value 'p' that intersects with cloud layer
p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) *
( -2 * skyVec[2] * radiusWorld +
2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) +
2 * SQR( skyVec[0] ) * radiusWorld * heightCloud +
SQR( skyVec[0] ) * SQR( heightCloud ) +
2 * SQR( skyVec[1] ) * radiusWorld * heightCloud +
SQR( skyVec[1] ) * SQR( heightCloud ) +
2 * SQR( skyVec[2] ) * radiusWorld * heightCloud +
SQR( skyVec[2] ) * SQR( heightCloud ) ) );
s_cloudTexP[i][t][s] = p;
// compute intersection point based on p
VectorScale( skyVec, p, v );
v[2] += radiusWorld;
// compute vector from world origin to intersection point 'v'
VectorNormalize( v );
sRad = acos( v[0] );
tRad = acos( v[1] );
s_cloudTexCoords[i][t][s][0] = sRad;
s_cloudTexCoords[i][t][s][1] = tRad;
}
}
}
}
//======================================================================================
/*
** RB_DrawSun
*/
void RB_DrawSun( void ) {
float size;
float dist;
vec3_t origin, vec1, vec2;
vec3_t temp;
if ( !backEnd.skyRenderedThisView ) {
return;
}
if ( !r_drawSun->integer ) {
return;
}
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
qglTranslatef (backEnd.viewParms.ori.origin[0], backEnd.viewParms.ori.origin[1], backEnd.viewParms.ori.origin[2]);
dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
size = dist * 0.4;
VectorScale( tr.sunDirection, dist, origin );
PerpendicularVector( vec1, tr.sunDirection );
CrossProduct( tr.sunDirection, vec1, vec2 );
VectorScale( vec1, size, vec1 );
VectorScale( vec2, size, vec2 );
// farthest depth range
qglDepthRange( 1.0, 1.0 );
// FIXME: use quad stamp
RB_BeginSurface( tr.sunShader, tess.fogNum );
VectorCopy( origin, temp );
VectorSubtract( temp, vec1, temp );
VectorSubtract( temp, vec2, temp );
VectorCopy( temp, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = 0;
tess.texCoords[tess.numVertexes][0][1] = 0;
tess.vertexColors[tess.numVertexes][0] = 255;
tess.vertexColors[tess.numVertexes][1] = 255;
tess.vertexColors[tess.numVertexes][2] = 255;
tess.numVertexes++;
VectorCopy( origin, temp );
VectorAdd( temp, vec1, temp );
VectorSubtract( temp, vec2, temp );
VectorCopy( temp, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = 0;
tess.texCoords[tess.numVertexes][0][1] = 1;
tess.vertexColors[tess.numVertexes][0] = 255;
tess.vertexColors[tess.numVertexes][1] = 255;
tess.vertexColors[tess.numVertexes][2] = 255;
tess.numVertexes++;
VectorCopy( origin, temp );
VectorAdd( temp, vec1, temp );
VectorAdd( temp, vec2, temp );
VectorCopy( temp, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = 1;
tess.texCoords[tess.numVertexes][0][1] = 1;
tess.vertexColors[tess.numVertexes][0] = 255;
tess.vertexColors[tess.numVertexes][1] = 255;
tess.vertexColors[tess.numVertexes][2] = 255;
tess.numVertexes++;
VectorCopy( origin, temp );
VectorSubtract( temp, vec1, temp );
VectorAdd( temp, vec2, temp );
VectorCopy( temp, tess.xyz[tess.numVertexes] );
tess.texCoords[tess.numVertexes][0][0] = 1;
tess.texCoords[tess.numVertexes][0][1] = 0;
tess.vertexColors[tess.numVertexes][0] = 255;
tess.vertexColors[tess.numVertexes][1] = 255;
tess.vertexColors[tess.numVertexes][2] = 255;
tess.numVertexes++;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 1;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 0;
tess.indexes[tess.numIndexes++] = 2;
tess.indexes[tess.numIndexes++] = 3;
RB_EndSurface();
// back to normal depth range
qglDepthRange( 0.0, 1.0 );
}
/*
================
RB_StageIteratorSky
All of the visible sky triangles are in tess
Other things could be stuck in here, like birds in the sky, etc
================
*/
void RB_StageIteratorSky( void ) {
if ( r_fastsky->integer ) {
return;
}
if (skyboxportal && !(backEnd.refdef.rdflags & RDF_SKYBOXPORTAL))
{
return;
}
hasskybox = 1;
// go through all the polygons and project them onto
// the sky box to see which blocks on each side need
// to be drawn
RB_ClipSkyPolygons( &tess );
// r_showsky will let all the sky blocks be drawn in
// front of everything to allow developers to see how
// much sky is getting sucked in
if ( r_showsky->integer ) {
qglDepthRange( 0.0, 0.0 );
} else {
qglDepthRange( 1.0, 1.0 );
}
// draw the outer skybox
if ( tess.shader->sky->outerbox[0] && tess.shader->sky->outerbox[0] != tr.defaultImage ) {
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
qglPushMatrix ();
GL_State( 0 );
qglTranslatef (backEnd.viewParms.ori.origin[0], backEnd.viewParms.ori.origin[1], backEnd.viewParms.ori.origin[2]);
DrawSkyBox( tess.shader );
qglPopMatrix();
}
// generate the vertexes for all the clouds, which will be drawn
// by the generic shader routine
R_BuildCloudData( &tess );
RB_StageIteratorGeneric();
// draw the inner skybox
// back to normal depth range
qglDepthRange( 0.0, 1.0 );
// note that sky was drawn so we will draw a sun later
backEnd.skyRenderedThisView = qtrue;
}

View file

@ -0,0 +1,78 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
// Filename:- tr_stl.cpp
//
// I mainly made this file because I was getting sick of all the stupid error messages in MS's STL implementation,
// and didn't want them showing up in the renderer files they were used in. This way keeps them more or less invisible
// because of minimal dependancies
//
#include "tr_local.h" // this isn't actually needed other than getting rid of warnings via pragmas
#include "tr_stl.h"
#include <map>
#include "../qcommon/sstring.h" // #include <string>
typedef std::map<sstring_t, const char *> ShaderEntryPtrs_t;
typedef ShaderEntryPtrs_t::size_type ShaderEntryPtr_size;
ShaderEntryPtrs_t ShaderEntryPtrs;
void ShaderEntryPtrs_Clear(void)
{
ShaderEntryPtrs.clear();
}
int ShaderEntryPtrs_Size(void)
{
return ShaderEntryPtrs.size();
}
void ShaderEntryPtrs_Insert(const char *token, const char *p)
{
ShaderEntryPtrs_t::iterator it = ShaderEntryPtrs.find(token);
if (it == ShaderEntryPtrs.end())
{
ShaderEntryPtrs[token] = p;
}
else
{
ri.Printf( PRINT_DEVELOPER, "Duplicate shader entry %s!\n",token );
}
}
// returns NULL if not found...
//
const char *ShaderEntryPtrs_Lookup(const char *psShaderName)
{
ShaderEntryPtrs_t::iterator it = ShaderEntryPtrs.find(psShaderName);
if (it != ShaderEntryPtrs.end())
{
const char *p = (*it).second;
return p;
}
return NULL;
}

View file

@ -0,0 +1,42 @@
/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
// Filename: tr_stl.h
//
// I had to make this new file, because if I put the STL "map" include inside tr_local.h then one of the other header
// files got compile errors because of using "map" in the function protos as a GLEnum, this way seemed simpler...
#pragma once
// REM this out if you want to compile without using STL (but slower of course)
//
#define USE_STL_FOR_SHADER_LOOKUPS
#ifdef USE_STL_FOR_SHADER_LOOKUPS
void ShaderEntryPtrs_Clear(void);
int ShaderEntryPtrs_Size(void);
const char *ShaderEntryPtrs_Lookup(const char *psShaderName);
void ShaderEntryPtrs_Insert(const char *token, const char *p);
#else
#define ShaderEntryPtrs_Clear()
#endif // #ifdef USE_STL_FOR_SHADER_LOOKUPS

View file

@ -0,0 +1,99 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2005 - 2015, ioquake3 contributors
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
// tr_subs.cpp - common function replacements for modular renderer
#include "tr_local.h"
void QDECL Com_Printf( const char *msg, ... )
{
va_list argptr;
char text[1024];
va_start(argptr, msg);
Q_vsnprintf(text, sizeof(text), msg, argptr);
va_end(argptr);
ri.Printf(PRINT_ALL, "%s", text);
}
void QDECL Com_Error( int level, const char *error, ... )
{
va_list argptr;
char text[1024];
va_start(argptr, error);
Q_vsnprintf(text, sizeof(text), error, argptr);
va_end(argptr);
ri.Error(level, "%s", text);
}
/*
================
Com_DPrintf
DLL glue
================
*/
void Com_DPrintf(const char *format, ...)
{
va_list argptr;
char text[1024];
va_start(argptr, format);
Q_vsnprintf(text, sizeof(text), format, argptr);
va_end(argptr);
ri.Printf(PRINT_DEVELOPER, "%s", text);
}
// HUNK
//int Hunk_MemoryRemaining( void ) {
// return ri.Hunk_MemoryRemaining();
//}
// ZONE
void *R_Malloc( int iSize, memtag_t eTag, qboolean bZeroit ) {
return ri.Malloc( iSize, eTag, bZeroit, 4 );
}
void R_Free( void *ptr ) {
ri.Z_Free( ptr );
}
int R_MemSize( memtag_t eTag ) {
return ri.Z_MemSize( eTag );
}
void R_MorphMallocTag( void *pvBuffer, memtag_t eDesiredTag ) {
ri.Z_MorphMallocTag( pvBuffer, eDesiredTag );
}
void *R_Hunk_Alloc( int iSize, qboolean bZeroit ) {
return ri.Malloc( iSize, TAG_HUNKALLOC, bZeroit, 4 );
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,811 @@
/*
===========================================================================
Copyright (C) 1999 - 2005, Id Software, Inc.
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
#include "../server/exe_headers.h"
#include "tr_local.h"
/*
=================
R_CullTriSurf
Returns true if the grid is completely culled away.
Also sets the clipped hint bit in tess
=================
*/
static qboolean R_CullTriSurf( srfTriangles_t *cv ) {
int boxCull;
boxCull = R_CullLocalBox( cv->bounds );
if ( boxCull == CULL_OUT ) {
return qtrue;
}
return qfalse;
}
/*
=================
R_CullGrid
Returns true if the grid is completely culled away.
Also sets the clipped hint bit in tess
=================
*/
static qboolean R_CullGrid( srfGridMesh_t *cv ) {
int boxCull;
int sphereCull;
if ( r_nocurves->integer ) {
return qtrue;
}
if ( tr.currentEntityNum != REFENTITYNUM_WORLD ) {
sphereCull = R_CullLocalPointAndRadius( cv->localOrigin, cv->meshRadius );
} else {
sphereCull = R_CullPointAndRadius( cv->localOrigin, cv->meshRadius );
}
boxCull = CULL_OUT;
// check for trivial reject
if ( sphereCull == CULL_OUT )
{
tr.pc.c_sphere_cull_patch_out++;
return qtrue;
}
// check bounding box if necessary
else if ( sphereCull == CULL_CLIP )
{
tr.pc.c_sphere_cull_patch_clip++;
boxCull = R_CullLocalBox( cv->meshBounds );
if ( boxCull == CULL_OUT )
{
tr.pc.c_box_cull_patch_out++;
return qtrue;
}
else if ( boxCull == CULL_IN )
{
tr.pc.c_box_cull_patch_in++;
}
else
{
tr.pc.c_box_cull_patch_clip++;
}
}
else
{
tr.pc.c_sphere_cull_patch_in++;
}
return qfalse;
}
/*
================
R_CullSurface
Tries to back face cull surfaces before they are lighted or
added to the sorting list.
This will also allow mirrors on both sides of a model without recursion.
================
*/
static qboolean R_CullSurface( surfaceType_t *surface, jk_shader_t *shader ) {
srfSurfaceFace_t *sface;
float d;
if ( r_nocull->integer==1 ) {
return qfalse;
}
if ( *surface == SF_GRID ) {
return R_CullGrid( (srfGridMesh_t *)surface );
}
if ( *surface == SF_TRIANGLES ) {
return R_CullTriSurf( (srfTriangles_t *)surface );
}
if ( *surface != SF_FACE ) {
return qfalse;
}
if ( shader->cullType == CT_TWO_SIDED ) {
return qfalse;
}
// face culling
if ( !r_facePlaneCull->integer ) {
return qfalse;
}
sface = ( srfSurfaceFace_t * ) surface;
d = DotProduct (tr.ori.viewOrigin, sface->plane.normal);
// 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 < sface->plane.dist - 8 ) {
return qtrue;
}
} else {
if ( d > sface->plane.dist + 8 ) {
return qtrue;
}
}
return qfalse;
}
static int R_DlightFace( srfSurfaceFace_t *face, int dlightBits ) {
float d;
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
d = DotProduct( dl->origin, face->plane.normal ) - face->plane.dist;
if ( !VectorCompare(face->plane.normal, vec3_origin) && (d < -dl->radius || d > dl->radius) ) {
// dlight doesn't reach the plane
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
face->dlightBits = dlightBits;
return dlightBits;
}
static int R_DlightGrid( srfGridMesh_t *grid, int dlightBits ) {
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
grid->dlightBits = dlightBits;
return dlightBits;
}
static int R_DlightTrisurf( srfTriangles_t *surf, int dlightBits ) {
// FIXME: more dlight culling to trisurfs...
surf->dlightBits = dlightBits;
return dlightBits;
#if 0
int i;
dlight_t *dl;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
if ( ! ( dlightBits & ( 1 << i ) ) ) {
continue;
}
dl = &tr.refdef.dlights[i];
if ( dl->origin[0] - dl->radius > grid->meshBounds[1][0]
|| dl->origin[0] + dl->radius < grid->meshBounds[0][0]
|| dl->origin[1] - dl->radius > grid->meshBounds[1][1]
|| dl->origin[1] + dl->radius < grid->meshBounds[0][1]
|| dl->origin[2] - dl->radius > grid->meshBounds[1][2]
|| dl->origin[2] + dl->radius < grid->meshBounds[0][2] ) {
// dlight doesn't reach the bounds
dlightBits &= ~( 1 << i );
}
}
if ( !dlightBits ) {
tr.pc.c_dlightSurfacesCulled++;
}
grid->dlightBits = dlightBits;
return dlightBits;
#endif
}
/*
====================
R_DlightSurface
The given surface is going to be drawn, and it touches a leaf
that is touched by one or more dlights, so try to throw out
more dlights if possible.
====================
*/
static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
if ( *surf->data == SF_FACE ) {
dlightBits = R_DlightFace( (srfSurfaceFace_t *)surf->data, dlightBits );
} else if ( *surf->data == SF_GRID ) {
dlightBits = R_DlightGrid( (srfGridMesh_t *)surf->data, dlightBits );
} else if ( *surf->data == SF_TRIANGLES ) {
dlightBits = R_DlightTrisurf( (srfTriangles_t *)surf->data, dlightBits );
} else {
dlightBits = 0;
}
if ( dlightBits ) {
tr.pc.c_dlightSurfaces++;
}
return dlightBits;
}
/*
======================
R_AddWorldSurface
======================
*/
static void R_AddWorldSurface( msurface_t *surf, int dlightBits, qboolean noViewCount = qfalse ) {
/*
if ( surf->viewCount == tr.viewCount ) {
return; // already in this view
}
*/
//rww - changed this to be like sof2mp's so RMG will look right.
//Will this affect anything that is non-rmg?
if (!noViewCount)
{
if ( surf->viewCount == tr.viewCount )
{
// already in this view, but lets make sure all the dlight bits are set
if ( *surf->data == SF_FACE )
{
((srfSurfaceFace_t *)surf->data)->dlightBits |= dlightBits;
}
else if ( *surf->data == SF_GRID )
{
((srfGridMesh_t *)surf->data)->dlightBits |= dlightBits;
}
else if ( *surf->data == SF_TRIANGLES )
{
((srfTriangles_t *)surf->data)->dlightBits |= dlightBits;
}
return;
}
surf->viewCount = tr.viewCount;
// FIXME: bmodel fog?
}
// surf->viewCount = tr.viewCount;
// FIXME: bmodel fog?
// try to cull before dlighting or adding
if ( R_CullSurface( surf->data, surf->shader ) ) {
return;
}
// check for dlighting
if ( dlightBits ) {
dlightBits = R_DlightSurface( surf, dlightBits );
dlightBits = ( dlightBits != 0 );
}
R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits );
}
/*
=============================================================
BRUSH MODELS
=============================================================
*/
/*
=================
R_AddBrushModelSurfaces
=================
*/
void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
bmodel_t *bmodel;
int clip;
model_t *pModel;
int i;
pModel = R_GetModelByHandle( ent->e.hModel );
bmodel = pModel->bmodel;
clip = R_CullLocalBox( bmodel->bounds );
if ( clip == CULL_OUT ) {
return;
}
if(pModel->bspInstance)
{
R_SetupEntityLighting(&tr.refdef, ent);
}
R_DlightBmodel( bmodel, qfalse );
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
R_AddWorldSurface( bmodel->firstSurface + i, tr.currentEntity->dlightBits, qtrue );
}
}
float GetQuadArea( vec3_t v1, vec3_t v2, vec3_t v3, vec3_t v4 )
{
vec3_t vec1, vec2, dis1, dis2;
// Get area of tri1
VectorSubtract( v1, v2, vec1 );
VectorSubtract( v1, v4, vec2 );
CrossProduct( vec1, vec2, dis1 );
VectorScale( dis1, 0.25f, dis1 );
// Get area of tri2
VectorSubtract( v3, v2, vec1 );
VectorSubtract( v3, v4, vec2 );
CrossProduct( vec1, vec2, dis2 );
VectorScale( dis2, 0.25f, dis2 );
// Return addition of disSqr of each tri area
return ( dis1[0] * dis1[0] + dis1[1] * dis1[1] + dis1[2] * dis1[2] +
dis2[0] * dis2[0] + dis2[1] * dis2[1] + dis2[2] * dis2[2] );
}
void RE_GetBModelVerts( int bmodelIndex, vec3_t *verts, vec3_t normal )
{
msurface_t *surfs;
srfSurfaceFace_t *face;
bmodel_t *bmodel;
model_t *pModel;
int i;
// Not sure if we really need to track the best two candidates
int maxDist[2]={0,0};
int maxIndx[2]={0,0};
int dist = 0;
float dot1, dot2;
pModel = R_GetModelByHandle( bmodelIndex );
bmodel = pModel->bmodel;
// Loop through all surfaces on the brush and find the best two candidates
for ( i = 0 ; i < bmodel->numSurfaces; i++ )
{
surfs = bmodel->firstSurface + i;
face = ( srfSurfaceFace_t *)surfs->data;
// It seems that the safest way to handle this is by finding the area of the faces
dist = GetQuadArea( face->points[0], face->points[1], face->points[2], face->points[3] );
// Check against the highest max
if ( dist > maxDist[0] )
{
// Shuffle our current maxes down
maxDist[1] = maxDist[0];
maxIndx[1] = maxIndx[0];
maxDist[0] = dist;
maxIndx[0] = i;
}
// Check against the second highest max
else if ( dist >= maxDist[1] )
{
// just stomp the old
maxDist[1] = dist;
maxIndx[1] = i;
}
}
// Hopefully we've found two best case candidates. Now we should see which of these faces the viewer
surfs = bmodel->firstSurface + maxIndx[0];
face = ( srfSurfaceFace_t *)surfs->data;
dot1 = DotProduct( face->plane.normal, tr.refdef.viewaxis[0] );
surfs = bmodel->firstSurface + maxIndx[1];
face = ( srfSurfaceFace_t *)surfs->data;
dot2 = DotProduct( face->plane.normal, tr.refdef.viewaxis[0] );
if ( dot2 < dot1 && dot2 < 0.0f )
{
i = maxIndx[1]; // use the second face
}
else if ( dot1 < dot2 && dot1 < 0.0f )
{
i = maxIndx[0]; // use the first face
}
else
{ // Possibly only have one face, so may as well use the first face, which also should be the best one
//i = rand() & 1; // ugh, we don't know which to use. I'd hope this would never happen
i = maxIndx[0]; // use the first face
}
surfs = bmodel->firstSurface + i;
face = ( srfSurfaceFace_t *)surfs->data;
for ( int t = 0; t < 4; t++ )
{
VectorCopy( face->points[t], verts[t] );
}
}
/*
=============================================================
WORLD MODEL
=============================================================
*/
/*
================
R_RecursiveWorldNode
================
*/
static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits ) {
do {
int newDlights[2];
// if the node wasn't marked as potentially visible, exit
if (node->visframe != tr.visCount) {
return;
}
// if the bounding volume is outside the frustum, nothing
// inside can be visible OPTIMIZE: don't do this all the way to leafs?
if ( r_nocull->integer!=1 ) {
int r;
if ( planeBits & 1 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~1; // all descendants will also be in front
}
}
if ( planeBits & 2 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~2; // all descendants will also be in front
}
}
if ( planeBits & 4 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~4; // all descendants will also be in front
}
}
if ( planeBits & 8 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~8; // all descendants will also be in front
}
}
if ( planeBits & 16 ) {
r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[4]);
if (r == 2) {
return; // culled
}
if ( r == 1 ) {
planeBits &= ~16; // all descendants will also be in front
}
}
}
if ( node->contents != -1 ) {
break;
}
// determine which dlights are needed
if ( r_nocull->integer!=2 )
{
newDlights[0] = 0;
newDlights[1] = 0;
if ( dlightBits )
{
int i;
for ( i = 0 ; i < tr.refdef.num_dlights ; i++ )
{
dlight_t *dl;
float dist;
if ( dlightBits & ( 1 << i ) ) {
dl = &tr.refdef.dlights[i];
dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
if ( dist > -dl->radius ) {
newDlights[0] |= ( 1 << i );
}
if ( dist < dl->radius ) {
newDlights[1] |= ( 1 << i );
}
}
}
}
}
else
{
newDlights[0] = dlightBits;
newDlights[1] = dlightBits;
}
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0] );
// tail recurse
node = node->children[1];
dlightBits = newDlights[1];
} while ( 1 );
{
// leaf node, so add mark surfaces
int c;
msurface_t *surf, **mark;
tr.pc.c_leafs++;
// add to z buffer bounds
if ( node->mins[0] < tr.viewParms.visBounds[0][0] ) {
tr.viewParms.visBounds[0][0] = node->mins[0];
}
if ( node->mins[1] < tr.viewParms.visBounds[0][1] ) {
tr.viewParms.visBounds[0][1] = node->mins[1];
}
if ( node->mins[2] < tr.viewParms.visBounds[0][2] ) {
tr.viewParms.visBounds[0][2] = node->mins[2];
}
if ( node->maxs[0] > tr.viewParms.visBounds[1][0] ) {
tr.viewParms.visBounds[1][0] = node->maxs[0];
}
if ( node->maxs[1] > tr.viewParms.visBounds[1][1] ) {
tr.viewParms.visBounds[1][1] = node->maxs[1];
}
if ( node->maxs[2] > tr.viewParms.visBounds[1][2] ) {
tr.viewParms.visBounds[1][2] = node->maxs[2];
}
// add the individual surfaces
mark = node->firstmarksurface;
c = node->nummarksurfaces;
while (c--) {
// the surface may have already been added if it
// spans multiple leafs
surf = *mark;
R_AddWorldSurface( surf, dlightBits );
mark++;
}
}
}
/*
===============
R_PointInLeaf
===============
*/
static mnode_t *R_PointInLeaf( vec3_t p ) {
mnode_t *node;
float d;
cplane_t *plane;
if ( !tr.world ) {
Com_Error (ERR_DROP, "R_PointInLeaf: bad model");
}
node = tr.world->nodes;
while( 1 ) {
if (node->contents != -1) {
break;
}
plane = node->plane;
d = DotProduct (p,plane->normal) - plane->dist;
if (d > 0) {
node = node->children[0];
} else {
node = node->children[1];
}
}
return node;
}
/*
==============
R_ClusterPVS
==============
*/
static const byte *R_ClusterPVS (int cluster) {
if (!tr.world || !tr.world->vis || cluster < 0 || cluster >= tr.world->numClusters ) {
return tr.world->novis;
}
return tr.world->vis + cluster * tr.world->clusterBytes;
}
/*
=================
R_inPVS
=================
*/
qboolean R_inPVS( vec3_t p1, vec3_t p2 ) {
mnode_t *leaf;
byte *vis;
leaf = R_PointInLeaf( p1 );
vis = ri.CM_ClusterPVS( leaf->cluster );
leaf = R_PointInLeaf( p2 );
if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) {
return qfalse;
}
return qtrue;
}
/*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current
cluster
===============
*/
static void R_MarkLeaves (void) {
const byte *vis;
mnode_t *leaf, *parent;
int i;
int cluster;
// lockpvs lets designers walk around to determine the
// extent of the current pvs
if ( r_lockpvs->integer ) {
return;
}
// current viewcluster
leaf = R_PointInLeaf( tr.viewParms.pvsOrigin );
cluster = leaf->cluster;
// if the cluster is the same and the area visibility matrix
// hasn't changed, we don't need to mark everything again
// if r_showcluster was just turned on, remark everything
if ( tr.viewCluster == cluster && !tr.refdef.areamaskModified
&& !r_showcluster->modified ) {
return;
}
if ( r_showcluster->modified || r_showcluster->integer ) {
r_showcluster->modified = qfalse;
if ( r_showcluster->integer ) {
ri.Printf( PRINT_ALL, "cluster:%i area:%i\n", cluster, leaf->area );
}
}
tr.visCount++;
tr.viewCluster = cluster;
if ( r_novis->integer || tr.viewCluster == -1 ) {
for (i=0 ; i<tr.world->numnodes ; i++) {
if (tr.world->nodes[i].contents != CONTENTS_SOLID) {
tr.world->nodes[i].visframe = tr.visCount;
}
}
return;
}
vis = R_ClusterPVS (tr.viewCluster);
for (i=0,leaf=tr.world->nodes ; i<tr.world->numnodes ; i++, leaf++) {
cluster = leaf->cluster;
if ( cluster < 0 || cluster >= tr.world->numClusters ) {
continue;
}
// check general pvs
if ( !(vis[cluster>>3] & (1<<(cluster&7))) ) {
continue;
}
// check for door connection
if ( (tr.refdef.areamask[leaf->area>>3] & (1<<(leaf->area&7)) ) ) {
continue; // not visible
}
parent = leaf;
do {
if (parent->visframe == tr.visCount)
break;
parent->visframe = tr.visCount;
parent = parent->parent;
} while (parent);
}
}
/*
=============
R_AddWorldSurfaces
=============
*/
void R_AddWorldSurfaces (void) {
if ( !r_drawworld->integer ) {
return;
}
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return;
}
tr.currentEntityNum = REFENTITYNUM_WORLD;
tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
// determine which leaves are in the PVS / areamask
R_MarkLeaves ();
// clear out the visible min/max
ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
// perform frustum culling and add all the potentially visible surfaces
if ( tr.refdef.num_dlights > 32 ) {
tr.refdef.num_dlights = 32 ;
}
R_RecursiveWorldNode( tr.world->nodes, 31, ( 1 << tr.refdef.num_dlights ) - 1 );
}

View file

@ -214,7 +214,7 @@ public:
const int entNum;
const int modelIndex;
const skin_t *skin;
const jk_shader_t *cust_shader;
const shader_t *cust_shader;
intptr_t *TransformedVertsArray;
const EG2_Collision eG2TraceType;
bool hitOne;
@ -243,7 +243,7 @@ public:
int initentNum,
int initmodelIndex,
const skin_t *initskin,
const jk_shader_t *initcust_shader,
const shader_t *initcust_shader,
intptr_t *initTransformedVertsArray,
const EG2_Collision einitG2TraceType,
#ifdef _G2_GORE
@ -1181,7 +1181,7 @@ static bool G2_TracePolys(const mdxmSurface_t *surface, const mdxmSurfHierarchy_
hitPoint, &x_pos, &y_pos,newCol.mBarycentricI,newCol.mBarycentricJ);
/*
const jk_shader_t *shader = 0;
const shader_t *shader = 0;
// now, we know what surface this hit belongs to, we need to go get the shader handle so we can get the correct hit location and hit material info
if ( cust_shader )
{
@ -1562,7 +1562,7 @@ void G2_TraceModels(CGhoul2Info_v &ghoul2, vec3_t rayStart, vec3_t rayEnd, CColl
{
int i, lod;
skin_t *skin;
jk_shader_t *cust_shader;
shader_t *cust_shader;
#if !defined(JK2_MODE) || defined(_G2_GORE)
qboolean firstModelOnly = qfalse;
#endif // !JK2_MODE || _G2_GORE

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -697,14 +697,6 @@ public:
return;
}
// Record The Extents Of The World Incase No Other Weather Zones Exist
//---------------------------------------------------------------------
if (!mWeatherZones.size())
{
Com_Printf("WARNING: No Weather Zones Encountered\n");
AddWeatherZone(tr.world->bmodels[0].bounds[0], tr.world->bmodels[0].bounds[1]);
}
// all this piece of code does really is fill in the bool "SWeatherZone::mMarkedOutside", plus the mPointCache[] for each zone,
// so we can diskload those. Maybe.
fileHandle_t f = ReadCachedWeatherFile();
@ -728,6 +720,15 @@ public:
uint32_t contents;
uint32_t bit;
// Record The Extents Of The World Incase No Other Weather Zones Exist
//---------------------------------------------------------------------
if (!mWeatherZones.size())
{
Com_Printf("WARNING: No Weather Zones Encountered\n");
AddWeatherZone(tr.world->bmodels[0].bounds[0], tr.world->bmodels[0].bounds[1]);
}
f = WriteCachedWeatherFile();
// Iterate Over All Weather Zones
@ -1060,17 +1061,7 @@ public:
}
mVertexCount = VertexCount;
#if defined(HAVE_GLES) // Check for point sprite use
if(mVertexCount == 1)
mGLModeEnum = GL_POINTS;
else
#endif
#ifdef HAVE_GLES
mGLModeEnum = (mVertexCount==3)?(GL_TRIANGLES):(GL_TRIANGLE_FAN);
#else
mGLModeEnum = (mVertexCount==3)?(GL_TRIANGLES):(GL_QUADS);
#endif
mGLModeEnum = (mVertexCount==3)?(GL_TRIANGLES):(GL_QUADS);
}
@ -1451,76 +1442,22 @@ public:
// Enable And Disable Things
//---------------------------
/*
if (mGLModeEnum==GL_POINTS && qglPointParameteriNV)
{
qglEnable(GL_POINT_SPRITE_NV);
qglEnable(GL_TEXTURE_2D);
qglDisable(GL_CULL_FACE);
qglPointSize(mWidth);
qglPointParameterfEXT( GL_POINT_SIZE_MIN_EXT, 4.0f );
qglPointParameterfEXT( GL_POINT_SIZE_MAX_EXT, 2047.0f );
qglTexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, GL_TRUE);
}
else
*/
#ifdef HAVE_GLES
GLfloat tex[2*6*mParticleCount];
GLfloat vtx[3*6*mParticleCount];
GLfloat col[4*6*mParticleCount];
GLfloat curcol[4];
qglGetFloatv(GL_CURRENT_COLOR, curcol);
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (!glcol)
qglEnableClientState( GL_COLOR_ARRAY );
if (mGLModeEnum==GL_POINTS)
{
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
// Nothing to do ?!
}
#else
//FIXME use this extension?
const float attenuation[3] =
{
1, 0.0, 0.0004
};
if (mGLModeEnum == GL_POINTS && qglPointParameterfEXT)
{ //fixme use custom parameters but gotta make sure it expects them on same scale first
qglPointSize(10.0);
qglPointParameterfEXT(GL_POINT_SIZE_MIN_EXT, 1.0);
qglPointParameterfEXT(GL_POINT_SIZE_MAX_EXT, 4.0);
qglPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, (float *)attenuation);
}
#endif
else
{
qglEnable(GL_TEXTURE_2D);
//qglDisable(GL_CULL_FACE);
//naughty, you are making the assumption that culling is on when you get here. -rww
GL_Cull(CT_TWO_SIDED);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilterMode==0)?(GL_LINEAR):(GL_NEAREST));
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (mFilterMode==0)?(GL_LINEAR):(GL_NEAREST));
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mFilterMode==0)?(GL_LINEAR):(GL_NEAREST));
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (mFilterMode==0)?(GL_LINEAR):(GL_NEAREST));
// Setup Matrix Mode And Translation
//-----------------------------------
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
// Setup Matrix Mode And Translation
//-----------------------------------
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
}
// Begin
//-------
#ifdef HAVE_GLES
int idx = 0;
#else
qglBegin(mGLModeEnum);
#endif
for (particleNum=0; particleNum<mParticleCount; particleNum++)
{
part = &(mParticles[particleNum]);
@ -1529,64 +1466,45 @@ public:
continue;
}
// If Oriented With Velocity, We Want To Calculate Vertx Offsets Differently For Each Particle
//---------------------------------------------------------------------------------------------
if (mOrientWithVelocity)
{
partDirection = part->mVelocity;
VectorNormalize(partDirection.v);
mCameraDown = partDirection;
mCameraDown *= (mHeight * -1);
if (mVertexCount==4)
{
mCameraLeftPlusUp = (mCameraLeft - mCameraDown);
mCameraLeftMinusUp = (mCameraLeft + mCameraDown);
}
else
{
mCameraLeftPlusUp = (mCameraDown + mCameraLeft);
}
}
// Blend Mode Zero -> Apply Alpha Just To Alpha Channel
//------------------------------------------------------
if (mBlendMode==0)
{
#ifdef HAVE_GLES
curcol[0]=mColor[0]; curcol[1]=mColor[1], curcol[2]=mColor[2]; curcol[3]=part->mAlpha;
#else
qglColor4f(mColor[0], mColor[1], mColor[2], part->mAlpha);
#endif
}
// Otherwise Apply Alpha To All Channels
//---------------------------------------
// Otherwise Apply Alpha To All Channels
//---------------------------------------
else
{
#ifdef HAVE_GLES
curcol[0]=mColor[0]*part->mAlpha; curcol[1]=mColor[1]*part->mAlpha, curcol[2]=mColor[2]*part->mAlpha; curcol[3]=mColor[3]*part->mAlpha;
#else
qglColor4f(mColor[0]*part->mAlpha, mColor[1]*part->mAlpha, mColor[2]*part->mAlpha, mColor[3]*part->mAlpha);
#endif
}
// Render A Point
//----------------
if (mGLModeEnum==GL_POINTS)
{
#ifdef HAVE_GLES
memcpy(vtx+idx*3, part->mPosition.v, 3*sizeof(GLfloat));
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
idx++;
#else
qglVertex3fv(part->mPosition.v);
#endif
}
// Render A Triangle
//-------------------
else if (mVertexCount==3)
// Render A Triangle
//-------------------
if (mVertexCount==3)
{
#ifdef HAVE_GLES
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=1.0f; tex[idx*2+1]=0.0f;
vtx[idx*3+0]=part->mPosition[0];
vtx[idx*3+1]=part->mPosition[1];
vtx[idx*3+2]=part->mPosition[2];
memcpy(col+idx*4+4, curcol, 4*sizeof(GLfloat));
tex[idx*2+2]=0.0f; tex[idx*2+3]=1.0f;
vtx[idx*3+3]=part->mPosition[0] + mCameraLeft[0];
vtx[idx*3+4]=part->mPosition[1] + mCameraLeft[1];
vtx[idx*3+5]=part->mPosition[2] + mCameraLeft[2];
memcpy(col+idx*4+8, curcol, 4*sizeof(GLfloat));
tex[idx*2+4]=0.0f; tex[idx*2+5]=0.0f;
vtx[idx*3+6]=part->mPosition[0] + mCameraLeftPlusUp[0];
vtx[idx*3+7]=part->mPosition[1] + mCameraLeftPlusUp[1];
vtx[idx*3+8]=part->mPosition[2] + mCameraLeftPlusUp[2];
idx+=3;
#else
qglTexCoord2f(1.0, 0.0);
qglTexCoord2f(1.0, 0.0);
qglVertex3f(part->mPosition[0],
part->mPosition[1],
part->mPosition[2]);
@ -1600,71 +1518,12 @@ public:
qglVertex3f(part->mPosition[0] + mCameraLeftPlusUp[0],
part->mPosition[1] + mCameraLeftPlusUp[1],
part->mPosition[2] + mCameraLeftPlusUp[2]);
#endif
}
// Render A Quad
//---------------
// Render A Quad
//---------------
else
{
#ifdef HAVE_GLES
/*tex[0]=0.0f; tex[1]=0.0f;
vtx[0]=part->mPosition[0] - mCameraLeftMinusUp[0];
vtx[1]=part->mPosition[1] - mCameraLeftMinusUp[1];
vtx[2]=part->mPosition[2] - mCameraLeftMinusUp[2];
tex[2]=1.0f; tex[3]=0.0f;
vtx[3]=part->mPosition[0] - mCameraLeftPlusUp[0];
vtx[4]=part->mPosition[1] - mCameraLeftPlusUp[1];
vtx[5]=part->mPosition[2] - mCameraLeftPlusUp[2];
tex[4]=1.0f; tex[5]=1.0f;
vtx[6]=part->mPosition[0] + mCameraLeftMinusUp[0];
vtx[7]=part->mPosition[1] + mCameraLeftMinusUp[1];
vtx[8]=part->mPosition[2] + mCameraLeftMinusUp[2];
tex[6]=0.0f; tex[7]=1.0f;
vtx[9]=part->mPosition[0] + mCameraLeftPlusUp[0];
vtx[10]=part->mPosition[1] + mCameraLeftPlusUp[1];
vtx[11]=part->mPosition[2] + mCameraLeftPlusUp[2];
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 3, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );*/
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=0.0f; tex[idx*2+1]=0.0f;
vtx[idx*3+0]=part->mPosition[0] - mCameraLeftMinusUp[0];
vtx[idx*3+1]=part->mPosition[1] - mCameraLeftMinusUp[1];
vtx[idx*3+2]=part->mPosition[2] - mCameraLeftMinusUp[2];
idx++;
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=1.0f; tex[idx*2+1]=0.0f;
vtx[idx*3+0]=part->mPosition[0] - mCameraLeftPlusUp[0];
vtx[idx*3+1]=part->mPosition[1] - mCameraLeftPlusUp[1];
vtx[idx*3+2]=part->mPosition[2] - mCameraLeftPlusUp[2];
idx++;
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=1.0f; tex[idx*2+1]=1.0f;
vtx[idx*3+0]=part->mPosition[0] + mCameraLeftMinusUp[0];
vtx[idx*3+1]=part->mPosition[1] + mCameraLeftMinusUp[1];
vtx[idx*3+2]=part->mPosition[2] + mCameraLeftMinusUp[2];
idx++;
// triangle 2
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=0.0f; tex[idx*2+1]=0.0f;
vtx[idx*3+0]=part->mPosition[0] - mCameraLeftMinusUp[0];
vtx[idx*3+1]=part->mPosition[1] - mCameraLeftMinusUp[1];
vtx[idx*3+2]=part->mPosition[2] - mCameraLeftMinusUp[2];
idx++;
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=1.0f; tex[idx*2+1]=1.0f;
vtx[idx*3+0]=part->mPosition[0] + mCameraLeftMinusUp[0];
vtx[idx*3+1]=part->mPosition[1] + mCameraLeftMinusUp[1];
vtx[idx*3+2]=part->mPosition[2] + mCameraLeftMinusUp[2];
idx++;
memcpy(col+idx*4, curcol, 4*sizeof(GLfloat));
tex[idx*2+0]=0.0f; tex[idx*2+1]=1.0f;
vtx[idx*3+0]=part->mPosition[0] + mCameraLeftPlusUp[0];
vtx[idx*3+1]=part->mPosition[1] + mCameraLeftPlusUp[1];
vtx[idx*3+2]=part->mPosition[2] + mCameraLeftPlusUp[2];
idx++;
#else
// Left bottom.
qglTexCoord2f( 0.0, 0.0 );
qglVertex3f(part->mPosition[0] - mCameraLeftMinusUp[0],
@ -1688,44 +1547,12 @@ public:
qglVertex3f(part->mPosition[0] + mCameraLeftPlusUp[0],
part->mPosition[1] + mCameraLeftPlusUp[1],
part->mPosition[2] + mCameraLeftPlusUp[2] );
#endif
}
}
#ifndef HAVE_GLES
qglEnd();
#endif
if (mGLModeEnum==GL_POINTS)
{
//qglDisable(GL_POINT_SPRITE_NV);
//qglTexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, GL_FALSE);
}
else
{
//qglEnable(GL_CULL_FACE);
//you don't need to do this when you are properly setting cull state.
#ifdef HAVE_GLES
// if (mGLModeEnum==GL_TRIANGLES) {
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 3, GL_FLOAT, 0, vtx );
qglColorPointer (4, GL_FLOAT, 0, col );
qglDrawArrays( GL_TRIANGLES, 0, idx );
// }
#endif
qglPopMatrix();
}
#ifdef HAVE_GLES
if (!glcol)
qglDisableClientState( GL_COLOR_ARRAY );
if (mGLModeEnum == GL_POINTS ) {
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
} else {
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
}
#endif
qglEnable(GL_CULL_FACE);
qglPopMatrix();
mParticlesRendered += mParticleCountRender;
}
@ -2142,13 +1969,8 @@ void R_WorldEffectCommand(const char *command)
COM_EndParseSession();
return;
}
int count = 1000;
const char* tempStr;
COM_ParseString(&command, &tempStr);
COM_ParseInt(&command, &count);
CParticleCloud& nCloud = mParticleClouds.push_back();
nCloud.Initialize(count, "gfx/effects/snowflake1.tga");
nCloud.Initialize(1000, "gfx/effects/snowflake1.bmp");
nCloud.mBlendMode = 1;
nCloud.mRotationChangeNext = 0;
nCloud.mColor = 0.75f;

View file

@ -109,7 +109,6 @@ const unsigned char g_strGlowPShaderARB[] =
};
/***********************************************************************************************************/
#ifndef HAVE_GLES
#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
@ -191,4 +190,3 @@ void ARB_InitGlowShaders(void) {
assert( iErrPos == -1 );
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -316,8 +316,8 @@ static void R_LoadVisibility( lump_t *l, world_t &worldData ) {
ShaderForShaderNum
===============
*/
static jk_shader_t *ShaderForShaderNum( int shaderNum, const int *lightmapNum, const byte *lightmapStyles, const byte *vertexStyles, world_t &worldData ) {
jk_shader_t *shader;
static shader_t *ShaderForShaderNum( int shaderNum, const int *lightmapNum, const byte *lightmapStyles, const byte *vertexStyles, world_t &worldData ) {
shader_t *shader;
dshader_t *dsh;
const byte *styles;
@ -981,14 +981,14 @@ R_LoadFogs
*/
static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump, world_t &worldData, int index ) {
int i;
jk_fog_t *out;
fog_t *out;
dfog_t *fogs;
dbrush_t *brushes, *brush;
dbrushside_t *sides;
int count, brushesCount, sidesCount;
int sideNum;
int planeNum;
jk_shader_t *shader;
shader_t *shader;
float d;
int firstSide=0;
int lightmaps[MAXLIGHTMAPS] = { LIGHTMAP_NONE } ;
@ -1001,7 +1001,7 @@ static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump, world
// create fog strucutres for them
worldData.numfogs = count + 1;
worldData.fogs = (jk_fog_t *)R_Hunk_Alloc ( (worldData.numfogs+1)*sizeof(*out), qtrue);
worldData.fogs = (fog_t *)R_Hunk_Alloc ( (worldData.numfogs+1)*sizeof(*out), qtrue);
worldData.globalFog = -1;
out = worldData.fogs + 1;
@ -1342,7 +1342,6 @@ void RE_LoadWorldMap_Actual( const char *name, world_t &worldData, int index ) {
if (!index)
{
skyboxportal = 0;
hasskybox = 0;
tr.sunDirection[0] = 0.45f;
tr.sunDirection[1] = 0.3f;

View file

@ -312,7 +312,7 @@ void RE_LAGoggles( void )
tr.refdef.rdflags |= (RDF_doLAGoggles|RDF_doFullbright);
tr.refdef.doLAGoggles = qtrue;
jk_fog_t *fog = &tr.world->fogs[tr.world->numfogs];
fog_t *fog = &tr.world->fogs[tr.world->numfogs];
fog->parms.color[0] = 0.75f;
fog->parms.color[1] = 0.42f + Q_flrand(0.0f, 1.0f) * 0.025f;
@ -383,7 +383,6 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
//
// do overdraw measurement
//
#ifndef HAVE_GLES
if ( r_measureOverdraw->integer )
{
if ( glConfig.stencilBits < 4 )
@ -418,7 +417,6 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
r_measureOverdraw->modified = qfalse;
}
}
#endif
//
// texturemode stuff
@ -459,13 +457,23 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) {
}
cmd->commandId = RC_DRAW_BUFFER;
{
if ( glConfig.stereoEnabled ) {
if ( stereoFrame == STEREO_LEFT ) {
cmd->buffer = (int)0;
cmd->buffer = (int)GL_BACK_LEFT;
} else if ( stereoFrame == STEREO_RIGHT ) {
cmd->buffer = (int)1;
cmd->buffer = (int)GL_BACK_RIGHT;
} else {
ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
Com_Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
}
} else {
if ( stereoFrame != STEREO_CENTER ) {
Com_Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
}
// if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) {
// cmd->buffer = (int)GL_FRONT;
// } else
{
cmd->buffer = (int)GL_BACK;
}
}
}
@ -479,30 +487,26 @@ Returns the number of msec spent in the back end
=============
*/
void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
swapBuffersCommand_t *cmd;
swapBuffersCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (swapBuffersCommand_t*)R_GetCommandBuffer(sizeof(*cmd));
if (!cmd) {
cmd = (swapBuffersCommand_t *) R_GetCommandBufferReserved( sizeof( *cmd ), 0 );
if ( !cmd ) {
return;
}
cmd->commandId = RC_SWAP_BUFFERS;
cmd->commandId = RC_FLUSH;
R_IssueRenderCommands( qtrue );
R_IssueRenderCommands( qfalse );
R_InitNextFrame();
// use the other buffers next frame, because another CPU
// may still be rendering into the current ones
R_InitNextFrame();
if (frontEndMsec) {
if ( frontEndMsec ) {
*frontEndMsec = tr.frontEndMsec;
}
tr.frontEndMsec = 0;
if (backEndMsec) {
if ( backEndMsec ) {
*backEndMsec = backEnd.pc.msec;
}
backEnd.pc.msec = 0;
@ -512,20 +516,3 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
styleUpdated[i] = false;
}
}
void RE_SubmitStereoFrame( ) {
swapBuffersCommand_t *cmd;
if ( !tr.registered ) {
return;
}
cmd = (swapBuffersCommand_t*)R_GetCommandBuffer(sizeof(*cmd));
if (!cmd) {
return;
}
cmd->commandId = RC_SWAP_BUFFERS;
R_IssueRenderCommands( qtrue );
}

View file

@ -77,13 +77,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
}
#endif
#ifdef HAVE_GLES
//don't do qglTexImage2D as this may end up doing a compressed image
//on which we are not allowed to do further sub images
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#else
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#endif
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@ -132,34 +126,6 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
}
qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
#ifdef HAVE_GLES
qglColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f );
GLfloat tex[] = {
0.5 / cols, 0.5 / rows,
( cols - 0.5 ) / cols , 0.5 / rows,
( cols - 0.5 ) / cols, ( rows - 0.5 ) / rows,
0.5 / cols, ( rows - 0.5 ) / rows
};
GLfloat vtx[] = {
x, y,
x + w, y,
x + w, y + h,
x, y + h
};
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
if (glcol)
qglEnableClientState(GL_COLOR_ARRAY);
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#else
qglBegin (GL_QUADS);
qglTexCoord2f ( 0.5f / cols, 0.5f / rows );
qglVertex2f (x, y);
@ -170,7 +136,6 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
qglVertex2f (x, y+h);
qglEnd ();
#endif
}
@ -183,11 +148,7 @@ void RE_UploadCinematic (int cols, int rows, const byte *data, int client, qbool
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
tr.scratchImage[client]->width = cols;
tr.scratchImage[client]->height = rows;
#ifdef HAVE_GLES
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#else
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#endif
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@ -466,7 +427,6 @@ static void RE_Blit(float fX0, float fY0, float fX1, float fY1, float fX2, float
qglColor3f( 1.0f, 1.0f, 1.0f );
#ifndef HAVE_GLES
qglBegin (GL_QUADS);
{
// TL...
@ -494,12 +454,10 @@ static void RE_Blit(float fX0, float fY0, float fX1, float fY1, float fX2, float
qglVertex2f( fX3, fY3);
}
qglEnd ();
#endif
}
static void RE_KillDissolve(void)
{
#ifndef HAVE_GLES
Dissolve.iStartTime = 0;
if (Dissolve.pImage)
@ -507,7 +465,6 @@ static void RE_KillDissolve(void)
R_Images_DeleteImage( Dissolve.pImage );
Dissolve.pImage = NULL;
}
#endif
}
// Draw the dissolve pic to the screen, over the top of what's already been rendered.
//
@ -516,7 +473,6 @@ static void RE_KillDissolve(void)
#define iSAFETY_SPRITE_OVERLAP 2 // #pixels to overlap blit region by, in case some drivers leave onscreen seams
qboolean RE_ProcessDissolve(void)
{
#ifndef HAVE_GLES
if (Dissolve.iStartTime)
{
if (Dissolve.bTouchNeeded)
@ -794,7 +750,7 @@ qboolean RE_ProcessDissolve(void)
RE_KillDissolve();
}
}
#endif
return qfalse;
}
@ -807,7 +763,6 @@ qboolean RE_InitDissolve(qboolean bForceCircularExtroWipe)
// ri.Printf( PRINT_ALL, "RE_InitDissolve()\n");
qboolean bReturn = qfalse;
#ifndef HAVE_GLES
if (//Dissolve.iStartTime == 0 // no point in interruping an existing one
//&&
tr.registered == qtrue // ... stops it crashing during first cinematic before the menus... :-)
@ -1064,8 +1019,6 @@ qboolean RE_InitDissolve(qboolean bForceCircularExtroWipe)
}
}
#endif
return bReturn;
}

View file

@ -658,7 +658,7 @@ class CRenderSurface
public:
int surfaceNum;
surfaceInfo_v &rootSList;
const jk_shader_t *cust_shader;
const shader_t *cust_shader;
int fogNum;
qboolean personalModel;
CBoneCache *boneCache;
@ -668,14 +668,14 @@ public:
int lod;
boltInfo_v &boltList;
#ifdef _G2_GORE
jk_shader_t *gore_shader;
shader_t *gore_shader;
CGoreSet *gore_set;
#endif
CRenderSurface(
int initsurfaceNum,
surfaceInfo_v &initrootSList,
const jk_shader_t *initcust_shader,
const shader_t *initcust_shader,
int initfogNum,
qboolean initpersonalModel,
CBoneCache *initboneCache,
@ -685,7 +685,7 @@ public:
int initlod,
#ifdef _G2_GORE
boltInfo_v &initboltList,
jk_shader_t *initgore_shader,
shader_t *initgore_shader,
CGoreSet *initgore_set):
#else
boltInfo_v &initboltList):
@ -786,7 +786,7 @@ R_AComputeFogNum
static int R_GComputeFogNum( trRefEntity_t *ent ) {
int i;
jk_fog_t *fog;
fog_t *fog;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
@ -2239,7 +2239,7 @@ void G2API_SetSurfaceOnOffFromSkin (CGhoul2Info *ghlInfo, qhandle_t renderSkin)
void RenderSurfaces(CRenderSurface &RS)
{
int i;
const jk_shader_t *shader = 0;
const shader_t *shader = 0;
int offFlags = 0;
#ifdef _G2_GORE
bool drawGore = true;
@ -2385,7 +2385,7 @@ void RenderSurfaces(CRenderSurface &RS)
newSurf2->scale=1.0f;
}
}
jk_shader_t *gshader;
shader_t *gshader;
if ((*kcur).second.shader)
{
gshader=R_GetShaderByHandle((*kcur).second.shader);
@ -2556,9 +2556,9 @@ R_AddGHOULSurfaces
==============
*/
void R_AddGhoulSurfaces( trRefEntity_t *ent ) {
jk_shader_t *cust_shader = 0;
shader_t *cust_shader = 0;
#ifdef _G2_GORE
jk_shader_t *gore_shader = 0;
shader_t *gore_shader = 0;
#endif
int fogNum = 0;
qboolean personalModel;
@ -3501,7 +3501,7 @@ qboolean R_LoadMDXM( model_t *mod, void *buffer, const char *mod_name, qboolean
mdxmSurface_t *surf;
int version;
int size;
jk_shader_t *sh;
shader_t *sh;
mdxmSurfHierarchy_t *surfInfo;
#ifdef Q3_BIG_ENDIAN

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "tr_WorldEffects.h"
glconfig_t glConfig;
jk_glstate_t glState;
glstate_t glState;
window_t window;
static void GfxInfo_f( void );
@ -185,14 +185,6 @@ cvar_t *com_buildScript;
cvar_t *r_environmentMapping;
cvar_t *r_screenshotJpegQuality;
void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
void ( APIENTRY * qglLockArraysEXT )( GLint, GLint );
void ( APIENTRY * qglUnlockArraysEXT )( void );
#ifndef HAVE_GLES
#if !defined(__APPLE__)
PFNGLSTENCILOPSEPARATEPROC qglStencilOpSeparate;
#endif
@ -215,7 +207,6 @@ PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC qglGetCombinerOutputParameterfvNV;
PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC qglGetCombinerOutputParameterivNV;
PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC qglGetFinalCombinerInputParameterfvNV;
PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC qglGetFinalCombinerInputParameterivNV;
#endif
PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
PFNGLBINDPROGRAMARBPROC qglBindProgramARB;
@ -237,10 +228,8 @@ PFNGLGETPROGRAMIVARBPROC qglGetProgramivARB;
PFNGLGETPROGRAMSTRINGARBPROC qglGetProgramStringARB;
PFNGLISPROGRAMARBPROC qglIsProgramARB;
#ifndef HAVE_GLES
PFNGLLOCKARRAYSEXTPROC qglLockArraysEXT;
PFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT;
#endif
bool g_bTextureRectangleHack = false;
@ -271,46 +260,16 @@ void R_Splash()
const float y1 = 240 - height / 2;
const float y2 = 240 + height / 2;
#ifdef HAVE_GLES
//GLimp_EndFrame();
GLfloat tex[] = {
0,0 ,
1,0,
0,1,
1,1
};
GLfloat vtx[] = {
x1, y1,
x2, y1,
x1, y2,
x2, y2
};
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
qglEnableClientState( GL_VERTEX_ARRAY );
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#else
qglBegin (GL_TRIANGLE_STRIP);
qglTexCoord2f( 0, 0 );
qglVertex2f(x1, y1);
qglTexCoord2f( 1 , 0 );
qglVertex2f(x2, y1);
qglTexCoord2f( 0, 1 );
qglVertex2f(x1, y2);
qglTexCoord2f( 1, 1 );
qglVertex2f(x2, y2);
qglTexCoord2f( 0, 0 );
qglVertex2f(x1, y1);
qglTexCoord2f( 1 , 0 );
qglVertex2f(x2, y1);
qglTexCoord2f( 0, 1 );
qglVertex2f(x1, y2);
qglTexCoord2f( 1, 1 );
qglVertex2f(x2, y2);
qglEnd();
#endif
}
ri.WIN_Present( &window );
@ -324,10 +283,6 @@ void R_Splash()
static void GLW_InitTextureCompression( void )
{
glConfig.textureCompression = TC_NONE;
return;
bool newer_tc, old_tc;
// Check for available tc methods.
newer_tc = ri.GL_ExtensionSupported("GL_ARB_texture_compression") && ri.GL_ExtensionSupported("GL_EXT_texture_compression_s3tc");
@ -504,7 +459,6 @@ static void GLimp_InitExtensions( void )
glConfig.clampToEdgeAvailable = qtrue;
Com_Printf ("...using GL_EXT_texture_edge_clamp\n" );
#ifndef HAVE_GLES
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
@ -569,7 +523,6 @@ static void GLimp_InitExtensions( void )
}
bool bNVRegisterCombiners = false;
// Register Combiners.
if ( ri.GL_ExtensionSupported( "GL_NV_register_combiners" ) )
{
@ -617,7 +570,7 @@ static void GLimp_InitExtensions( void )
bNVRegisterCombiners = false;
Com_Printf ("...GL_NV_register_combiners not found\n" );
}
#endif
// NOTE: Vertex and Fragment Programs are very dependant on each other - this is actually a
// good thing! So, just check to see which we support (one or the other) and load the shared
// function pointers. ARB rocks!
@ -703,7 +656,6 @@ static void GLimp_InitExtensions( void )
// Find out how many general combiners they have.
#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
GLint iNumGeneralCombiners = 0;
bool bNVRegisterCombiners = false;
if(bNVRegisterCombiners)
qglGetIntegerv( GL_MAX_GENERAL_COMBINERS_NV, &iNumGeneralCombiners );
@ -722,13 +674,11 @@ static void GLimp_InitExtensions( void )
}
#if !defined(__APPLE__)
#ifndef HAVE_GLES
qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri.GL_GetProcAddress("glStencilOpSeparate");
if (qglStencilOpSeparate)
{
glConfig.doStencilShadowsInOneDrawcall = qtrue;
}
#endif
#else
glConfig.doStencilShadowsInOneDrawcall = qtrue;
#endif
@ -779,7 +729,7 @@ static void InitOpenGL( void )
// set default state
GL_SetDefaultState();
//R_Splash(); //get something on screen asap
R_Splash(); //get something on screen asap
}
else
{
@ -1218,19 +1168,14 @@ void GL_SetDefaultState( void )
//
glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
#ifndef HAVE_GLES
qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
#endif
qglDepthMask( GL_TRUE );
qglDisable( GL_DEPTH_TEST );
qglEnable( GL_SCISSOR_TEST );
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
#ifdef HAVE_GLES
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
#endif
qglDisable( GL_ALPHA_TEST );
qglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
@ -1568,10 +1513,10 @@ void R_Register( void )
//
r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compress_textures", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compress_textures", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_compressed_lightmaps = ri.Cvar_Get( "r_ext_compress_lightmaps", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_preferred_tc_method = ri.Cvar_Get( "r_ext_preferred_tc_method", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_gamma_control = ri.Cvar_Get( "r_ext_gamma_control", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_gamma_control = ri.Cvar_Get( "r_ext_gamma_control", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE_ND | CVAR_LATCH);
r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE_ND | CVAR_LATCH);
@ -1591,7 +1536,7 @@ void R_Register( void )
r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_texturebitslm = ri.Cvar_Get( "r_texturebitslm", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "0", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_mapOverBrightBits = ri.Cvar_Get( "r_mapOverBrightBits", "0", CVAR_ARCHIVE_ND|CVAR_LATCH );
r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE_ND | CVAR_LATCH );
r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
@ -1608,7 +1553,7 @@ void R_Register( void )
//
// archived variables that can change at any time
//
r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "1000", CVAR_ARCHIVE_ND );
r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE_ND );
r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE_ND );
r_flares = ri.Cvar_Get ("r_flares", "1", CVAR_ARCHIVE_ND );
r_lodscale = ri.Cvar_Get( "r_lodscale", "10", CVAR_ARCHIVE_ND );
@ -1623,7 +1568,7 @@ void R_Register( void )
// r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "0", CVAR_ARCHIVE );
r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE_ND);
r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
r_gamma = ri.Cvar_Get( "r_gamma", "1.027344", CVAR_ARCHIVE_ND );
r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE_ND );
r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE_ND );
r_dlightStyle = ri.Cvar_Get ("r_dlightStyle", "1", CVAR_ARCHIVE_ND);
@ -1686,7 +1631,7 @@ void R_Register( void )
r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
r_shadows = ri.Cvar_Get( "cg_shadows", "3", 0 );
r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
r_shadowRange = ri.Cvar_Get( "r_shadowRange", "1000", CVAR_ARCHIVE_ND );
/*
@ -1844,7 +1789,6 @@ void RE_Shutdown( qboolean destroyWindow, qboolean restarting ) {
for ( size_t i = 0; i < numCommands; i++ )
ri.Cmd_RemoveCommand( commands[i].cmd );
#ifndef HAVE_GLES
if ( r_DynamicGlow && r_DynamicGlow->integer )
{
// Release the Glow Vertex Shader.
@ -1877,7 +1821,6 @@ void RE_Shutdown( qboolean destroyWindow, qboolean restarting ) {
// Release the blur texture.
qglDeleteTextures( 1, &tr.blurImage );
}
#endif
R_ShutdownWorldEffects();
R_ShutdownFonts();
@ -2091,7 +2034,6 @@ extern "C" Q_EXPORT refexport_t* QDECL GetRefAPI ( int apiVersion, refimport_t *
REX(BeginFrame);
REX(EndFrame);
REX(SubmitStereoFrame);
REX(ProcessDissolve);
REX(InitDissolve);

View file

@ -31,15 +31,10 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "mdx_format.h"
#include "qgl.h"
#if defined(_XBOX) || defined(HAVE_GLES)
#define GL_INDEX_TYPE GL_UNSIGNED_SHORT
typedef unsigned short glIndex_t;
#else
#define GL_INDEX_TYPE GL_UNSIGNED_INT
typedef unsigned int glIndex_t;
#endif
//extern refimport_t ri;
extern refimport_t ri;
// 13 bits
@ -435,7 +430,7 @@ typedef struct {
} fogParms_t;
typedef struct jk_shader_s {
typedef struct shader_s {
char name[MAX_QPATH]; // game path, including extension
int lightmapIndex[MAXLIGHTMAPS]; // for a shader to match, both name and lightmapIndex must match
byte styles[MAXLIGHTMAPS];
@ -482,9 +477,9 @@ typedef struct jk_shader_s {
// True if this shader has a stage with glow in it (just an optimization).
bool hasGlow;
// struct jk_shader_s *remappedShader; // current shader this one is remapped too
struct jk_shader_s *next;
} jk_shader_t;
// struct shader_s *remappedShader; // current shader this one is remapped too
struct shader_s *next;
} shader_t;
/*
@ -513,7 +508,7 @@ Ghoul2 Insert End
// skins allow models to be retextured without modifying the model file
typedef struct {
char name[MAX_QPATH];
jk_shader_t *shader;
shader_t *shader;
} skinSurface_t;
typedef struct skin_s {
@ -534,7 +529,7 @@ typedef struct {
// for clipping distance in fog when outside
qboolean hasSurface;
float surface[4];
} jk_fog_t;
} fog_t;
typedef struct {
orientationr_t ori;
@ -709,7 +704,7 @@ BRUSH MODELS
typedef struct msurface_s {
int viewCount; // if == tr.viewCount, already added
struct jk_shader_s *shader;
struct shader_s *shader;
int fogIndex;
surfaceType_t *data; // any of srf*_t
@ -774,7 +769,7 @@ typedef struct {
msurface_t **marksurfaces;
int numfogs;
jk_fog_t *fogs;
fog_t *fogs;
int globalFog;
int startLightMapIndex;
@ -907,7 +902,7 @@ typedef struct {
#define FUNCTABLE_MASK (FUNCTABLE_SIZE-1)
// the renderer front end should never modify jk_glstate_t
// the renderer front end should never modify glstate_t
typedef struct {
int currenttextures[2];
int currenttmu;
@ -915,7 +910,7 @@ typedef struct {
int texEnv[2];
int faceCulling;
uint32_t glStateBits;
} jk_glstate_t;
} glstate_t;
typedef struct {
@ -1000,12 +995,12 @@ typedef struct {
// Image used to downsample and blur scene to. - AReis
GLuint blurImage;
jk_shader_t *defaultShader;
jk_shader_t *shadowShader;
jk_shader_t *distortionShader;
jk_shader_t *projectionShadowShader;
shader_t *defaultShader;
shader_t *shadowShader;
shader_t *distortionShader;
shader_t *projectionShadowShader;
jk_shader_t *sunShader;
shader_t *sunShader;
int numLightmaps;
image_t *lightmaps[MAX_LIGHTMAPS];
@ -1051,8 +1046,8 @@ typedef struct {
// shader indexes from drawsurfs will be looked up in sortedShaders[]
// lower indexed sortedShaders must be rendered first (opaque surfaces before translucent)
int numShaders;
jk_shader_t *shaders[MAX_SHADERS];
jk_shader_t *sortedShaders[MAX_SHADERS];
shader_t *shaders[MAX_SHADERS];
shader_t *sortedShaders[MAX_SHADERS];
int iNumDeniedShaders; // used for error-messages only
int numSkins;
@ -1081,7 +1076,7 @@ void R_Images_DeleteImage(image_t *pImage);
extern backEndState_t backEnd;
extern trGlobals_t tr;
extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init
extern jk_glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
extern window_t window;
@ -1241,10 +1236,10 @@ void R_AddLightningBoltSurfaces( trRefEntity_t *e );
void R_AddPolygonSurfaces( void );
void R_DecomposeSort( unsigned sort, int *entityNum, jk_shader_t **shader,
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
int *fogNum, int *dlightMap );
void R_AddDrawSurf( const surfaceType_t *surface, const jk_shader_t *shader, int fogIndex, int dlightMap );
void R_AddDrawSurf( const surfaceType_t *surface, const shader_t *shader, int fogIndex, int dlightMap );
#define CULL_IN 0 // completely unclipped
@ -1314,7 +1309,7 @@ void RE_GetScreenShot(byte *data, int w, int h);
byte* RE_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip);
void RE_TempRawImage_CleanUp();
void RE_BeginRegistration( glconfig_t *glconfig, intptr_t pVrClientInfo );
void RE_BeginRegistration( glconfig_t *glconfig );
void RE_LoadWorldMap( const char *mapname );
void RE_SetWorldVisData( const byte *vis );
qhandle_t RE_RegisterModel( const char *name );
@ -1338,8 +1333,7 @@ model_t *R_AllocModel( void );
void R_Init( void );
image_t *R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, qboolean allowTC, int glWrapClampMode );
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height,
GLenum format, qboolean mipmap, qboolean allowPicmip, qboolean allowTC, int glWrapClampMode, bool bRectangle = false );
image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, GLenum format, qboolean mipmap, qboolean allowPicmip, qboolean allowTC, int wrapClampMode);
qboolean R_GetModeInfo( int *width, int *height, int mode );
@ -1373,17 +1367,16 @@ extern const byte stylesDefault[MAXLIGHTMAPS];
qhandle_t RE_RegisterShader( const char *name );
qhandle_t RE_RegisterShaderNoMip( const char *name );
jk_shader_t *R_FindShader( const char *name, const int *lightmapIndex, const byte *styles, qboolean mipRawImage );
jk_shader_t *R_GetShaderByHandle( qhandle_t hShader );
shader_t *R_FindShader( const char *name, const int *lightmapIndex, const byte *styles, qboolean mipRawImage );
shader_t *R_GetShaderByHandle( qhandle_t hShader );
void R_InitShaders( void );
void R_ShaderList_f( void );
//
// tr_arb.c
//
#ifndef HAVE_GLES
void ARB_InitGlowShaders( void );
#endif
/*
====================================================================
@ -1424,7 +1417,7 @@ struct shaderCommands_s
stageVars_t svars QALIGN(16);
jk_shader_t *shader;
shader_t *shader;
int fogNum;
int dlightBits; // or together of all vertexDlightBits
@ -1456,7 +1449,7 @@ extern shaderCommands_t tess;
extern color4ub_t styleColors[MAX_LIGHT_STYLES];
extern bool styleUpdated[MAX_LIGHT_STYLES];
void RB_BeginSurface(jk_shader_t *shader, int fogNum );
void RB_BeginSurface(shader_t *shader, int fogNum );
void RB_EndSurface(void);
void RB_CheckOverflow( int verts, int indexes );
#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);}
@ -1737,7 +1730,7 @@ typedef struct {
typedef struct {
int commandId;
jk_shader_t *shader;
shader_t *shader;
float x, y;
float w, h;
float s1, t1;
@ -1746,7 +1739,7 @@ typedef struct {
typedef struct {
int commandId;
jk_shader_t *shader;
shader_t *shader;
float x, y;
float w, h;
float s1, t1;
@ -1785,7 +1778,6 @@ typedef enum {
RC_DRAW_BUFFER,
RC_SWAP_BUFFERS,
RC_WORLD_EFFECTS,
RC_FLUSH
} renderCommand_t;
@ -1826,7 +1818,6 @@ void RE_LAGoggles( void );
void RE_Scissor ( float x, float y, float w, float h);
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
void RE_SubmitStereoFrame( );
qboolean RE_ProcessDissolve(void);
qboolean RE_InitDissolve(qboolean bForceCircularExtroWipe);

View file

@ -27,7 +27,6 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "../server/exe_headers.h"
#include "tr_local.h"
#include <JKVR/VrClientInfo.h>
#if !defined(G2_H_INC)
#include "../ghoul2/G2.h"
@ -35,8 +34,6 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
trGlobals_t tr;
vr_client_info_t *vr;
static float s_flipMatrix[16] = {
// convert from our coordinate system (looking down X)
// to OpenGL's coordinate system (looking down -Z)
@ -894,7 +891,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128
float shortest = 1000000000;
int entityNum;
int numTriangles;
jk_shader_t *shader;
shader_t *shader;
int fogNum;
int dlighted;
vec4_t clip, eye;
@ -1052,7 +1049,7 @@ See if a sprite is inside a fog volume
*/
int R_SpriteFogNum( trRefEntity_t *ent ) {
int i;
jk_fog_t *fog;
fog_t *fog;
if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
return 0;
@ -1162,7 +1159,7 @@ static void R_RadixSort( drawSurf_t *source, int size )
R_AddDrawSurf
=================
*/
void R_AddDrawSurf( const surfaceType_t *surface, const jk_shader_t *shader, int fogIndex, int dlightMap )
void R_AddDrawSurf( const surfaceType_t *surface, const shader_t *shader, int fogIndex, int dlightMap )
{
int index;
@ -1193,7 +1190,7 @@ void R_AddDrawSurf( const surfaceType_t *surface, const jk_shader_t *shader, int
R_DecomposeSort
=================
*/
void R_DecomposeSort( unsigned sort, int *entityNum, jk_shader_t **shader,
void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
int *fogNum, int *dlightMap ) {
*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ];
@ -1207,7 +1204,7 @@ R_SortDrawSurfs
=================
*/
void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
jk_shader_t *shader;
shader_t *shader;
int fogNum;
int entityNum;
int dlighted;
@ -1263,7 +1260,7 @@ R_AddEntitySurfaces
*/
void R_AddEntitySurfaces (void) {
trRefEntity_t *ent;
jk_shader_t *shader;
shader_t *shader;
if ( !r_drawentities->integer ) {
return;
@ -1409,36 +1406,22 @@ void R_DebugPolygon( int color, int numPoints, float *points ) {
// draw solid shade
#ifdef HAVE_GLES
qglColor4f( color&1, (color>>1)&1, (color>>2)&1, 1.0f );
qglVertexPointer ( 3, GL_FLOAT, 0, points );
qglDrawArrays( GL_TRIANGLE_FAN, 0, numPoints );
#else
qglColor3f( color&1, (color>>1)&1, (color>>2)&1 );
qglBegin( GL_POLYGON );
for ( i = 0 ; i < numPoints ; i++ ) {
qglVertex3fv( points + i * 3 );
}
qglEnd();
#endif
// draw wireframe outline
#ifndef HAVE_GLES
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
#endif
qglDepthRange( 0, 0 );
#ifdef HAVE_GLES
qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
qglVertexPointer ( 3, GL_FLOAT, 0, points );
qglDrawArrays( GL_LINES, 0, numPoints );
#else
qglColor3f( 1, 1, 1 );
qglBegin( GL_POLYGON );
for ( i = 0 ; i < numPoints ; i++ ) {
qglVertex3fv( points + i * 3 );
}
qglEnd();
#endif
qglDepthRange( 0, 1 );
}
@ -1478,7 +1461,7 @@ void R_SetViewFogIndex (void)
{
if ( tr.world->numfogs > 1 )
{//more than just the LA goggles
jk_fog_t *fog;
fog_t *fog;
int contents = ri.SV_PointContents( tr.refdef.vieworg, 0 );
if ( (contents&CONTENTS_FOG) )
{//only take a tr.refdef.fogIndex if the tr.refdef.vieworg is actually *in* that fog brush (assumption: checks pointcontents for any CONTENTS_FOG, not that particular brush...)

View file

@ -242,7 +242,7 @@ R_ComputeFogNum
*/
static int R_ComputeFogNum( md3Header_t *header, trRefEntity_t *ent ) {
int i;
jk_fog_t *fog;
fog_t *fog;
md3Frame_t *md3Frame;
vec3_t localOrigin;
@ -304,8 +304,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
md3Header_t *header = 0;
md3Surface_t *surface = 0;
md3Shader_t *md3Shader = 0;
jk_shader_t *shader = 0;
jk_shader_t *main_shader = 0;
shader_t *shader = 0;
shader_t *main_shader = 0;
int cull;
int lod;
int fogNum;

View file

@ -30,7 +30,6 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "tr_local.h"
#include "qcommon/matcomp.h"
#include "../qcommon/sstring.h"
#include <JKVR/VrClientInfo.h>
#define LL(x) x=LittleLong(x)
#define LS(x) x=LittleShort(x)
@ -224,7 +223,7 @@ void *RE_RegisterModels_Malloc(int iSize, void *pvDiskBufferIfJustLoaded, const
const char *const psShaderName = &((char*)ModelBin.pModelDiskImage)[iShaderNameOffset];
int *const piShaderPokePtr= (int *) &((char*)ModelBin.pModelDiskImage)[iShaderPokeOffset];
jk_shader_t *sh = R_FindShader( psShaderName, lightmapsNone, stylesDefault, qtrue );
shader_t *sh = R_FindShader( psShaderName, lightmapsNone, stylesDefault, qtrue );
if ( sh->defaultShader )
{
@ -922,7 +921,7 @@ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_
// register the shaders
shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders );
for ( j = 0 ; j < surf->numShaders ; j++, shader++ ) {
jk_shader_t *sh;
shader_t *sh;
sh = R_FindShader( shader->name, lightmapsNone, stylesDefault, qtrue );
if ( sh->defaultShader ) {
@ -978,13 +977,12 @@ void CM_SetupShaderProperties(void);
/*
** RE_BeginRegistration
*/
void RE_BeginRegistration( glconfig_t *glconfigOut, intptr_t pVrClientInfo ) {
void RE_BeginRegistration( glconfig_t *glconfigOut ) {
ri.Hunk_ClearToMark();
R_Init();
*glconfigOut = glConfig;
vr = (vr_client_info_t*)pVrClientInfo;
R_IssuePendingRenderCommands();

View file

@ -85,7 +85,7 @@ void CQuickSpriteSystem::Flush(void)
if (mUseFog && r_drawfog->integer == 2 &&
mFogIndex == tr.world->globalFog)
{ //enable hardware fog when we draw this thing if applicable -rww
jk_fog_t *fog = tr.world->fogs + mFogIndex;
fog_t *fog = tr.world->fogs + mFogIndex;
qglFogf(GL_FOG_MODE, GL_EXP2);
qglFogf(GL_FOG_DENSITY, logtestExp2 / fog->parms.depthForOpaque);
@ -104,37 +104,6 @@ void CQuickSpriteSystem::Flush(void)
//
// set arrays and lock
//
#ifdef HAVE_GLES
unsigned short indexes[(mNextVert/2)*3];
int idx;
// split TRIANGLE_FAN in 2 TRIANGLES
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
qglEnableClientState( GL_COLOR_ARRAY);
/*for (int i=0; i<mNextVert; i+=4) {
qglTexCoordPointer(2, GL_FLOAT, 0, mTextureCoords+i);
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors+i );
qglVertexPointer (3, GL_FLOAT, 16, mVerts+i);
qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}*/
qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords );
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors );
qglVertexPointer (3, GL_FLOAT, 16, mVerts);
idx = 0;
for (int i=0; i<mNextVert; i+=4) {
// Triangle 1
indexes[idx+0]=i;
indexes[idx+1]=i+1;
indexes[idx+2]=i+2;
idx+=3;
// Triangle 2
indexes[idx+0]=i;
indexes[idx+1]=i+2;
indexes[idx+2]=i+3;
idx+=3;
}
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
qglEnableClientState( GL_TEXTURE_COORD_ARRAY);
qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords );
@ -150,7 +119,6 @@ void CQuickSpriteSystem::Flush(void)
}
qglDrawArrays(GL_QUADS, 0, mNextVert);
#endif
backEnd.pc.c_vertexes += mNextVert;
backEnd.pc.c_indexes += mNextVert;
@ -163,7 +131,7 @@ void CQuickSpriteSystem::Flush(void)
if (mUseFog && (r_drawfog->integer != 2 || mFogIndex != tr.world->globalFog))
#endif
{
jk_fog_t *fog = tr.world->fogs + mFogIndex;
fog_t *fog = tr.world->fogs + mFogIndex;
//
// render the fog pass
@ -174,16 +142,6 @@ void CQuickSpriteSystem::Flush(void)
//
// set arrays and lock
//
#ifdef HAVE_GLES
qglDisableClientState( GL_COLOR_ARRAY );
qglColor4ubv((GLubyte *)&fog->colorInt);
/*for (int i=0; i<mNextVert; i+=4) {
qglTexCoordPointer(2, GL_FLOAT, 0, mFogTextureCoords+i);
qglVertexPointer (3, GL_FLOAT, 16, mVerts+i);
qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}*/
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
qglTexCoordPointer( 2, GL_FLOAT, 0, mFogTextureCoords);
// qglEnableClientState( GL_TEXTURE_COORD_ARRAY); // Done above
@ -193,7 +151,6 @@ void CQuickSpriteSystem::Flush(void)
// qglVertexPointer (3, GL_FLOAT, 16, mVerts); // Done above
qglDrawArrays(GL_QUADS, 0, mNextVert);
#endif
// Second pass from fog
backEnd.pc.c_totalIndexes += mNextVert;

View file

@ -25,7 +25,6 @@ along with this program; if not, see <http://www.gnu.org/licenses/>.
#include "../server/exe_headers.h"
#include "tr_local.h"
#include <JKVR/VrClientInfo.h>
int r_firstSceneDrawSurf;
@ -42,7 +41,6 @@ int r_numpolyverts;
int skyboxportal;
int drawskyboxportal;
int hasskybox; // Used to indicate whether the BSP contains a skybox (if not, then use fog colour if applicable)
/*
====================
@ -100,7 +98,7 @@ Adds all the scene's polys into this view's drawsurf list
*/
void R_AddPolygonSurfaces( void ) {
int i;
jk_shader_t *sh;
shader_t *sh;
srfPoly_t *poly;
tr.currentEntityNum = REFENTITYNUM_WORLD;
@ -122,7 +120,7 @@ void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *vert
srfPoly_t *poly;
int i;
int fogIndex = 0;
jk_fog_t *fog;
fog_t *fog;
vec3_t bounds[2];
if ( !tr.registered ) {
@ -298,11 +296,6 @@ void RE_RenderScene( const refdef_t *fd ) {
tr.refdef.fov_x = fd->fov_x;
tr.refdef.fov_y = fd->fov_y;
memset( &parms, 0, sizeof( parms ) );
VectorCopy( fd->viewaxis[0], parms.ori.axis[0] );
VectorCopy( fd->viewaxis[1], parms.ori.axis[1] );
VectorCopy( fd->viewaxis[2], parms.ori.axis[2] );
VectorCopy( fd->vieworg, tr.refdef.vieworg );
VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
@ -391,6 +384,7 @@ void RE_RenderScene( const refdef_t *fd ) {
// The refdef takes 0-at-the-top y coordinates, so
// convert to GL's 0-at-the-bottom space
//
memset( &parms, 0, sizeof( parms ) );
parms.viewportX = tr.refdef.x;
parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
parms.viewportWidth = tr.refdef.width;
@ -401,9 +395,9 @@ void RE_RenderScene( const refdef_t *fd ) {
parms.fovY = tr.refdef.fov_y;
VectorCopy( fd->vieworg, parms.ori.origin );
// VectorCopy( fd->viewaxis[0], parms.ori.axis[0] );
// VectorCopy( fd->viewaxis[1], parms.ori.axis[1] );
// VectorCopy( fd->viewaxis[2], parms.ori.axis[2] );
VectorCopy( fd->viewaxis[0], parms.ori.axis[0] );
VectorCopy( fd->viewaxis[1], parms.ori.axis[1] );
VectorCopy( fd->viewaxis[2], parms.ori.axis[2] );
VectorCopy( fd->vieworg, parms.pvsOrigin );

View file

@ -51,8 +51,6 @@ This is just for OpenGL conformance testing, it should never be the fastest
================
*/
static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
#ifndef HAVE_GLES
qglColor4ubv( tess.svars.colors[ index ] );
if ( glState.currenttmu ) {
qglMultiTexCoord2fARB( 0, tess.svars.texcoords[ 0 ][ index ][0], tess.svars.texcoords[ 0 ][ index ][1] );
@ -61,7 +59,6 @@ static void APIENTRY R_ArrayElementDiscrete( GLint index ) {
qglTexCoord2fv( tess.svars.texcoords[ 0 ][ index ] );
}
qglVertex3fv( tess.xyz[ index ] );
#endif
}
/*
@ -70,7 +67,6 @@ R_DrawStripElements
===================
*/
#ifndef HAVE_GLES
static int c_vertexes; // for seeing how long our average strips are
static int c_begins;
static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void ( APIENTRY *element )(GLint) ) {
@ -78,14 +74,13 @@ static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void
glIndex_t last[3];
qboolean even;
qglBegin( GL_TRIANGLE_STRIP );
c_begins++;
if ( numIndexes <= 0 ) {
return;
}
qglBegin( GL_TRIANGLE_STRIP );
// prime the strip
element( indexes[0] );
element( indexes[1] );
@ -111,8 +106,8 @@ static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void
assert( (int)indexes[i+2] < tess.numVertexes );
even = qtrue;
}
// otherwise we're done with this strip so finish it and start
// a new one
// otherwise we're done with this strip so finish it and start
// a new one
else
{
qglEnd();
@ -139,8 +134,8 @@ static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void
even = qfalse;
}
// otherwise we're done with this strip so finish it and start
// a new one
// otherwise we're done with this strip so finish it and start
// a new one
else
{
qglEnd();
@ -165,8 +160,6 @@ static void R_DrawStripElements( int numIndexes, const glIndex_t *indexes, void
qglEnd();
}
#endif
/*
==================
@ -193,37 +186,13 @@ static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
if ( primitives == 2 ) {
qglDrawElements( GL_TRIANGLES,
numIndexes,
GL_INDEX_TYPE,
indexes );
return;
}
#if defined(HAVE_GLES)
if (primitives == 1 || primitives == 3)
{
// if (tess.useConstantColor)
// {
// qglDisableClientState( GL_COLOR_ARRAY );
// qglColor4ubv( tess.constantColor );
// }
/*qglDrawElements( GL_TRIANGLES,
numIndexes,
GL_INDEX_TYPE,
indexes );*/
#if 1 // VVFIXME : Temporary solution to try and increase framerate
//qglIndexedTriToStrip( numIndexes, indexes );
qglDrawElements( GL_TRIANGLES,
numIndexes,
GL_INDEX_TYPE,
indexes );
#endif
return;
}
#else // HAVE_GLES
if ( primitives == 1 ) {
R_DrawStripElements( numIndexes, indexes, qglArrayElement );
return;
@ -233,13 +202,14 @@ static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
R_DrawStripElements( numIndexes, indexes, R_ArrayElementDiscrete );
return;
}
#endif // HAVE_GLES
// anything else will cause no drawing
}
/*
=============================================================
@ -316,34 +286,103 @@ DrawTris
Draws triangle outlines for debugging
================
*/
static void DrawTris (shaderCommands_t *input) {
if (input->numVertexes <= 0) {
return;
}
static void DrawTris (shaderCommands_t *input)
{
GL_Bind( tr.whiteImage );
qglColor3f (1,1,1);
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
qglDepthRange( 0, 0 );
qglDisableClientState (GL_COLOR_ARRAY);
qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD
if (qglLockArraysEXT) {
qglLockArraysEXT(0, input->numVertexes);
GLimp_LogComment( "glLockArraysEXT\n" );
if ( r_showtriscolor->integer )
{
int i = r_showtriscolor->integer;
if (i == 42) {
i = Q_irand(0,8);
}
switch (i)
{
case 1:
qglColor3f( 1.0, 0.0, 0.0); //red
break;
case 2:
qglColor3f( 0.0, 1.0, 0.0); //green
break;
case 3:
qglColor3f( 1.0, 1.0, 0.0); //yellow
break;
case 4:
qglColor3f( 0.0, 0.0, 1.0); //blue
break;
case 5:
qglColor3f( 0.0, 1.0, 1.0); //cyan
break;
case 6:
qglColor3f( 1.0, 0.0, 1.0); //magenta
break;
case 7:
qglColor3f( 0.8f, 0.8f, 0.8f); //white/grey
break;
case 8:
qglColor3f( 0.0, 0.0, 0.0); //black
break;
}
}
else
{
qglColor3f( 1.0, 1.0, 1.0); //white
}
R_DrawElements( input->numIndexes, input->indexes );
if ( r_showtris->integer == 2 )
{
// tries to do non-xray style showtris
GL_State( GLS_POLYMODE_LINE );
if (qglUnlockArraysEXT) {
qglUnlockArraysEXT();
GLimp_LogComment( "glUnlockArraysEXT\n" );
qglEnable( GL_POLYGON_OFFSET_LINE );
qglPolygonOffset( -1, -2 );
qglDisableClientState( GL_COLOR_ARRAY );
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); // padded for SIMD
if ( qglLockArraysEXT )
{
qglLockArraysEXT( 0, input->numVertexes );
GLimp_LogComment( "glLockArraysEXT\n" );
}
R_DrawElements( input->numIndexes, input->indexes );
if ( qglUnlockArraysEXT )
{
qglUnlockArraysEXT( );
GLimp_LogComment( "glUnlockArraysEXT\n" );
}
qglDisable( GL_POLYGON_OFFSET_LINE );
}
else
{
// same old showtris
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
qglDepthRange( 0, 0 );
qglDisableClientState (GL_COLOR_ARRAY);
qglDisableClientState (GL_TEXTURE_COORD_ARRAY);
qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD
if (qglLockArraysEXT) {
qglLockArraysEXT(0, input->numVertexes);
GLimp_LogComment( "glLockArraysEXT\n" );
}
R_DrawElements( input->numIndexes, input->indexes );
if (qglUnlockArraysEXT) {
qglUnlockArraysEXT();
GLimp_LogComment( "glUnlockArraysEXT\n" );
}
qglDepthRange( 0, 1 );
}
qglDepthRange( 0, 1 );
}
/*
@ -362,9 +401,6 @@ static void DrawNormals (shaderCommands_t *input) {
qglDepthRange( 0, 0 ); // never occluded
GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
#ifdef HAVE_GLES
/*SEB *TODO* */
#else
qglBegin (GL_LINES);
for (i = 0 ; i < input->numVertexes ; i++) {
qglVertex3fv (input->xyz[i]);
@ -372,7 +408,6 @@ static void DrawNormals (shaderCommands_t *input) {
qglVertex3fv (temp);
}
qglEnd ();
#endif
qglDepthRange( 0, 1 );
}
@ -387,9 +422,9 @@ because a surface may be forced to perform a RB_End due
to overflow.
==============
*/
void RB_BeginSurface( jk_shader_t *shader, int fogNum ) {
// jk_shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
jk_shader_t *state = shader;
void RB_BeginSurface( shader_t *shader, int fogNum ) {
// shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
shader_t *state = shader;
tess.numIndexes = 0;
tess.numVertexes = 0;
@ -1296,7 +1331,7 @@ Blends a fog texture on top of everything else
===================
*/
static void RB_FogPass( void ) {
jk_fog_t *fog;
fog_t *fog;
int i;
qglEnableClientState( GL_COLOR_ARRAY );
@ -1461,7 +1496,7 @@ static void ComputeColors( shaderStage_t *pStage, alphaGen_t forceAlphaGen, colo
break;
case CGEN_FOG:
{
const jk_fog_t *fog = tr.world->fogs + tess.fogNum;
const fog_t *fog = tr.world->fogs + tess.fogNum;
for ( i = 0; i < tess.numVertexes; i++ ) {
byteAlias_t *ba = (byteAlias_t *)&tess.svars.colors[i];
@ -1769,7 +1804,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
#ifndef JK2_MODE
bool UseGLFog = false;
bool FogColorChange = false;
jk_fog_t *fog = NULL;
fog_t *fog = NULL;
if (tess.fogNum && tess.shader->fogPass && (tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs)
&& r_drawfog->value == 2)

View file

@ -821,7 +821,7 @@ void RB_CalcFogTexCoords( float *st ) {
float s, t;
float eyeT;
qboolean eyeOutside;
jk_fog_t *fog;
fog_t *fog;
vec3_t localVec;
vec4_t fogDistanceVector, fogDepthVector;
@ -1057,12 +1057,6 @@ void RB_CalcSpecularAlpha( unsigned char *alphas ) {
alphas += 3;
//What the hell is this doing as a NaN?!?
if (Q_isnan(backEnd.ori.viewOrigin[0]))
{
return;
}
numVertexes = tess.numVertexes;
for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
float ilength;

View file

@ -35,7 +35,7 @@ static char *s_shaderText;
// the shader is parsed into these global variables, then copied into
// dynamically allocated memory if it is valid.
static shaderStage_t stages[MAX_SHADER_STAGES];
static jk_shader_t shader;
static shader_t shader;
static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
// Hash value (generated using the generateHashValueForText function) for the original
@ -48,7 +48,7 @@ static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
#define FILE_HASH_SIZE 1024
static jk_shader_t* sh_hashTable[FILE_HASH_SIZE];
static shader_t* sh_hashTable[FILE_HASH_SIZE];
const int lightmapsNone[MAXLIGHTMAPS] =
{
@ -130,7 +130,7 @@ way to ask for different implicit lighting modes (vertex, lightmap, etc)
*/
qhandle_t RE_RegisterShaderLightMap( const char *name, const int *lightmapIndex, const byte *styles )
{
jk_shader_t *sh;
shader_t *sh;
if ( strlen( name ) >= MAX_QPATH ) {
Com_Printf( "Shader name exceeds MAX_QPATH\n" );
@ -159,10 +159,10 @@ Will always return a valid shader, but it might be the
default shader if the real one can't be found.
==================
*/
jk_shader_t *R_FindShaderByName( const char *name ) {
shader_t *R_FindShaderByName( const char *name ) {
char strippedName[MAX_QPATH];
int hash;
jk_shader_t *sh;
shader_t *sh;
if ( (name==NULL) || (name[0] == 0) ) { // bk001205
return tr.defaultShader;
@ -193,7 +193,7 @@ jk_shader_t *R_FindShaderByName( const char *name ) {
void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) {
char strippedName[MAX_QPATH];
int hash;
jk_shader_t *sh, *sh2;
shader_t *sh, *sh2;
qhandle_t h;
sh = R_FindShaderByName( shaderName );
@ -2698,7 +2698,7 @@ static void FixRenderCommandList( int newShader ) {
{
int i;
drawSurf_t *drawSurf;
jk_shader_t *shader;
shader_t *shader;
int fogNum;
int entityNum;
int dlightMap;
@ -2758,7 +2758,7 @@ Sets shader->sortedIndex
static void SortNewShader( void ) {
int i;
float sort;
jk_shader_t *newShader;
shader_t *newShader;
newShader = tr.shaders[ tr.numShaders - 1 ];
sort = newShader->sort;
@ -2785,8 +2785,8 @@ static void SortNewShader( void ) {
GeneratePermanentShader
====================
*/
static jk_shader_t *GeneratePermanentShader( void ) {
jk_shader_t *newShader;
static shader_t *GeneratePermanentShader( void ) {
shader_t *newShader;
int i, b;
int size;
@ -2796,7 +2796,7 @@ static jk_shader_t *GeneratePermanentShader( void ) {
return tr.defaultShader;
}
newShader = (jk_shader_t *)R_Hunk_Alloc( sizeof( jk_shader_t ), qtrue );
newShader = (shader_t *)R_Hunk_Alloc( sizeof( shader_t ), qtrue );
*newShader = shader;
@ -2967,7 +2967,7 @@ Returns a freshly allocated shader with all the needed info
from the current global working shader
=========================
*/
static jk_shader_t *FinishShader( void ) {
static shader_t *FinishShader( void ) {
int stage, lmStage, stageIndex;
qboolean hasLightmapStage;
@ -3323,7 +3323,7 @@ static const char *FindShaderInShaderText( const char *shadername ) {
#endif
}
inline qboolean IsShader(jk_shader_t *sh, const char *name, const int *lightmapIndex, const byte *styles)
inline qboolean IsShader(shader_t *sh, const char *name, const int *lightmapIndex, const byte *styles)
{
int i;
@ -3422,12 +3422,12 @@ and src*dest blending applied with the texture, as apropriate for
most world construction surfaces.
===============
*/
jk_shader_t *R_FindShader( const char *name, const int *lightmapIndex, const byte *styles, qboolean mipRawImage ) {
shader_t *R_FindShader( const char *name, const int *lightmapIndex, const byte *styles, qboolean mipRawImage ) {
char strippedName[MAX_QPATH];
int hash;
const char *shaderText;
image_t *image;
jk_shader_t *sh;
shader_t *sh;
if ( strlen( name ) >= MAX_QPATH ) {
Com_Printf( S_COLOR_RED"Shader name exceeds MAX_QPATH! %s\n",name );
@ -3569,7 +3569,7 @@ way to ask for different implicit lighting modes (vertex, lightmap, etc)
====================
*/
qhandle_t RE_RegisterShader( const char *name ) {
jk_shader_t *sh;
shader_t *sh;
sh = R_FindShader( name, lightmaps2d, stylesDefault, qtrue );
@ -3594,7 +3594,7 @@ For menu graphics that should never be picmiped
====================
*/
qhandle_t RE_RegisterShaderNoMip( const char *name ) {
jk_shader_t *sh;
shader_t *sh;
sh = R_FindShader( name, lightmaps2d, stylesDefault, qfalse );
@ -3616,10 +3616,10 @@ qhandle_t RE_RegisterShaderNoMip( const char *name ) {
R_GetShaderByHandle
When a handle is passed in by another module, this range checks
it and returns a valid (possibly default) jk_shader_t to be used internally.
it and returns a valid (possibly default) shader_t to be used internally.
====================
*/
jk_shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
if ( hShader < 0 ) {
ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
return tr.defaultShader;
@ -3642,7 +3642,7 @@ A second parameter will cause it to print in sorted order
void R_ShaderList_f (void) {
int i;
int count;
jk_shader_t *shader;
shader_t *shader;
ri.Printf (PRINT_ALL, "-----------------------\n");
@ -3851,9 +3851,7 @@ static void CreateInternalShaders( void ) {
tr.distortionShader = FinishShader();
shader.defaultShader = true;
#ifndef HAVE_GLES
ARB_InitGlowShaders();
#endif
}
static void CreateExternalShaders( void ) {

View file

@ -49,10 +49,7 @@ static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
static int numEdgeDefs[SHADER_MAX_VERTEXES];
static int facing[SHADER_MAX_INDEXES/3];
static vec3_t shadowXyz[SHADER_MAX_VERTEXES];
#ifdef HAVE_GLES
static unsigned short indexes[6 * MAX_EDGE_DEFS * SHADER_MAX_VERTEXES + SHADER_MAX_INDEXES * 2];
static int idx = 0;
#endif
void R_AddEdgeDef( int i1, int i2, int facing ) {
int c;
@ -72,8 +69,8 @@ void R_RenderShadowEdges( void ) {
int c;
int j;
int i2;
//int c_edges, c_rejected;
#if 0
int c_edges, c_rejected;
int c2, k;
int hit[2];
#endif
@ -91,10 +88,6 @@ void R_RenderShadowEdges( void ) {
c_rejected = 0;
#endif
#ifdef HAVE_GLES
idx = 0;
#endif
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
c = numEdgeDefs[ i ];
for ( j = 0 ; j < c ; j++ ) {
@ -107,23 +100,12 @@ void R_RenderShadowEdges( void ) {
//we are going to render all edges even though it is a tiny bit slower. -rww
#if 1
i2 = edgeDefs[ i ][ j ].i2;
#ifdef HAVE_GLES
// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRIANGLE_STRIP call
// even if it seems less efficiant, it's faster on the PANDORA
indexes[idx++] = i;
indexes[idx++] = i + tess.numVertexes;
indexes[idx++] = i2;
indexes[idx++] = i2;
indexes[idx++] = i + tess.numVertexes;
indexes[idx++] = i2 + tess.numVertexes;
#else
qglBegin( GL_TRIANGLE_STRIP );
qglVertex3fv( tess.xyz[ i ] );
qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
qglVertex3fv( tess.xyz[ i2 ] );
qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
qglVertex3fv( tess.xyz[ i ] );
qglVertex3fv( shadowXyz[ i ] );
qglVertex3fv( tess.xyz[ i2 ] );
qglVertex3fv( shadowXyz[ i2 ] );
qglEnd();
#endif
#else
hit[0] = 0;
hit[1] = 0;
@ -138,13 +120,12 @@ void R_RenderShadowEdges( void ) {
// if it doesn't share the edge with another front facing
// triangle, it is a sil edge
if (hit[1] != 1)
{
if ( hit[ 1 ] == 0 ) {
qglBegin( GL_TRIANGLE_STRIP );
qglVertex3fv( tess.xyz[ i ] );
qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
qglVertex3fv( shadowXyz[ i ] );
qglVertex3fv( tess.xyz[ i2 ] );
qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
qglVertex3fv( shadowXyz[ i2 ] );
qglEnd();
c_edges++;
} else {
@ -170,30 +151,17 @@ void R_RenderShadowEdges( void ) {
o2 = tess.indexes[ i*3 + 1 ];
o3 = tess.indexes[ i*3 + 2 ];
#ifdef HAVE_GLES
indexes[idx++]=o1;
indexes[idx++]=o2;
indexes[idx++]=o3;
indexes[idx++]=o3 + tess.numVertexes;
indexes[idx++]=o2 + tess.numVertexes;
indexes[idx++]=o1 + tess.numVertexes;
#else
qglBegin(GL_TRIANGLES);
qglVertex3fv(tess.xyz[o1]);
qglVertex3fv(tess.xyz[o2]);
qglVertex3fv(tess.xyz[o3]);
qglVertex3fv(tess.xyz[o1]);
qglVertex3fv(tess.xyz[o2]);
qglVertex3fv(tess.xyz[o3]);
qglEnd();
qglBegin(GL_TRIANGLES);
qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
qglVertex3fv(shadowXyz[o3]);
qglVertex3fv(shadowXyz[o2]);
qglVertex3fv(shadowXyz[o1]);
qglEnd();
#endif
}
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#endif
#endif
}
@ -260,11 +228,6 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
int numTris;
vec3_t lightDir;
// we can only do this if we have enough space in the vertex buffers
if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
return;
}
if ( glConfig.stencilBits < 4 ) {
return;
}
@ -289,16 +252,16 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
VectorAdd(tess.xyz[i], backEnd.ori.origin, worldxyz);
groundDist = worldxyz[2] - backEnd.currentEntity->e.shadowPlane;
groundDist += 16.0f; //fudge factor
VectorMA( tess.xyz[i], -groundDist, lightDir, tess.xyz[i+tess.numVertexes] );
VectorMA( tess.xyz[i], -groundDist, lightDir, shadowXyz[i] );
}
#else
if (lightPos)
{
for ( i = 0 ; i < tess.numVertexes ; i++ )
{
tess.xyz[i+tess.numVertexes][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f);
tess.xyz[i+tess.numVertexes][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f);
tess.xyz[i+tess.numVertexes][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f);
shadowXyz[i][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f);
shadowXyz[i][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f);
shadowXyz[i][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f);
}
}
else
@ -307,7 +270,7 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
// project vertexes away from light direction
for ( i = 0 ; i < tess.numVertexes ; i++ ) {
VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] );
VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] );
}
}
#endif
@ -344,8 +307,8 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
planeEq[1] = v1[2]*(v2[0]-v3[0]) + v2[2]*(v3[0]-v1[0]) + v3[2]*(v1[0]-v2[0]);
planeEq[2] = v1[0]*(v2[1]-v3[1]) + v2[0]*(v3[1]-v1[1]) + v3[0]*(v1[1]-v2[1]);
planeEq[3] = -( v1[0]*( v2[1]*v3[2] - v3[1]*v2[2] ) +
v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) +
v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) );
v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) +
v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) );
d = planeEq[0]*lightPos[0]+
planeEq[1]*lightPos[1]+
@ -383,52 +346,30 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
//qglDisable(GL_DEPTH_TEST);
#endif
#ifdef HAVE_GLES
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
qglVertexPointer (3, GL_FLOAT, 16, tess.xyz);
#endif
#ifdef _STENCIL_REVERSE
qglDepthFunc(GL_LESS);
//now using the Carmack Reverse<tm> -rww
if ( backEnd.viewParms.isMirror ) {
//qglCullFace( GL_BACK );
GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
if (glConfig.doStencilShadowsInOneDrawcall)
{
GL_Cull(CT_TWO_SIDED);
qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
R_RenderShadowEdges();
//qglCullFace( GL_FRONT );
qglDisable(GL_STENCIL_TEST);
}
else
{
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
} else {
//qglCullFace( GL_FRONT );
GL_Cull(CT_FRONT_SIDED);
qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
R_RenderShadowEdges();
//qglCullFace( GL_BACK );
GL_Cull(CT_BACK_SIDED);
qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
}
qglDepthFunc(GL_LEQUAL);
@ -443,11 +384,7 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
qglCullFace( GL_BACK );
qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
} else {
qglCullFace( GL_BACK );
qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
@ -457,24 +394,13 @@ void RB_DoShadowTessEnd( vec3_t lightPos )
qglCullFace( GL_FRONT );
qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
#ifdef HAVE_GLES
qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
#else
R_RenderShadowEdges();
#endif
}
#endif
// reenable writing to the color buffer
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
#ifdef HAVE_GLES
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
#endif
#ifdef _DEBUG_STENCIL_SHADOWS
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
@ -500,7 +426,7 @@ void RB_ShadowFinish( void ) {
}
#ifdef _DEBUG_STENCIL_SHADOWS
return;
return;
#endif
qglEnable( GL_STENCIL_TEST );
@ -520,7 +446,7 @@ void RB_ShadowFinish( void ) {
GL_Bind( tr.whiteImage );
qglPushMatrix();
qglLoadIdentity ();
qglLoadIdentity ();
// qglColor3f( 0.6f, 0.6f, 0.6f );
// GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
@ -532,33 +458,12 @@ void RB_ShadowFinish( void ) {
//GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
#ifdef HAVE_GLES
GLfloat vtx[] = {
-100, 100, -10,
100, 100, -10,
100, -100, -10,
-100, -100, -10
};
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
qglVertexPointer ( 3, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
#else
qglBegin( GL_QUADS );
qglVertex3f( -100, 100, -10 );
qglVertex3f( 100, 100, -10 );
qglVertex3f( 100, -100, -10 );
qglVertex3f( -100, -100, -10 );
qglEnd ();
#endif
qglColor4f(1,1,1,1);
qglDisable( GL_STENCIL_TEST );
@ -677,11 +582,7 @@ void RB_CaptureScreenImage(void)
cY = 0;
}
#ifdef HAVE_GLES
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cX, cY, radX, radY, 0);
#else
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, cX, cY, radX, radY, 0);
#endif
}
@ -754,49 +655,20 @@ void RB_DistortionFill(void)
GL_State(0);
}
#ifdef HAVE_GLES
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );
GLfloat tex[] = {
0+spost2, 1-spost,
0+spost2, 0+spost,
1-spost2, 0+spost,
1-spost2, 1-spost
};
GLfloat vtx[] = {
0, 0,
0, glConfig.vidHeight,
glConfig.vidWidth, glConfig.vidHeight,
glConfig.vidWidth, 0
};
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
/* if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );*/
#else
qglBegin(GL_QUADS);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglEnd();
#endif
if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f)
{ //no overrides
@ -825,52 +697,22 @@ void RB_DistortionFill(void)
}
spost2 *= 0.2f;
#ifdef HAVE_GLES
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
/* GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (glcol)
qglDisableClientState( GL_COLOR_ARRAY );*/
GLfloat tex[] = {
0+spost2, 1-spost,
0+spost2, 0+spost,
1-spost2, 0+spost,
1-spost2, 1-spost
};
GLfloat vtx[] = {
0, 0,
0, glConfig.vidHeight,
glConfig.vidWidth, glConfig.vidHeight,
glConfig.vidWidth, 0
};
qglTexCoordPointer( 2, GL_FLOAT, 0, tex );
qglVertexPointer ( 2, GL_FLOAT, 0, vtx );
qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
#else
qglBegin(GL_QUADS);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglColor4f(1.0f, 1.0f, 1.0f, alpha);
qglTexCoord2f(0+spost2, 1-spost);
qglVertex2f(0, 0);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(0+spost2, 0+spost);
qglVertex2f(0, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 0+spost);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglTexCoord2f(1-spost2, 1-spost);
qglVertex2f(glConfig.vidWidth, 0);
qglEnd();
#endif
}
#ifdef HAVE_GLES
if (glcol)
qglEnableClientState( GL_COLOR_ARRAY );
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
//pop the view matrices back
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();

View file

@ -371,65 +371,25 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max
int s, t;
GL_Bind( image );
#ifdef HAVE_GLES
GLfloat vtx[3*1024]; // arbitrary sized
GLfloat tex[2*1024];
int idx;
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (!text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
{
#ifdef HAVE_GLES
idx=0;
#else
qglBegin( GL_TRIANGLE_STRIP );
#endif
for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
#ifdef HAVE_GLES
memcpy(tex+idx*2, s_skyTexCoords[t][s], sizeof(GLfloat)*2);
memcpy(vtx+idx*3, s_skyPoints[t][s], sizeof(GLfloat)*3);
idx++;
memcpy(tex+idx*2, s_skyTexCoords[t+1][s], sizeof(GLfloat)*2);
memcpy(vtx+idx*3, s_skyPoints[t+1][s], sizeof(GLfloat)*3);
idx++;
#else
qglTexCoord2fv( s_skyTexCoords[t][s] );
qglVertex3fv( s_skyPoints[t][s] );
qglTexCoord2fv( s_skyTexCoords[t+1][s] );
qglVertex3fv( s_skyPoints[t+1][s] );
#endif
}
#ifdef HAVE_GLES
qglVertexPointer (3, GL_FLOAT, 0, vtx);
qglTexCoordPointer(2, GL_FLOAT, 0, tex);
qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx);
#else
qglEnd();
#endif
}
#ifdef HAVE_GLES
if (glcol)
qglEnableClientState(GL_COLOR_ARRAY);
if (!text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
}
static void DrawSkyBox( jk_shader_t *shader )
static void DrawSkyBox( shader_t *shader )
{
int i;
@ -549,7 +509,7 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad
}
}
static void FillCloudBox( const jk_shader_t *shader, int stage )
static void FillCloudBox( const shader_t *shader, int stage )
{
int i;
@ -845,8 +805,6 @@ void RB_StageIteratorSky( void ) {
return;
}
hasskybox = 1;
// go through all the polygons and project them onto
// the sky box to see which blocks on each side need
// to be drawn

View file

@ -1096,38 +1096,29 @@ static void RB_SurfaceBeam( void )
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
qglColor3f( 1, 0, 0 );
#ifdef HAVE_GLES
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (glcol)
qglDisableClientState(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
GLfloat vtx[NUM_BEAM_SEGS*6+6];
for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
memcpy(vtx+i*6, start_points[ i % NUM_BEAM_SEGS], sizeof(GLfloat)*3);
memcpy(vtx+i*6+3, end_points[ i % NUM_BEAM_SEGS], sizeof(GLfloat)*3);
switch(e->skinNum)
{
case 1://Green
qglColor3f( 0, 1, 0 );
break;
case 2://Blue
qglColor3f( 0.5, 0.5, 1 );
break;
case 0://red
default:
qglColor3f( 1, 0, 0 );
break;
}
qglVertexPointer (3, GL_FLOAT, 0, vtx);
qglDrawArrays(GL_TRIANGLE_STRIP, 0, NUM_BEAM_SEGS*2+2);
if (glcol)
qglEnableClientState(GL_COLOR_ARRAY);
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
#else
qglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
qglVertex3fv( start_points[ i % NUM_BEAM_SEGS] );
qglVertex3fv( end_points[ i % NUM_BEAM_SEGS] );
}
qglEnd();
#endif
}
//------------------
// DoSprite
//------------------
@ -1929,38 +1920,6 @@ static void RB_SurfaceAxis( void ) {
GL_Bind( tr.whiteImage );
GL_State( GLS_DEFAULT );
qglLineWidth( 3 );
#ifdef HAVE_GLES
GLfloat col[] = {
1,0,0, 1,
1,0,0, 1,
0,1,0, 1,
0,1,0, 1,
0,0,1, 1,
0,0,1, 1
};
GLfloat vtx[] = {
0,0,0,
16,0,0,
0,0,0,
0,16,0,
0,0,0,
0,0,16
};
GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
if (text)
qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
if (!glcol)
qglEnableClientState( GL_COLOR_ARRAY);
qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, col );
qglVertexPointer (3, GL_FLOAT, 0, vtx);
qglDrawArrays(GL_LINES, 0, 6);
if (text)
qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
if (!glcol)
qglDisableClientState( GL_COLOR_ARRAY);
#else
qglBegin( GL_LINES );
qglColor3f( 1,0,0 );
qglVertex3f( 0,0,0 );
@ -1972,7 +1931,6 @@ static void RB_SurfaceAxis( void ) {
qglVertex3f( 0,0,0 );
qglVertex3f( 0,0,16 );
qglEnd();
#endif
qglLineWidth( 1 );
}
@ -2040,7 +1998,7 @@ static bool RB_TestZFlare( vec3_t point) {
// if the point is off the screen, don't bother adding it
// calculate screen coordinates and depth
R_TransformModelToClip( point, backEnd.ori.modelMatrix,
backEnd.viewParms.projectionMatrix, eye, clip );
backEnd.viewParms.projectionMatrix, eye, clip );
// check to see if the point is completely off screen
for ( i = 0 ; i < 3 ; i++ ) {
@ -2052,7 +2010,7 @@ static bool RB_TestZFlare( vec3_t point) {
R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window );
if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth
|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
return qfalse; // shouldn't happen, since we check the clip[] above, except for FP rounding
}
@ -2062,9 +2020,6 @@ static bool RB_TestZFlare( vec3_t point) {
float screenZ;
// read back the z buffer contents
#if defined(HAVE_GLES)
depth = 0.0f;
#else
if ( r_flares->integer !=1 ) { //skipping the the z-test
return true;
}
@ -2072,10 +2027,9 @@ static bool RB_TestZFlare( vec3_t point) {
// don't bother with another sync
glState.finishCalled = qfalse;
qglReadPixels( backEnd.viewParms.viewportX + window[0],backEnd.viewParms.viewportY + window[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
#endif
screenZ = backEnd.viewParms.projectionMatrix[14] /
( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
visible = ( -eye[2] - -screenZ ) < 24;
return visible;
@ -2138,11 +2092,7 @@ void RB_SurfaceFlare( srfFlare_t *surf ) {
void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {
// all appropriate state must be set in RB_BeginSurface
// this isn't implemented yet...
#ifdef HAVE_GLES
assert(0);
#else
qglCallList( surf->listNum );
#endif
}
void RB_SurfaceSkip( void *surf ) {

View file

@ -113,7 +113,7 @@ added to the sorting list.
This will also allow mirrors on both sides of a model without recursion.
================
*/
static qboolean R_CullSurface( surfaceType_t *surface, jk_shader_t *shader ) {
static qboolean R_CullSurface( surfaceType_t *surface, shader_t *shader ) {
srfSurfaceFace_t *sface;
float d;