From e7dbd29c6c14c9395649cd963a45c0fc09911349 Mon Sep 17 00:00:00 2001 From: Richard Allen Date: Sun, 21 Jul 2013 00:47:18 +0000 Subject: [PATCH] Removing a old version of our Renderer. The history of the renderergl2 folder is that when we added it to Reaction we called it renderergl2 but months later it was also added to ioq3 under the name rend2. To stay compatible with ioq3 we made the same change here. However we neglected to remove the old renderergl2 folder which has now become an issue since ioq3 has now decided to rename rend2 back to renderergl2 :) --- code/cgame/cg_local.h | 2 +- code/renderergl2/qgl.h | 755 ------ code/renderergl2/tr_animation.c | 658 ----- code/renderergl2/tr_backend.c | 1739 -------------- code/renderergl2/tr_bsp.c | 3319 -------------------------- code/renderergl2/tr_cmds.c | 667 ------ code/renderergl2/tr_curve.c | 806 ------- code/renderergl2/tr_extensions.c | 682 ------ code/renderergl2/tr_extramath.c | 240 -- code/renderergl2/tr_extramath.h | 104 - code/renderergl2/tr_extratypes.h | 44 - code/renderergl2/tr_fbo.c | 822 ------- code/renderergl2/tr_fbo.h | 64 - code/renderergl2/tr_flares.c | 532 ----- code/renderergl2/tr_font.c | 552 ----- code/renderergl2/tr_glsl.c | 2674 --------------------- code/renderergl2/tr_image.c | 3419 -------------------------- code/renderergl2/tr_init.c | 1538 ------------ code/renderergl2/tr_light.c | 455 ---- code/renderergl2/tr_local.h | 2819 ---------------------- code/renderergl2/tr_main.c | 2878 ---------------------- code/renderergl2/tr_marks.c | 466 ---- code/renderergl2/tr_mesh.c | 405 ---- code/renderergl2/tr_model.c | 1580 ------------ code/renderergl2/tr_model_iqm.c | 1058 -------- code/renderergl2/tr_postprocess.c | 490 ---- code/renderergl2/tr_postprocess.h | 33 - code/renderergl2/tr_scene.c | 515 ---- code/renderergl2/tr_shade.c | 1798 -------------- code/renderergl2/tr_shade_calc.c | 1339 ----------- code/renderergl2/tr_shader.c | 3710 ----------------------------- code/renderergl2/tr_shadows.c | 343 --- code/renderergl2/tr_sky.c | 955 -------- code/renderergl2/tr_subs.c | 48 - code/renderergl2/tr_surface.c | 1690 ------------- code/renderergl2/tr_vbo.c | 932 -------- code/renderergl2/tr_world.c | 851 ------- 37 files changed, 1 insertion(+), 40981 deletions(-) delete mode 100644 code/renderergl2/qgl.h delete mode 100644 code/renderergl2/tr_animation.c delete mode 100644 code/renderergl2/tr_backend.c delete mode 100644 code/renderergl2/tr_bsp.c delete mode 100644 code/renderergl2/tr_cmds.c delete mode 100644 code/renderergl2/tr_curve.c delete mode 100644 code/renderergl2/tr_extensions.c delete mode 100644 code/renderergl2/tr_extramath.c delete mode 100644 code/renderergl2/tr_extramath.h delete mode 100644 code/renderergl2/tr_extratypes.h delete mode 100644 code/renderergl2/tr_fbo.c delete mode 100644 code/renderergl2/tr_fbo.h delete mode 100644 code/renderergl2/tr_flares.c delete mode 100644 code/renderergl2/tr_font.c delete mode 100644 code/renderergl2/tr_glsl.c delete mode 100644 code/renderergl2/tr_image.c delete mode 100644 code/renderergl2/tr_init.c delete mode 100644 code/renderergl2/tr_light.c delete mode 100644 code/renderergl2/tr_local.h delete mode 100644 code/renderergl2/tr_main.c delete mode 100644 code/renderergl2/tr_marks.c delete mode 100644 code/renderergl2/tr_mesh.c delete mode 100644 code/renderergl2/tr_model.c delete mode 100644 code/renderergl2/tr_model_iqm.c delete mode 100644 code/renderergl2/tr_postprocess.c delete mode 100644 code/renderergl2/tr_postprocess.h delete mode 100644 code/renderergl2/tr_scene.c delete mode 100644 code/renderergl2/tr_shade.c delete mode 100644 code/renderergl2/tr_shade_calc.c delete mode 100644 code/renderergl2/tr_shader.c delete mode 100644 code/renderergl2/tr_shadows.c delete mode 100644 code/renderergl2/tr_sky.c delete mode 100644 code/renderergl2/tr_subs.c delete mode 100644 code/renderergl2/tr_surface.c delete mode 100644 code/renderergl2/tr_vbo.c delete mode 100644 code/renderergl2/tr_world.c diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 224f8568..72cc4d7b 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -405,7 +405,7 @@ // #include "../qcommon/q_shared.h" #include "../renderer/tr_types.h" -#include "../renderergl2/tr_extratypes.h" +#include "../rend2/tr_extratypes.h" #include "../game/bg_public.h" #include "cg_public.h" diff --git a/code/renderergl2/qgl.h b/code/renderergl2/qgl.h deleted file mode 100644 index 6013a87c..00000000 --- a/code/renderergl2/qgl.h +++ /dev/null @@ -1,755 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -/* -** QGL.H -*/ - -#ifndef __QGL_H__ -#define __QGL_H__ - -#ifdef USE_LOCAL_HEADERS -# include "SDL_opengl.h" -#else -# include -#endif - -extern void (APIENTRYP qglActiveTextureARB) (GLenum texture); -extern void (APIENTRYP qglClientActiveTextureARB) (GLenum texture); -extern void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t); - -extern void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count); -extern void (APIENTRYP qglUnlockArraysEXT) (void); - -// GL_EXT_draw_range_elements -extern void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); - -// GL_EXT_multi_draw_arrays -extern void (APIENTRY * qglMultiDrawArraysEXT) (GLenum, GLint *, GLsizei *, GLsizei); -extern void (APIENTRY * qglMultiDrawElementsEXT) (GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei); - -// GL_ARB_shading_language_100 -#ifndef GL_ARB_shading_language_100 -#define GL_ARB_shading_language_100 -#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C -#endif - -// GL_ARB_vertex_program -extern void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); -extern void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *); -extern void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized, - GLsizei stride, const GLvoid * pointer); -extern void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index); -extern void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index); - -// GL_ARB_vertex_buffer_object -extern void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer); -extern void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers); -extern void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers); -extern GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer); -extern void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); -extern void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); -extern void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data); -extern void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params); -extern void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params); - -// GL_ARB_shader_objects -extern void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj); -extern GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname); -extern void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj); -extern GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType); -extern void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string, - const GLint * length); -extern void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj); -extern GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void); -extern void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj); -extern void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj); -extern void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj); -extern void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj); -extern void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0); -extern void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1); -extern void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -extern void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -extern void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0); -extern void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1); -extern void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2); -extern void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -extern void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value); -extern void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value); -extern void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value); -extern void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value); -extern void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value); -extern void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value); -extern void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value); -extern void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -extern void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -extern void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -extern void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params); -extern void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params); -extern void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); -extern void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, - GLhandleARB * obj); -extern GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name); -extern void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length, - GLint * size, GLenum * type, GLcharARB * name); -extern void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params); -extern void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params); -extern void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source); - -// GL_ARB_vertex_shader -extern void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name); -extern void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, - GLint * size, GLenum * type, GLcharARB * name); -extern GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name); - -// GL_ARB_texture_compression -extern void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, - GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, - GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, - GLsizei imageSize, const GLvoid *data); -extern void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod, - GLvoid *img); - -// GL_NVX_gpu_memory_info -#ifndef GL_NVX_gpu_memory_info -#define GL_NVX_gpu_memory_info -#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 -#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 -#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 -#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A -#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B -#endif - -// GL_ATI_meminfo -#ifndef GL_ATI_meminfo -#define GL_ATI_meminfo -#define GL_VBO_FREE_MEMORY_ATI 0x87FB -#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC -#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD -#endif - -// GL_ARB_texture_float -#ifndef GL_ARB_texture_float -#define GL_ARB_texture_float -#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 -#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 -#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 -#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 -#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 -#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 -#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 -#define GL_RGBA32F_ARB 0x8814 -#define GL_RGB32F_ARB 0x8815 -#define GL_ALPHA32F_ARB 0x8816 -#define GL_INTENSITY32F_ARB 0x8817 -#define GL_LUMINANCE32F_ARB 0x8818 -#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 -#define GL_RGBA16F_ARB 0x881A -#define GL_RGB16F_ARB 0x881B -#define GL_ALPHA16F_ARB 0x881C -#define GL_INTENSITY16F_ARB 0x881D -#define GL_LUMINANCE16F_ARB 0x881E -#define GL_LUMINANCE_ALPHA16F_ARB 0x881F -#endif - -#ifndef GL_ARB_half_float_pixel -#define GL_ARB_half_float_pixel -#define GL_HALF_FLOAT_ARB 0x140B -#endif - -// GL_EXT_framebuffer_object -extern GLboolean (APIENTRY * qglIsRenderbufferEXT)(GLuint renderbuffer); -extern void (APIENTRY * qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer); -extern void (APIENTRY * qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers); -extern void (APIENTRY * qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers); -extern void (APIENTRY * qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -extern void (APIENTRY * qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params); -extern GLboolean (APIENTRY * qglIsFramebufferEXT)(GLuint framebuffer); -extern void (APIENTRY * qglBindFramebufferEXT)(GLenum target, GLuint framebuffer); -extern void (APIENTRY * qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers); -extern void (APIENTRY * qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers); -extern GLenum (APIENTRY * qglCheckFramebufferStatusEXT)(GLenum target); -extern void (APIENTRY * qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level); -extern void (APIENTRY * qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level); -extern void (APIENTRY * qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset); -extern void (APIENTRY * qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, - GLuint renderbuffer); -extern void (APIENTRY * qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params); -extern void (APIENTRY * qglGenerateMipmapEXT)(GLenum target); - -#ifndef GL_EXT_framebuffer_object -#define GL_EXT_framebuffer_object -#define GL_FRAMEBUFFER_EXT 0x8D40 -#define GL_RENDERBUFFER_EXT 0x8D41 -#define GL_STENCIL_INDEX1_EXT 0x8D46 -#define GL_STENCIL_INDEX4_EXT 0x8D47 -#define GL_STENCIL_INDEX8_EXT 0x8D48 -#define GL_STENCIL_INDEX16_EXT 0x8D49 -#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 -#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 -#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 -#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD -#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 -#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 -#endif - -// GL_EXT_packed_depth_stencil -#ifndef GL_EXT_packed_depth_stencil -#define GL_EXT_packed_depth_stencil -#define GL_DEPTH_STENCIL_EXT 0x84F9 -#define GL_UNSIGNED_INT_24_8_EXT 0x84FA -#define GL_DEPTH24_STENCIL8_EXT 0x88F0 -#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 -#endif - -// GL_ARB_occlusion_query -extern void (APIENTRY * qglGenQueriesARB)(GLsizei n, GLuint *ids); -extern void (APIENTRY * qglDeleteQueriesARB)(GLsizei n, const GLuint *ids); -extern GLboolean (APIENTRY * qglIsQueryARB)(GLuint id); -extern void (APIENTRY * qglBeginQueryARB)(GLenum target, GLuint id); -extern void (APIENTRY * qglEndQueryARB)(GLenum target); -extern void (APIENTRY * qglGetQueryivARB)(GLenum target, GLenum pname, GLint *params); -extern void (APIENTRY * qglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params); -extern void (APIENTRY * qglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params); - -#ifndef GL_ARB_occlusion_query -#define GL_ARB_occlusion_query -#define GL_SAMPLES_PASSED_ARB 0x8914 -#define GL_QUERY_COUNTER_BITS_ARB 0x8864 -#define GL_CURRENT_QUERY_ARB 0x8865 -#define GL_QUERY_RESULT_ARB 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 -#endif - -// GL_EXT_framebuffer_blit -extern void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - -#ifndef GL_EXT_framebuffer_blit -#define GL_EXT_framebuffer_blit -#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA -#endif - -// GL_EXT_framebuffer_multisample -extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height); - -#ifndef GL_EXT_framebuffer_multisample -#define GL_EXT_framebuffer_multisample -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 -#endif - -#ifndef GL_EXT_texture_sRGB -#define GL_EXT_texture_sRGB -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB8_EXT 0x8C41 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 -#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 -#define GL_SLUMINANCE_EXT 0x8C46 -#define GL_SLUMINANCE8_EXT 0x8C47 -#define GL_COMPRESSED_SRGB_EXT 0x8C48 -#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 -#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A -#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B -#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F -#endif - -#ifndef GL_EXT_framebuffer_sRGB -#define GL_EXT_framebuffer_sRGB -#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 -#endif - -#ifndef GL_EXT_texture_compression_latc -#define GL_EXT_texture_compression_latc -#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 -#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 -#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 -#endif - -#ifndef GL_ARB_texture_compression_bptc -#define GL_ARB_texture_compression_bptc -#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C -#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D -#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E -#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F -#endif - -// GL_ARB_draw_buffers -extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs); -#ifndef GL_ARB_draw_buffers -#define GL_ARB_draw_buffers -#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 -#define GL_DRAW_BUFFER0_ARB 0x8825 -#define GL_DRAW_BUFFER1_ARB 0x8826 -#define GL_DRAW_BUFFER2_ARB 0x8827 -#define GL_DRAW_BUFFER3_ARB 0x8828 -#define GL_DRAW_BUFFER4_ARB 0x8829 -#define GL_DRAW_BUFFER5_ARB 0x882A -#define GL_DRAW_BUFFER6_ARB 0x882B -#define GL_DRAW_BUFFER7_ARB 0x882C -#define GL_DRAW_BUFFER8_ARB 0x882D -#define GL_DRAW_BUFFER9_ARB 0x882E -#define GL_DRAW_BUFFER10_ARB 0x882F -#define GL_DRAW_BUFFER11_ARB 0x8830 -#define GL_DRAW_BUFFER12_ARB 0x8831 -#define GL_DRAW_BUFFER13_ARB 0x8832 -#define GL_DRAW_BUFFER14_ARB 0x8833 -#define GL_DRAW_BUFFER15_ARB 0x8834 -#endif - -#ifndef GL_ARB_depth_clamp -#define GL_ARB_depth_clamp -#define GL_DEPTH_CLAMP 0x864F -#endif - -#if defined(WIN32) -// WGL_ARB_create_context -#ifndef WGL_ARB_create_context -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 -#endif - -extern HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList); -#endif - -#if 0 //defined(__linux__) -// GLX_ARB_create_context -#ifndef GLX_ARB_create_context -#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 -#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define GLX_CONTEXT_FLAGS_ARB 0x2094 -#endif - -extern GLXContext (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list); -#endif - -//=========================================================================== - -#define qglAccum glAccum -#define qglAlphaFunc glAlphaFunc -#define qglAreTexturesResident glAreTexturesResident -#define qglArrayElement glArrayElement -#define qglBegin glBegin -#define qglBindTexture glBindTexture -#define qglBitmap glBitmap -#define qglBlendFunc glBlendFunc -#define qglCallList glCallList -#define qglCallLists glCallLists -#define qglClear glClear -#define qglClearAccum glClearAccum -#define qglClearColor glClearColor -#define qglClearDepth glClearDepth -#define qglClearIndex glClearIndex -#define qglClearStencil glClearStencil -#define qglClipPlane glClipPlane -#define qglColor3b glColor3b -#define qglColor3bv glColor3bv -#define qglColor3d glColor3d -#define qglColor3dv glColor3dv -#define qglColor3f glColor3f -#define qglColor3fv glColor3fv -#define qglColor3i glColor3i -#define qglColor3iv glColor3iv -#define qglColor3s glColor3s -#define qglColor3sv glColor3sv -#define qglColor3ub glColor3ub -#define qglColor3ubv glColor3ubv -#define qglColor3ui glColor3ui -#define qglColor3uiv glColor3uiv -#define qglColor3us glColor3us -#define qglColor3usv glColor3usv -#define qglColor4b glColor4b -#define qglColor4bv glColor4bv -#define qglColor4d glColor4d -#define qglColor4dv glColor4dv -#define qglColor4f glColor4f -#define qglColor4fv glColor4fv -#define qglColor4i glColor4i -#define qglColor4iv glColor4iv -#define qglColor4s glColor4s -#define qglColor4sv glColor4sv -#define qglColor4ub glColor4ub -#define qglColor4ubv glColor4ubv -#define qglColor4ui glColor4ui -#define qglColor4uiv glColor4uiv -#define qglColor4us glColor4us -#define qglColor4usv glColor4usv -#define qglColorMask glColorMask -#define qglColorMaterial glColorMaterial -#define qglColorPointer glColorPointer -#define qglCopyPixels glCopyPixels -#define qglCopyTexImage1D glCopyTexImage1D -#define qglCopyTexImage2D glCopyTexImage2D -#define qglCopyTexSubImage1D glCopyTexSubImage1D -#define qglCopyTexSubImage2D glCopyTexSubImage2D -#define qglCullFace glCullFace -#define qglDeleteLists glDeleteLists -#define qglDeleteTextures glDeleteTextures -#define qglDepthFunc glDepthFunc -#define qglDepthMask glDepthMask -#define qglDepthRange glDepthRange -#define qglDisable glDisable -#define qglDisableClientState glDisableClientState -#define qglDrawArrays glDrawArrays -#define qglDrawBuffer glDrawBuffer -#define qglDrawElements glDrawElements -#define qglDrawPixels glDrawPixels -#define qglEdgeFlag glEdgeFlag -#define qglEdgeFlagPointer glEdgeFlagPointer -#define qglEdgeFlagv glEdgeFlagv -#define qglEnable glEnable -#define qglEnableClientState glEnableClientState -#define qglEnd glEnd -#define qglEndList glEndList -#define qglEvalCoord1d glEvalCoord1d -#define qglEvalCoord1dv glEvalCoord1dv -#define qglEvalCoord1f glEvalCoord1f -#define qglEvalCoord1fv glEvalCoord1fv -#define qglEvalCoord2d glEvalCoord2d -#define qglEvalCoord2dv glEvalCoord2dv -#define qglEvalCoord2f glEvalCoord2f -#define qglEvalCoord2fv glEvalCoord2fv -#define qglEvalMesh1 glEvalMesh1 -#define qglEvalMesh2 glEvalMesh2 -#define qglEvalPoint1 glEvalPoint1 -#define qglEvalPoint2 glEvalPoint2 -#define qglFeedbackBuffer glFeedbackBuffer -#define qglFinish glFinish -#define qglFlush glFlush -#define qglFogf glFogf -#define qglFogfv glFogfv -#define qglFogi glFogi -#define qglFogiv glFogiv -#define qglFrontFace glFrontFace -#define qglFrustum glFrustum -#define qglGenLists glGenLists -#define qglGenTextures glGenTextures -#define qglGetBooleanv glGetBooleanv -#define qglGetClipPlane glGetClipPlane -#define qglGetDoublev glGetDoublev -#define qglGetError glGetError -#define qglGetFloatv glGetFloatv -#define qglGetIntegerv glGetIntegerv -#define qglGetLightfv glGetLightfv -#define qglGetLightiv glGetLightiv -#define qglGetMapdv glGetMapdv -#define qglGetMapfv glGetMapfv -#define qglGetMapiv glGetMapiv -#define qglGetMaterialfv glGetMaterialfv -#define qglGetMaterialiv glGetMaterialiv -#define qglGetPixelMapfv glGetPixelMapfv -#define qglGetPixelMapuiv glGetPixelMapuiv -#define qglGetPixelMapusv glGetPixelMapusv -#define qglGetPointerv glGetPointerv -#define qglGetPolygonStipple glGetPolygonStipple -#define qglGetString glGetString -#define qglGetTexGendv glGetTexGendv -#define qglGetTexGenfv glGetTexGenfv -#define qglGetTexGeniv glGetTexGeniv -#define qglGetTexImage glGetTexImage -#define qglGetTexLevelParameterfv glGetTexLevelParameterfv -#define qglGetTexLevelParameteriv glGetTexLevelParameteriv -#define qglGetTexParameterfv glGetTexParameterfv -#define qglGetTexParameteriv glGetTexParameteriv -#define qglHint glHint -#define qglIndexMask glIndexMask -#define qglIndexPointer glIndexPointer -#define qglIndexd glIndexd -#define qglIndexdv glIndexdv -#define qglIndexf glIndexf -#define qglIndexfv glIndexfv -#define qglIndexi glIndexi -#define qglIndexiv glIndexiv -#define qglIndexs glIndexs -#define qglIndexsv glIndexsv -#define qglIndexub glIndexub -#define qglIndexubv glIndexubv -#define qglInitNames glInitNames -#define qglInterleavedArrays glInterleavedArrays -#define qglIsEnabled glIsEnabled -#define qglIsList glIsList -#define qglIsTexture glIsTexture -#define qglLightModelf glLightModelf -#define qglLightModelfv glLightModelfv -#define qglLightModeli glLightModeli -#define qglLightModeliv glLightModeliv -#define qglLightf glLightf -#define qglLightfv glLightfv -#define qglLighti glLighti -#define qglLightiv glLightiv -#define qglLineStipple glLineStipple -#define qglLineWidth glLineWidth -#define qglListBase glListBase -#define qglLoadIdentity glLoadIdentity -#define qglLoadMatrixd glLoadMatrixd -#define qglLoadMatrixf glLoadMatrixf -#define qglLoadName glLoadName -#define qglLogicOp glLogicOp -#define qglMap1d glMap1d -#define qglMap1f glMap1f -#define qglMap2d glMap2d -#define qglMap2f glMap2f -#define qglMapGrid1d glMapGrid1d -#define qglMapGrid1f glMapGrid1f -#define qglMapGrid2d glMapGrid2d -#define qglMapGrid2f glMapGrid2f -#define qglMaterialf glMaterialf -#define qglMaterialfv glMaterialfv -#define qglMateriali glMateriali -#define qglMaterialiv glMaterialiv -#define qglMatrixMode glMatrixMode -#define qglMultMatrixd glMultMatrixd -#define qglMultMatrixf glMultMatrixf -#define qglNewList glNewList -#define qglNormal3b glNormal3b -#define qglNormal3bv glNormal3bv -#define qglNormal3d glNormal3d -#define qglNormal3dv glNormal3dv -#define qglNormal3f glNormal3f -#define qglNormal3fv glNormal3fv -#define qglNormal3i glNormal3i -#define qglNormal3iv glNormal3iv -#define qglNormal3s glNormal3s -#define qglNormal3sv glNormal3sv -#define qglNormalPointer glNormalPointer -#define qglOrtho glOrtho -#define qglPassThrough glPassThrough -#define qglPixelMapfv glPixelMapfv -#define qglPixelMapuiv glPixelMapuiv -#define qglPixelMapusv glPixelMapusv -#define qglPixelStoref glPixelStoref -#define qglPixelStorei glPixelStorei -#define qglPixelTransferf glPixelTransferf -#define qglPixelTransferi glPixelTransferi -#define qglPixelZoom glPixelZoom -#define qglPointSize glPointSize -#define qglPolygonMode glPolygonMode -#define qglPolygonOffset glPolygonOffset -#define qglPolygonStipple glPolygonStipple -#define qglPopAttrib glPopAttrib -#define qglPopClientAttrib glPopClientAttrib -#define qglPopMatrix glPopMatrix -#define qglPopName glPopName -#define qglPrioritizeTextures glPrioritizeTextures -#define qglPushAttrib glPushAttrib -#define qglPushClientAttrib glPushClientAttrib -#define qglPushMatrix glPushMatrix -#define qglPushName glPushName -#define qglRasterPos2d glRasterPos2d -#define qglRasterPos2dv glRasterPos2dv -#define qglRasterPos2f glRasterPos2f -#define qglRasterPos2fv glRasterPos2fv -#define qglRasterPos2i glRasterPos2i -#define qglRasterPos2iv glRasterPos2iv -#define qglRasterPos2s glRasterPos2s -#define qglRasterPos2sv glRasterPos2sv -#define qglRasterPos3d glRasterPos3d -#define qglRasterPos3dv glRasterPos3dv -#define qglRasterPos3f glRasterPos3f -#define qglRasterPos3fv glRasterPos3fv -#define qglRasterPos3i glRasterPos3i -#define qglRasterPos3iv glRasterPos3iv -#define qglRasterPos3s glRasterPos3s -#define qglRasterPos3sv glRasterPos3sv -#define qglRasterPos4d glRasterPos4d -#define qglRasterPos4dv glRasterPos4dv -#define qglRasterPos4f glRasterPos4f -#define qglRasterPos4fv glRasterPos4fv -#define qglRasterPos4i glRasterPos4i -#define qglRasterPos4iv glRasterPos4iv -#define qglRasterPos4s glRasterPos4s -#define qglRasterPos4sv glRasterPos4sv -#define qglReadBuffer glReadBuffer -#define qglReadPixels glReadPixels -#define qglRectd glRectd -#define qglRectdv glRectdv -#define qglRectf glRectf -#define qglRectfv glRectfv -#define qglRecti glRecti -#define qglRectiv glRectiv -#define qglRects glRects -#define qglRectsv glRectsv -#define qglRenderMode glRenderMode -#define qglRotated glRotated -#define qglRotatef glRotatef -#define qglScaled glScaled -#define qglScalef glScalef -#define qglScissor glScissor -#define qglSelectBuffer glSelectBuffer -#define qglShadeModel glShadeModel -#define qglStencilFunc glStencilFunc -#define qglStencilMask glStencilMask -#define qglStencilOp glStencilOp -#define qglTexCoord1d glTexCoord1d -#define qglTexCoord1dv glTexCoord1dv -#define qglTexCoord1f glTexCoord1f -#define qglTexCoord1fv glTexCoord1fv -#define qglTexCoord1i glTexCoord1i -#define qglTexCoord1iv glTexCoord1iv -#define qglTexCoord1s glTexCoord1s -#define qglTexCoord1sv glTexCoord1sv -#define qglTexCoord2d glTexCoord2d -#define qglTexCoord2dv glTexCoord2dv -#define qglTexCoord2f glTexCoord2f -#define qglTexCoord2fv glTexCoord2fv -#define qglTexCoord2i glTexCoord2i -#define qglTexCoord2iv glTexCoord2iv -#define qglTexCoord2s glTexCoord2s -#define qglTexCoord2sv glTexCoord2sv -#define qglTexCoord3d glTexCoord3d -#define qglTexCoord3dv glTexCoord3dv -#define qglTexCoord3f glTexCoord3f -#define qglTexCoord3fv glTexCoord3fv -#define qglTexCoord3i glTexCoord3i -#define qglTexCoord3iv glTexCoord3iv -#define qglTexCoord3s glTexCoord3s -#define qglTexCoord3sv glTexCoord3sv -#define qglTexCoord4d glTexCoord4d -#define qglTexCoord4dv glTexCoord4dv -#define qglTexCoord4f glTexCoord4f -#define qglTexCoord4fv glTexCoord4fv -#define qglTexCoord4i glTexCoord4i -#define qglTexCoord4iv glTexCoord4iv -#define qglTexCoord4s glTexCoord4s -#define qglTexCoord4sv glTexCoord4sv -#define qglTexCoordPointer glTexCoordPointer -#define qglTexEnvf glTexEnvf -#define qglTexEnvfv glTexEnvfv -#define qglTexEnvi glTexEnvi -#define qglTexEnviv glTexEnviv -#define qglTexGend glTexGend -#define qglTexGendv glTexGendv -#define qglTexGenf glTexGenf -#define qglTexGenfv glTexGenfv -#define qglTexGeni glTexGeni -#define qglTexGeniv glTexGeniv -#define qglTexImage1D glTexImage1D -#define qglTexImage2D glTexImage2D -#define qglTexParameterf glTexParameterf -#define qglTexParameterfv glTexParameterfv -#define qglTexParameteri glTexParameteri -#define qglTexParameteriv glTexParameteriv -#define qglTexSubImage1D glTexSubImage1D -#define qglTexSubImage2D glTexSubImage2D -#define qglTranslated glTranslated -#define qglTranslatef glTranslatef -#define qglVertex2d glVertex2d -#define qglVertex2dv glVertex2dv -#define qglVertex2f glVertex2f -#define qglVertex2fv glVertex2fv -#define qglVertex2i glVertex2i -#define qglVertex2iv glVertex2iv -#define qglVertex2s glVertex2s -#define qglVertex2sv glVertex2sv -#define qglVertex3d glVertex3d -#define qglVertex3dv glVertex3dv -#define qglVertex3f glVertex3f -#define qglVertex3fv glVertex3fv -#define qglVertex3i glVertex3i -#define qglVertex3iv glVertex3iv -#define qglVertex3s glVertex3s -#define qglVertex3sv glVertex3sv -#define qglVertex4d glVertex4d -#define qglVertex4dv glVertex4dv -#define qglVertex4f glVertex4f -#define qglVertex4fv glVertex4fv -#define qglVertex4i glVertex4i -#define qglVertex4iv glVertex4iv -#define qglVertex4s glVertex4s -#define qglVertex4sv glVertex4sv -#define qglVertexPointer glVertexPointer -#define qglViewport glViewport - -#endif diff --git a/code/renderergl2/tr_animation.c b/code/renderergl2/tr_animation.c deleted file mode 100644 index 794111c6..00000000 --- a/code/renderergl2/tr_animation.c +++ /dev/null @@ -1,658 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "tr_local.h" - -/* - -All bones should be an identity orientation to display the mesh exactly -as it is specified. - -For all other frames, the bones represent the transformation from the -orientation of the bone in the base frame to the orientation in this -frame. - -*/ - -/* -============== -R_AddAnimSurfaces -============== -*/ -void R_AddAnimSurfaces( trRefEntity_t *ent ) { - md4Header_t *header; - md4Surface_t *surface; - md4LOD_t *lod; - shader_t *shader; - int i; - - header = (md4Header_t *) tr.currentModel->modelData; - lod = (md4LOD_t *)( (byte *)header + header->ofsLODs ); - - surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces ); - for ( i = 0 ; i < lod->numSurfaces ; i++ ) { - shader = R_GetShaderByHandle( surface->shaderIndex ); - R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse, qfalse ); - surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd ); - } -} - -/* -============== -RB_SurfaceAnim -============== -*/ -void RB_SurfaceAnim( md4Surface_t *surface ) { - int i, j, k; - float frontlerp, backlerp; - int *triangles; - int indexes; - int baseIndex, baseVertex; - int numVerts; - md4Vertex_t *v; - md4Bone_t bones[MD4_MAX_BONES]; - md4Bone_t *bonePtr, *bone; - md4Header_t *header; - md4Frame_t *frame; - md4Frame_t *oldFrame; - int frameSize; - - - if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { - backlerp = 0; - frontlerp = 1; - } else { - backlerp = backEnd.currentEntity->e.backlerp; - frontlerp = 1.0f - backlerp; - } - header = (md4Header_t *)((byte *)surface + surface->ofsHeader); - - frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] ); - - frame = (md4Frame_t *)((byte *)header + header->ofsFrames + - backEnd.currentEntity->e.frame * frameSize ); - oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + - backEnd.currentEntity->e.oldframe * frameSize ); - - RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 ); - - triangles = (int *) ((byte *)surface + surface->ofsTriangles); - indexes = surface->numTriangles * 3; - baseIndex = tess.numIndexes; - baseVertex = tess.numVertexes; - for (j = 0 ; j < indexes ; j++) { - tess.indexes[baseIndex + j] = baseIndex + triangles[j]; - } - tess.numIndexes += indexes; - - // - // lerp all the needed bones - // - if ( !backlerp ) { - // no lerping needed - bonePtr = frame->bones; - } else { - bonePtr = bones; - for ( i = 0 ; i < header->numBones*12 ; i++ ) { - ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] - + backlerp * ((float *)oldFrame->bones)[i]; - } - } - - // - // deform the vertexes by the lerped bones - // - numVerts = surface->numVerts; - // FIXME - // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left - // in for reference. - //v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12); - v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts); - for ( j = 0; j < numVerts; j++ ) { - vec3_t tempVert, tempNormal; - md4Weight_t *w; - - VectorClear( tempVert ); - VectorClear( tempNormal ); - w = v->weights; - for ( k = 0 ; k < v->numWeights ; k++, w++ ) { - bone = bonePtr + w->boneIndex; - - tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); - tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); - tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); - - tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); - tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); - tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); - } - - tess.xyz[baseVertex + j][0] = tempVert[0]; - tess.xyz[baseVertex + j][1] = tempVert[1]; - tess.xyz[baseVertex + j][2] = tempVert[2]; - - tess.normal[baseVertex + j][0] = tempNormal[0]; - tess.normal[baseVertex + j][1] = tempNormal[1]; - tess.normal[baseVertex + j][2] = tempNormal[2]; - - tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; - tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; - - // FIXME - // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left - // in for reference. - //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); - v = (md4Vertex_t *)&v->weights[v->numWeights]; - } - - tess.numVertexes += surface->numVerts; -} - - -#ifdef RAVENMD4 - -// copied and adapted from tr_mesh.c - -/* -============= -R_MDRCullModel -============= -*/ - -static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) { - vec3_t bounds[2]; - mdrFrame_t *oldFrame, *newFrame; - int i, frameSize; - - frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - - // compute frame pointers - newFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); - oldFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * 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 ) ) - { - // Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend - // we do. After all, the purpose of md4s are not that different, are they? - - 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; - } -} - -/* -================= -R_MDRComputeFogNum - -================= -*/ - -int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) { - int i, j; - fog_t *fog; - mdrFrame_t *mdrFrame; - vec3_t localOrigin; - int frameSize; - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { - return 0; - } - - frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - - // FIXME: non-normalized axis issues - mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); - VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin ); - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { - fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) { - break; - } - if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) { - break; - } - } - if ( j == 3 ) { - return i; - } - } - - return 0; -} - - -/* -============== -R_MDRAddAnimSurfaces -============== -*/ - -// much stuff in there is just copied from R_AddMd3Surfaces in tr_mesh.c - -void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) { - mdrHeader_t *header; - mdrSurface_t *surface; - mdrLOD_t *lod; - shader_t *shader; - skin_t *skin; - int i, j; - int lodnum = 0; - int fogNum = 0; - int cull; - qboolean personalModel; - - header = (mdrHeader_t *) tr.currentModel->modelData; - - personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal; - - if ( ent->e.renderfx & RF_WRAP_FRAMES ) - { - ent->e.frame %= header->numFrames; - ent->e.oldframe %= header->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 >= header->numFrames) - || (ent->e.frame < 0) - || (ent->e.oldframe >= header->numFrames) - || (ent->e.oldframe < 0) ) - { - ri.Printf( PRINT_DEVELOPER, "R_MDRAddAnimSurfaces: 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; - } - - // - // cull the entire model if merged bounding box of both frames - // is outside the view frustum. - // - cull = R_MDRCullModel (header, ent); - if ( cull == CULL_OUT ) { - return; - } - - // figure out the current LOD of the model we're rendering, and set the lod pointer respectively. - lodnum = R_ComputeLOD(ent); - // check whether this model has as that many LODs at all. If not, try the closest thing we got. - if(header->numLODs <= 0) - return; - if(header->numLODs <= lodnum) - lodnum = header->numLODs - 1; - - lod = (mdrLOD_t *)( (byte *)header + header->ofsLODs); - for(i = 0; i < lodnum; i++) - { - lod = (mdrLOD_t *) ((byte *) lod + lod->ofsEnd); - } - - // set up lighting - if ( !personalModel || r_shadows->integer > 1 ) - { - R_SetupEntityLighting( &tr.refdef, ent ); - } - - // fogNum? - fogNum = R_MDRComputeFogNum( header, ent ); - - surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces ); - - for ( i = 0 ; i < lod->numSurfaces ; i++ ) - { - - if(ent->e.customShader) - shader = R_GetShaderByHandle(ent->e.customShader); - else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins) - { - skin = R_GetSkinByHandle(ent->e.customSkin); - shader = tr.defaultShader; - - for(j = 0; j < skin->numSurfaces; j++) - { - if (!strcmp(skin->surfaces[j]->name, surface->name)) - { - shader = skin->surfaces[j]->shader; - break; - } - } - } - else if(surface->shaderIndex > 0) - shader = R_GetShaderByHandle( surface->shaderIndex ); - else - shader = tr.defaultShader; - - // 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_NOSHADOW | RF_DEPTHHACK ) ) - && shader->sort == SS_OPAQUE ) - { - R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, 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( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse ); - } - - if (!personalModel) - R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse ); - - surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd ); - } -} - -/* -============== -RB_MDRSurfaceAnim -============== -*/ -void RB_MDRSurfaceAnim( md4Surface_t *surface ) -{ - int i, j, k; - float frontlerp, backlerp; - int *triangles; - int indexes; - int baseIndex, baseVertex; - int numVerts; - mdrVertex_t *v; - mdrHeader_t *header; - mdrFrame_t *frame; - mdrFrame_t *oldFrame; - mdrBone_t bones[MD4_MAX_BONES], *bonePtr, *bone; - - int frameSize; - - // don't lerp if lerping off, or this is the only frame, or the last frame... - // - if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame) - { - backlerp = 0; // if backlerp is 0, lerping is off and frontlerp is never used - frontlerp = 1; - } - else - { - backlerp = backEnd.currentEntity->e.backlerp; - frontlerp = 1.0f - backlerp; - } - - header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader); - - frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - - frame = (mdrFrame_t *)((byte *)header + header->ofsFrames + - backEnd.currentEntity->e.frame * frameSize ); - oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames + - backEnd.currentEntity->e.oldframe * frameSize ); - - RB_CheckOverflow( surface->numVerts, surface->numTriangles ); - - triangles = (int *) ((byte *)surface + surface->ofsTriangles); - indexes = surface->numTriangles * 3; - baseIndex = tess.numIndexes; - baseVertex = tess.numVertexes; - - // Set up all triangles. - for (j = 0 ; j < indexes ; j++) - { - tess.indexes[baseIndex + j] = baseVertex + triangles[j]; - } - tess.numIndexes += indexes; - - // - // lerp all the needed bones - // - if ( !backlerp ) - { - // no lerping needed - bonePtr = frame->bones; - } - else - { - bonePtr = bones; - - for ( i = 0 ; i < header->numBones*12 ; i++ ) - { - ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i]; - } - } - - // - // deform the vertexes by the lerped bones - // - numVerts = surface->numVerts; - v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts); - for ( j = 0; j < numVerts; j++ ) - { - vec3_t tempVert, tempNormal; - mdrWeight_t *w; - - VectorClear( tempVert ); - VectorClear( tempNormal ); - w = v->weights; - for ( k = 0 ; k < v->numWeights ; k++, w++ ) - { - bone = bonePtr + w->boneIndex; - - tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] ); - tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] ); - tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] ); - - tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal ); - tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal ); - tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal ); - } - - tess.xyz[baseVertex + j][0] = tempVert[0]; - tess.xyz[baseVertex + j][1] = tempVert[1]; - tess.xyz[baseVertex + j][2] = tempVert[2]; - - tess.normal[baseVertex + j][0] = tempNormal[0]; - tess.normal[baseVertex + j][1] = tempNormal[1]; - tess.normal[baseVertex + j][2] = tempNormal[2]; - - tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; - tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; - - v = (mdrVertex_t *)&v->weights[v->numWeights]; - } - - tess.numVertexes += surface->numVerts; -} - - -#define MC_MASK_X ((1<<(MC_BITS_X))-1) -#define MC_MASK_Y ((1<<(MC_BITS_Y))-1) -#define MC_MASK_Z ((1<<(MC_BITS_Z))-1) -#define MC_MASK_VECT ((1<<(MC_BITS_VECT))-1) - -#define MC_SCALE_VECT (1.0f/(float)((1<<(MC_BITS_VECT-1))-2)) - -#define MC_POS_X (0) -#define MC_SHIFT_X (0) - -#define MC_POS_Y ((((MC_BITS_X))/8)) -#define MC_SHIFT_Y ((((MC_BITS_X)%8))) - -#define MC_POS_Z ((((MC_BITS_X+MC_BITS_Y))/8)) -#define MC_SHIFT_Z ((((MC_BITS_X+MC_BITS_Y)%8))) - -#define MC_POS_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z))/8)) -#define MC_SHIFT_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z)%8))) - -#define MC_POS_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT))/8)) -#define MC_SHIFT_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT)%8))) - -#define MC_POS_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2))/8)) -#define MC_SHIFT_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2)%8))) - -#define MC_POS_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3))/8)) -#define MC_SHIFT_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3)%8))) - -#define MC_POS_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4))/8)) -#define MC_SHIFT_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4)%8))) - -#define MC_POS_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5))/8)) -#define MC_SHIFT_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5)%8))) - -#define MC_POS_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6))/8)) -#define MC_SHIFT_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6)%8))) - -#define MC_POS_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7))/8)) -#define MC_SHIFT_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7)%8))) - -#define MC_POS_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8))/8)) -#define MC_SHIFT_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8)%8))) - -void MC_UnCompress(float mat[3][4],const unsigned char * comp) -{ - int val; - - val=(int)((unsigned short *)(comp))[0]; - val-=1<<(MC_BITS_X-1); - mat[0][3]=((float)(val))*MC_SCALE_X; - - val=(int)((unsigned short *)(comp))[1]; - val-=1<<(MC_BITS_Y-1); - mat[1][3]=((float)(val))*MC_SCALE_Y; - - val=(int)((unsigned short *)(comp))[2]; - val-=1<<(MC_BITS_Z-1); - mat[2][3]=((float)(val))*MC_SCALE_Z; - - val=(int)((unsigned short *)(comp))[3]; - val-=1<<(MC_BITS_VECT-1); - mat[0][0]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[4]; - val-=1<<(MC_BITS_VECT-1); - mat[0][1]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[5]; - val-=1<<(MC_BITS_VECT-1); - mat[0][2]=((float)(val))*MC_SCALE_VECT; - - - val=(int)((unsigned short *)(comp))[6]; - val-=1<<(MC_BITS_VECT-1); - mat[1][0]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[7]; - val-=1<<(MC_BITS_VECT-1); - mat[1][1]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[8]; - val-=1<<(MC_BITS_VECT-1); - mat[1][2]=((float)(val))*MC_SCALE_VECT; - - - val=(int)((unsigned short *)(comp))[9]; - val-=1<<(MC_BITS_VECT-1); - mat[2][0]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[10]; - val-=1<<(MC_BITS_VECT-1); - mat[2][1]=((float)(val))*MC_SCALE_VECT; - - val=(int)((unsigned short *)(comp))[11]; - val-=1<<(MC_BITS_VECT-1); - mat[2][2]=((float)(val))*MC_SCALE_VECT; -} -#endif diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c deleted file mode 100644 index f0578f8e..00000000 --- a/code/renderergl2/tr_backend.c +++ /dev/null @@ -1,1739 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "tr_local.h" - -backEndData_t *backEndData[SMP_FRAMES]; -backEndState_t backEnd; - - -static float s_flipMatrix[16] = { - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - 0, 0, -1, 0, - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 1 -}; - - -/* -** GL_Bind2 -*/ -void GL_Bind2( image_t *image, GLenum type ) { - int texnum; - - if ( !image ) { - ri.Printf( PRINT_WARNING, "GL_Bind2: NULL image\n" ); - texnum = tr.defaultImage->texnum; - } else { - texnum = image->texnum; - } - - if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option - texnum = tr.dlightImage->texnum; - } - - if ( glState.currenttextures[glState.currenttmu] != texnum ) { - image->frameUsed = tr.frameCount; - glState.currenttextures[glState.currenttmu] = texnum; - qglBindTexture (type, texnum); - } -} - -/* -** GL_Bind2 -*/ -void GL_Bind( image_t *image ) -{ - GL_Bind2( image, GL_TEXTURE_2D ); -} - -/* -** GL_BindCubemap -*/ -void GL_BindCubemap( image_t *image ) -{ - GL_Bind2( image, GL_TEXTURE_CUBE_MAP ); -} - -/* -** GL_SelectTexture -*/ -void GL_SelectTexture( int unit ) -{ - if ( glState.currenttmu == unit ) - { - return; - } - - if (!(unit >= 0 && unit <= 31)) - ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit ); - - qglActiveTextureARB( GL_TEXTURE0_ARB + unit ); - - glState.currenttmu = unit; -} - - -/* -** GL_BindMultitexture -*/ -void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) { - int texnum0, texnum1; - - texnum0 = image0->texnum; - texnum1 = image1->texnum; - - if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option - texnum0 = texnum1 = tr.dlightImage->texnum; - } - - if ( glState.currenttextures[1] != texnum1 ) { - GL_SelectTexture( 1 ); - image1->frameUsed = tr.frameCount; - glState.currenttextures[1] = texnum1; - qglBindTexture( GL_TEXTURE_2D, texnum1 ); - } - if ( glState.currenttextures[0] != texnum0 ) { - GL_SelectTexture( 0 ); - image0->frameUsed = tr.frameCount; - glState.currenttextures[0] = texnum0; - qglBindTexture( GL_TEXTURE_2D, texnum0 ); - } -} - -/* -** GL_BindToTMU -*/ -void GL_BindToTMU( image_t *image, int tmu ) -{ - int texnum; - int oldtmu = glState.currenttmu; - - if (!image) - texnum = 0; - else - texnum = image->texnum; - - if ( glState.currenttextures[tmu] != texnum ) { - GL_SelectTexture( tmu ); - if (image) - image->frameUsed = tr.frameCount; - glState.currenttextures[tmu] = texnum; - qglBindTexture( GL_TEXTURE_2D, texnum ); - GL_SelectTexture( oldtmu ); - } -} - - -/* -** GL_Cull -*/ -void GL_Cull( int cullType ) { -#ifdef REACTION - // Makro - flip culling if needed - qboolean flip = (backEnd.currentEntity != NULL && backEnd.currentEntity->mirrored != qfalse && cullType != CT_TWO_SIDED); - cullType ^= flip; // this assumes CT_BACK_SIDED and CT_FRONT_SIDED are 0 or 1 -#endif - - if ( glState.faceCulling == cullType ) { - return; - } - - glState.faceCulling = cullType; - - if ( cullType == CT_TWO_SIDED ) - { - qglDisable( GL_CULL_FACE ); - } - else - { - qboolean cullFront; - qglEnable( GL_CULL_FACE ); - - cullFront = (cullType == CT_FRONT_SIDED); - if ( backEnd.viewParms.isMirror ) - { - cullFront = !cullFront; - } - - qglCullFace( cullFront ? GL_FRONT : GL_BACK ); - } -} - -/* -** GL_TexEnv -*/ -void GL_TexEnv( int env ) -{ - if ( env == glState.texEnv[glState.currenttmu] ) - { - return; - } - - glState.texEnv[glState.currenttmu] = env; - - - switch ( env ) - { - case GL_MODULATE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - break; - case GL_REPLACE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - break; - case GL_DECAL: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); - break; - case GL_ADD: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); - break; - default: - ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env ); - break; - } -} - -/* -** GL_State -** -** This routine is responsible for setting the most commonly changed state -** in Q3. -*/ -void GL_State( unsigned long stateBits ) -{ - unsigned long diff = stateBits ^ glState.glStateBits; - - if ( !diff ) - { - return; - } - - // - // check depthFunc bits - // - if ( diff & GLS_DEPTHFUNC_BITS ) - { - if ( stateBits & GLS_DEPTHFUNC_EQUAL ) - { - qglDepthFunc( GL_EQUAL ); - } - else if ( stateBits & GLS_DEPTHFUNC_GREATER) - { - qglDepthFunc( GL_GREATER ); - } - else - { - qglDepthFunc( GL_LEQUAL ); - } - } - - // - // check blend bits - // - if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) - { - GLenum srcFactor, dstFactor; - - if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) - { - switch ( stateBits & GLS_SRCBLEND_BITS ) - { - case GLS_SRCBLEND_ZERO: - srcFactor = GL_ZERO; - break; - case GLS_SRCBLEND_ONE: - srcFactor = GL_ONE; - break; - case GLS_SRCBLEND_DST_COLOR: - srcFactor = GL_DST_COLOR; - break; - case GLS_SRCBLEND_ONE_MINUS_DST_COLOR: - srcFactor = GL_ONE_MINUS_DST_COLOR; - break; - case GLS_SRCBLEND_SRC_ALPHA: - srcFactor = GL_SRC_ALPHA; - break; - case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA: - srcFactor = GL_ONE_MINUS_SRC_ALPHA; - break; - case GLS_SRCBLEND_DST_ALPHA: - srcFactor = GL_DST_ALPHA; - break; - case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA: - srcFactor = GL_ONE_MINUS_DST_ALPHA; - break; - case GLS_SRCBLEND_ALPHA_SATURATE: - srcFactor = GL_SRC_ALPHA_SATURATE; - break; - default: - srcFactor = GL_ONE; // to get warning to shut up - ri.Error( ERR_DROP, "GL_State: invalid src blend state bits" ); - break; - } - - switch ( stateBits & GLS_DSTBLEND_BITS ) - { - case GLS_DSTBLEND_ZERO: - dstFactor = GL_ZERO; - break; - case GLS_DSTBLEND_ONE: - dstFactor = GL_ONE; - break; - case GLS_DSTBLEND_SRC_COLOR: - dstFactor = GL_SRC_COLOR; - break; - case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR: - dstFactor = GL_ONE_MINUS_SRC_COLOR; - break; - case GLS_DSTBLEND_SRC_ALPHA: - dstFactor = GL_SRC_ALPHA; - break; - case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA: - dstFactor = GL_ONE_MINUS_SRC_ALPHA; - break; - case GLS_DSTBLEND_DST_ALPHA: - dstFactor = GL_DST_ALPHA; - break; - case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA: - dstFactor = GL_ONE_MINUS_DST_ALPHA; - break; - default: - dstFactor = GL_ONE; // to get warning to shut up - ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits" ); - break; - } - - qglEnable( GL_BLEND ); - qglBlendFunc( srcFactor, dstFactor ); - } - else - { - qglDisable( GL_BLEND ); - } - } - - // - // check depthmask - // - if ( diff & GLS_DEPTHMASK_TRUE ) - { - if ( stateBits & GLS_DEPTHMASK_TRUE ) - { - qglDepthMask( GL_TRUE ); - } - else - { - qglDepthMask( GL_FALSE ); - } - } - - // - // fill/line mode - // - if ( diff & GLS_POLYMODE_LINE ) - { - if ( stateBits & GLS_POLYMODE_LINE ) - { - qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - } - else - { - qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - } - - // - // depthtest - // - if ( diff & GLS_DEPTHTEST_DISABLE ) - { - if ( stateBits & GLS_DEPTHTEST_DISABLE ) - { - qglDisable( GL_DEPTH_TEST ); - } - else - { - qglEnable( GL_DEPTH_TEST ); - } - } - - // - // alpha test - // - if ( diff & GLS_ATEST_BITS ) - { - switch ( stateBits & GLS_ATEST_BITS ) - { - case 0: - qglDisable( GL_ALPHA_TEST ); - break; - case GLS_ATEST_GT_0: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_GREATER, 0.0f ); - break; - case GLS_ATEST_LT_80: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_LESS, 0.5f ); - break; - case GLS_ATEST_GE_80: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_GEQUAL, 0.5f ); - break; - default: - assert( 0 ); - break; - } - } - - glState.glStateBits = stateBits; -} - - -void GL_SetProjectionMatrix(matrix_t matrix) -{ - Matrix16Copy(matrix, glState.projection); - Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection); -} - - -void GL_SetModelviewMatrix(matrix_t matrix) -{ - Matrix16Copy(matrix, glState.modelview); - Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection); -} - - -/* -================ -RB_Hyperspace - -A player has predicted a teleport, but hasn't arrived yet -================ -*/ -static void RB_Hyperspace( void ) { - float c; - - if ( !backEnd.isHyperspace ) { - // do initialization shit - } - - c = ( backEnd.refdef.time & 255 ) / 255.0f; - qglClearColor( c, c, c, 1 ); - qglClear( GL_COLOR_BUFFER_BIT ); - - backEnd.isHyperspace = qtrue; -} - - -static void SetViewportAndScissor( void ) { - GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix ); - - // set the window clipping - qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); -} - -/* -================= -RB_BeginDrawingView - -Any mirrored or portaled views have already been drawn, so prepare -to actually render the visible surfaces for this view -================= -*/ -void RB_BeginDrawingView (void) { - int clearBits = 0; - - // sync with gl if needed - if ( r_finish->integer == 1 && !glState.finishCalled ) { - qglFinish (); - glState.finishCalled = qtrue; - } - if ( r_finish->integer == 0 ) { - glState.finishCalled = qtrue; - } - - // we will need to change the projection matrix before drawing - // 2D images again - backEnd.projection2D = qfalse; - - if (glRefConfig.framebufferObject) - { - // FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world - if (backEnd.viewParms.targetFbo == tr.renderFbo && backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) - { - FBO_Bind(tr.screenScratchFbo); - } - else - { - FBO_Bind(backEnd.viewParms.targetFbo); - } - } - - // - // set the modelview matrix for the viewer - // - SetViewportAndScissor(); - - // ensures that depth writes are enabled for the depth clear - GL_State( GLS_DEFAULT ); - // clear relevant buffers - clearBits = GL_DEPTH_BUFFER_BIT; - - if ( r_measureOverdraw->integer || r_shadows->integer == 2 ) - { - clearBits |= GL_STENCIL_BUFFER_BIT; - } - if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) - { - clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used -#ifdef _DEBUG - qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky -#else - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky -#endif - } - - // clear to white for shadow maps - if (backEnd.viewParms.flags & VPF_SHADOWMAP) - { - clearBits |= GL_COLOR_BUFFER_BIT; - qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); - } - - qglClear( clearBits ); - - if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) - { - RB_Hyperspace(); - return; - } - else - { - backEnd.isHyperspace = qfalse; - } - - glState.faceCulling = -1; // force face culling to set next time - - // we will only draw a sun if there was sky rendered in this view - backEnd.skyRenderedThisView = qfalse; - -#ifdef REACTION - backEnd.viewHasSunFlare = qfalse; -#endif - - // clip to the plane of the portal - if ( backEnd.viewParms.isPortal ) { -#if 0 - float plane[4]; - double plane2[4]; - - plane[0] = backEnd.viewParms.portalPlane.normal[0]; - plane[1] = backEnd.viewParms.portalPlane.normal[1]; - plane[2] = backEnd.viewParms.portalPlane.normal[2]; - plane[3] = backEnd.viewParms.portalPlane.dist; - - plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane); - plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane); - plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane); - plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3]; -#endif - GL_SetModelviewMatrix( s_flipMatrix ); - } -} - - -#define MAC_EVENT_PUMP_MSEC 5 - -/* -================== -RB_RenderDrawSurfList -================== -*/ -void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { - shader_t *shader, *oldShader; - int fogNum, oldFogNum; - int entityNum, oldEntityNum; - int dlighted, oldDlighted; - int pshadowed, oldPshadowed; - qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair; - int i; - drawSurf_t *drawSurf; - int oldSort; - float originalTime; - FBO_t* fbo = NULL; - qboolean inQuery = qfalse; - -#if 1 //def REACTION - float depth[2]; -#endif - - - // save original time for entity shader offsets - originalTime = backEnd.refdef.floatTime; - - fbo = glState.currentFBO; - - // draw everything - oldEntityNum = -1; - backEnd.currentEntity = &tr.worldEntity; - oldShader = NULL; - oldFogNum = -1; - oldDepthRange = qfalse; - wasCrosshair = qfalse; - oldDlighted = qfalse; - oldPshadowed = qfalse; - oldSort = -1; - depthRange = qfalse; - -#if 1 //def REACTION - depth[0] = 0.f; - depth[1] = 1.f; -#endif - - backEnd.pc.c_surfaces += numDrawSurfs; - - for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) { - if ( drawSurf->sort == oldSort ) { - if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE) - continue; - - // fast path, same as previous sort - rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); - continue; - } - oldSort = drawSurf->sort; - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); - - // - // change the tess parameters if needed - // a "entityMergable" shader is a shader that can have surfaces from seperate - // entities merged into a single batch, like smoke and blood puff sprites - if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed - || ( entityNum != oldEntityNum && !shader->entityMergable ) ) { - if (oldShader != NULL) { - RB_EndSurface(); - } - RB_BeginSurface( shader, fogNum ); - backEnd.pc.c_surfBatches++; - oldShader = shader; - oldFogNum = fogNum; - oldDlighted = dlighted; - oldPshadowed = pshadowed; - } - - if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE) - continue; - - // - // change the modelview matrix if needed - // - if ( entityNum != oldEntityNum ) { - qboolean sunflare = qfalse; - depthRange = isCrosshair = qfalse; - -#ifdef REACTION - // if we were rendering to a FBO and the previous entity was a sunflare - // and the current one isn't, switch back to the main fbo - if (oldEntityNum != -1 && fbo && !backEnd.depthFill && - RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].e.renderfx & RF_SUNFLARE) && - 0 == (backEnd.refdef.entities[entityNum].e.renderfx & RF_SUNFLARE)) - { - if (inQuery) { - inQuery = qfalse; - qglEndQueryARB(GL_SAMPLES_PASSED_ARB); - } - FBO_Bind(fbo); - qglDepthRange(depth[0], depth[1]); - } -#endif - - if ( entityNum != ENTITYNUM_WORLD ) { - backEnd.currentEntity = &backEnd.refdef.entities[entityNum]; - backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime; - // we have to reset the shaderTime as well otherwise image animations start - // from the wrong frame - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - - // set up the transformation matrix - R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or ); - - // set up the dynamic lighting if needed - if ( backEnd.currentEntity->needDlights ) { - R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); - } - -#ifdef REACTION - // if the current entity is a sunflare - if(backEnd.currentEntity->e.renderfx & RF_SUNFLARE && !backEnd.depthFill) { - // if we're rendering to a fbo - if (fbo) { - VectorCopy(backEnd.currentEntity->e.origin, backEnd.sunFlarePos); - // switch FBO - FBO_Bind(tr.godRaysFbo); - - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); - qglClear( GL_COLOR_BUFFER_BIT ); - - qglDepthRange(1.f, 1.f); - if (glRefConfig.occlusionQuery && !inQuery && !backEnd.viewHasSunFlare) { - inQuery = qtrue; - tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue; - qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, tr.sunFlareQuery[tr.sunFlareQueryIndex]); - } - sunflare = qtrue; - } else { - depthRange = qtrue; - } - } -#endif - - if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK) - { - // hack the depth range to prevent view model from poking into walls - depthRange = qtrue; - - if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR) - isCrosshair = qtrue; - } - } else { - backEnd.currentEntity = &tr.worldEntity; - backEnd.refdef.floatTime = originalTime; - backEnd.or = backEnd.viewParms.world; - // we have to reset the shaderTime as well otherwise image animations on - // the world (like water) continue with the wrong frame - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); - } - - GL_SetModelviewMatrix( backEnd.or.modelMatrix ); - - // - // change depthrange. Also change projection matrix so first person weapon does not look like coming - // out of the screen. - // - if (oldDepthRange != depthRange || wasCrosshair != isCrosshair) - { - if (depthRange) - { - if(backEnd.viewParms.stereoFrame != STEREO_CENTER) - { - if(isCrosshair) - { - if(oldDepthRange) - { - // was not a crosshair but now is, change back proj matrix - GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix ); - } - } - else - { - viewParms_t temp = backEnd.viewParms; - - R_SetupProjection(&temp, r_znear->value, 0, qfalse); - - GL_SetProjectionMatrix( temp.projectionMatrix ); - } - } - -#if 1 //def REACTION - if(!oldDepthRange) - { - depth[0] = 0; - depth[1] = 0.3f; - qglDepthRange (0, 0.3); - } -#endif - } - else - { - if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER) - { - GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix ); - } - - if (!sunflare) - qglDepthRange (0, 1); -#if 1 //def REACTION - depth[0] = 0; - depth[1] = 1; -#endif - } - - oldDepthRange = depthRange; - wasCrosshair = isCrosshair; - } - - oldEntityNum = entityNum; - } - - // add the triangles for this surface - rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); - } - - backEnd.refdef.floatTime = originalTime; - - // draw the contents of the last shader batch - if (oldShader != NULL) { - RB_EndSurface(); - } - - if (inQuery) { - inQuery = qfalse; - qglEndQueryARB(GL_SAMPLES_PASSED_ARB); - } -#ifdef REACTION - // HACK: flip Z and render black to god rays buffer - if (backEnd.frameHasSunFlare && !backEnd.depthFill) - { - vec4_t black; - VectorSet4(black, 0, 0, 0, 1); - qglDepthRange (1, 1); - FBO_BlitFromTexture(tr.whiteImage, NULL, NULL, tr.godRaysFbo, NULL, NULL, black, GLS_DEPTHFUNC_GREATER); - } -#endif - - FBO_Bind(fbo); - - // go back to the world modelview matrix - - GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix ); - //if ( depthRange ) { - qglDepthRange (0, 1); - //} -} - - -/* -============================================================================ - -RENDER BACK END THREAD FUNCTIONS - -============================================================================ -*/ - -/* -================ -RB_SetGL2D - -================ -*/ -void RB_SetGL2D (void) { - matrix_t matrix; - int width, height; - - if (backEnd.projection2D && backEnd.last2DFBO == glState.currentFBO) - return; - - backEnd.projection2D = qtrue; - backEnd.last2DFBO = glState.currentFBO; - - if (glState.currentFBO) - { - width = glState.currentFBO->width; - height = glState.currentFBO->height; - } - else - { - width = glConfig.vidWidth; - height = glConfig.vidHeight; - } - - // set 2D virtual screen size - qglViewport( 0, 0, width, height ); - qglScissor( 0, 0, width, height ); - - Matrix16Ortho(0, width, height, 0, 0, 1, matrix); - GL_SetProjectionMatrix(matrix); - Matrix16Identity(matrix); - GL_SetModelviewMatrix(matrix); - - GL_State( GLS_DEPTHTEST_DISABLE | - GLS_SRCBLEND_SRC_ALPHA | - GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - - qglDisable( GL_CULL_FACE ); - qglDisable( GL_CLIP_PLANE0 ); - - // set time for 2D shaders - backEnd.refdef.time = ri.Milliseconds(); - backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f; - - // reset color scaling - backEnd.refdef.colorScale = 1.0f; -} - - -/* -============= -RE_StretchRaw - -FIXME: not exactly backend -Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle. -Used for cinematics. -============= -*/ -void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { - int i, j; - int start, end; - shaderProgram_t *sp = &tr.textureColorShader; - vec4_t color; - - if ( !tr.registered ) { - return; - } - R_SyncRenderThread(); - - // we definately want to sync every frame for the cinematics - qglFinish(); - - start = 0; - if ( r_speeds->integer ) { - start = ri.Milliseconds(); - } - - // make sure rows and cols are powers of 2 - for ( i = 0 ; ( 1 << i ) < cols ; i++ ) { - } - for ( j = 0 ; ( 1 << j ) < rows ; j++ ) { - } - if ( ( 1 << i ) != cols || ( 1 << j ) != rows) { - ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows); - } - - GL_Bind( tr.scratchImage[client] ); - - // if the scratchImage isn't in the format we want, specify it as a new texture - if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { - tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; - tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; - qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } else { - if (dirty) { - // otherwise, just subimage upload it so that drivers can tell we are going to be changing - // it and don't try and do a texture compression - qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); - } - } - - if ( r_speeds->integer ) { - end = ri.Milliseconds(); - ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start ); - } - - // FIXME: HUGE hack - if (glRefConfig.framebufferObject && !glState.currentFBO) - { - if (backEnd.framePostProcessed) - { - FBO_Bind(tr.screenScratchFbo); - } - else - { - FBO_Bind(tr.renderFbo); - } - } - - RB_SetGL2D(); - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; - - tess.xyz[tess.numVertexes][0] = x; - tess.xyz[tess.numVertexes][1] = y; - tess.xyz[tess.numVertexes][2] = 0; - tess.xyz[tess.numVertexes][3] = 1; - tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols; - tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows; - tess.texCoords[tess.numVertexes][1][0] = 0; - tess.texCoords[tess.numVertexes][1][1] = 1; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = x + w; - tess.xyz[tess.numVertexes][1] = y; - tess.xyz[tess.numVertexes][2] = 0; - tess.xyz[tess.numVertexes][3] = 1; - tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols; - tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows; - tess.texCoords[tess.numVertexes][1][0] = 0; - tess.texCoords[tess.numVertexes][1][1] = 1; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = x + w; - tess.xyz[tess.numVertexes][1] = y + h; - tess.xyz[tess.numVertexes][2] = 0; - tess.xyz[tess.numVertexes][3] = 1; - tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols; - tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows; - tess.texCoords[tess.numVertexes][1][0] = 0; - tess.texCoords[tess.numVertexes][1][1] = 1; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = x; - tess.xyz[tess.numVertexes][1] = y + h; - tess.xyz[tess.numVertexes][2] = 0; - tess.xyz[tess.numVertexes][3] = 1; - tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols; - tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows; - tess.texCoords[tess.numVertexes][1][0] = 0; - tess.texCoords[tess.numVertexes][1][1] = 1; - 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; - - // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); - - sp = &tr.textureColorShader; - - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - VectorSet4(color, 1, 1, 1, 1); - GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color); - - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex); - - //R_BindNullVBO(); - //R_BindNullIBO(); - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; -} - -void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { - - GL_Bind( tr.scratchImage[client] ); - - // if the scratchImage isn't in the format we want, specify it as a new texture - if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { - tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; - tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; - qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } else { - if (dirty) { - // otherwise, just subimage upload it so that drivers can tell we are going to be changing - // it and don't try and do a texture compression - qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); - } - } -} - - -/* -============= -RB_SetColor - -============= -*/ -const void *RB_SetColor( const void *data ) { - const setColorCommand_t *cmd; - - cmd = (const setColorCommand_t *)data; - - backEnd.color2D[0] = cmd->color[0] * 255; - backEnd.color2D[1] = cmd->color[1] * 255; - backEnd.color2D[2] = cmd->color[2] * 255; - backEnd.color2D[3] = cmd->color[3] * 255; - - return (const void *)(cmd + 1); -} - -/* -============= -RB_StretchPic -============= -*/ -const void *RB_StretchPic ( const void *data ) { - const stretchPicCommand_t *cmd; - shader_t *shader; - int numVerts, numIndexes; - - cmd = (const stretchPicCommand_t *)data; - - // FIXME: HUGE hack - if (glRefConfig.framebufferObject && !glState.currentFBO) - { - if (backEnd.framePostProcessed) - { - FBO_Bind(tr.screenScratchFbo); - } - else - { - FBO_Bind(tr.renderFbo); - } - } - - RB_SetGL2D(); - - shader = cmd->shader; - if ( shader != tess.shader ) { - if ( tess.numIndexes ) { - RB_EndSurface(); - } - backEnd.currentEntity = &backEnd.entity2D; - RB_BeginSurface( shader, 0 ); - } - - RB_CHECKOVERFLOW( 4, 6 ); - numVerts = tess.numVertexes; - numIndexes = tess.numIndexes; - - tess.numVertexes += 4; - tess.numIndexes += 6; - - tess.indexes[ numIndexes ] = numVerts + 3; - tess.indexes[ numIndexes + 1 ] = numVerts + 0; - tess.indexes[ numIndexes + 2 ] = numVerts + 2; - tess.indexes[ numIndexes + 3 ] = numVerts + 2; - tess.indexes[ numIndexes + 4 ] = numVerts + 0; - tess.indexes[ numIndexes + 5 ] = numVerts + 1; - - { - vec4_t color; - - VectorScale4(backEnd.color2D, 1.0f / 255.0f, color); - - VectorCopy4(color, tess.vertexColors[ numVerts ]); - VectorCopy4(color, tess.vertexColors[ numVerts + 1]); - VectorCopy4(color, tess.vertexColors[ numVerts + 2]); - VectorCopy4(color, tess.vertexColors[ numVerts + 3 ]); - } - - tess.xyz[ numVerts ][0] = cmd->x; - tess.xyz[ numVerts ][1] = cmd->y; - tess.xyz[ numVerts ][2] = 0; - - tess.texCoords[ numVerts ][0][0] = cmd->s1; - tess.texCoords[ numVerts ][0][1] = cmd->t1; - - tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; - tess.xyz[ numVerts + 1 ][1] = cmd->y; - tess.xyz[ numVerts + 1 ][2] = 0; - - tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; - tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; - - tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; - tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; - tess.xyz[ numVerts + 2 ][2] = 0; - - tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; - tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; - - tess.xyz[ numVerts + 3 ][0] = cmd->x; - tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; - tess.xyz[ numVerts + 3 ][2] = 0; - - tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; - tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; - - return (const void *)(cmd + 1); -} - - -/* -============= -RB_DrawSurfs - -============= -*/ -const void *RB_DrawSurfs( const void *data ) { - const drawSurfsCommand_t *cmd; - - // finish any 2D drawing if needed - if ( tess.numIndexes ) { - RB_EndSurface(); - } - - cmd = (const drawSurfsCommand_t *)data; - - backEnd.refdef = cmd->refdef; - backEnd.viewParms = cmd->viewParms; - - // clear the z buffer, set the modelview, etc - RB_BeginDrawingView (); - - if ((backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp) - { - qglEnable(GL_DEPTH_CLAMP); - } - - if (r_depthPrepass->integer || (backEnd.viewParms.flags & VPF_DEPTHSHADOW)) - { - backEnd.depthFill = qtrue; - qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); - qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); - backEnd.depthFill = qfalse; - - if (backEnd.viewParms.flags & VPF_USESUNLIGHT) - { - vec4_t quadVerts[4]; - vec2_t texCoords[4]; - FBO_t *oldFbo = glState.currentFBO; - - // If we're using multisampling, resolve the depth first - if (tr.msaaResolveFbo) - { - FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - - FBO_Bind(tr.screenShadowFbo); - - VectorSet4(quadVerts[0], -1, 1, 0, 1); - VectorSet4(quadVerts[1], 1, 1, 0, 1); - VectorSet4(quadVerts[2], 1, -1, 0, 1); - VectorSet4(quadVerts[3], -1, -1, 0, 1); - - texCoords[0][0] = 0; texCoords[0][1] = 1; - texCoords[1][0] = 1; texCoords[1][1] = 1; - texCoords[2][0] = 1; texCoords[2][1] = 0; - texCoords[3][0] = 0; texCoords[3][1] = 0; - - GL_State( GLS_DEPTHTEST_DISABLE ); - - GLSL_BindProgram(&tr.shadowmaskShader); - - GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP); - GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); - GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); - GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); - - GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); - GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); - GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); - - GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg); - { - vec4_t viewInfo; - vec3_t viewVector; - - float zmax = backEnd.viewParms.zFar; - float ymax = zmax * tan(backEnd.viewParms.fovY * M_PI / 360.0f); - float xmax = zmax * tan(backEnd.viewParms.fovX * M_PI / 360.0f); - - float zmin = r_znear->value; - - VectorScale(backEnd.refdef.viewaxis[0], zmax, viewVector); - GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWFORWARD, viewVector); - VectorScale(backEnd.refdef.viewaxis[1], xmax, viewVector); - GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWLEFT, viewVector); - VectorScale(backEnd.refdef.viewaxis[2], ymax, viewVector); - GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWUP, viewVector); - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWINFO, viewInfo); - } - - - RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); - - FBO_Bind(oldFbo); - } - } - - if ((backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp) - { - qglDisable(GL_DEPTH_CLAMP); - } - - if (!(backEnd.viewParms.flags & VPF_DEPTHSHADOW)) - { - RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); - -#if 0 - RB_DrawSun(); -#endif - // darken down any stencil shadows - RB_ShadowFinish(); - - // add light flares on lights that aren't obscured - RB_RenderFlares(); - } - - if (glRefConfig.framebufferObject) - FBO_Bind(NULL); - - return (const void *)(cmd + 1); -} - - -/* -============= -RB_DrawBuffer - -============= -*/ -const void *RB_DrawBuffer( const void *data ) { - const drawBufferCommand_t *cmd; - - cmd = (const drawBufferCommand_t *)data; - - qglDrawBuffer( cmd->buffer ); - - // clear screen for debugging - if ( r_clear->integer ) { - qglClearColor( 1, 0, 0.5, 1 ); - qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - } - - return (const void *)(cmd + 1); -} - -/* -=============== -RB_ShowImages - -Draw all the images to the screen, on top of whatever -was there. This is used to test for texture thrashing. - -Also called by RE_EndRegistration -=============== -*/ -void RB_ShowImages( void ) { - int i; - image_t *image; - float x, y, w, h; - int start, end; - - RB_SetGL2D(); - - qglClear( GL_COLOR_BUFFER_BIT ); - - qglFinish(); - - start = ri.Milliseconds(); - - for ( i=0 ; iinteger == 2 ) { - w *= image->uploadWidth / 512.0f; - h *= image->uploadHeight / 512.0f; - } - - { - vec4_t quadVerts[4]; - - GL_Bind(image); - - VectorSet4(quadVerts[0], x, y, 0, 1); - VectorSet4(quadVerts[1], x + w, y, 0, 1); - VectorSet4(quadVerts[2], x + w, y + h, 0, 1); - VectorSet4(quadVerts[3], x, y + h, 0, 1); - - RB_InstantQuad(quadVerts); - } - } - - qglFinish(); - - end = ri.Milliseconds(); - ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start ); - -} - -/* -============= -RB_ColorMask - -============= -*/ -const void *RB_ColorMask(const void *data) -{ - const colorMaskCommand_t *cmd = data; - - if (glRefConfig.framebufferObject) - { - // reverse color mask, so 0 0 0 0 is the default - backEnd.colorMask[0] = !cmd->rgba[0]; - backEnd.colorMask[1] = !cmd->rgba[1]; - backEnd.colorMask[2] = !cmd->rgba[2]; - backEnd.colorMask[3] = !cmd->rgba[3]; - } - - qglColorMask(cmd->rgba[0], cmd->rgba[1], cmd->rgba[2], cmd->rgba[3]); - - return (const void *)(cmd + 1); -} - -/* -============= -RB_ClearDepth - -============= -*/ -const void *RB_ClearDepth(const void *data) -{ - const clearDepthCommand_t *cmd = data; - - if(tess.numIndexes) - RB_EndSurface(); - - // texture swapping test - if (r_showImages->integer) - RB_ShowImages(); - - qglClear(GL_DEPTH_BUFFER_BIT); - - return (const void *)(cmd + 1); -} - -/* -============= -RB_SwapBuffers - -============= -*/ -const void *RB_SwapBuffers( const void *data ) { - const swapBuffersCommand_t *cmd; - - // finish any 2D drawing if needed - if ( tess.numIndexes ) { - RB_EndSurface(); - } - - // texture swapping test - if ( r_showImages->integer ) { - RB_ShowImages(); - } - - cmd = (const swapBuffersCommand_t *)data; - - // we measure overdraw by reading back the stencil buffer and - // counting up the number of increments that have happened - if ( r_measureOverdraw->integer ) { - int i; - long sum = 0; - unsigned char *stencilReadback; - - stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight ); - qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback ); - - for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) { - sum += stencilReadback[i]; - } - - backEnd.pc.c_overDraw += sum; - ri.Hunk_FreeTempMemory( stencilReadback ); - } - - if (glRefConfig.framebufferObject) - { - // copy final image to screen - vec4_t color; - - if (backEnd.framePostProcessed) - { - // frame was postprocessed into screen fbo, copy from there - } - else if (!glRefConfig.framebuffer_srgb) - { - // Copy render to screenscratch, possibly resolving MSAA - FBO_FastBlit(tr.renderFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - else - { - FBO_t *srcFbo = tr.renderFbo; - - if (tr.msaaResolveFbo) - { - // Resolve the MSAA before copying - FBO_FastBlit(srcFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - srcFbo = tr.msaaResolveFbo; - } - - // need to copy from resolve to screenscratch to fix gamma - FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, NULL, 0); - } - - color[0] = - color[1] = - color[2] = pow(2, tr.overbrightBits); //exp2(tr.overbrightBits); - color[3] = 1.0f; - - // turn off colormask when copying final image - if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3]) - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - FBO_Blit(tr.screenScratchFbo, NULL, NULL, NULL, NULL, NULL, color, 0); - - if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3]) - qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); - } - - if ( !glState.finishCalled ) { - qglFinish(); - } - - GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" ); - - GLimp_EndFrame(); - - backEnd.framePostProcessed = qfalse; - backEnd.projection2D = qfalse; -#ifdef REACTION - backEnd.frameHasSunFlare = qfalse; -#endif - - return (const void *)(cmd + 1); -} - -/* -============= -RB_CapShadowMap - -============= -*/ -const void *RB_CapShadowMap(const void *data) -{ - const capShadowmapCommand_t *cmd = data; - - if (cmd->map != -1) - { - GL_SelectTexture(0); - if (cmd->cubeSide != -1) - { - GL_BindCubemap(tr.shadowCubemaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); - } - else - { - GL_Bind(tr.pshadowMaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); - } - } - - return (const void *)(cmd + 1); -} - - - -/* -============= -RB_PostProcess - -============= -*/ -const void *RB_PostProcess(const void *data) -{ - const postProcessCommand_t *cmd = data; - FBO_t *srcFbo; - qboolean autoExposure; - - if (!glRefConfig.framebufferObject) - { - // do nothing - backEnd.framePostProcessed = qtrue; - - return (const void *)(cmd + 1); - } - - srcFbo = tr.renderFbo; - if (tr.msaaResolveFbo) - { - // Resolve the MSAA before anything else - FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - srcFbo = tr.msaaResolveFbo; - } - - if (r_postProcess->integer && r_hdr->integer && (r_toneMap->integer == 2 || (r_toneMap->integer == 1 && tr.autoExposure))) - { - autoExposure = (r_autoExposure->integer == 1 && tr.autoExposure) || (r_autoExposure->integer == 2); - RB_ToneMap(srcFbo, autoExposure); - } - else if (!glRefConfig.framebuffer_srgb && r_cameraExposure->value == 0.0f) - { - FBO_FastBlit(srcFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - else - { - vec4_t color; - - color[0] = - color[1] = - color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value); - color[3] = 1.0f; - - FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, 0); - } - -#ifdef REACTION - if (r_postProcess->integer && glRefConfig.framebufferObject) - { - RB_GodRays(); - - if (1) - RB_BokehBlur(backEnd.refdef.blurFactor); - else - RB_GaussianBlur(backEnd.refdef.blurFactor); - } -#endif - - if (0) - { - vec4i_t dstBox; - VectorSet4(dstBox, 0, 0, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); - VectorSet4(dstBox, 128, 0, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); - VectorSet4(dstBox, 256, 0, 128, 128); - FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); - } - - if (0) - { - vec4i_t dstBox; - VectorSet4(dstBox, 256, tr.screenScratchFbo->height - 256, 256, 256); - FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); - VectorSet4(dstBox, 512, tr.screenScratchFbo->height - 256, 256, 256); - FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0); - } - - backEnd.framePostProcessed = qtrue; - - return (const void *)(cmd + 1); -} - -/* -==================== -RB_ExecuteRenderCommands - -This function will be called synchronously if running without -smp extensions, or asynchronously by another thread. -==================== -*/ -void RB_ExecuteRenderCommands( const void *data ) { - int t1, t2; - - t1 = ri.Milliseconds (); - - if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) { - backEnd.smpFrame = 0; - } else { - backEnd.smpFrame = 1; - } - - while ( 1 ) { - data = PADP(data, sizeof(void *)); - - switch ( *(const int *)data ) { - case RC_SET_COLOR: - data = RB_SetColor( data ); - break; - case RC_STRETCH_PIC: - data = RB_StretchPic( data ); - break; - case RC_DRAW_SURFS: - data = RB_DrawSurfs( data ); - break; - case RC_DRAW_BUFFER: - data = RB_DrawBuffer( data ); - break; - case RC_SWAP_BUFFERS: - data = RB_SwapBuffers( data ); - break; - case RC_SCREENSHOT: - data = RB_TakeScreenshotCmd( data ); - break; - case RC_VIDEOFRAME: - data = RB_TakeVideoFrameCmd( data ); - break; - case RC_COLORMASK: - data = RB_ColorMask(data); - break; - case RC_CLEARDEPTH: - data = RB_ClearDepth(data); - break; - case RC_CAPSHADOWMAP: - data = RB_CapShadowMap(data); - break; - case RC_POSTPROCESS: - data = RB_PostProcess(data); - break; - case RC_END_OF_LIST: - default: - // stop rendering on this thread - t2 = ri.Milliseconds (); - backEnd.pc.msec = t2 - t1; - return; - } - } - -} - - -/* -================ -RB_RenderThread -================ -*/ -void RB_RenderThread( void ) { - const void *data; - - // wait for either a rendering command or a quit command - while ( 1 ) { - // sleep until we have work to do - data = GLimp_RendererSleep(); - - if ( !data ) { - return; // all done, renderer is shutting down - } - - renderThreadActive = qtrue; - - RB_ExecuteRenderCommands( data ); - - renderThreadActive = qfalse; - } -} - - diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c deleted file mode 100644 index c06efa91..00000000 --- a/code/renderergl2/tr_bsp.c +++ /dev/null @@ -1,3319 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_map.c - -#include "tr_local.h" - -/* - -Loads and prepares a map file for scene rendering. - -A single entry point: - -void RE_LoadWorldMap( const char *name ); - -*/ - -static world_t s_worldData; -static byte *fileBase; - -int c_subdivisions; -int c_gridVerts; - -//=============================================================================== - -static void HSVtoRGB( float h, float s, float v, float rgb[3] ) -{ - int i; - float f; - float p, q, t; - - h *= 5; - - i = floor( h ); - f = h - i; - - p = v * ( 1 - s ); - q = v * ( 1 - s * f ); - t = v * ( 1 - s * ( 1 - f ) ); - - switch ( i ) - { - case 0: - rgb[0] = v; - rgb[1] = t; - rgb[2] = p; - break; - case 1: - rgb[0] = q; - rgb[1] = v; - rgb[2] = p; - break; - case 2: - rgb[0] = p; - rgb[1] = v; - rgb[2] = t; - break; - case 3: - rgb[0] = p; - rgb[1] = q; - rgb[2] = v; - break; - case 4: - rgb[0] = t; - rgb[1] = p; - rgb[2] = v; - break; - case 5: - rgb[0] = v; - rgb[1] = p; - rgb[2] = q; - break; - } -} - -/* -=============== -R_ColorShiftLightingBytes - -=============== -*/ -static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) { - int shift, r, g, b; - - // shift the color data based on overbright range - shift = r_mapOverBrightBits->integer - tr.overbrightBits; - - // shift the data based on overbright range - r = in[0] << shift; - g = in[1] << shift; - b = in[2] << shift; - - // normalize by color instead of saturating to white - if ( ( r | g | b ) > 255 ) { - int max; - - max = r > g ? r : g; - max = max > b ? max : b; - r = r * 255 / max; - g = g * 255 / max; - b = b * 255 / max; - } - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in[3]; -} - - -/* -=============== -R_ColorShiftLightingBytes - -=============== -*/ -static void R_ColorShiftLightingFloats(float in[4], float out[4], float scale ) -{ - scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits); - - out[0] = in[0] * scale; - out[1] = in[1] * scale; - out[2] = in[2] * scale; - out[3] = in[3]; -} - - -void ColorToRGBE(const vec3_t color, unsigned char rgbe[4]) -{ - vec3_t sample; - float maxComponent; - int e; - - VectorCopy(color, sample); - - maxComponent = sample[0]; - if(sample[1] > maxComponent) - maxComponent = sample[1]; - if(sample[2] > maxComponent) - maxComponent = sample[2]; - - if(maxComponent < 1e-32) - { - rgbe[0] = 0; - rgbe[1] = 0; - rgbe[2] = 0; - rgbe[3] = 0; - } - else - { -#if 0 - maxComponent = frexp(maxComponent, &e) * 255.0 / maxComponent; - rgbe[0] = (unsigned char) (sample[0] * maxComponent); - rgbe[1] = (unsigned char) (sample[1] * maxComponent); - rgbe[2] = (unsigned char) (sample[2] * maxComponent); - rgbe[3] = (unsigned char) (e + 128); -#else - e = ceil(log(maxComponent) / log(2.0f));//ceil(log2(maxComponent)); - VectorScale(sample, 1.0 / pow(2.0f, e)/*exp2(e)*/, sample); - - rgbe[0] = (unsigned char) (sample[0] * 255); - rgbe[1] = (unsigned char) (sample[1] * 255); - rgbe[2] = (unsigned char) (sample[2] * 255); - rgbe[3] = (unsigned char) (e + 128); -#endif - } -} - - -void ColorToRGBA16F(const vec3_t color, unsigned short rgba16f[4]) -{ - rgba16f[0] = FloatToHalf(color[0]); - rgba16f[1] = FloatToHalf(color[1]); - rgba16f[2] = FloatToHalf(color[2]); - rgba16f[3] = FloatToHalf(1.0f); -} - - -/* -=============== -R_LoadLightmaps - -=============== -*/ -#define DEFAULT_LIGHTMAP_SIZE 128 -#define MAX_LIGHTMAP_PAGES 2 -static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) { - byte *buf, *buf_p; - dsurface_t *surf; - int len; - byte *image; - int i, j, numLightmaps, textureInternalFormat = 0; - float maxIntensity = 0; - double sumIntensity = 0; - - len = l->filelen; - if ( !len ) { - return; - } - buf = fileBase + l->fileofs; - - // we are about to upload textures - R_SyncRenderThread(); - - // check for deluxe mapping - tr.worldDeluxeMapping = qtrue; - for( i = 0, surf = (dsurface_t *)(fileBase + surfs->fileofs); - i < surfs->filelen / sizeof(dsurface_t); i++, surf++ ) { - int lightmapNum = LittleLong( surf->lightmapNum ); - - if ( lightmapNum >= 0 && (lightmapNum & 1) != 0 ) { - tr.worldDeluxeMapping = qfalse; - break; - } - } - - tr.lightmapSize = DEFAULT_LIGHTMAP_SIZE; - numLightmaps = len / (tr.lightmapSize * tr.lightmapSize * 3); - - image = ri.Malloc(tr.lightmapSize * tr.lightmapSize * 4 * 2); - - if (tr.worldDeluxeMapping) - numLightmaps >>= 1; - - if(numLightmaps == 1) - { - //FIXME: HACK: maps with only one lightmap turn up fullbright for some reason. - //this avoids this, but isn't the correct solution. - numLightmaps++; - } - else if (r_mergeLightmaps->integer && numLightmaps >= 1024 ) - { - // FIXME: fat light maps don't support more than 1024 light maps - ri.Printf(PRINT_WARNING, "WARNING: number of lightmaps > 1024\n"); - numLightmaps = 1024; - } - - // use fat lightmaps of an appropriate size - if (r_mergeLightmaps->integer) - { - tr.fatLightmapSize = 512; - tr.fatLightmapStep = tr.fatLightmapSize / tr.lightmapSize; - - // at most MAX_LIGHTMAP_PAGES - while (tr.fatLightmapStep * tr.fatLightmapStep * MAX_LIGHTMAP_PAGES < numLightmaps && tr.fatLightmapSize != glConfig.maxTextureSize ) - { - tr.fatLightmapSize <<= 1; - tr.fatLightmapStep = tr.fatLightmapSize / tr.lightmapSize; - } - - tr.numLightmaps = numLightmaps / (tr.fatLightmapStep * tr.fatLightmapStep); - - if (numLightmaps % (tr.fatLightmapStep * tr.fatLightmapStep) != 0) - tr.numLightmaps++; - } - else - { - tr.numLightmaps = numLightmaps; - } - - tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); - - if (tr.worldDeluxeMapping) - { - tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); - } - - if (r_hdr->integer && glRefConfig.textureFloat && glRefConfig.halfFloatPixel) - textureInternalFormat = GL_RGBA16F_ARB; - - if (r_mergeLightmaps->integer) - { - for (i = 0; i < tr.numLightmaps; i++) - { - tr.lightmaps[i] = R_CreateImage(va("_fatlightmap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat ); - - if (tr.worldDeluxeMapping) - { - tr.deluxemaps[i] = R_CreateImage(va("_fatdeluxemap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 ); - } - } - } - - for(i = 0; i < numLightmaps; i++) - { - int xoff = 0, yoff = 0; - int lightmapnum = i; - // expand the 24 bit on-disk to 32 bit - - if (r_mergeLightmaps->integer) - { - int lightmaponpage = i % (tr.fatLightmapStep * tr.fatLightmapStep); - xoff = (lightmaponpage % tr.fatLightmapStep) * tr.lightmapSize; - yoff = (lightmaponpage / tr.fatLightmapStep) * tr.lightmapSize; - - lightmapnum /= (tr.fatLightmapStep * tr.fatLightmapStep); - } - - // if (tr.worldLightmapping) - { - char filename[MAX_QPATH]; - byte *hdrLightmap = NULL; - float lightScale = 1.0f; - int size = 0; - - // look for hdr lightmaps - if (r_hdr->integer) - { - Com_sprintf( filename, sizeof( filename ), "maps/%s/lm_%04d.hdr", s_worldData.baseName, i * (tr.worldDeluxeMapping ? 2 : 1) ); - //ri.Printf(PRINT_ALL, "looking for %s\n", filename); - - size = ri.FS_ReadFile(filename, (void **)&hdrLightmap); - } - - if (hdrLightmap) - { - byte *p = hdrLightmap; - //ri.Printf(PRINT_ALL, "found!\n"); - - /* FIXME: don't just skip over this header and actually parse it */ - while (size && !(*p == '\n' && *(p+1) == '\n')) - { - size--; - p++; - } - - if (!size) - ri.Error(ERR_DROP, "Bad header for %s!\n", filename); - - size -= 2; - p += 2; - - while (size && !(*p == '\n')) - { - size--; - p++; - } - - size--; - p++; - - buf_p = (byte *)p; - -#if 0 // HDRFILE_RGBE - if (size != tr.lightmapSize * tr.lightmapSize * 4) - ri.Error(ERR_DROP, "Bad size for %s (%i)!\n", filename, size); -#else // HDRFILE_FLOAT - if (size != tr.lightmapSize * tr.lightmapSize * 12) - ri.Error(ERR_DROP, "Bad size for %s (%i)!\n", filename, size); -#endif - } - else - { - if (tr.worldDeluxeMapping) - buf_p = buf + (i * 2) * tr.lightmapSize * tr.lightmapSize * 3; - else - buf_p = buf + i * tr.lightmapSize * tr.lightmapSize * 3; - } - - lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); //exp2(r_mapOverBrightBits->integer - tr.overbrightBits - 8); - - for ( j = 0 ; j < tr.lightmapSize * tr.lightmapSize; j++ ) - { - if (r_hdr->integer) - { - float color[3]; - - if (hdrLightmap) - { -#if 0 // HDRFILE_RGBE - float exponent = exp2(buf_p[j*4+3] - 128); - - color[0] = buf_p[j*4+0] * exponent; - color[1] = buf_p[j*4+1] * exponent; - color[2] = buf_p[j*4+2] * exponent; -#else // HDRFILE_FLOAT - memcpy(color, &buf_p[j*12], 12); - - color[0] = LittleFloat(color[0]); - color[1] = LittleFloat(color[1]); - color[2] = LittleFloat(color[2]); -#endif - } - else - { - //hack: convert LDR lightmap to HDR one - color[0] = (buf_p[j*3+0] + 1.0f); - color[1] = (buf_p[j*3+1] + 1.0f); - color[2] = (buf_p[j*3+2] + 1.0f); - - // if under an arbitrary value (say 12) grey it out - // this prevents weird splotches in dimly lit areas - if (color[0] + color[1] + color[2] < 12.0f) - { - float avg = (color[0] + color[1] + color[2]) * 0.3333f; - color[0] = avg; - color[1] = avg; - color[2] = avg; - } - } - - VectorScale(color, lightScale, color); - - if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel) - ColorToRGBA16F(color, (unsigned short *)(&image[j*8])); - else - ColorToRGBE(color, &image[j*4]); - } - else - { - if ( r_lightmap->integer == 2 ) - { // color code by intensity as development tool (FIXME: check range) - float r = buf_p[j*3+0]; - float g = buf_p[j*3+1]; - float b = buf_p[j*3+2]; - float intensity; - float out[3] = {0.0, 0.0, 0.0}; - - intensity = 0.33f * r + 0.685f * g + 0.063f * b; - - if ( intensity > 255 ) - intensity = 1.0f; - else - intensity /= 255.0f; - - if ( intensity > maxIntensity ) - maxIntensity = intensity; - - HSVtoRGB( intensity, 1.00, 0.50, out ); - - image[j*4+0] = out[0] * 255; - image[j*4+1] = out[1] * 255; - image[j*4+2] = out[2] * 255; - image[j*4+3] = 255; - - sumIntensity += intensity; - } - else - { - R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); - image[j*4+3] = 255; - } - } - } - - if (r_mergeLightmaps->integer) - R_UpdateSubImage(tr.lightmaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize); - else - tr.lightmaps[i] = R_CreateImage(va("*lightmap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat ); - - if (hdrLightmap) - ri.FS_FreeFile(hdrLightmap); - } - - if (tr.worldDeluxeMapping) - { - buf_p = buf + (i * 2 + 1) * tr.lightmapSize * tr.lightmapSize * 3; - - for ( j = 0 ; j < tr.lightmapSize * tr.lightmapSize; j++ ) { - image[j*4+0] = buf_p[j*3+0]; - image[j*4+1] = buf_p[j*3+1]; - image[j*4+2] = buf_p[j*3+2]; - - // make 0,0,0 into 127,127,127 - if ((image[j*4+0] == 0) && (image[j*4+0] == 0) && (image[j*4+2] == 0)) - { - image[j*4+0] = - image[j*4+1] = - image[j*4+2] = 127; - } - - image[j*4+3] = 255; - } - - if (r_mergeLightmaps->integer) - { - R_UpdateSubImage(tr.deluxemaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize ); - } - else - { - tr.deluxemaps[i] = R_CreateImage(va("*deluxemap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 ); - } - } - } - - if ( r_lightmap->integer == 2 ) { - ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); - } - - ri.Free(image); -} - - -static float FatPackU(float input, int lightmapnum) -{ - if (lightmapnum < 0) - return input; - - if (tr.worldDeluxeMapping) - lightmapnum >>= 1; - - lightmapnum %= (tr.fatLightmapStep * tr.fatLightmapStep); - - if(tr.fatLightmapSize > 0) - { - int x = lightmapnum % tr.fatLightmapStep; - - return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)x); - } - - return input; -} - -static float FatPackV(float input, int lightmapnum) -{ - if (lightmapnum < 0) - return input; - - if (tr.worldDeluxeMapping) - lightmapnum >>= 1; - - lightmapnum %= (tr.fatLightmapStep * tr.fatLightmapStep); - - if(tr.fatLightmapSize > 0) - { - int y = lightmapnum / tr.fatLightmapStep; - - return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)y); - } - - return input; -} - - -static int FatLightmap(int lightmapnum) -{ - if (lightmapnum < 0) - return lightmapnum; - - if (tr.worldDeluxeMapping) - lightmapnum >>= 1; - - if (tr.fatLightmapSize > 0) - { - return lightmapnum / (tr.fatLightmapStep * tr.fatLightmapStep); - } - - return lightmapnum; -} - -/* -================= -RE_SetWorldVisData - -This is called by the clipmodel subsystem so we can share the 1.8 megs of -space in big maps... -================= -*/ -void RE_SetWorldVisData( const byte *vis ) { - tr.externalVisData = vis; -} - - -/* -================= -R_LoadVisibility -================= -*/ -static void R_LoadVisibility( lump_t *l ) { - int len; - byte *buf; - - len = ( s_worldData.numClusters + 63 ) & ~63; - s_worldData.novis = ri.Hunk_Alloc( len, h_low ); - Com_Memset( s_worldData.novis, 0xff, len ); - - len = l->filelen; - if ( !len ) { - return; - } - buf = fileBase + l->fileofs; - - s_worldData.numClusters = LittleLong( ((int *)buf)[0] ); - s_worldData.clusterBytes = LittleLong( ((int *)buf)[1] ); - - // CM_Load should have given us the vis data to share, so - // we don't need to allocate another copy - if ( tr.externalVisData ) { - s_worldData.vis = tr.externalVisData; - } else { - byte *dest; - - dest = ri.Hunk_Alloc( len - 8, h_low ); - Com_Memcpy( dest, buf + 8, len - 8 ); - s_worldData.vis = dest; - } -} - -//=============================================================================== - - -/* -=============== -ShaderForShaderNum -=============== -*/ -static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) { - shader_t *shader; - dshader_t *dsh; - - int _shaderNum = LittleLong( shaderNum ); - if ( _shaderNum < 0 || _shaderNum >= s_worldData.numShaders ) { - ri.Error( ERR_DROP, "ShaderForShaderNum: bad num %i", _shaderNum ); - } - dsh = &s_worldData.shaders[ _shaderNum ]; - - if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) { - lightmapNum = LIGHTMAP_BY_VERTEX; - } - - if ( r_fullbright->integer ) { - lightmapNum = LIGHTMAP_WHITEIMAGE; - } - - shader = R_FindShader( dsh->shader, lightmapNum, qtrue ); - - // if the shader had errors, just use default shader - if ( shader->defaultShader ) { - return tr.defaultShader; - } - - return shader; -} - -/* -=============== -ParseFace -=============== -*/ -static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { - int i, j; - srfSurfaceFace_t *cv; - srfTriangle_t *tri; - int numVerts, numTriangles, badTriangles; - int realLightmapNum; - - realLightmapNum = LittleLong( ds->lightmapNum ); - - // get fog volume - surf->fogIndex = LittleLong( ds->fogNum ) + 1; - - // get shader value - surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) ); - if ( r_singleShader->integer && !surf->shader->isSky ) { - surf->shader = tr.defaultShader; - } - - numVerts = LittleLong(ds->numVerts); - if (numVerts > MAX_FACE_POINTS) { - ri.Printf( PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numVerts); - numVerts = MAX_FACE_POINTS; - surf->shader = tr.defaultShader; - } - - numTriangles = LittleLong(ds->numIndexes) / 3; - - //cv = ri.Hunk_Alloc(sizeof(*cv), h_low); - cv = (void *)surf->data; - cv->surfaceType = SF_FACE; - - cv->numTriangles = numTriangles; - cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low); - - cv->numVerts = numVerts; - cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); - - // copy vertexes - surf->cullinfo.type = CULLINFO_PLANE | CULLINFO_BOX; - ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]); - verts += LittleLong(ds->firstVert); - for(i = 0; i < numVerts; i++) - { - vec4_t color; - - for(j = 0; j < 3; j++) - { - cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]); - cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]); - } - AddPointToBounds(cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]); - for(j = 0; j < 2; j++) - { - cv->verts[i].st[j] = LittleFloat(verts[i].st[j]); - //cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]); - } - cv->verts[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum); - cv->verts[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum); - - if (hdrVertColors) - { - color[0] = hdrVertColors[(ds->firstVert + i) * 3 ]; - color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1]; - color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2]; - } - else - { - //hack: convert LDR vertex colors to HDR - if (r_hdr->integer) - { - color[0] = verts[i].color[0] + 1.0f; - color[1] = verts[i].color[1] + 1.0f; - color[2] = verts[i].color[2] + 1.0f; - } - else - { - color[0] = verts[i].color[0]; - color[1] = verts[i].color[1]; - color[2] = verts[i].color[2]; - } - - } - color[3] = verts[i].color[3] / 255.0f; - - R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f ); - } - - // copy triangles - badTriangles = 0; - indexes += LittleLong(ds->firstIndex); - for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - tri->indexes[j] = LittleLong(indexes[i * 3 + j]); - - if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts) - { - ri.Error(ERR_DROP, "Bad index in face surface"); - } - } - - if ((tri->indexes[0] == tri->indexes[1]) || (tri->indexes[1] == tri->indexes[2]) || (tri->indexes[0] == tri->indexes[2])) - { - tri--; - badTriangles++; - } - } - - if (badTriangles) - { - ri.Printf(PRINT_WARNING, "Face has bad triangles, originally shader %s %d tris %d verts, now %d tris\n", surf->shader->name, numTriangles, numVerts, numTriangles - badTriangles); - cv->numTriangles -= badTriangles; - } - - // take the plane information from the lightmap vector - for ( i = 0 ; i < 3 ; i++ ) { - cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); - } - cv->plane.dist = DotProduct( cv->verts[0].xyz, cv->plane.normal ); - SetPlaneSignbits( &cv->plane ); - cv->plane.type = PlaneTypeForNormal( cv->plane.normal ); - surf->cullinfo.plane = cv->plane; - - surf->data = (surfaceType_t *)cv; - -#ifdef USE_VERT_TANGENT_SPACE - // Tr3B - calc tangent spaces - { - srfVert_t *dv[3]; - - for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++) - { - dv[0] = &cv->verts[tri->indexes[0]]; - dv[1] = &cv->verts[tri->indexes[1]]; - dv[2] = &cv->verts[tri->indexes[2]]; - - R_CalcTangentVectors(dv); - } - } -#endif -} - - -/* -=============== -ParseMesh -=============== -*/ -static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) { - srfGridMesh_t *grid; - int i, j; - int width, height, numPoints; - srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE]; - vec3_t bounds[2]; - vec3_t tmpVec; - static surfaceType_t skipData = SF_SKIP; - int realLightmapNum; - - realLightmapNum = LittleLong( ds->lightmapNum ); - - // get fog volume - surf->fogIndex = LittleLong( ds->fogNum ) + 1; - - // get shader value - surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) ); - if ( r_singleShader->integer && !surf->shader->isSky ) { - surf->shader = tr.defaultShader; - } - - // we may have a nodraw surface, because they might still need to - // be around for movement clipping - if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) { - surf->data = &skipData; - return; - } - - width = LittleLong( ds->patchWidth ); - height = LittleLong( ds->patchHeight ); - - if(width < 0 || width > MAX_PATCH_SIZE || height < 0 || height > MAX_PATCH_SIZE) - ri.Error(ERR_DROP, "ParseMesh: bad size"); - - verts += LittleLong( ds->firstVert ); - numPoints = width * height; - for(i = 0; i < numPoints; i++) - { - vec4_t color; - - for(j = 0; j < 3; j++) - { - points[i].xyz[j] = LittleFloat(verts[i].xyz[j]); - points[i].normal[j] = LittleFloat(verts[i].normal[j]); - } - - for(j = 0; j < 2; j++) - { - points[i].st[j] = LittleFloat(verts[i].st[j]); - //points[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]); - } - points[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum); - points[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum); - - if (hdrVertColors) - { - color[0] = hdrVertColors[(ds->firstVert + i) * 3 ]; - color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1]; - color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2]; - } - else - { - //hack: convert LDR vertex colors to HDR - if (r_hdr->integer) - { - color[0] = verts[i].color[0] + 1.0f; - color[1] = verts[i].color[1] + 1.0f; - color[2] = verts[i].color[2] + 1.0f; - } - else - { - color[0] = verts[i].color[0]; - color[1] = verts[i].color[1]; - color[2] = verts[i].color[2]; - } - } - color[3] = verts[i].color[3] / 255.0f; - - R_ColorShiftLightingFloats( color, points[i].vertexColors, 1.0f / 255.0f ); - } - - // pre-tesseleate - grid = R_SubdividePatchToGrid( width, height, points ); - surf->data = (surfaceType_t *)grid; - - // copy the level of detail origin, which is the center - // of the group of all curves that must subdivide the same - // to avoid cracking - for ( i = 0 ; i < 3 ; i++ ) { - bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] ); - bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] ); - } - VectorAdd( bounds[0], bounds[1], bounds[1] ); - VectorScale( bounds[1], 0.5f, grid->lodOrigin ); - VectorSubtract( bounds[0], grid->lodOrigin, tmpVec ); - grid->lodRadius = VectorLength( tmpVec ); -} - -/* -=============== -ParseTriSurf -=============== -*/ -static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) { - srfTriangles_t *cv; - srfTriangle_t *tri; - int i, j; - int numVerts, numTriangles, badTriangles; - - // get fog volume - surf->fogIndex = LittleLong( ds->fogNum ) + 1; - - // get shader - surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX ); - if ( r_singleShader->integer && !surf->shader->isSky ) { - surf->shader = tr.defaultShader; - } - - numVerts = LittleLong(ds->numVerts); - numTriangles = LittleLong(ds->numIndexes) / 3; - - //cv = ri.Hunk_Alloc(sizeof(*cv), h_low); - cv = (void *)surf->data; - cv->surfaceType = SF_TRIANGLES; - - cv->numTriangles = numTriangles; - cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low); - - cv->numVerts = numVerts; - cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); - - surf->data = (surfaceType_t *) cv; - - // copy vertexes - surf->cullinfo.type = CULLINFO_BOX; - ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]); - verts += LittleLong(ds->firstVert); - for(i = 0; i < numVerts; i++) - { - vec4_t color; - - for(j = 0; j < 3; j++) - { - cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]); - cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]); - } - - AddPointToBounds( cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1] ); - - for(j = 0; j < 2; j++) - { - cv->verts[i].st[j] = LittleFloat(verts[i].st[j]); - cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]); - } - - if (hdrVertColors) - { - color[0] = hdrVertColors[(ds->firstVert + i) * 3 ]; - color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1]; - color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2]; - } - else - { - //hack: convert LDR vertex colors to HDR - if (r_hdr->integer) - { - color[0] = verts[i].color[0] + 1.0f; - color[1] = verts[i].color[1] + 1.0f; - color[2] = verts[i].color[2] + 1.0f; - } - else - { - color[0] = verts[i].color[0]; - color[1] = verts[i].color[1]; - color[2] = verts[i].color[2]; - } - } - color[3] = verts[i].color[3] / 255.0f; - - R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f ); - } - - // copy triangles - badTriangles = 0; - indexes += LittleLong(ds->firstIndex); - for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - tri->indexes[j] = LittleLong(indexes[i * 3 + j]); - - if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts) - { - ri.Error(ERR_DROP, "Bad index in face surface"); - } - } - - if ((tri->indexes[0] == tri->indexes[1]) || (tri->indexes[1] == tri->indexes[2]) || (tri->indexes[0] == tri->indexes[2])) - { - tri--; - badTriangles++; - } - } - - if (badTriangles) - { - ri.Printf(PRINT_WARNING, "Trisurf has bad triangles, originally shader %s %d tris %d verts, now %d tris\n", surf->shader->name, numTriangles, numVerts, numTriangles - badTriangles); - cv->numTriangles -= badTriangles; - } - -#ifdef USE_VERT_TANGENT_SPACE - // Tr3B - calc tangent spaces - { - srfVert_t *dv[3]; - - for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++) - { - dv[0] = &cv->verts[tri->indexes[0]]; - dv[1] = &cv->verts[tri->indexes[1]]; - dv[2] = &cv->verts[tri->indexes[2]]; - - R_CalcTangentVectors(dv); - } - } -#endif -} - -/* -=============== -ParseFlare -=============== -*/ -static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) { - srfFlare_t *flare; - int i; - - // get fog volume - surf->fogIndex = LittleLong( ds->fogNum ) + 1; - - // get shader - surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX ); - if ( r_singleShader->integer && !surf->shader->isSky ) { - surf->shader = tr.defaultShader; - } - - //flare = ri.Hunk_Alloc( sizeof( *flare ), h_low ); - flare = (void *)surf->data; - flare->surfaceType = SF_FLARE; - - surf->data = (surfaceType_t *)flare; - - for ( i = 0 ; i < 3 ; i++ ) { - flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] ); - flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] ); - flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); - } -} - - -/* -================= -R_MergedWidthPoints - -returns true if there are grid points merged on a width edge -================= -*/ -int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) { - int i, j; - - for (i = 1; i < grid->width-1; i++) { - for (j = i + 1; j < grid->width-1; j++) { - if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue; - if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue; - if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue; - return qtrue; - } - } - return qfalse; -} - -/* -================= -R_MergedHeightPoints - -returns true if there are grid points merged on a height edge -================= -*/ -int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) { - int i, j; - - for (i = 1; i < grid->height-1; i++) { - for (j = i + 1; j < grid->height-1; j++) { - if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue; - if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue; - if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue; - return qtrue; - } - } - return qfalse; -} - -/* -================= -R_FixSharedVertexLodError_r - -NOTE: never sync LoD through grid edges with merged points! - -FIXME: write generalized version that also avoids cracks between a patch and one that meets half way? -================= -*/ -void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) { - int j, k, l, m, n, offset1, offset2, touch; - srfGridMesh_t *grid2; - - for ( j = start; j < s_worldData.numsurfaces; j++ ) { - // - grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; - // if this surface is not a grid - if ( grid2->surfaceType != SF_GRID ) continue; - // if the LOD errors are already fixed for this patch - if ( grid2->lodFixed == 2 ) continue; - // grids in the same LOD group should have the exact same lod radius - if ( grid1->lodRadius != grid2->lodRadius ) continue; - // grids in the same LOD group should have the exact same lod origin - if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue; - if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue; - if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue; - // - touch = qfalse; - for (n = 0; n < 2; n++) { - // - if (n) offset1 = (grid1->height-1) * grid1->width; - else offset1 = 0; - if (R_MergedWidthPoints(grid1, offset1)) continue; - for (k = 1; k < grid1->width-1; k++) { - for (m = 0; m < 2; m++) { - - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - if (R_MergedWidthPoints(grid2, offset2)) continue; - for ( l = 1; l < grid2->width-1; l++) { - // - if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue; - if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue; - if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue; - // ok the points are equal and should have the same lod error - grid2->widthLodError[l] = grid1->widthLodError[k]; - touch = qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (m) offset2 = grid2->width-1; - else offset2 = 0; - if (R_MergedHeightPoints(grid2, offset2)) continue; - for ( l = 1; l < grid2->height-1; l++) { - // - if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue; - if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue; - if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue; - // ok the points are equal and should have the same lod error - grid2->heightLodError[l] = grid1->widthLodError[k]; - touch = qtrue; - } - } - } - } - for (n = 0; n < 2; n++) { - // - if (n) offset1 = grid1->width-1; - else offset1 = 0; - if (R_MergedHeightPoints(grid1, offset1)) continue; - for (k = 1; k < grid1->height-1; k++) { - for (m = 0; m < 2; m++) { - - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - if (R_MergedWidthPoints(grid2, offset2)) continue; - for ( l = 1; l < grid2->width-1; l++) { - // - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue; - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue; - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue; - // ok the points are equal and should have the same lod error - grid2->widthLodError[l] = grid1->heightLodError[k]; - touch = qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (m) offset2 = grid2->width-1; - else offset2 = 0; - if (R_MergedHeightPoints(grid2, offset2)) continue; - for ( l = 1; l < grid2->height-1; l++) { - // - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue; - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue; - if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue; - // ok the points are equal and should have the same lod error - grid2->heightLodError[l] = grid1->heightLodError[k]; - touch = qtrue; - } - } - } - } - if (touch) { - grid2->lodFixed = 2; - R_FixSharedVertexLodError_r ( start, grid2 ); - //NOTE: this would be correct but makes things really slow - //grid2->lodFixed = 1; - } - } -} - -/* -================= -R_FixSharedVertexLodError - -This function assumes that all patches in one group are nicely stitched together for the highest LoD. -If this is not the case this function will still do its job but won't fix the highest LoD cracks. -================= -*/ -void R_FixSharedVertexLodError( void ) { - int i; - srfGridMesh_t *grid1; - - for ( i = 0; i < s_worldData.numsurfaces; i++ ) { - // - grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; - // if this surface is not a grid - if ( grid1->surfaceType != SF_GRID ) - continue; - // - if ( grid1->lodFixed ) - continue; - // - grid1->lodFixed = 2; - // recursively fix other patches in the same LOD group - R_FixSharedVertexLodError_r( i + 1, grid1); - } -} - - -/* -=============== -R_StitchPatches -=============== -*/ -int R_StitchPatches( int grid1num, int grid2num ) { - float *v1, *v2; - srfGridMesh_t *grid1, *grid2; - int k, l, m, n, offset1, offset2, row, column; - - grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; - grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data; - for (n = 0; n < 2; n++) { - // - if (n) offset1 = (grid1->height-1) * grid1->width; - else offset1 = 0; - if (R_MergedWidthPoints(grid1, offset1)) - continue; - for (k = 0; k < grid1->width-2; k += 2) { - - for (m = 0; m < 2; m++) { - - if ( grid2->width >= MAX_GRID_SIZE ) - break; - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - for ( l = 0; l < grid2->width-1; l++) { - // - v1 = grid1->verts[k + offset1].xyz; - v2 = grid2->verts[l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[k + 2 + offset1].xyz; - v2 = grid2->verts[l + 1 + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[l + offset2].xyz; - v2 = grid2->verts[l + 1 + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert column into grid2 right after after column l - if (m) row = grid2->height-1; - else row = 0; - grid2 = R_GridInsertColumn( grid2, l+1, row, - grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (grid2->height >= MAX_GRID_SIZE) - break; - if (m) offset2 = grid2->width-1; - else offset2 = 0; - for ( l = 0; l < grid2->height-1; l++) { - // - v1 = grid1->verts[k + offset1].xyz; - v2 = grid2->verts[grid2->width * l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[k + 2 + offset1].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[grid2->width * l + offset2].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert row into grid2 right after after row l - if (m) column = grid2->width-1; - else column = 0; - grid2 = R_GridInsertRow( grid2, l+1, column, - grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - } - } - for (n = 0; n < 2; n++) { - // - if (n) offset1 = grid1->width-1; - else offset1 = 0; - if (R_MergedHeightPoints(grid1, offset1)) - continue; - for (k = 0; k < grid1->height-2; k += 2) { - for (m = 0; m < 2; m++) { - - if ( grid2->width >= MAX_GRID_SIZE ) - break; - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - for ( l = 0; l < grid2->width-1; l++) { - // - v1 = grid1->verts[grid1->width * k + offset1].xyz; - v2 = grid2->verts[l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz; - v2 = grid2->verts[l + 1 + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[l + offset2].xyz; - v2 = grid2->verts[(l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert column into grid2 right after after column l - if (m) row = grid2->height-1; - else row = 0; - grid2 = R_GridInsertColumn( grid2, l+1, row, - grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (grid2->height >= MAX_GRID_SIZE) - break; - if (m) offset2 = grid2->width-1; - else offset2 = 0; - for ( l = 0; l < grid2->height-1; l++) { - // - v1 = grid1->verts[grid1->width * k + offset1].xyz; - v2 = grid2->verts[grid2->width * l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[grid2->width * l + offset2].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert row into grid2 right after after row l - if (m) column = grid2->width-1; - else column = 0; - grid2 = R_GridInsertRow( grid2, l+1, column, - grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - } - } - for (n = 0; n < 2; n++) { - // - if (n) offset1 = (grid1->height-1) * grid1->width; - else offset1 = 0; - if (R_MergedWidthPoints(grid1, offset1)) - continue; - for (k = grid1->width-1; k > 1; k -= 2) { - - for (m = 0; m < 2; m++) { - - if ( grid2->width >= MAX_GRID_SIZE ) - break; - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - for ( l = 0; l < grid2->width-1; l++) { - // - v1 = grid1->verts[k + offset1].xyz; - v2 = grid2->verts[l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[k - 2 + offset1].xyz; - v2 = grid2->verts[l + 1 + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[l + offset2].xyz; - v2 = grid2->verts[(l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert column into grid2 right after after column l - if (m) row = grid2->height-1; - else row = 0; - grid2 = R_GridInsertColumn( grid2, l+1, row, - grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (grid2->height >= MAX_GRID_SIZE) - break; - if (m) offset2 = grid2->width-1; - else offset2 = 0; - for ( l = 0; l < grid2->height-1; l++) { - // - v1 = grid1->verts[k + offset1].xyz; - v2 = grid2->verts[grid2->width * l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[k - 2 + offset1].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[grid2->width * l + offset2].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert row into grid2 right after after row l - if (m) column = grid2->width-1; - else column = 0; - grid2 = R_GridInsertRow( grid2, l+1, column, - grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]); - if (!grid2) - break; - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - } - } - for (n = 0; n < 2; n++) { - // - if (n) offset1 = grid1->width-1; - else offset1 = 0; - if (R_MergedHeightPoints(grid1, offset1)) - continue; - for (k = grid1->height-1; k > 1; k -= 2) { - for (m = 0; m < 2; m++) { - - if ( grid2->width >= MAX_GRID_SIZE ) - break; - if (m) offset2 = (grid2->height-1) * grid2->width; - else offset2 = 0; - for ( l = 0; l < grid2->width-1; l++) { - // - v1 = grid1->verts[grid1->width * k + offset1].xyz; - v2 = grid2->verts[l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz; - v2 = grid2->verts[l + 1 + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[l + offset2].xyz; - v2 = grid2->verts[(l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert column into grid2 right after after column l - if (m) row = grid2->height-1; - else row = 0; - grid2 = R_GridInsertColumn( grid2, l+1, row, - grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - for (m = 0; m < 2; m++) { - - if (grid2->height >= MAX_GRID_SIZE) - break; - if (m) offset2 = grid2->width-1; - else offset2 = 0; - for ( l = 0; l < grid2->height-1; l++) { - // - v1 = grid1->verts[grid1->width * k + offset1].xyz; - v2 = grid2->verts[grid2->width * l + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - - v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) > .1) - continue; - if ( fabs(v1[1] - v2[1]) > .1) - continue; - if ( fabs(v1[2] - v2[2]) > .1) - continue; - // - v1 = grid2->verts[grid2->width * l + offset2].xyz; - v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz; - if ( fabs(v1[0] - v2[0]) < .01 && - fabs(v1[1] - v2[1]) < .01 && - fabs(v1[2] - v2[2]) < .01) - continue; - // - //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" ); - // insert row into grid2 right after after row l - if (m) column = grid2->width-1; - else column = 0; - grid2 = R_GridInsertRow( grid2, l+1, column, - grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]); - grid2->lodStitched = qfalse; - s_worldData.surfaces[grid2num].data = (void *) grid2; - return qtrue; - } - } - } - } - return qfalse; -} - -/* -=============== -R_TryStitchPatch - -This function will try to stitch patches in the same LoD group together for the highest LoD. - -Only single missing vertice cracks will be fixed. - -Vertices will be joined at the patch side a crack is first found, at the other side -of the patch (on the same row or column) the vertices will not be joined and cracks -might still appear at that side. -=============== -*/ -int R_TryStitchingPatch( int grid1num ) { - int j, numstitches; - srfGridMesh_t *grid1, *grid2; - - numstitches = 0; - grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data; - for ( j = 0; j < s_worldData.numsurfaces; j++ ) { - // - grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data; - // if this surface is not a grid - if ( grid2->surfaceType != SF_GRID ) continue; - // grids in the same LOD group should have the exact same lod radius - if ( grid1->lodRadius != grid2->lodRadius ) continue; - // grids in the same LOD group should have the exact same lod origin - if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue; - if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue; - if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue; - // - while (R_StitchPatches(grid1num, j)) - { - numstitches++; - } - } - return numstitches; -} - -/* -=============== -R_StitchAllPatches -=============== -*/ -void R_StitchAllPatches( void ) { - int i, stitched, numstitches; - srfGridMesh_t *grid1; - - numstitches = 0; - do - { - stitched = qfalse; - for ( i = 0; i < s_worldData.numsurfaces; i++ ) { - // - grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data; - // if this surface is not a grid - if ( grid1->surfaceType != SF_GRID ) - continue; - // - if ( grid1->lodStitched ) - continue; - // - grid1->lodStitched = qtrue; - stitched = qtrue; - // - numstitches += R_TryStitchingPatch( i ); - } - } - while (stitched); - ri.Printf( PRINT_ALL, "stitched %d LoD cracks\n", numstitches ); -} - -/* -=============== -R_MovePatchSurfacesToHunk -=============== -*/ -void R_MovePatchSurfacesToHunk(void) { - int i, size; - srfGridMesh_t *grid, *hunkgrid; - - for ( i = 0; i < s_worldData.numsurfaces; i++ ) { - // - grid = (srfGridMesh_t *) s_worldData.surfaces[i].data; - // if this surface is not a grid - if ( grid->surfaceType != SF_GRID ) - continue; - // - size = sizeof(*grid); - hunkgrid = ri.Hunk_Alloc(size, h_low); - Com_Memcpy(hunkgrid, grid, size); - - hunkgrid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low ); - Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 ); - - hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low ); - Com_Memcpy( hunkgrid->heightLodError, grid->heightLodError, grid->height * 4 ); - - hunkgrid->numTriangles = grid->numTriangles; - hunkgrid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low); - Com_Memcpy(hunkgrid->triangles, grid->triangles, grid->numTriangles * sizeof(srfTriangle_t)); - - hunkgrid->numVerts = grid->numVerts; - hunkgrid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low); - Com_Memcpy(hunkgrid->verts, grid->verts, grid->numVerts * sizeof(srfVert_t)); - - R_FreeSurfaceGridMesh( grid ); - - s_worldData.surfaces[i].data = (void *) hunkgrid; - } -} - - -/* -================= -BSPSurfaceCompare -compare function for qsort() -================= -*/ -static int BSPSurfaceCompare(const void *a, const void *b) -{ - msurface_t *aa, *bb; - - aa = *(msurface_t **) a; - bb = *(msurface_t **) b; - - // shader first - if(aa->shader->sortedIndex < bb->shader->sortedIndex) - return -1; - - else if(aa->shader->sortedIndex > bb->shader->sortedIndex) - return 1; - - // by fogIndex - if(aa->fogIndex < bb->fogIndex) - return -1; - - else if(aa->fogIndex > bb->fogIndex) - return 1; - - return 0; -} - - -static void CopyVert(const srfVert_t * in, srfVert_t * out) -{ - int j; - - for(j = 0; j < 3; j++) - { - out->xyz[j] = in->xyz[j]; -#ifdef USE_VERT_TANGENT_SPACE - out->tangent[j] = in->tangent[j]; - out->bitangent[j] = in->bitangent[j]; -#endif - out->normal[j] = in->normal[j]; - out->lightdir[j] = in->lightdir[j]; - } - - for(j = 0; j < 2; j++) - { - out->st[j] = in->st[j]; - out->lightmap[j] = in->lightmap[j]; - } - - for(j = 0; j < 4; j++) - { - out->vertexColors[j] = in->vertexColors[j]; - } -} - - -/* -=============== -R_CreateWorldVBO -=============== -*/ -static void R_CreateWorldVBO(void) -{ - int i, j, k; - - int numVerts; - srfVert_t *verts; - - int numTriangles; - srfTriangle_t *triangles; - - int numSurfaces; - msurface_t *surface; - msurface_t **surfacesSorted; - - int startTime, endTime; - - startTime = ri.Milliseconds(); - - numVerts = 0; - numTriangles = 0; - numSurfaces = 0; - for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++) - { - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data; - - if(face->numVerts) - numVerts += face->numVerts; - - if(face->numTriangles) - numTriangles += face->numTriangles; - - numSurfaces++; - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *grid = (srfGridMesh_t *) surface->data; - - if(grid->numVerts) - numVerts += grid->numVerts; - - if(grid->numTriangles) - numTriangles += grid->numTriangles; - - numSurfaces++; - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *tri = (srfTriangles_t *) surface->data; - - if(tri->numVerts) - numVerts += tri->numVerts; - - if(tri->numTriangles) - numTriangles += tri->numTriangles; - - numSurfaces++; - } - } - - if(!numVerts || !numTriangles) - return; - - ri.Printf(PRINT_ALL, "...calculating world VBO ( %i verts %i tris )\n", numVerts, numTriangles); - - // create arrays - - verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t)); - - triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t)); - - // presort surfaces - surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted)); - - j = 0; - for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces; k++, surface++) - { - if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES) - { - surfacesSorted[j++] = surface; - } - } - - qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare); - - // set up triangle indices - numVerts = 0; - numTriangles = 0; - for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) - { - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) - { - srfTriangle_t *tri; - - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - } - } - - numTriangles += srf->numTriangles; - } - - if(srf->numVerts) - numVerts += srf->numVerts; - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; - - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) - { - srfTriangle_t *tri; - - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - } - } - - numTriangles += srf->numTriangles; - } - - if(srf->numVerts) - numVerts += srf->numVerts; - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *srf = (srfTriangles_t *) surface->data; - - srf->firstIndex = numTriangles * 3; - - if(srf->numTriangles) - { - srfTriangle_t *tri; - - for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j]; - } - } - - numTriangles += srf->numTriangles; - } - - if(srf->numVerts) - numVerts += srf->numVerts; - } - } - - // build vertices - numVerts = 0; - for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) - { - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - srf->firstVert = numVerts; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - CopyVert(&srf->verts[i], &verts[numVerts + i]); - } - - numVerts += srf->numVerts; - } - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; - - srf->firstVert = numVerts; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - CopyVert(&srf->verts[i], &verts[numVerts + i]); - } - - numVerts += srf->numVerts; - } - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *srf = (srfTriangles_t *) surface->data; - - srf->firstVert = numVerts; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - CopyVert(&srf->verts[i], &verts[numVerts + i]); - } - - numVerts += srf->numVerts; - } - } - } - -#ifdef USE_VERT_TANGENT_SPACE - s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts, - ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT | - ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); -#else - s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts, - ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | - ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); -#endif - - s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC); - - endTime = ri.Milliseconds(); - ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); - - // point triangle surfaces to world VBO - for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k]) - { - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = s_worldData.vbo; - srf->ibo = s_worldData.ibo; - } - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; - - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = s_worldData.vbo; - srf->ibo = s_worldData.ibo; - } - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *srf = (srfTriangles_t *) surface->data; - - if( srf->numVerts && srf->numTriangles) - { - srf->vbo = s_worldData.vbo; - srf->ibo = s_worldData.ibo; - } - } - } - - - startTime = ri.Milliseconds(); - - ri.Free(surfacesSorted); - - ri.Hunk_FreeTempMemory(triangles); - ri.Hunk_FreeTempMemory(verts); -} - -/* -=============== -R_LoadSurfaces -=============== -*/ -static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) { - dsurface_t *in; - msurface_t *out; - drawVert_t *dv; - int *indexes; - int count; - int numFaces, numMeshes, numTriSurfs, numFlares; - int i; - float *hdrVertColors = NULL; - - numFaces = 0; - numMeshes = 0; - numTriSurfs = 0; - numFlares = 0; - - in = (void *)(fileBase + surfs->fileofs); - if (surfs->filelen % sizeof(*in)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - count = surfs->filelen / sizeof(*in); - - dv = (void *)(fileBase + verts->fileofs); - if (verts->filelen % sizeof(*dv)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - - indexes = (void *)(fileBase + indexLump->fileofs); - if ( indexLump->filelen % sizeof(*indexes)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - - out = ri.Hunk_Alloc ( count * sizeof(*out), h_low ); - - s_worldData.surfaces = out; - s_worldData.numsurfaces = count; - s_worldData.surfacesViewCount = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesViewCount), h_low ); - s_worldData.surfacesDlightBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesDlightBits), h_low ); - s_worldData.surfacesPshadowBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesPshadowBits), h_low ); - - // load hdr vertex colors - if (r_hdr->integer) - { - char filename[MAX_QPATH]; - int size; - - Com_sprintf( filename, sizeof( filename ), "maps/%s/vertlight.raw", s_worldData.baseName); - //ri.Printf(PRINT_ALL, "looking for %s\n", filename); - - size = ri.FS_ReadFile(filename, (void **)&hdrVertColors); - - if (hdrVertColors) - { - //ri.Printf(PRINT_ALL, "Found!\n"); - if (size != sizeof(float) * 3 * (verts->filelen / sizeof(*dv))) - ri.Error(ERR_DROP, "Bad size for %s (%i, expected %lu)!\n", filename, size, sizeof(float) * 3 * (verts->filelen / sizeof(*dv))); - } - } - - - // Two passes, allocate surfaces first, then load them full of data - // This ensures surfaces are close together to reduce L2 cache misses when using VBOs, - // which don't actually use the verts and tris - in = (void *)(fileBase + surfs->fileofs); - out = s_worldData.surfaces; - for ( i = 0 ; i < count ; i++, in++, out++ ) { - switch ( LittleLong( in->surfaceType ) ) { - case MST_PATCH: - // FIXME: do this - break; - case MST_TRIANGLE_SOUP: - out->data = ri.Hunk_Alloc( sizeof(srfTriangles_t), h_low); - break; - case MST_PLANAR: - out->data = ri.Hunk_Alloc( sizeof(srfSurfaceFace_t), h_low); - break; - case MST_FLARE: - out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low); - break; - default: - break; - } - } - - in = (void *)(fileBase + surfs->fileofs); - out = s_worldData.surfaces; - for ( i = 0 ; i < count ; i++, in++, out++ ) { - switch ( LittleLong( in->surfaceType ) ) { - case MST_PATCH: - ParseMesh ( in, dv, hdrVertColors, out ); - { - srfGridMesh_t *surface = (srfGridMesh_t *)out->data; - - out->cullinfo.type = CULLINFO_BOX | CULLINFO_SPHERE; - VectorCopy(surface->meshBounds[0], out->cullinfo.bounds[0]); - VectorCopy(surface->meshBounds[1], out->cullinfo.bounds[1]); - VectorCopy(surface->localOrigin, out->cullinfo.localOrigin); - out->cullinfo.radius = surface->meshRadius; - } - numMeshes++; - break; - case MST_TRIANGLE_SOUP: - ParseTriSurf( in, dv, hdrVertColors, out, indexes ); - numTriSurfs++; - break; - case MST_PLANAR: - ParseFace( in, dv, hdrVertColors, out, indexes ); - numFaces++; - break; - case MST_FLARE: - ParseFlare( in, dv, out, indexes ); - { - out->cullinfo.type = CULLINFO_NONE; - } - numFlares++; - break; - default: - ri.Error( ERR_DROP, "Bad surfaceType" ); - } - } - - if (hdrVertColors) - { - ri.FS_FreeFile(hdrVertColors); - } - -#ifdef PATCH_STITCHING - R_StitchAllPatches(); -#endif - - R_FixSharedVertexLodError(); - -#ifdef PATCH_STITCHING - R_MovePatchSurfacesToHunk(); -#endif - - ri.Printf( PRINT_ALL, "...loaded %d faces, %i meshes, %i trisurfs, %i flares\n", - numFaces, numMeshes, numTriSurfs, numFlares ); -} - - - -/* -================= -R_LoadSubmodels -================= -*/ -static void R_LoadSubmodels( lump_t *l ) { - dmodel_t *in; - bmodel_t *out; - int i, j, count; - - in = (void *)(fileBase + l->fileofs); - if (l->filelen % sizeof(*in)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - count = l->filelen / sizeof(*in); - - s_worldData.numBModels = count; - s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low ); - - for ( i=0 ; itype = MOD_BRUSH; - model->bmodel = out; - Com_sprintf( model->name, sizeof( model->name ), "*%d", i ); - - for (j=0 ; j<3 ; j++) { - out->bounds[0][j] = LittleFloat (in->mins[j]); - out->bounds[1][j] = LittleFloat (in->maxs[j]); - } - - out->firstSurface = LittleLong( in->firstSurface ); - out->numSurfaces = LittleLong( in->numSurfaces ); - - if(i == 0) - { - // Tr3B: add this for limiting VBO surface creation - s_worldData.numWorldSurfaces = out->numSurfaces; - } - } -} - - - -//================================================================== - -/* -================= -R_SetParent -================= -*/ -static void R_SetParent (mnode_t *node, mnode_t *parent) -{ - node->parent = parent; - if (node->contents != -1) - return; - R_SetParent (node->children[0], node); - R_SetParent (node->children[1], node); -} - -/* -================= -R_LoadNodesAndLeafs -================= -*/ -static void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) { - int i, j, p; - dnode_t *in; - dleaf_t *inLeaf; - mnode_t *out; - int numNodes, numLeafs; - - in = (void *)(fileBase + nodeLump->fileofs); - if (nodeLump->filelen % sizeof(dnode_t) || - leafLump->filelen % sizeof(dleaf_t) ) { - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - } - numNodes = nodeLump->filelen / sizeof(dnode_t); - numLeafs = leafLump->filelen / sizeof(dleaf_t); - - out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low); - - s_worldData.nodes = out; - s_worldData.numnodes = numNodes + numLeafs; - s_worldData.numDecisionNodes = numNodes; - - // load nodes - for ( i=0 ; imins[j] = LittleLong (in->mins[j]); - out->maxs[j] = LittleLong (in->maxs[j]); - } - - p = LittleLong(in->planeNum); - out->plane = s_worldData.planes + p; - - out->contents = CONTENTS_NODE; // differentiate from leafs - - for (j=0 ; j<2 ; j++) - { - p = LittleLong (in->children[j]); - if (p >= 0) - out->children[j] = s_worldData.nodes + p; - else - out->children[j] = s_worldData.nodes + numNodes + (-1 - p); - } - } - - // load leafs - inLeaf = (void *)(fileBase + leafLump->fileofs); - for ( i=0 ; imins[j] = LittleLong (inLeaf->mins[j]); - out->maxs[j] = LittleLong (inLeaf->maxs[j]); - } - - out->cluster = LittleLong(inLeaf->cluster); - out->area = LittleLong(inLeaf->area); - - if ( out->cluster >= s_worldData.numClusters ) { - s_worldData.numClusters = out->cluster + 1; - } - - out->firstmarksurface = LittleLong(inLeaf->firstLeafSurface); - out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces); - } - - // chain decendants - R_SetParent (s_worldData.nodes, NULL); -} - -//============================================================================= - -/* -================= -R_LoadShaders -================= -*/ -static void R_LoadShaders( lump_t *l ) { - int i, count; - dshader_t *in, *out; - - in = (void *)(fileBase + l->fileofs); - if (l->filelen % sizeof(*in)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - count = l->filelen / sizeof(*in); - out = ri.Hunk_Alloc ( count*sizeof(*out), h_low ); - - s_worldData.shaders = out; - s_worldData.numShaders = count; - - Com_Memcpy( out, in, count*sizeof(*out) ); - - for ( i=0 ; ifileofs); - if (l->filelen % sizeof(*in)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - count = l->filelen / sizeof(*in); - out = ri.Hunk_Alloc ( count*sizeof(*out), h_low); - - s_worldData.marksurfaces = out; - s_worldData.nummarksurfaces = count; - - for ( i=0 ; ifileofs); - if (l->filelen % sizeof(*in)) - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - count = l->filelen / sizeof(*in); - out = ri.Hunk_Alloc ( count*2*sizeof(*out), h_low); - - s_worldData.planes = out; - s_worldData.numplanes = count; - - for ( i=0 ; inormal[j] = LittleFloat (in->normal[j]); - if (out->normal[j] < 0) { - bits |= 1<dist = LittleFloat (in->dist); - out->type = PlaneTypeForNormal( out->normal ); - out->signbits = bits; - } -} - -/* -================= -R_LoadFogs - -================= -*/ -static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) { - int i; - fog_t *out; - dfog_t *fogs; - dbrush_t *brushes, *brush; - dbrushside_t *sides; - int count, brushesCount, sidesCount; - int sideNum; - int planeNum; - shader_t *shader; - float d; - int firstSide; - - fogs = (void *)(fileBase + l->fileofs); - if (l->filelen % sizeof(*fogs)) { - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - } - count = l->filelen / sizeof(*fogs); - - // create fog strucutres for them - s_worldData.numfogs = count + 1; - s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out), h_low); - out = s_worldData.fogs + 1; - - if ( !count ) { - return; - } - - brushes = (void *)(fileBase + brushesLump->fileofs); - if (brushesLump->filelen % sizeof(*brushes)) { - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - } - brushesCount = brushesLump->filelen / sizeof(*brushes); - - sides = (void *)(fileBase + sidesLump->fileofs); - if (sidesLump->filelen % sizeof(*sides)) { - ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); - } - sidesCount = sidesLump->filelen / sizeof(*sides); - - for ( i=0 ; ioriginalBrushNumber = LittleLong( fogs->brushNum ); - - if ( (unsigned)out->originalBrushNumber >= brushesCount ) { - ri.Error( ERR_DROP, "fog brushNumber out of range" ); - } - brush = brushes + out->originalBrushNumber; - - firstSide = LittleLong( brush->firstSide ); - - if ( (unsigned)firstSide > sidesCount - 6 ) { - ri.Error( ERR_DROP, "fog brush sideNumber out of range" ); - } - - // brushes are always sorted with the axial sides first - sideNum = firstSide + 0; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[0][0] = -s_worldData.planes[ planeNum ].dist; - - sideNum = firstSide + 1; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[1][0] = s_worldData.planes[ planeNum ].dist; - - sideNum = firstSide + 2; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[0][1] = -s_worldData.planes[ planeNum ].dist; - - sideNum = firstSide + 3; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[1][1] = s_worldData.planes[ planeNum ].dist; - - sideNum = firstSide + 4; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[0][2] = -s_worldData.planes[ planeNum ].dist; - - sideNum = firstSide + 5; - planeNum = LittleLong( sides[ sideNum ].planeNum ); - out->bounds[1][2] = s_worldData.planes[ planeNum ].dist; - - // get information from the shader for fog parameters - shader = R_FindShader( fogs->shader, LIGHTMAP_NONE, qtrue ); - - out->parms = shader->fogParms; - - out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight, - shader->fogParms.color[1] * tr.identityLight, - shader->fogParms.color[2] * tr.identityLight, 1.0 ); - - d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque; - out->tcScale = 1.0f / ( d * 8 ); - - // set the gradient vector - sideNum = LittleLong( fogs->visibleSide ); - - if ( sideNum == -1 ) { - out->hasSurface = qfalse; - } else { - out->hasSurface = qtrue; - planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum ); - VectorSubtract( vec3_origin, s_worldData.planes[ planeNum ].normal, out->surface ); - out->surface[3] = -s_worldData.planes[ planeNum ].dist; - } - - out++; - } - -} - - -/* -================ -R_LoadLightGrid - -================ -*/ -void R_LoadLightGrid( lump_t *l ) { - int i; - vec3_t maxs; - int numGridPoints; - world_t *w; - float *wMins, *wMaxs; - - w = &s_worldData; - - w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0]; - w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1]; - w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2]; - - wMins = w->bmodels[0].bounds[0]; - wMaxs = w->bmodels[0].bounds[1]; - - for ( i = 0 ; i < 3 ; i++ ) { - w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] ); - maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] ); - w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1; - } - - numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2]; - - if ( l->filelen != numGridPoints * 8 ) { - ri.Printf( PRINT_WARNING, "WARNING: light grid mismatch\n" ); - w->lightGridData = NULL; - return; - } - - w->lightGridData = ri.Hunk_Alloc( l->filelen, h_low ); - Com_Memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen ); - - // deal with overbright bits - for ( i = 0 ; i < numGridPoints ; i++ ) { - R_ColorShiftLightingBytes( &w->lightGridData[i*8], &w->lightGridData[i*8] ); - R_ColorShiftLightingBytes( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] ); - } - - // load hdr lightgrid - if (r_hdr->integer) - { - char filename[MAX_QPATH]; - float *hdrLightGrid; - int size; - - Com_sprintf( filename, sizeof( filename ), "maps/%s/lightgrid.raw", s_worldData.baseName); - //ri.Printf(PRINT_ALL, "looking for %s\n", filename); - - size = ri.FS_ReadFile(filename, (void **)&hdrLightGrid); - - if (hdrLightGrid) - { - float lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits); - - //ri.Printf(PRINT_ALL, "found!\n"); - - if (size != sizeof(float) * 6 * numGridPoints) - { - ri.Error(ERR_DROP, "Bad size for %s (%i, expected %lu)!\n", filename, size, sizeof(float) * 6 * numGridPoints); - } - - w->hdrLightGrid = ri.Hunk_Alloc(size, h_low); - - for (i = 0; i < numGridPoints ; i++) - { - w->hdrLightGrid[i * 6 ] = hdrLightGrid[i * 6 ] * lightScale; - w->hdrLightGrid[i * 6 + 1] = hdrLightGrid[i * 6 + 1] * lightScale; - w->hdrLightGrid[i * 6 + 2] = hdrLightGrid[i * 6 + 2] * lightScale; - w->hdrLightGrid[i * 6 + 3] = hdrLightGrid[i * 6 + 3] * lightScale; - w->hdrLightGrid[i * 6 + 4] = hdrLightGrid[i * 6 + 4] * lightScale; - w->hdrLightGrid[i * 6 + 5] = hdrLightGrid[i * 6 + 5] * lightScale; - } - } - - if (hdrLightGrid) - ri.FS_FreeFile(hdrLightGrid); - } -} - -/* -================ -R_LoadEntities -================ -*/ -void R_LoadEntities( lump_t *l ) { - char *p, *token, *s; - char keyname[MAX_TOKEN_CHARS]; - char value[MAX_TOKEN_CHARS]; - world_t *w; - - w = &s_worldData; - w->lightGridSize[0] = 64; - w->lightGridSize[1] = 64; - w->lightGridSize[2] = 128; - - p = (char *)(fileBase + l->fileofs); - - // store for reference by the cgame - w->entityString = ri.Hunk_Alloc( l->filelen + 1, h_low ); - strcpy( w->entityString, p ); - w->entityParsePoint = w->entityString; - - token = COM_ParseExt( &p, qtrue ); - if (!*token || *token != '{') { - return; - } - - // only parse the world spawn - while ( 1 ) { - // parse key - token = COM_ParseExt( &p, qtrue ); - - if ( !*token || *token == '}' ) { - break; - } - Q_strncpyz(keyname, token, sizeof(keyname)); - - // parse value - token = COM_ParseExt( &p, qtrue ); - - if ( !*token || *token == '}' ) { - break; - } - Q_strncpyz(value, token, sizeof(value)); - - // check for remapping of shaders for vertex lighting - s = "vertexremapshader"; - if (!Q_strncmp(keyname, s, strlen(s)) ) { - s = strchr(value, ';'); - if (!s) { - ri.Printf( PRINT_WARNING, "WARNING: no semi colon in vertexshaderremap '%s'\n", value ); - break; - } - *s++ = 0; - if (r_vertexLight->integer) { - R_RemapShader(value, s, "0"); - } - continue; - } - // check for remapping of shaders - s = "remapshader"; - if (!Q_strncmp(keyname, s, strlen(s)) ) { - s = strchr(value, ';'); - if (!s) { - ri.Printf( PRINT_WARNING, "WARNING: no semi colon in shaderremap '%s'\n", value ); - break; - } - *s++ = 0; - R_RemapShader(value, s, "0"); - continue; - } - // check for a different grid size - if (!Q_stricmp(keyname, "gridsize")) { - sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2] ); - continue; - } - - // check for auto exposure - if (!Q_stricmp(keyname, "autoExposure")) { - int check; - sscanf(value, "%d", &check ); - - if (check) { - tr.autoExposure = qtrue; - } - continue; - } - - if (!Q_stricmp(keyname, "autoExposureMinMax")) { - sscanf(value, "%f %f", &tr.autoExposureMinMax[0], &tr.autoExposureMinMax[1]); - continue; - } - } -} - -/* -================= -R_GetEntityToken -================= -*/ -qboolean R_GetEntityToken( char *buffer, int size ) { - const char *s; - - s = COM_Parse( &s_worldData.entityParsePoint ); - Q_strncpyz( buffer, s, size ); - if ( !s_worldData.entityParsePoint || !s[0] ) { - s_worldData.entityParsePoint = s_worldData.entityString; - return qfalse; - } else { - return qtrue; - } -} - - -/* -================= -R_MergeLeafSurfaces - -Merges surfaces that share a common leaf -================= -*/ -void R_MergeLeafSurfaces(void) -{ - int i, j, k; - int numWorldSurfaces; - int mergedSurfIndex; - int numMergedSurfaces; - int numUnmergedSurfaces; - IBO_t *ibo; - - msurface_t *mergedSurf; - - glIndex_t *iboIndexes, *outIboIndexes; - int numIboIndexes; - - int startTime, endTime; - - startTime = ri.Milliseconds(); - - numWorldSurfaces = s_worldData.numWorldSurfaces; - - // use viewcount to keep track of mergers - for (i = 0; i < numWorldSurfaces; i++) - { - s_worldData.surfacesViewCount[i] = -1; - } - - // create ibo - ibo = tr.ibos[tr.numIBOs++] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - memset(ibo, 0, sizeof(*ibo)); - Q_strncpyz(ibo->name, "staticWorldMesh_IBO_mergedSurfs", sizeof(ibo->name)); - - // allocate more than we need - iboIndexes = outIboIndexes = ri.Malloc(s_worldData.ibo->indexesSize); - - // mark matching surfaces - for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++) - { - mnode_t *leaf = s_worldData.nodes + s_worldData.numDecisionNodes + i; - - for (j = 0; j < leaf->nummarksurfaces; j++) - { - msurface_t *surf1; - shader_t *shader1; - int fogIndex1; - int surfNum1; - - surfNum1 = *(s_worldData.marksurfaces + leaf->firstmarksurface + j); - - if (s_worldData.surfacesViewCount[surfNum1] != -1) - continue; - - surf1 = s_worldData.surfaces + surfNum1; - - if ((*surf1->data != SF_GRID) && (*surf1->data != SF_TRIANGLES) && (*surf1->data != SF_FACE)) - continue; - - shader1 = surf1->shader; - - if(shader1->isSky) - continue; - - if(shader1->isPortal) - continue; - - if(ShaderRequiresCPUDeforms(shader1)) - continue; - - fogIndex1 = surf1->fogIndex; - - s_worldData.surfacesViewCount[surfNum1] = surfNum1; - - for (k = j + 1; k < leaf->nummarksurfaces; k++) - { - msurface_t *surf2; - shader_t *shader2; - int fogIndex2; - int surfNum2; - - surfNum2 = *(s_worldData.marksurfaces + leaf->firstmarksurface + k); - - if (s_worldData.surfacesViewCount[surfNum2] != -1) - continue; - - surf2 = s_worldData.surfaces + surfNum2; - - if ((*surf2->data != SF_GRID) && (*surf2->data != SF_TRIANGLES) && (*surf2->data != SF_FACE)) - continue; - - shader2 = surf2->shader; - - if (shader1 != shader2) - continue; - - fogIndex2 = surf2->fogIndex; - - if (fogIndex1 != fogIndex2) - continue; - - s_worldData.surfacesViewCount[surfNum2] = surfNum1; - } - } - } - - // count merged/unmerged surfaces - numMergedSurfaces = 0; - numUnmergedSurfaces = 0; - for (i = 0; i < numWorldSurfaces; i++) - { - if (s_worldData.surfacesViewCount[i] == i) - { - numMergedSurfaces++; - } - else if (s_worldData.surfacesViewCount[i] == -1) - { - numUnmergedSurfaces++; - } - } - - // Allocate merged surfaces - s_worldData.mergedSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low); - s_worldData.mergedSurfacesViewCount = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, h_low); - s_worldData.mergedSurfacesDlightBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * numMergedSurfaces, h_low); - s_worldData.numMergedSurfaces = numMergedSurfaces; - - // view surfaces are like mark surfaces, except negative ones represent merged surfaces - // -1 represents 0, -2 represents 1, and so on - s_worldData.viewSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, h_low); - - // copy view surfaces into mark surfaces - for (i = 0; i < s_worldData.nummarksurfaces; i++) - { - s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i]; - } - - // actually merge surfaces - numIboIndexes = 0; - mergedSurfIndex = 0; - mergedSurf = s_worldData.mergedSurfaces; - for (i = 0; i < numWorldSurfaces; i++) - { - msurface_t *surf1; - - vec3_t bounds[2]; - - int numSurfsToMerge; - int numTriangles; - int numVerts; - int firstIndex; - - srfVBOMesh_t *vboSurf; - - if (s_worldData.surfacesViewCount[i] != i) - continue; - - surf1 = s_worldData.surfaces + i; - - // count verts, indexes, and surfaces - numSurfsToMerge = 0; - numTriangles = 0; - numVerts = 0; - for (j = i; j < numWorldSurfaces; j++) - { - msurface_t *surf2; - - if (s_worldData.surfacesViewCount[j] != i) - continue; - - surf2 = s_worldData.surfaces + j; - - switch(*surf2->data) - { - case SF_FACE: - { - srfSurfaceFace_t *face; - - face = (srfSurfaceFace_t *) surf2->data; - numTriangles += face->numTriangles; - numVerts += face->numVerts; - } - break; - - case SF_GRID: - { - srfGridMesh_t *grid; - - grid = (srfGridMesh_t *) surf2->data; - numTriangles += grid->numTriangles; - numVerts += grid->numVerts; - } - break; - - case SF_TRIANGLES: - { - srfTriangles_t *tris; - - tris = (srfTriangles_t *) surf2->data; - numTriangles += tris->numTriangles; - numVerts += tris->numVerts; - } - break; - - default: - break; - } - - numSurfsToMerge++; - } - - if (numVerts == 0 || numTriangles == 0 || numSurfsToMerge < 2) - { - continue; - } - - // Merge surfaces (indexes) and calculate bounds - ClearBounds(bounds[0], bounds[1]); - firstIndex = numIboIndexes; - for (j = i; j < numWorldSurfaces; j++) - { - msurface_t *surf2; - - if (s_worldData.surfacesViewCount[j] != i) - continue; - - surf2 = s_worldData.surfaces + j; - - AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]); - AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]); - - switch(*surf2->data) - { - case SF_FACE: - { - srfSurfaceFace_t *face; - - face = (srfSurfaceFace_t *) surf2->data; - - for (k = 0; k < face->numTriangles; k++) - { - *outIboIndexes++ = face->triangles[k].indexes[0] + face->firstVert; - *outIboIndexes++ = face->triangles[k].indexes[1] + face->firstVert; - *outIboIndexes++ = face->triangles[k].indexes[2] + face->firstVert; - numIboIndexes += 3; - } - } - break; - - case SF_GRID: - { - srfGridMesh_t *grid; - - grid = (srfGridMesh_t *) surf2->data; - - for (k = 0; k < grid->numTriangles; k++) - { - *outIboIndexes++ = grid->triangles[k].indexes[0] + grid->firstVert; - *outIboIndexes++ = grid->triangles[k].indexes[1] + grid->firstVert; - *outIboIndexes++ = grid->triangles[k].indexes[2] + grid->firstVert; - numIboIndexes += 3; - } - } - break; - - case SF_TRIANGLES: - { - srfTriangles_t *tris; - - tris = (srfTriangles_t *) surf2->data; - - for (k = 0; k < tris->numTriangles; k++) - { - *outIboIndexes++ = tris->triangles[k].indexes[0] + tris->firstVert; - *outIboIndexes++ = tris->triangles[k].indexes[1] + tris->firstVert; - *outIboIndexes++ = tris->triangles[k].indexes[2] + tris->firstVert; - numIboIndexes += 3; - } - } - break; - - // never happens, but silences a compile warning - default: - break; - } - } - - vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); - memset(vboSurf, 0, sizeof(*vboSurf)); - vboSurf->surfaceType = SF_VBO_MESH; - - vboSurf->vbo = s_worldData.vbo; - vboSurf->ibo = ibo; - - vboSurf->numIndexes = numTriangles * 3; - vboSurf->numVerts = numVerts; - vboSurf->firstIndex = firstIndex; - - vboSurf->shader = surf1->shader; - vboSurf->fogIndex = surf1->fogIndex; - - VectorCopy(bounds[0], vboSurf->bounds[0]); - VectorCopy(bounds[1], vboSurf->bounds[1]); - - VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]); - VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]); - - mergedSurf->cullinfo.type = CULLINFO_BOX; - mergedSurf->data = (surfaceType_t *)vboSurf; - mergedSurf->fogIndex = surf1->fogIndex; - mergedSurf->shader = surf1->shader; - - // redirect view surfaces to this surf - for (j = i; j < numWorldSurfaces; j++) - { - if (s_worldData.surfacesViewCount[j] != i) - continue; - - for (k = 0; k < s_worldData.nummarksurfaces; k++) - { - int *mark = s_worldData.marksurfaces + k; - int *view = s_worldData.viewSurfaces + k; - - if (*mark == j) - *view = -(mergedSurfIndex + 1); - } - } - - mergedSurfIndex++; - mergedSurf++; - } - - // finish up the ibo - R_SyncRenderThread(); - - qglGenBuffersARB(1, &ibo->indexesVBO); - - R_BindIBO(ibo); - - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB); - - R_BindNullIBO(); - - GL_CheckErrors(); - - ri.Free(iboIndexes); - - endTime = ri.Milliseconds(); - - ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n", - numWorldSurfaces, numMergedSurfaces, numUnmergedSurfaces, (endTime - startTime) / 1000.0f); - - // reset viewcounts - for (i = 0; i < numWorldSurfaces; i++) - { - s_worldData.surfacesViewCount[i] = -1; - } -} - - -void R_CalcVertexLightDirs( void ) -{ - int i, k; - msurface_t *surface; - - for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++) - { - if(*surface->data == SF_FACE) - { - srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData ); - } - } - } - else if(*surface->data == SF_GRID) - { - srfGridMesh_t *srf = (srfGridMesh_t *) surface->data; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData ); - } - } - } - else if(*surface->data == SF_TRIANGLES) - { - srfTriangles_t *srf = (srfTriangles_t *) surface->data; - - if(srf->numVerts) - { - for(i = 0; i < srf->numVerts; i++) - { - R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData ); - } - } - } - } -} - - -/* -================= -RE_LoadWorldMap - -Called directly from cgame -================= -*/ -void RE_LoadWorldMap( const char *name ) { - int i; - dheader_t *header; - union { - byte *b; - void *v; - } buffer; - byte *startMarker; - - if ( tr.worldMapLoaded ) { - ri.Error( ERR_DROP, "ERROR: attempted to redundantly load world map\n" ); - } - - // set default map light scale - tr.mapLightScale = 1.0; - - // set default sun direction to be used if it isn't - // overridden by a shader - tr.sunDirection[0] = 0.45f; - tr.sunDirection[1] = 0.3f; - tr.sunDirection[2] = 0.9f; - - VectorNormalize( tr.sunDirection ); - - // set default autoexposure settings - tr.autoExposureMinMax[0] = -3.0; - tr.autoExposureMinMax[1] = 3.0; - - tr.worldMapLoaded = qtrue; - - // load it - ri.FS_ReadFile( name, &buffer.v ); - if ( !buffer.b ) { - ri.Error (ERR_DROP, "RE_LoadWorldMap: %s not found", name); - } - - // clear tr.world so if the level fails to load, the next - // try will not look at the partially loaded version - tr.world = NULL; - - Com_Memset( &s_worldData, 0, sizeof( s_worldData ) ); - Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) ); - - Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) ); - COM_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName)); - - startMarker = ri.Hunk_Alloc(0, h_low); - c_gridVerts = 0; - - header = (dheader_t *)buffer.b; - fileBase = (byte *)header; - - i = LittleLong (header->version); - if ( i != BSP_VERSION ) { - ri.Error (ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be %i)", - name, i, BSP_VERSION); - } - - // swap all the lumps - for (i=0 ; ilumps[LUMP_ENTITIES] ); - R_LoadShaders( &header->lumps[LUMP_SHADERS] ); - R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS], &header->lumps[LUMP_SURFACES] ); - R_LoadPlanes (&header->lumps[LUMP_PLANES]); - R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] ); - R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES] ); - R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]); - R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]); - R_LoadSubmodels (&header->lumps[LUMP_MODELS]); - R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] ); - R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] ); - - // determine vertex light directions - R_CalcVertexLightDirs(); - - // create static VBOS from the world - R_CreateWorldVBO(); - if (r_mergeLeafSurfaces->integer) - { - R_MergeLeafSurfaces(); - } - - s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker; - - // only set tr.world now that we know the entire level has loaded properly - tr.world = &s_worldData; - - // make sure the VBO glState entries are safe - R_BindNullVBO(); - R_BindNullIBO(); - - ri.FS_FreeFile( buffer.v ); -} diff --git a/code/renderergl2/tr_cmds.c b/code/renderergl2/tr_cmds.c deleted file mode 100644 index 5d6f54f0..00000000 --- a/code/renderergl2/tr_cmds.c +++ /dev/null @@ -1,667 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "tr_local.h" - -volatile renderCommandList_t *renderCommandList; - -volatile qboolean renderThreadActive; - - -/* -===================== -R_PerformanceCounters -===================== -*/ -void R_PerformanceCounters( void ) { - if ( !r_speeds->integer ) { - // clear the counters even if we aren't printing - Com_Memset( &tr.pc, 0, sizeof( tr.pc ) ); - Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) ); - return; - } - - if (r_speeds->integer == 1) { - ri.Printf (PRINT_ALL, "%i/%i/%i shaders/batches/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n", - backEnd.pc.c_shaders, backEnd.pc.c_surfBatches, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes, - backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3, - R_SumOfUsedImages()/(1000000.0f), 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 ) - { - ri.Printf( PRINT_ALL, "VBO draws: static %i dynamic %i\nMultidraws: %i merged %i\n", - backEnd.pc.c_staticVboDraws, backEnd.pc.c_dynamicVboDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged ); - ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n", - backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws); - } - - Com_Memset( &tr.pc, 0, sizeof( tr.pc ) ); - Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) ); -} - - -/* -==================== -R_InitCommandBuffers -==================== -*/ -void R_InitCommandBuffers( void ) { - glConfig.smpActive = qfalse; - if ( r_smp->integer ) { - ri.Printf( PRINT_ALL, "Trying SMP acceleration...\n" ); - if ( GLimp_SpawnRenderThread( RB_RenderThread ) ) { - ri.Printf( PRINT_ALL, "...succeeded.\n" ); - glConfig.smpActive = qtrue; - } else { - ri.Printf( PRINT_ALL, "...failed.\n" ); - } - } -} - -/* -==================== -R_ShutdownCommandBuffers -==================== -*/ -void R_ShutdownCommandBuffers( void ) { - // kill the rendering thread - if ( glConfig.smpActive ) { - GLimp_WakeRenderer( NULL ); - glConfig.smpActive = qfalse; - } -} - -/* -==================== -R_IssueRenderCommands -==================== -*/ -int c_blockedOnRender; -int c_blockedOnMain; - -void R_IssueRenderCommands( qboolean runPerformanceCounters ) { - renderCommandList_t *cmdList; - - cmdList = &backEndData[tr.smpFrame]->commands; - assert(cmdList); - // add an end-of-list command - *(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST; - - // clear it out, in case this is a sync and not a buffer flip - cmdList->used = 0; - - if ( glConfig.smpActive ) { - // if the render thread is not idle, wait for it - if ( renderThreadActive ) { - c_blockedOnRender++; - if ( r_showSmp->integer ) { - ri.Printf( PRINT_ALL, "R" ); - } - } else { - c_blockedOnMain++; - if ( r_showSmp->integer ) { - ri.Printf( PRINT_ALL, "." ); - } - } - - // sleep until the renderer has completed - GLimp_FrontEndSleep(); - } - - // at this point, the back end thread is idle, so it is ok - // to look at its performance counters - if ( runPerformanceCounters ) { - R_PerformanceCounters(); - } - - // actually start the commands going - if ( !r_skipBackEnd->integer ) { - // let it start on the new batch - if ( !glConfig.smpActive ) { - RB_ExecuteRenderCommands( cmdList->cmds ); - } else { - GLimp_WakeRenderer( cmdList ); - } - } -} - - -/* -==================== -R_SyncRenderThread - -Issue any pending commands and wait for them to complete. -After exiting, the render thread will have completed its work -and will remain idle and the main thread is free to issue -OpenGL calls until R_IssueRenderCommands is called. -==================== -*/ -void R_SyncRenderThread( void ) { - if ( !tr.registered ) { - return; - } - R_IssueRenderCommands( qfalse ); - - if ( !glConfig.smpActive ) { - return; - } - GLimp_FrontEndSleep(); -} - -/* -============ -R_GetCommandBuffer - -make sure there is enough command space, waiting on the -render thread if needed. -============ -*/ -void *R_GetCommandBuffer( int bytes ) { - renderCommandList_t *cmdList; - - cmdList = &backEndData[tr.smpFrame]->commands; - bytes = PAD(bytes, sizeof(void *)); - - // always leave room for the end of list command - if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) { - if ( bytes > MAX_RENDER_COMMANDS - 4 ) { - 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_AddDrawSurfCmd - -============= -*/ -void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) { - drawSurfsCommand_t *cmd; - - cmd = 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; -} - - -/* -============= -R_AddCapShadowmapCmd - -============= -*/ -void R_AddCapShadowmapCmd( int map, int cubeSide ) { - capShadowmapCommand_t *cmd; - - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; - } - cmd->commandId = RC_CAPSHADOWMAP; - - cmd->map = map; - cmd->cubeSide = cubeSide; -} - - -/* -============= -R_PostProcessingCmd - -============= -*/ -void R_AddPostProcessCmd( ) { - postProcessCommand_t *cmd; - - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; - } - cmd->commandId = RC_POSTPROCESS; - - 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 = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; - } - cmd->commandId = RC_SET_COLOR; - if ( !rgba ) { - static float colorWhite[4] = { 1, 1, 1, 1 }; - - 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 = 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; -} - -#define MODE_RED_CYAN 1 -#define MODE_RED_BLUE 2 -#define MODE_RED_GREEN 3 -#define MODE_GREEN_MAGENTA 4 -#define MODE_MAX MODE_GREEN_MAGENTA - -void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode) -{ - rgba[0] = rgba[1] = rgba[2] = rgba[3] = GL_TRUE; - - if(colormode > MODE_MAX) - { - if(stereoFrame == STEREO_LEFT) - stereoFrame = STEREO_RIGHT; - else if(stereoFrame == STEREO_RIGHT) - stereoFrame = STEREO_LEFT; - - colormode -= MODE_MAX; - } - - if(colormode == MODE_GREEN_MAGENTA) - { - if(stereoFrame == STEREO_LEFT) - rgba[0] = rgba[2] = GL_FALSE; - else if(stereoFrame == STEREO_RIGHT) - rgba[1] = GL_FALSE; - } - else - { - if(stereoFrame == STEREO_LEFT) - rgba[1] = rgba[2] = GL_FALSE; - else if(stereoFrame == STEREO_RIGHT) - { - rgba[0] = GL_FALSE; - - if(colormode == MODE_RED_BLUE) - rgba[1] = GL_FALSE; - else if(colormode == MODE_RED_GREEN) - rgba[2] = GL_FALSE; - } - } -} - - -/* -==================== -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; - colorMaskCommand_t *colcmd = NULL; - - if ( !tr.registered ) { - return; - } - glState.finishCalled = qfalse; - - tr.frameCount++; - tr.frameSceneNum = 0; - - // - // do overdraw measurement - // - 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_SyncRenderThread(); - 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_SyncRenderThread(); - qglDisable( GL_STENCIL_TEST ); - } - r_measureOverdraw->modified = qfalse; - } - - // - // texturemode stuff - // - if ( r_textureMode->modified ) { - R_SyncRenderThread(); - GL_TextureMode( r_textureMode->string ); - r_textureMode->modified = qfalse; - } - - // - // gamma stuff - // - if ( r_gamma->modified ) { - r_gamma->modified = qfalse; - - R_SyncRenderThread(); - R_SetColorMappings(); - } - - // check for errors - if ( !r_ignoreGLErrors->integer ) - { - int err; - - R_SyncRenderThread(); - if ((err = qglGetError()) != GL_NO_ERROR) - ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err); - } - - if (glConfig.stereoEnabled) { - if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) - return; - - cmd->commandId = RC_DRAW_BUFFER; - - if ( stereoFrame == STEREO_LEFT ) { - cmd->buffer = (int)GL_BACK_LEFT; - } else if ( stereoFrame == STEREO_RIGHT ) { - cmd->buffer = (int)GL_BACK_RIGHT; - } else { - ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); - } - } - else - { - if(r_anaglyphMode->integer) - { - if(r_anaglyphMode->modified) - { - // clear both, front and backbuffer. - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - backEnd.colorMask[0] = GL_FALSE; - backEnd.colorMask[1] = GL_FALSE; - backEnd.colorMask[2] = GL_FALSE; - backEnd.colorMask[3] = GL_FALSE; - qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - qglDrawBuffer(GL_FRONT); - qglClear(GL_COLOR_BUFFER_BIT); - qglDrawBuffer(GL_BACK); - qglClear(GL_COLOR_BUFFER_BIT); - - if (glRefConfig.framebufferObject) - { - // clear all framebuffers - // FIXME: must be a better way to do this - int i; - - for (i = 0; i < 3; i++) - { - if (i == 1 && !tr.msaaResolveFbo) - continue; - - switch(i) - { - case 0: - FBO_Bind(tr.renderFbo); - break; - - case 1: - FBO_Bind(tr.msaaResolveFbo); - break; - - case 2: - FBO_Bind(tr.screenScratchFbo); - break; - } - - qglDrawBuffer(GL_FRONT); - qglClear(GL_COLOR_BUFFER_BIT); - qglDrawBuffer(GL_BACK); - qglClear(GL_COLOR_BUFFER_BIT); - - } - - FBO_Bind(NULL); - } - - r_anaglyphMode->modified = qfalse; - } - - if(stereoFrame == STEREO_LEFT) - { - if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) - return; - - if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) - return; - } - else if(stereoFrame == STEREO_RIGHT) - { - clearDepthCommand_t *cldcmd; - - if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) - return; - - cldcmd->commandId = RC_CLEARDEPTH; - - if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) - return; - } - else - ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); - - R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); - colcmd->commandId = RC_COLORMASK; - } - else - { - if(stereoFrame != STEREO_CENTER) - ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); - - if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) - return; - } - - if(cmd) - { - cmd->commandId = RC_DRAW_BUFFER; - - if(r_anaglyphMode->modified) - { - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - backEnd.colorMask[0] = 0; - backEnd.colorMask[1] = 0; - backEnd.colorMask[2] = 0; - backEnd.colorMask[3] = 0; - r_anaglyphMode->modified = qfalse; - } - - if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) - cmd->buffer = (int)GL_FRONT; - else - cmd->buffer = (int)GL_BACK; - } - } - - tr.refdef.stereoFrame = 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 = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; - } - cmd->commandId = RC_SWAP_BUFFERS; - - R_IssueRenderCommands( qtrue ); - - // use the other buffers next frame, because another CPU - // may still be rendering into the current ones - R_ToggleSmpFrame(); - - if ( frontEndMsec ) { - *frontEndMsec = tr.frontEndMsec; - } - tr.frontEndMsec = 0; - if ( backEndMsec ) { - *backEndMsec = backEnd.pc.msec; - } - backEnd.pc.msec = 0; -} - -/* -============= -RE_TakeVideoFrame -============= -*/ -void RE_TakeVideoFrame( int width, int height, - byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ) -{ - videoFrameCommand_t *cmd; - - if( !tr.registered ) { - return; - } - - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); - if( !cmd ) { - return; - } - - cmd->commandId = RC_VIDEOFRAME; - - cmd->width = width; - cmd->height = height; - cmd->captureBuffer = captureBuffer; - cmd->encodeBuffer = encodeBuffer; - cmd->motionJpeg = motionJpeg; -} diff --git a/code/renderergl2/tr_curve.c b/code/renderergl2/tr_curve.c deleted file mode 100644 index 3d439257..00000000 --- a/code/renderergl2/tr_curve.c +++ /dev/null @@ -1,806 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#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, - srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { - -*/ - - -/* -============ -LerpDrawVert -============ -*/ -static void LerpDrawVert( srfVert_t *a, srfVert_t *b, srfVert_t *out ) { - out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]); - out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]); - out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]); - - out->st[0] = 0.5f * (a->st[0] + b->st[0]); - out->st[1] = 0.5f * (a->st[1] + b->st[1]); - - out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]); - out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]); - - out->vertexColors[0] = 0.5f * (a->vertexColors[0] + b->vertexColors[0]); - out->vertexColors[1] = 0.5f * (a->vertexColors[1] + b->vertexColors[1]); - out->vertexColors[2] = 0.5f * (a->vertexColors[2] + b->vertexColors[2]); - out->vertexColors[3] = 0.5f * (a->vertexColors[3] + b->vertexColors[3]); -} - -/* -============ -Transpose -============ -*/ -static void Transpose( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { - int i, j; - srfVert_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, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { - int i, j, k, dist; - vec3_t normal; - vec3_t sum; - int count = 0; - vec3_t base; - vec3_t delta; - int x, y; - srfVert_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 = VectorLengthSquared( 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 = VectorLengthSquared( 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"); - //} - VectorNormalize2( sum, dv->normal ); - } - } -} - -#ifdef USE_VERT_TANGENT_SPACE -static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles, - srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) -{ - int i, j; - srfVert_t *dv[3]; - static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE]; - srfTriangle_t *tri; - - // FIXME: use more elegant way - for(i = 0; i < width; i++) - { - for(j = 0; j < height; j++) - { - dv[0] = &ctrl2[j * width + i]; - *dv[0] = ctrl[j][i]; - } - } - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - dv[0] = &ctrl2[tri->indexes[0]]; - dv[1] = &ctrl2[tri->indexes[1]]; - dv[2] = &ctrl2[tri->indexes[2]]; - - R_CalcTangentVectors(dv); - } - -#if 0 - for(i = 0; i < (width * height); i++) - { - dv0 = &ctrl2[i]; - - VectorNormalize(dv0->normal); -#if 0 - VectorNormalize(dv0->tangent); - VectorNormalize(dv0->bitangent); -#else - d = DotProduct(dv0->tangent, dv0->normal); - VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent); - VectorNormalize(dv0->tangent); - - d = DotProduct(dv0->bitangent, dv0->normal); - VectorMA(dv0->bitangent, -d, dv0->normal, dv0->bitangent); - VectorNormalize(dv0->bitangent); -#endif - } -#endif - - -#if 0 - // do another extra smoothing for normals to avoid flat shading - for(i = 0; i < (width * height); i++) - { - for(j = 0; j < (width * height); j++) - { - if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse)) - { - VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal); - } - } - - VectorNormalize(ctrl2[i].normal); - } -#endif - - for(i = 0; i < width; i++) - { - for(j = 0; j < height; j++) - { - dv[0] = &ctrl2[j * width + i]; - dv[1] = &ctrl[j][i]; - - VectorCopy(dv[0]->tangent, dv[1]->tangent); - VectorCopy(dv[0]->bitangent, dv[1]->bitangent); - } - } -} -#endif - - -static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], - srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) -{ - int i, j; - int numTriangles; - int w, h; - srfVert_t *dv; - static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE]; - - h = height - 1; - w = width - 1; - numTriangles = 0; - for(i = 0; i < h; i++) - { - for(j = 0; j < w; j++) - { - int v1, v2, v3, v4; - - // vertex order to be reckognized as tristrips - v1 = i * width + j + 1; - v2 = v1 - 1; - v3 = v2 + width; - v4 = v3 + 1; - - triangles[numTriangles].indexes[0] = v2; - triangles[numTriangles].indexes[1] = v3; - triangles[numTriangles].indexes[2] = v1; - numTriangles++; - - triangles[numTriangles].indexes[0] = v1; - triangles[numTriangles].indexes[1] = v3; - triangles[numTriangles].indexes[2] = v4; - numTriangles++; - } - } - - R_CalcSurfaceTriangleNeighbors(numTriangles, triangles); - - // FIXME: use more elegant way - for(i = 0; i < width; i++) - { - for(j = 0; j < height; j++) - { - dv = &ctrl2[j * width + i]; - *dv = ctrl[j][i]; - } - } - - R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2); - - return numTriangles; -} - - -/* -============ -InvertCtrl -============ -*/ -static void InvertCtrl( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) { - int i, j; - srfVert_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]; - - Com_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( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], - int width, int height ) { - int i, j; - srfVert_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_CreateSurfaceGridMesh -================= -*/ -srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height, - srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE], - int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) { - int i, j, size; - srfVert_t *vert; - vec3_t tmpVec; - srfGridMesh_t *grid; - - // copy the results out to a grid - size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid ); - -#ifdef PATCH_STITCHING - grid = /*ri.Hunk_Alloc*/ ri.Malloc( size ); - Com_Memset(grid, 0, size); - - grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 ); - Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 ); - - grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 ); - Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 ); - - grid->numTriangles = numTriangles; - grid->triangles = ri.Malloc(grid->numTriangles * sizeof(srfTriangle_t)); - Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t)); - - grid->numVerts = (width * height); - grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t)); -#else - grid = ri.Hunk_Alloc( size ); - Com_Memset(grid, 0, size); - - grid->widthLodError = ri.Hunk_Alloc( width * 4 ); - Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 ); - - grid->heightLodError = ri.Hunk_Alloc( height * 4 ); - Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 ); - - grid->numTriangles = numTriangles; - grid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low); - Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t)); - - grid->numVerts = (width * height); - grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low); -#endif - - 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; -} - -/* -================= -R_FreeSurfaceGridMesh -================= -*/ -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) { - ri.Free(grid->widthLodError); - ri.Free(grid->heightLodError); - ri.Free(grid->triangles); - ri.Free(grid->verts); - ri.Free(grid); -} - -/* -================= -R_SubdividePatchToGrid -================= -*/ -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, - srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { - int i, j, k, l; - srfVert_t_cleared( prev ); - srfVert_t_cleared( next ); - srfVert_t_cleared( mid ); - float len, maxLen; - int dir; - int t; - srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; - float errorTable[2][MAX_GRID_SIZE]; - int numTriangles; - static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]; - int consecutiveComplete; - - 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; - } - - consecutiveComplete = 0; - - // horizontal subdivisions - for ( j = 0 ; ; j = (j + 2) % (width - 1) ) { - // check subdivided midpoints against control points - - // FIXME: also check midpoints of adjacent patches against the control points - // this would basically stitch all patches in the same LOD group together. - - maxLen = 0; - for ( i = 0 ; i < height ; i++ ) { - vec3_t midxyz; - vec3_t midxyz2; - 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.25f; - } - - // 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, midxyz2); - len = VectorLengthSquared( midxyz2 ); // we will do the sqrt later - if ( len > maxLen ) { - maxLen = len; - } - } - - maxLen = sqrt(maxLen); - - // if all the points are on the lines, remove the entire columns - if ( maxLen < 0.1f ) { - errorTable[dir][j+1] = 999; - // if we go over the whole grid twice without adding any columns, stop - if (++consecutiveComplete >= width) - break; - continue; - } - - // see if we want to insert subdivided columns - if ( width + 2 > MAX_GRID_SIZE ) { - errorTable[dir][j+1] = 1.0f/maxLen; - break; // can't subdivide any more - } - - if ( maxLen <= r_subdivisions->value ) { - errorTable[dir][j+1] = 1.0f/maxLen; - // if we go over the whole grid twice without adding any columns, stop - if (++consecutiveComplete >= width) - break; - continue; // didn't need subdivision - } - - errorTable[dir][j+2] = 1.0f/maxLen; - - consecutiveComplete = 0; - - // 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; - } - - // skip the new one, we'll get it on the next pass - 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 triangles - numTriangles = MakeMeshTriangles(width, height, ctrl, triangles); - - // calculate normals - MakeMeshNormals( width, height, ctrl ); -#ifdef USE_VERT_TANGENT_SPACE - MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles); -#endif - - return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles); -} - -/* -=============== -R_GridInsertColumn -=============== -*/ -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) { - int i, j; - int width, height, oldwidth; - srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; - float errorTable[2][MAX_GRID_SIZE]; - float lodRadius; - vec3_t lodOrigin; - int numTriangles; - static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]; - - oldwidth = 0; - width = grid->width + 1; - if (width > MAX_GRID_SIZE) - return NULL; - height = grid->height; - for (i = 0; i < width; i++) { - if (i == column) { - //insert new column - for (j = 0; j < grid->height; j++) { - LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] ); - if (j == row) - VectorCopy(point, ctrl[j][i].xyz); - } - errorTable[0][i] = loderror; - continue; - } - errorTable[0][i] = grid->widthLodError[oldwidth]; - for (j = 0; j < grid->height; j++) { - ctrl[j][i] = grid->verts[j * grid->width + oldwidth]; - } - oldwidth++; - } - for (j = 0; j < grid->height; j++) { - errorTable[1][j] = grid->heightLodError[j]; - } - // put all the aproximating points on the curve - //PutPointsOnCurve( ctrl, width, height ); - - // calculate triangles - numTriangles = MakeMeshTriangles(width, height, ctrl, triangles); - - // calculate normals - MakeMeshNormals( width, height, ctrl ); - - VectorCopy(grid->lodOrigin, lodOrigin); - lodRadius = grid->lodRadius; - // free the old grid - R_FreeSurfaceGridMesh(grid); - // create a new grid - grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles); - grid->lodRadius = lodRadius; - VectorCopy(lodOrigin, grid->lodOrigin); - return grid; -} - -/* -=============== -R_GridInsertRow -=============== -*/ -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) { - int i, j; - int width, height, oldheight; - srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; - float errorTable[2][MAX_GRID_SIZE]; - float lodRadius; - vec3_t lodOrigin; - int numTriangles; - static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]; - - oldheight = 0; - width = grid->width; - height = grid->height + 1; - if (height > MAX_GRID_SIZE) - return NULL; - for (i = 0; i < height; i++) { - if (i == row) { - //insert new row - for (j = 0; j < grid->width; j++) { - LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] ); - if (j == column) - VectorCopy(point, ctrl[i][j].xyz); - } - errorTable[1][i] = loderror; - continue; - } - errorTable[1][i] = grid->heightLodError[oldheight]; - for (j = 0; j < grid->width; j++) { - ctrl[i][j] = grid->verts[oldheight * grid->width + j]; - } - oldheight++; - } - for (j = 0; j < grid->width; j++) { - errorTable[0][j] = grid->widthLodError[j]; - } - // put all the aproximating points on the curve - //PutPointsOnCurve( ctrl, width, height ); - - // calculate triangles - numTriangles = MakeMeshTriangles(width, height, ctrl, triangles); - - // calculate normals - MakeMeshNormals( width, height, ctrl ); - - VectorCopy(grid->lodOrigin, lodOrigin); - lodRadius = grid->lodRadius; - // free the old grid - R_FreeSurfaceGridMesh(grid); - // create a new grid - grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles); - grid->lodRadius = lodRadius; - VectorCopy(lodOrigin, grid->lodOrigin); - return grid; -} diff --git a/code/renderergl2/tr_extensions.c b/code/renderergl2/tr_extensions.c deleted file mode 100644 index f888cbc8..00000000 --- a/code/renderergl2/tr_extensions.c +++ /dev/null @@ -1,682 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2011 James Canete (use.less01@gmail.com) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_extensions.c - extensions needed by the renderer not in sdl_glimp.c - -#ifdef USE_LOCAL_HEADERS -# include "SDL.h" -#else -# include -#endif - -#include "tr_local.h" - -// GL_EXT_draw_range_elements -void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); - -// GL_EXT_multi_draw_arrays -void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); - -// GL_ARB_vertex_shader -void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name); -void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, - GLint * size, GLenum * type, GLcharARB * name); -GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name); - -// GL_ARB_vertex_program -void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); -void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *); -void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized, - GLsizei stride, const GLvoid * pointer); -void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index); -void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index); - -// GL_ARB_vertex_buffer_object -void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer); -void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers); -void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers); - -GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer); -void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); -void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); -void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data); - -void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params); -void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params); - -// GL_ARB_shader_objects -void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj); - -GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname); -void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj); - -GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType); -void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string, - const GLint * length); -void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj); - -GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void); -void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj); -void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj); -void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj); -void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj); -void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0); -void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1); -void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0); -void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1); -void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2); -void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value); -void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value); -void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value); -void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value); -void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value); -void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value); -void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value); -void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); -void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params); -void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params); -void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); -void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, - GLhandleARB * obj); -GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name); -void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length, - GLint * size, GLenum * type, GLcharARB * name); -void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params); -void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params); -void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source); - -// GL_ARB_texture_compression -void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, - GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, - GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, - GLsizei imageSize, const GLvoid *data); -void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod, - GLvoid *img); - -// GL_EXT_framebuffer_object -GLboolean (APIENTRY * qglIsRenderbufferEXT)(GLuint renderbuffer); -void (APIENTRY * qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer); -void (APIENTRY * qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers); -void (APIENTRY * qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers); - -void (APIENTRY * qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); - -void (APIENTRY * qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params); - -GLboolean (APIENTRY * qglIsFramebufferEXT)(GLuint framebuffer); -void (APIENTRY * qglBindFramebufferEXT)(GLenum target, GLuint framebuffer); -void (APIENTRY * qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers); -void (APIENTRY * qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers); - -GLenum (APIENTRY * qglCheckFramebufferStatusEXT)(GLenum target); - -void (APIENTRY * qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level); -void (APIENTRY * qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level); -void (APIENTRY * qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset); - -void (APIENTRY * qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget, - GLuint renderbuffer); - -void (APIENTRY * qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params); - -void (APIENTRY * qglGenerateMipmapEXT)(GLenum target); - -// GL_ARB_occlusion_query -void (APIENTRY * qglGenQueriesARB)(GLsizei n, GLuint *ids); -void (APIENTRY * qglDeleteQueriesARB)(GLsizei n, const GLuint *ids); -GLboolean (APIENTRY * qglIsQueryARB)(GLuint id); -void (APIENTRY * qglBeginQueryARB)(GLenum target, GLuint id); -void (APIENTRY * qglEndQueryARB)(GLenum target); -void (APIENTRY * qglGetQueryivARB)(GLenum target, GLenum pname, GLint *params); -void (APIENTRY * qglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params); -void (APIENTRY * qglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params); - -// GL_EXT_framebuffer_blit -void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - -// GL_EXT_framebuffer_multisample -void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height); - -// GL_ARB_draw_buffers -void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs); - -static qboolean GLimp_HaveExtension(const char *ext) -{ - const char *ptr = Q_stristr( glConfig.extensions_string, ext ); - if (ptr == NULL) - return qfalse; - ptr += strlen(ext); - return ((*ptr == ' ') || (*ptr == '\0')); // verify it's complete string. -} - -void GLimp_InitExtraExtensions() -{ - char *extension; - const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" }; - - // GL_EXT_draw_range_elements - extension = "GL_EXT_draw_range_elements"; - glRefConfig.drawRangeElements = qfalse; - qglMultiDrawArraysEXT = NULL; - qglMultiDrawElementsEXT = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglDrawRangeElementsEXT = (void *) SDL_GL_GetProcAddress("glDrawRangeElementsEXT"); - - if ( r_ext_draw_range_elements->integer) - glRefConfig.drawRangeElements = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.drawRangeElements], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_multi_draw_arrays - extension = "GL_EXT_multi_draw_arrays"; - glRefConfig.multiDrawArrays = qfalse; - qglMultiDrawArraysEXT = NULL; - qglMultiDrawElementsEXT = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawArraysEXT"); - qglMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawElementsEXT"); - - if ( r_ext_multi_draw_arrays->integer ) - glRefConfig.multiDrawArrays = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.multiDrawArrays], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_vertex_program - //glRefConfig.vertexProgram = qfalse; - extension = "GL_ARB_vertex_program"; - qglVertexAttrib4fARB = NULL; - qglVertexAttrib4fvARB = NULL; - qglVertexAttribPointerARB = NULL; - qglEnableVertexAttribArrayARB = NULL; - qglDisableVertexAttribArrayARB = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fARB"); - qglVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fvARB"); - qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) SDL_GL_GetProcAddress("glVertexAttribPointerARB"); - qglEnableVertexAttribArrayARB = - (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArrayARB"); - qglDisableVertexAttribArrayARB = - (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArrayARB"); - - ri.Printf(PRINT_ALL, result[1], extension); - //glRefConfig.vertexProgram = qtrue; - } - else - { - ri.Error(ERR_FATAL, result[2], extension); - } - - // GL_ARB_vertex_buffer_object - //glRefConfig.vertexBufferObject = qfalse; - extension = "GL_ARB_vertex_buffer_object"; - qglBindBufferARB = NULL; - qglDeleteBuffersARB = NULL; - qglGenBuffersARB = NULL; - qglIsBufferARB = NULL; - qglBufferDataARB = NULL; - qglBufferSubDataARB = NULL; - qglGetBufferSubDataARB = NULL; - qglGetBufferParameterivARB = NULL; - qglGetBufferPointervARB = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB"); - qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB"); - qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB"); - qglIsBufferARB = (PFNGLISBUFFERARBPROC) SDL_GL_GetProcAddress("glIsBufferARB"); - qglBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB"); - qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB"); - qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glGetBufferSubDataARB"); - qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetBufferParameterivARB"); - qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) SDL_GL_GetProcAddress("glGetBufferPointervARB"); - ri.Printf(PRINT_ALL, result[1], extension); - //glRefConfig.vertexBufferObject = qtrue; - } - else - { - ri.Error(ERR_FATAL, result[2], extension); - } - - // GL_ARB_shader_objects - extension = "GL_ARB_shader_objects"; - //glRefConfig.shaderObjects = qfalse; - qglDeleteObjectARB = NULL; - qglGetHandleARB = NULL; - qglDetachObjectARB = NULL; - qglCreateShaderObjectARB = NULL; - qglShaderSourceARB = NULL; - qglCompileShaderARB = NULL; - qglCreateProgramObjectARB = NULL; - qglAttachObjectARB = NULL; - qglLinkProgramARB = NULL; - qglUseProgramObjectARB = NULL; - qglValidateProgramARB = NULL; - qglUniform1fARB = NULL; - qglUniform2fARB = NULL; - qglUniform3fARB = NULL; - qglUniform4fARB = NULL; - qglUniform1iARB = NULL; - qglUniform2iARB = NULL; - qglUniform3iARB = NULL; - qglUniform4iARB = NULL; - qglUniform1fvARB = NULL; - qglUniform2fvARB = NULL; - qglUniform3fvARB = NULL; - qglUniform4fvARB = NULL; - qglUniform2ivARB = NULL; - qglUniform3ivARB = NULL; - qglUniform4ivARB = NULL; - qglUniformMatrix2fvARB = NULL; - qglUniformMatrix3fvARB = NULL; - qglUniformMatrix4fvARB = NULL; - qglGetObjectParameterfvARB = NULL; - qglGetObjectParameterivARB = NULL; - qglGetInfoLogARB = NULL; - qglGetAttachedObjectsARB = NULL; - qglGetUniformLocationARB = NULL; - qglGetActiveUniformARB = NULL; - qglGetUniformfvARB = NULL; - qglGetUniformivARB = NULL; - qglGetShaderSourceARB = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB"); - qglGetHandleARB = (PFNGLGETHANDLEARBPROC) SDL_GL_GetProcAddress("glGetHandleARB"); - qglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) SDL_GL_GetProcAddress("glDetachObjectARB"); - qglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB"); - qglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB"); - qglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB"); - qglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB"); - qglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB"); - qglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB"); - qglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB"); - qglValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) SDL_GL_GetProcAddress("glValidateProgramARB"); - qglUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB"); - qglUniform2fARB = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB"); - qglUniform3fARB = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB"); - qglUniform4fARB = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB"); - qglUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB"); - qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB"); - qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB"); - qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB"); - qglUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB"); - qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB"); - qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB"); - qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB"); - qglUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) SDL_GL_GetProcAddress("glUniform2ivARB"); - qglUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) SDL_GL_GetProcAddress("glUniform3ivARB"); - qglUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) SDL_GL_GetProcAddress("glUniform4ivARB"); - qglUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix2fvARB"); - qglUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix3fvARB"); - qglUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix4fvARB"); - qglGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterfvARB"); - qglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB"); - qglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB"); - qglGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) SDL_GL_GetProcAddress("glGetAttachedObjectsARB"); - qglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB"); - qglGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB"); - qglGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) SDL_GL_GetProcAddress("glGetUniformfvARB"); - qglGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) SDL_GL_GetProcAddress("glGetUniformivARB"); - qglGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glGetShaderSourceARB"); - ri.Printf(PRINT_ALL, result[1], extension); - //glRefConfig.shaderObjects = qtrue; - } - else - { - ri.Error(ERR_FATAL, result[2], extension); - } - - // GL_ARB_vertex_shader - //glRefConfig.vertexShader = qfalse; - extension = "GL_ARB_vertex_shader"; - qglBindAttribLocationARB = NULL; - qglGetActiveAttribARB = NULL; - qglGetAttribLocationARB = NULL; - if( GLimp_HaveExtension( extension ) ) - { - //int reservedComponents; - - //qglGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig.maxVertexUniforms); - //qglGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &glConfig.maxVaryingFloats); - //qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig.maxVertexAttribs); - - //reservedComponents = 16 * 10; // approximation how many uniforms we have besides the bone matrices - -#if 0 - if(glConfig.driverType == GLDRV_MESA) - { - // HACK - // restrict to number of vertex uniforms to 512 because of: - // xreal.x86_64: nv50_program.c:4181: nv50_program_validate_data: Assertion `p->param_nr <= 512' failed - - glConfig.maxVertexUniforms = Q_bound(0, glConfig.maxVertexUniforms, 512); - } -#endif - - //glConfig.maxVertexSkinningBones = (int) Q_bound(0.0, (Q_max(glConfig.maxVertexUniforms - reservedComponents, 0) / 16), MAX_BONES); - //glConfig.vboVertexSkinningAvailable = r_vboVertexSkinning->integer && ((glConfig.maxVertexSkinningBones >= 12) ? qtrue : qfalse); - - qglBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB"); - qglGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) SDL_GL_GetProcAddress("glGetActiveAttribARB"); - qglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetAttribLocationARB"); - ri.Printf(PRINT_ALL, result[1], extension); - //glRefConfig.vertexShader = qtrue; - } - else - { - ri.Error(ERR_FATAL, result[2], extension); - } - - // GL_ARB_shading_language_100 - extension = "GL_ARB_shading_language_100"; - glRefConfig.textureFloat = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - char version[256]; - - Q_strncpyz( version, (char *) qglGetString (GL_SHADING_LANGUAGE_VERSION_ARB), sizeof( version ) ); - - sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion); - - ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version); - } - else - { - ri.Error(ERR_FATAL, result[2], extension); - } - - glRefConfig.memInfo = MI_NONE; - - if( GLimp_HaveExtension( "GL_NVX_gpu_memory_info" ) ) - { - glRefConfig.memInfo = MI_NVX; - } - else if( GLimp_HaveExtension( "GL_ATI_meminfo" ) ) - { - glRefConfig.memInfo = MI_ATI; - } - - extension = "GL_ARB_texture_non_power_of_two"; - glRefConfig.textureNonPowerOfTwo = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - if(1) //(r_ext_texture_non_power_of_two->integer) - { - glRefConfig.textureNonPowerOfTwo = qtrue; - } - - ri.Printf(PRINT_ALL, result[glRefConfig.textureNonPowerOfTwo], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_texture_float - extension = "GL_ARB_texture_float"; - glRefConfig.textureFloat = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - if( r_ext_texture_float->integer ) - { - glRefConfig.textureFloat = qtrue; - } - - ri.Printf(PRINT_ALL, result[glRefConfig.textureFloat], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_half_float_pixel - extension = "GL_ARB_half_float_pixel"; - glRefConfig.halfFloatPixel = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - if( r_arb_half_float_pixel->integer ) - glRefConfig.halfFloatPixel = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.halfFloatPixel], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_framebuffer_object - extension = "GL_EXT_framebuffer_object"; - glRefConfig.framebufferObject = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &glRefConfig.maxRenderbufferSize); - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &glRefConfig.maxColorAttachments); - - qglIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsRenderbufferEXT"); - qglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindRenderbufferEXT"); - qglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT"); - qglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenRenderbuffersEXT"); - qglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) SDL_GL_GetProcAddress("glRenderbufferStorageEXT"); - qglGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT"); - qglIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsFramebufferEXT"); - qglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindFramebufferEXT"); - qglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteFramebuffersEXT"); - qglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenFramebuffersEXT"); - qglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT"); - qglFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture1DEXT"); - qglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture2DEXT"); - qglFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture3DEXT"); - qglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT"); - qglGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT"); - qglGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) SDL_GL_GetProcAddress("glGenerateMipmapEXT"); - - if(r_ext_framebuffer_object->value) - glRefConfig.framebufferObject = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.framebufferObject], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_packed_depth_stencil - extension = "GL_EXT_packed_depth_stencil"; - glRefConfig.packedDepthStencil = qfalse; - if( GLimp_HaveExtension(extension)) - { - glRefConfig.packedDepthStencil = qtrue; - ri.Printf(PRINT_ALL, result[glRefConfig.packedDepthStencil], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_occlusion_query - extension = "GL_ARB_occlusion_query"; - glRefConfig.occlusionQuery = qfalse; - if (GLimp_HaveExtension(extension)) - { - qglGenQueriesARB = (PFNGLGENQUERIESARBPROC) SDL_GL_GetProcAddress("glGenQueriesARB"); - qglDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) SDL_GL_GetProcAddress("glDeleteQueriesARB"); - qglIsQueryARB = (PFNGLISQUERYARBPROC) SDL_GL_GetProcAddress("glIsQueryARB"); - qglBeginQueryARB = (PFNGLBEGINQUERYARBPROC) SDL_GL_GetProcAddress("glBeginQueryARB"); - qglEndQueryARB = (PFNGLENDQUERYARBPROC) SDL_GL_GetProcAddress("glEndQueryARB"); - qglGetQueryivARB = (PFNGLGETQUERYIVARBPROC) SDL_GL_GetProcAddress("glGetQueryivARB"); - qglGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectivARB"); - qglGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectuivARB"); - glRefConfig.occlusionQuery = qtrue; - ri.Printf(PRINT_ALL, result[glRefConfig.occlusionQuery], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_framebuffer_blit - extension = "GL_EXT_framebuffer_blit"; - glRefConfig.framebufferBlit = qfalse; - if (GLimp_HaveExtension(extension)) - { - qglBlitFramebufferEXT = (void *)SDL_GL_GetProcAddress("glBlitFramebufferEXT"); - glRefConfig.framebufferBlit = qtrue; - ri.Printf(PRINT_ALL, result[glRefConfig.framebufferBlit], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_framebuffer_multisample - extension = "GL_EXT_framebuffer_multisample"; - glRefConfig.framebufferMultisample = qfalse; - if (GLimp_HaveExtension(extension)) - { - qglRenderbufferStorageMultisampleEXT = (void *)SDL_GL_GetProcAddress("glRenderbufferStorageMultisampleEXT"); - glRefConfig.framebufferMultisample = qtrue; - ri.Printf(PRINT_ALL, result[glRefConfig.framebufferMultisample], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_texture_sRGB - extension = "GL_EXT_texture_sRGB"; - glRefConfig.texture_srgb = qfalse; - if (GLimp_HaveExtension(extension)) - { - if (r_srgb->integer) - glRefConfig.texture_srgb = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.texture_srgb], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_EXT_framebuffer_sRGB - extension = "GL_EXT_framebuffer_sRGB"; - glRefConfig.framebuffer_srgb = qfalse; - if (GLimp_HaveExtension(extension)) - { - if (r_srgb->integer) - glRefConfig.framebuffer_srgb = qtrue; - - ri.Printf(PRINT_ALL, result[glRefConfig.framebuffer_srgb], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - glRefConfig.textureCompression = TCR_NONE; - - // GL_EXT_texture_compression_latc - extension = "GL_EXT_texture_compression_latc"; - if (GLimp_HaveExtension(extension)) - { - if (r_ext_compressed_textures->integer) - glRefConfig.textureCompression |= TCR_LATC; - - ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_texture_compression_bptc - extension = "GL_ARB_texture_compression_bptc"; - if (GLimp_HaveExtension(extension)) - { - if (r_ext_compressed_textures->integer >= 2) - glRefConfig.textureCompression |= TCR_BPTC; - - ri.Printf(PRINT_ALL, result[(r_ext_compressed_textures->integer >= 2) ? 1 : 0], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_draw_buffers - extension = "GL_ARB_draw_buffers"; - qglDrawBuffersARB = NULL; - if( GLimp_HaveExtension( extension ) ) - { - qglDrawBuffersARB = (void *) SDL_GL_GetProcAddress("glDrawBuffersARB"); - - ri.Printf(PRINT_ALL, result[1], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } - - // GL_ARB_depth_clamp - extension = "GL_ARB_depth_clamp"; - glRefConfig.depthClamp = qfalse; - if( GLimp_HaveExtension( extension ) ) - { - glRefConfig.depthClamp = qtrue; - ri.Printf(PRINT_ALL, result[1], extension); - } - else - { - ri.Printf(PRINT_ALL, result[2], extension); - } -} diff --git a/code/renderergl2/tr_extramath.c b/code/renderergl2/tr_extramath.c deleted file mode 100644 index 8cb6fe1a..00000000 --- a/code/renderergl2/tr_extramath.c +++ /dev/null @@ -1,240 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2010 James Canete (use.less01@gmail.com) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_extramath.c - extra math needed by the renderer not in qmath.c - -#include "tr_local.h" - -// Some matrix helper functions -// FIXME: do these already exist in ioq3 and I don't know about them? - -void Matrix16Zero( matrix_t out ) -{ - out[ 0] = 0.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f; - out[ 1] = 0.0f; out[ 5] = 0.0f; out[ 9] = 0.0f; out[13] = 0.0f; - out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 0.0f; out[14] = 0.0f; - out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 0.0f; -} - -void Matrix16Identity( matrix_t out ) -{ - out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f; - out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = 0.0f; - out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = 0.0f; - out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f; -} - -void Matrix16Copy( const matrix_t in, matrix_t out ) -{ - out[ 0] = in[ 0]; out[ 4] = in[ 4]; out[ 8] = in[ 8]; out[12] = in[12]; - out[ 1] = in[ 1]; out[ 5] = in[ 5]; out[ 9] = in[ 9]; out[13] = in[13]; - out[ 2] = in[ 2]; out[ 6] = in[ 6]; out[10] = in[10]; out[14] = in[14]; - out[ 3] = in[ 3]; out[ 7] = in[ 7]; out[11] = in[11]; out[15] = in[15]; -} - -void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out ) -{ - out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3]; - out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3]; - out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3]; - out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3]; - - out[ 4] = in1[ 0] * in2[ 4] + in1[ 4] * in2[ 5] + in1[ 8] * in2[ 6] + in1[12] * in2[ 7]; - out[ 5] = in1[ 1] * in2[ 4] + in1[ 5] * in2[ 5] + in1[ 9] * in2[ 6] + in1[13] * in2[ 7]; - out[ 6] = in1[ 2] * in2[ 4] + in1[ 6] * in2[ 5] + in1[10] * in2[ 6] + in1[14] * in2[ 7]; - out[ 7] = in1[ 3] * in2[ 4] + in1[ 7] * in2[ 5] + in1[11] * in2[ 6] + in1[15] * in2[ 7]; - - out[ 8] = in1[ 0] * in2[ 8] + in1[ 4] * in2[ 9] + in1[ 8] * in2[10] + in1[12] * in2[11]; - out[ 9] = in1[ 1] * in2[ 8] + in1[ 5] * in2[ 9] + in1[ 9] * in2[10] + in1[13] * in2[11]; - out[10] = in1[ 2] * in2[ 8] + in1[ 6] * in2[ 9] + in1[10] * in2[10] + in1[14] * in2[11]; - out[11] = in1[ 3] * in2[ 8] + in1[ 7] * in2[ 9] + in1[11] * in2[10] + in1[15] * in2[11]; - - out[12] = in1[ 0] * in2[12] + in1[ 4] * in2[13] + in1[ 8] * in2[14] + in1[12] * in2[15]; - out[13] = in1[ 1] * in2[12] + in1[ 5] * in2[13] + in1[ 9] * in2[14] + in1[13] * in2[15]; - out[14] = in1[ 2] * in2[12] + in1[ 6] * in2[13] + in1[10] * in2[14] + in1[14] * in2[15]; - out[15] = in1[ 3] * in2[12] + in1[ 7] * in2[13] + in1[11] * in2[14] + in1[15] * in2[15]; -} - -void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out ) -{ - out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3]; - out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3]; - out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3]; - out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3]; -} - -qboolean Matrix16Compare( const matrix_t a, const matrix_t b ) -{ - return !(a[ 0] != b[ 0] || a[ 4] != b[ 4] || a[ 8] != b[ 8] || a[12] != b[12] || - a[ 1] != b[ 1] || a[ 5] != b[ 5] || a[ 9] != b[ 9] || a[13] != b[13] || - a[ 2] != b[ 2] || a[ 6] != b[ 6] || a[10] != b[10] || a[14] != b[14] || - a[ 3] != b[ 3] || a[ 7] != b[ 7] || a[11] != b[11] || a[15] != b[15]); -} - -void Matrix16Dump( const matrix_t in ) -{ - ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 0], in[ 4], in[ 8], in[12]); - ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 1], in[ 5], in[ 9], in[13]); - ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 2], in[ 6], in[10], in[14]); - ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 3], in[ 7], in[11], in[15]); -} - -void Matrix16Translation( vec3_t vec, matrix_t out ) -{ - out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = vec[0]; - out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = vec[1]; - out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = vec[2]; - out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f; -} - -void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out ) -{ - out[ 0] = 2.0f / (right - left); out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = -(right + left) / (right - left); - out[ 1] = 0.0f; out[ 5] = 2.0f / (top - bottom); out[ 9] = 0.0f; out[13] = -(top + bottom) / (top - bottom); - out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 2.0f / (zfar - znear); out[14] = -(zfar + znear) / (zfar - znear); - out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f; -} - -void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out) -{ - out[0] = axes[0][0]; - out[1] = axes[1][0]; - out[2] = axes[2][0]; - out[3] = 0; - - out[4] = axes[0][1]; - out[5] = axes[1][1]; - out[6] = axes[2][1]; - out[7] = 0; - - out[8] = axes[0][2]; - out[9] = axes[1][2]; - out[10] = axes[2][2]; - out[11] = 0; - - out[12] = -DotProduct(origin, axes[0]); - out[13] = -DotProduct(origin, axes[1]); - out[14] = -DotProduct(origin, axes[2]); - out[15] = 1; -} - -void Matrix16SimpleInverse( const matrix_t in, matrix_t out) -{ - vec3_t v; - float invSqrLen; - - VectorCopy(in + 0, v); - invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - out[ 0] = v[0]; out[ 4] = v[1]; out[ 8] = v[2]; out[12] = -DotProduct(v, &in[12]); - - VectorCopy(in + 4, v); - invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - out[ 1] = v[0]; out[ 5] = v[1]; out[ 9] = v[2]; out[13] = -DotProduct(v, &in[12]); - - VectorCopy(in + 8, v); - invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - out[ 2] = v[0]; out[ 6] = v[1]; out[10] = v[2]; out[14] = -DotProduct(v, &in[12]); - - out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f; -} - -void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c) -{ - c[0] = a[0] * (1.0f - lerp) + b[0] * lerp; - c[1] = a[1] * (1.0f - lerp) + b[1] * lerp; - c[2] = a[2] * (1.0f - lerp) + b[2] * lerp; -} - -qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2) -{ - float radiusSum = radius1 + radius2; - vec3_t diff; - - VectorSubtract(origin1, origin2, diff); - - if (DotProduct(diff, diff) <= radiusSum * radiusSum) - { - return qtrue; - } - - return qfalse; -} - -void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3) -{ - vec3_t diff; - - VectorScale(origin1, 0.5f, origin3); - VectorMA(origin3, 0.5f, origin2, origin3); - - VectorSubtract(origin1, origin2, diff); - *radius3 = VectorLength(diff) * 0.5f + MAX(radius1, radius2); -} - -int NextPowerOfTwo(int in) -{ - int out; - - for (out = 1; out < in; out <<= 1) - ; - - return out; -} - -unsigned short FloatToHalf(float in) -{ - unsigned short out; - - union - { - float f; - unsigned int i; - } f32; - - int sign, inExponent, inFraction; - int outExponent, outFraction; - - f32.f = in; - - sign = (f32.i & 0x80000000) >> 31; - inExponent = (f32.i & 0x7F800000) >> 23; - inFraction = f32.i & 0x007FFFFF; - - outExponent = CLAMP(inExponent - 127, -15, 16) + 15; - - outFraction = 0; - if (outExponent == 0x1F) - { - if (inExponent == 0xFF && inFraction != 0) - outFraction = 0x3FF; - } - else if (outExponent == 0x00) - { - if (inExponent == 0x00 && inFraction != 0) - outFraction = 0x3FF; - } - else - outFraction = inFraction >> 13; - - out = (sign << 15) | (outExponent << 10) | outFraction; - - return out; -} diff --git a/code/renderergl2/tr_extramath.h b/code/renderergl2/tr_extramath.h deleted file mode 100644 index 54f043b9..00000000 --- a/code/renderergl2/tr_extramath.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2010 James Canete (use.less01@gmail.com) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_extramath.h - -#ifndef __TR_EXTRAMATH_H__ -#define __TR_EXTRAMATH_H__ - -typedef vec_t matrix_t[16]; -typedef int vec2i_t[2]; -typedef int vec3i_t[3]; -typedef int vec4i_t[4]; - -void Matrix16Zero( matrix_t out ); -void Matrix16Identity( matrix_t out ); -void Matrix16Copy( const matrix_t in, matrix_t out ); -void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out ); -void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out ); -qboolean Matrix16Compare(const matrix_t a, const matrix_t b); -void Matrix16Dump( const matrix_t in ); -void Matrix16Translation( vec3_t vec, matrix_t out ); -void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out ); -void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out); -void Matrix16SimpleInverse( const matrix_t in, matrix_t out); - -#define VectorCopy2(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1]) - -#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) -#define VectorSet4(v,x,y,z,w) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w)) -#define DotProduct4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3]) -#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b)) - -#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4]) - -#define OffsetByteToFloat(a) ((float)(a) * 1.0f/127.5f - 1.0f) -#define FloatToOffsetByte(a) (byte)(((a) + 1.0f) * 127.5f) -#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f) -#define FloatToByte(a) (byte)((a) * 255.0f) - -#define RGBtosRGB(a) (((a) < 0.0031308f) ? (12.92f * (a)) : (1.055f * pow((a), 0.41666f) - 0.055f)) -#define sRGBtoRGB(a) (((a) <= 0.04045f) ? ((a) / 12.92f) : (pow((((a) + 0.055f) / 1.055f), 2.4)) ) - -static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2) -{ - if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3]) - { - return 0; - } - return 1; -} - -static ID_INLINE int VectorCompare5(const vec5_t v1, const vec5_t v2) -{ - if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3] || v1[4] != v2[4]) - { - return 0; - } - return 1; -} - -void VectorLerp( vec3_t a, vec3_t b, float lerp, vec3_t c); - - -qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2); -void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3); - -#ifndef SGN -#define SGN(x) (((x) >= 0) ? !!(x) : -1) -#endif - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef CLAMP -#define CLAMP(a,b,c) MIN(MAX((a),(b)),(c)) -#endif - -int NextPowerOfTwo(int in); -unsigned short FloatToHalf(float in); - -#endif diff --git a/code/renderergl2/tr_extratypes.h b/code/renderergl2/tr_extratypes.h deleted file mode 100644 index 60471120..00000000 --- a/code/renderergl2/tr_extratypes.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2009-2011 Andrei Drexler, Richard Allen, James Canete - -This file is part of Reaction source code. - -Reaction source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Reaction source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Reaction source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#ifndef __TR_EXTRATYPES_H__ -#define __TR_EXTRATYPES_H__ - -// tr_extratypes.h, for mods that want to extend tr_types.h without losing compatibility with original VMs - -// extra renderfx flags start at 0x0400 -#define RF_SUNFLARE 0x0400 - -// extra refdef flags start at 0x0008 -#define RDF_NOFOG 0x0008 // don't apply fog -#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t -#define RDF_SUNLIGHT 0x0020 // SmileTheory - render sunlight and shadows - -typedef struct { - float blurFactor; - float sunDir[3]; - float sunCol[3]; - float sunAmbCol[3]; -} refdefex_t; - -#endif - diff --git a/code/renderergl2/tr_fbo.c b/code/renderergl2/tr_fbo.c deleted file mode 100644 index a830d145..00000000 --- a/code/renderergl2/tr_fbo.c +++ /dev/null @@ -1,822 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Kirk Barnes -Copyright (C) 2006-2008 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_fbo.c -#include "tr_local.h" - -/* -============= -R_CheckFBO -============= -*/ -qboolean R_CheckFBO(const FBO_t * fbo) -{ - int code; - int id; - - qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer); - - code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - - if(code == GL_FRAMEBUFFER_COMPLETE_EXT) - { - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - return qtrue; - } - - // an error occured - switch (code) - { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete attachment\n", fbo->name); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing attachment\n", fbo->name); - break; - - //case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: - // ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, duplicate attachment\n", fbo->name); - // break; - - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same dimensions\n", - fbo->name); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same format\n", - fbo->name); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing draw buffer\n", fbo->name); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing read buffer\n", fbo->name); - break; - - default: - ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code); - //ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code); - //assert(0); - break; - } - - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - - return qfalse; -} - -/* -============ -FBO_Create -============ -*/ -FBO_t *FBO_Create(const char *name, int width, int height) -{ - FBO_t *fbo; - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "FBO_Create: \"%s\" is too long\n", name); - } - - if(width <= 0 || width > glRefConfig.maxRenderbufferSize) - { - ri.Error(ERR_DROP, "FBO_Create: bad width %i", width); - } - - if(height <= 0 || height > glRefConfig.maxRenderbufferSize) - { - ri.Error(ERR_DROP, "FBO_Create: bad height %i", height); - } - - if(tr.numFBOs == MAX_FBOS) - { - ri.Error(ERR_DROP, "FBO_Create: MAX_FBOS hit"); - } - - fbo = tr.fbos[tr.numFBOs] = ri.Hunk_Alloc(sizeof(*fbo), h_low); - Q_strncpyz(fbo->name, name, sizeof(fbo->name)); - fbo->index = tr.numFBOs++; - fbo->width = width; - fbo->height = height; - - qglGenFramebuffersEXT(1, &fbo->frameBuffer); - - return fbo; -} - -void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample) -{ - uint32_t *pRenderBuffer; - GLenum attachment; - qboolean absent; - - switch(format) - { - case GL_RGB: - case GL_RGBA: - case GL_RGB8: - case GL_RGBA8: - case GL_RGB16F_ARB: - case GL_RGBA16F_ARB: - case GL_RGB32F_ARB: - case GL_RGBA32F_ARB: - fbo->colorFormat = format; - pRenderBuffer = &fbo->colorBuffers[index]; - attachment = GL_COLOR_ATTACHMENT0_EXT + index; - break; - - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16_ARB: - case GL_DEPTH_COMPONENT24_ARB: - case GL_DEPTH_COMPONENT32_ARB: - fbo->depthFormat = format; - pRenderBuffer = &fbo->depthBuffer; - attachment = GL_DEPTH_ATTACHMENT_EXT; - break; - - case GL_STENCIL_INDEX: - case GL_STENCIL_INDEX1_EXT: - case GL_STENCIL_INDEX4_EXT: - case GL_STENCIL_INDEX8_EXT: - case GL_STENCIL_INDEX16_EXT: - fbo->stencilFormat = format; - pRenderBuffer = &fbo->stencilBuffer; - attachment = GL_STENCIL_ATTACHMENT_EXT; - break; - - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - fbo->packedDepthStencilFormat = format; - pRenderBuffer = &fbo->packedDepthStencilBuffer; - attachment = 0; // special for stencil and depth - break; - - default: - ri.Printf(PRINT_WARNING, "FBO_CreateBuffer: invalid format %d\n", format); - return; - } - - absent = *pRenderBuffer == 0; - if (absent) - qglGenRenderbuffersEXT(1, pRenderBuffer); - - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer); - if (multisample && glRefConfig.framebufferMultisample) - { - qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height); - } - else - { - qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height); - } - - if(absent) - { - if (attachment == 0) - { - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); - } - else - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer); - } -} - - -/* -================= -R_AttachFBOTexture1D -================= -*/ -void R_AttachFBOTexture1D(int texId, int index) -{ - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index); - return; - } - - qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0); -} - -/* -================= -R_AttachFBOTexture2D -================= -*/ -void R_AttachFBOTexture2D(int target, int texId, int index) -{ - if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target); - return; - } - - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index); - return; - } - - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0); -} - -/* -================= -R_AttachFBOTexture3D -================= -*/ -void R_AttachFBOTexture3D(int texId, int index, int zOffset) -{ - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index); - return; - } - - qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset); -} - -/* -================= -R_AttachFBOTextureDepth -================= -*/ -void R_AttachFBOTextureDepth(int texId) -{ - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); -} - -/* -================= -R_AttachFBOTexturePackedDepthStencil -================= -*/ -void R_AttachFBOTexturePackedDepthStencil(int texId) -{ - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); -} - -void FBO_AttachTextureImage(image_t *img, int index) -{ - if (!glState.currentFBO) - { - ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture image with no FBO bound!\n"); - return; - } - - R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index); - glState.currentFBO->colorImage[index] = img; -} - -/* -============ -FBO_Bind -============ -*/ -void FBO_Bind(FBO_t * fbo) -{ - if (fbo && glState.currentFBO == fbo) - return; - - if (r_logFile->integer) - { - // don't just call LogComment, or we will get a call to va() every frame! - if (fbo) - GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo->name)); - else - GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n"); - } - - if (!fbo) - { - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - glState.currentFBO = NULL; - - return; - } - - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer); - - /* - if(fbo->colorBuffers[0]) - { - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]); - } - */ - - /* - if(fbo->depthBuffer) - { - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer); - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer); - } - */ - - glState.currentFBO = fbo; -} - -/* -============ -FBO_Init -============ -*/ -void FBO_Init(void) -{ - int i; - // int width, height, hdrFormat, multisample; - int hdrFormat, multisample; - - ri.Printf(PRINT_ALL, "------- FBO_Init -------\n"); - - if(!glRefConfig.framebufferObject) - return; - - tr.numFBOs = 0; - - GL_CheckErrors(); - - // make sure the render thread is stopped - R_SyncRenderThread(); - -/* if(glRefConfig.textureNonPowerOfTwo) - { - width = glConfig.vidWidth; - height = glConfig.vidHeight; - } - else - { - width = NextPowerOfTwo(glConfig.vidWidth); - height = NextPowerOfTwo(glConfig.vidHeight); - } */ - - hdrFormat = GL_RGBA8; - if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat) - { - hdrFormat = GL_RGB16F_ARB; - } - - qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample); - - if (r_ext_framebuffer_multisample->integer < multisample) - { - multisample = r_ext_framebuffer_multisample->integer; - } - - if (multisample < 2 || !glRefConfig.framebufferBlit) - multisample = 0; - - if (multisample != r_ext_framebuffer_multisample->integer) - { - ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample); - } - - if (multisample && glRefConfig.framebufferMultisample) - { - tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.renderFbo); - - FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample); - FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample); - - R_CheckFBO(tr.renderFbo); - - - tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.msaaResolveFbo); - - //FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.renderImage, 0); - - //FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - - R_CheckFBO(tr.msaaResolveFbo); - } - else - { - tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.renderFbo); - - //FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.renderImage, 0); - - //FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - - R_CheckFBO(tr.renderFbo); - } - - // clear render buffer - // this fixes the corrupt screen bug with r_hdr 1 on older hardware - FBO_Bind(tr.renderFbo); - qglClearColor( 1, 0, 0.5, 1 ); - qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - FBO_Bind(NULL); - -#ifdef REACTION - { - tr.godRaysFbo = FBO_Create("_godRays", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.godRaysFbo); - - //FBO_CreateBuffer(tr.godRaysFbo, GL_RGBA8, 0, multisample); - FBO_AttachTextureImage(tr.godRaysImage, 0); - - //FBO_CreateBuffer(tr.godRaysFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - - R_CheckFBO(tr.godRaysFbo); - } -#endif - - // FIXME: Don't use separate color/depth buffers for a shadow buffer - for( i = 0; i < MAX_DRAWN_PSHADOWS; i++) - { - tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height); - FBO_Bind(tr.pshadowFbos[i]); - - //FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0); - FBO_AttachTextureImage(tr.pshadowMaps[i], 0); - - FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0); - //R_AttachFBOTextureDepth(tr.textureDepthImage->texnum); - - R_CheckFBO(tr.pshadowFbos[i]); - } - - for ( i = 0; i < 3; i++) - { - tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); - FBO_Bind(tr.sunShadowFbo[i]); - - //FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0); - //FBO_AttachTextureImage(tr.sunShadowImage, 0); - qglDrawBuffer(GL_NONE); - qglReadBuffer(GL_NONE); - - //FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum); - - R_CheckFBO(tr.sunShadowFbo[i]); - } - - for (i = 0; i < 2; i++) - { - tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); - FBO_Bind(tr.textureScratchFbo[i]); - - //FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0); - FBO_AttachTextureImage(tr.textureScratchImage[i], 0); - - R_CheckFBO(tr.textureScratchFbo[i]); - } - - { - tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height); - FBO_Bind(tr.calcLevelsFbo); - - //FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.calcLevelsImage, 0); - - R_CheckFBO(tr.calcLevelsFbo); - } - - { - tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height); - FBO_Bind(tr.targetLevelsFbo); - - //FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.targetLevelsImage, 0); - - R_CheckFBO(tr.targetLevelsFbo); - } - - { - //tr.screenScratchFbo = FBO_Create("_screenscratch", width, height); - tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height); - FBO_Bind(tr.screenScratchFbo); - - //FBO_CreateBuffer(tr.screenScratchFbo, format, 0, 0); - FBO_AttachTextureImage(tr.screenScratchImage, 0); - - // FIXME: hack: share zbuffer between render fbo and pre-screen fbo - //FBO_CreateBuffer(tr.screenScratchFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - - R_CheckFBO(tr.screenScratchFbo); - } - - for (i = 0; i < 2; i++) - { - tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); - FBO_Bind(tr.quarterFbo[i]); - - //FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.quarterImage[i], 0); - - R_CheckFBO(tr.quarterFbo[i]); - } - - { - tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height); - FBO_Bind(tr.screenShadowFbo); - - FBO_AttachTextureImage(tr.screenShadowImage, 0); - - R_CheckFBO(tr.screenShadowFbo); - } - - GL_CheckErrors(); - - FBO_Bind(NULL); -} - -/* -============ -FBO_Shutdown -============ -*/ -void FBO_Shutdown(void) -{ - int i, j; - FBO_t *fbo; - - ri.Printf(PRINT_ALL, "------- FBO_Shutdown -------\n"); - - if(!glRefConfig.framebufferObject) - return; - - FBO_Bind(NULL); - - for(i = 0; i < tr.numFBOs; i++) - { - fbo = tr.fbos[i]; - - for(j = 0; j < glRefConfig.maxColorAttachments; j++) - { - if(fbo->colorBuffers[j]) - qglDeleteRenderbuffersEXT(1, &fbo->colorBuffers[j]); - } - - if(fbo->depthBuffer) - qglDeleteRenderbuffersEXT(1, &fbo->depthBuffer); - - if(fbo->stencilBuffer) - qglDeleteRenderbuffersEXT(1, &fbo->stencilBuffer); - - if(fbo->frameBuffer) - qglDeleteFramebuffersEXT(1, &fbo->frameBuffer); - } -} - -/* -============ -R_FBOList_f -============ -*/ -void R_FBOList_f(void) -{ - int i; - FBO_t *fbo; - - if(!glRefConfig.framebufferObject) - { - ri.Printf(PRINT_ALL, "GL_EXT_framebuffer_object is not available.\n"); - return; - } - - ri.Printf(PRINT_ALL, " size name\n"); - ri.Printf(PRINT_ALL, "----------------------------------------------------------\n"); - - for(i = 0; i < tr.numFBOs; i++) - { - fbo = tr.fbos[i]; - - ri.Printf(PRINT_ALL, " %4i: %4i %4i %s\n", i, fbo->width, fbo->height, fbo->name); - } - - ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs); -} - -// FIXME -extern void RB_SetGL2D (void); - -void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, vec4i_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) -{ - vec4i_t dstBox, srcBox; - vec2_t srcTexScale; - vec4_t color; - vec4_t quadVerts[4]; - vec2_t texCoords[4]; - vec2_t invTexRes; - - if (!src) - return; - - if (inSrcBox) - { - VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]); - } - else - { - VectorSet4(srcBox, 0, 0, src->width, src->height); - } - - // framebuffers are 0 bottom, Y up. - if (inDstBox) - { - if (dst) - { - dstBox[0] = inDstBox[0]; - dstBox[1] = dst->height - inDstBox[1] - inDstBox[3]; - dstBox[2] = inDstBox[0] + inDstBox[2]; - dstBox[3] = dst->height - inDstBox[1]; - } - else - { - dstBox[0] = inDstBox[0]; - dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3]; - dstBox[2] = inDstBox[0] + inDstBox[2]; - dstBox[3] = glConfig.vidHeight - inDstBox[1]; - } - } - else if (dst) - { - VectorSet4(dstBox, 0, dst->height, dst->width, 0); - } - else - { - VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0); - } - - if (inSrcTexScale) - { - VectorCopy2(inSrcTexScale, srcTexScale); - } - else - { - srcTexScale[0] = srcTexScale[1] = 1.0f; - } - - if (inColor) - { - VectorCopy4(inColor, color); - } - else - { - color[0] = color[1] = color[2] = color[3] = 1.0f; - } - - if (!shaderProgram) - { - shaderProgram = &tr.textureColorShader; - } - - FBO_Bind(dst); - - RB_SetGL2D(); - - GL_SelectTexture(TB_COLORMAP); - - GL_Bind(src); - - VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1); - VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1); - VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1); - VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1); - - texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height; - texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height; - texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height; - texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height; - - invTexRes[0] = 1.0f / src->width * srcTexScale[0]; - invTexRes[1] = 1.0f / src->height * srcTexScale[1]; - - GL_State( blend ); - - GLSL_BindProgram(shaderProgram); - - GLSL_SetUniformMatrix16(shaderProgram, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - GLSL_SetUniformVec4(shaderProgram, TEXTURECOLOR_UNIFORM_COLOR, color); - GLSL_SetUniformVec2(shaderProgram, TEXTURECOLOR_UNIFORM_INVTEXRES, invTexRes); - GLSL_SetUniformVec2(shaderProgram, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, tr.autoExposureMinMax); - - RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); -} - -void FBO_Blit(FBO_t *src, vec4i_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend) -{ - vec4i_t srcBox; - - if (!src) - return; - - // framebuffers are 0 bottom, Y up. - if (inSrcBox) - { - srcBox[0] = inSrcBox[0]; - srcBox[1] = src->height - inSrcBox[1] - inSrcBox[3]; - srcBox[2] = inSrcBox[2]; - srcBox[3] = inSrcBox[3]; - } - else - { - VectorSet4(srcBox, 0, src->height, src->width, -src->height); - } - - FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE); -} - -void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter) -{ - vec4i_t srcBoxFinal, dstBoxFinal; - GLuint srcFb, dstFb; - - if (!glRefConfig.framebufferBlit) - { - FBO_Blit(src, srcBox, NULL, dst, dstBox, NULL, NULL, 0); - return; - } - - // get to a neutral state first - FBO_Bind(NULL); - - srcFb = src ? src->frameBuffer : 0; - dstFb = dst ? dst->frameBuffer : 0; - - if (!srcBox) - { - if (src) - { - VectorSet4(srcBoxFinal, 0, 0, src->width, src->height); - } - else - { - VectorSet4(srcBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight); - } - } - else - { - VectorSet4(srcBoxFinal, srcBox[0], srcBox[1], srcBox[0] + srcBox[2], srcBox[1] + srcBox[3]); - } - - if (!dstBox) - { - if (dst) - { - VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height); - } - else - { - VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight); - } - } - else - { - VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]); - } - - qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb); - qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb); - qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3], - dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3], - buffers, filter); - - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glState.currentFBO = NULL; -} \ No newline at end of file diff --git a/code/renderergl2/tr_fbo.h b/code/renderergl2/tr_fbo.h deleted file mode 100644 index 0257398f..00000000 --- a/code/renderergl2/tr_fbo.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2010 James Canete (use.less01@gmail.com) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_fbo.h - -#ifndef __TR_FBO_H__ -#define __TR_FBO_H__ - -struct image_s; -struct shaderProgram_s; - -typedef struct FBO_s -{ - char name[MAX_QPATH]; - - int index; - - uint32_t frameBuffer; - - uint32_t colorBuffers[16]; - int colorFormat; - struct image_s *colorImage[16]; - - uint32_t depthBuffer; - int depthFormat; - - uint32_t stencilBuffer; - int stencilFormat; - - uint32_t packedDepthStencilBuffer; - int packedDepthStencilFormat; - - int width; - int height; -} FBO_t; - -void FBO_Bind(FBO_t *fbo); -void FBO_Init(void); -void FBO_Shutdown(void); - -void FBO_BlitFromTexture(struct image_s *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend); -void FBO_Blit(FBO_t *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend); -void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter); - - -#endif diff --git a/code/renderergl2/tr_flares.c b/code/renderergl2/tr_flares.c deleted file mode 100644 index 8e6c321f..00000000 --- a/code/renderergl2/tr_flares.c +++ /dev/null @@ -1,532 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_flares.c - -#include "tr_local.h" - -/* -============================================================================= - -LIGHT FLARES - -A light flare is an effect that takes place inside the eye when bright light -sources are visible. The size of the flare reletive to the screen is nearly -constant, irrespective of distance, but the intensity should be proportional to the -projected area of the light source. - -A surface that has been flagged as having a light flare will calculate the depth -buffer value that its midpoint should have when the surface is added. - -After all opaque surfaces have been rendered, the depth buffer is read back for -each flare in view. If the point has not been obscured by a closer surface, the -flare should be drawn. - -Surfaces that have a repeated texture should never be flagged as flaring, because -there will only be a single flare added at the midpoint of the polygon. - -To prevent abrupt popping, the intensity of the flare is interpolated up and -down as it changes visibility. This involves scene to scene state, unlike almost -all other aspects of the renderer, and is complicated by the fact that a single -frame may have multiple scenes. - -RB_RenderFlares() will be called once per view (twice in a mirrored scene, potentially -up to five or more times in a frame with 3D status bar icons). - -============================================================================= -*/ - - -// flare states maintain visibility over multiple frames for fading -// layers: view, mirror, menu -typedef struct flare_s { - struct flare_s *next; // for active chain - - int addedFrame; - - qboolean inPortal; // true if in a portal view of the scene - int frameSceneNum; - void *surface; - int fogNum; - - int fadeTime; - - qboolean visible; // state of last test - float drawIntensity; // may be non 0 even if !visible due to fading - - int windowX, windowY; - float eyeZ; - - vec3_t origin; - vec3_t color; -} flare_t; - -#define MAX_FLARES 128 - -flare_t r_flareStructs[MAX_FLARES]; -flare_t *r_activeFlares, *r_inactiveFlares; - -int flareCoeff; - -/* -================== -R_ClearFlares -================== -*/ -void R_ClearFlares( void ) { - int i; - - Com_Memset( r_flareStructs, 0, sizeof( r_flareStructs ) ); - r_activeFlares = NULL; - r_inactiveFlares = NULL; - - for ( i = 0 ; i < MAX_FLARES ; i++ ) { - r_flareStructs[i].next = r_inactiveFlares; - r_inactiveFlares = &r_flareStructs[i]; - } -} - - -/* -================== -RB_AddFlare - -This is called at surface tesselation time -================== -*/ -void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) { - int i; - flare_t *f; - vec3_t local; - float d = 1; - vec4_t eye, clip, normalized, window; - - backEnd.pc.c_flareAdds++; - - if(normal && (normal[0] || normal[1] || normal[2])) - { - VectorSubtract( backEnd.viewParms.or.origin, point, local ); - VectorNormalizeFast(local); - d = DotProduct(local, normal); - - // If the viewer is behind the flare don't add it. - if(d < 0) - return; - } - - // if the point is off the screen, don't bother adding it - // calculate screen coordinates and depth - R_TransformModelToClip( point, backEnd.or.modelMatrix, - backEnd.viewParms.projectionMatrix, eye, clip ); - - // check to see if the point is completely off screen - for ( i = 0 ; i < 3 ; i++ ) { - if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) { - return; - } - } - - R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window ); - - if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth - || window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) { - return; // shouldn't happen, since we check the clip[] above, except for FP rounding - } - - // see if a flare with a matching surface, scene, and view exists - for ( f = r_activeFlares ; f ; f = f->next ) { - if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum - && f->inPortal == backEnd.viewParms.isPortal ) { - break; - } - } - - // allocate a new one - if (!f ) { - if ( !r_inactiveFlares ) { - // the list is completely full - return; - } - f = r_inactiveFlares; - r_inactiveFlares = r_inactiveFlares->next; - f->next = r_activeFlares; - r_activeFlares = f; - - f->surface = surface; - f->frameSceneNum = backEnd.viewParms.frameSceneNum; - f->inPortal = backEnd.viewParms.isPortal; - f->addedFrame = -1; - } - - if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) { - f->visible = qfalse; - f->fadeTime = backEnd.refdef.time - 2000; - } - - f->addedFrame = backEnd.viewParms.frameCount; - f->fogNum = fogNum; - - VectorCopy(point, f->origin); - VectorCopy( color, f->color ); - - // fade the intensity of the flare down as the - // light surface turns away from the viewer - VectorScale( f->color, d, f->color ); - - // save info needed to test - f->windowX = backEnd.viewParms.viewportX + window[0]; - f->windowY = backEnd.viewParms.viewportY + window[1]; - - f->eyeZ = eye[2]; -} - -/* -================== -RB_AddDlightFlares -================== -*/ -void RB_AddDlightFlares( void ) { - dlight_t *l; - int i, j, k; - fog_t *fog = NULL; - - if ( !r_flares->integer ) { - return; - } - - l = backEnd.refdef.dlights; - - if(tr.world) - fog = tr.world->fogs; - - for (i=0 ; inumfogs ; j++ ) { - fog = &tr.world->fogs[j]; - for ( k = 0 ; k < 3 ; k++ ) { - if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { - break; - } - } - if ( k == 3 ) { - break; - } - } - if ( j == tr.world->numfogs ) { - j = 0; - } - } - else - j = 0; - - RB_AddFlare( (void *)l, j, l->origin, l->color, NULL ); - } -} - -/* -=============================================================================== - -FLARE BACK END - -=============================================================================== -*/ - -/* -================== -RB_TestFlare -================== -*/ -void RB_TestFlare( flare_t *f ) { - float depth; - qboolean visible; - float fade; - float screenZ; - - backEnd.pc.c_flareTests++; - - // doing a readpixels is as good as doing a glFinish(), so - // don't bother with another sync - glState.finishCalled = qfalse; - - // read back the z buffer contents - qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth ); - - screenZ = backEnd.viewParms.projectionMatrix[14] / - ( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] ); - - visible = ( -f->eyeZ - -screenZ ) < 24; - - if ( visible ) { - if ( !f->visible ) { - f->visible = qtrue; - f->fadeTime = backEnd.refdef.time - 1; - } - fade = ( ( backEnd.refdef.time - f->fadeTime ) /1000.0f ) * r_flareFade->value; - } else { - if ( f->visible ) { - f->visible = qfalse; - f->fadeTime = backEnd.refdef.time - 1; - } - fade = 1.0f - ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value; - } - - if ( fade < 0 ) { - fade = 0; - } - if ( fade > 1 ) { - fade = 1; - } - - f->drawIntensity = fade; -} - - -/* -================== -RB_RenderFlare -================== -*/ -void RB_RenderFlare( flare_t *f ) { - float size; - vec3_t color; - int iColor[3]; - float distance, intensity, factor; - byte fogFactors[3] = {255, 255, 255}; - - backEnd.pc.c_flareRenders++; - - // We don't want too big values anyways when dividing by distance. - if(f->eyeZ > -1.0f) - distance = 1.0f; - else - distance = -f->eyeZ; - - // calculate the flare size.. - size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance ); - -/* - * This is an alternative to intensity scaling. It changes the size of the flare on screen instead - * with growing distance. See in the description at the top why this is not the way to go. - // size will change ~ 1/r. - size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f)); -*/ - -/* - * As flare sizes stay nearly constant with increasing distance we must decrease the intensity - * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be - * got by considering the ratio of - * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare) - * An important requirement is: - * intensity <= 1 for all distances. - * - * The formula used here to compute the intensity is as follows: - * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2 - * As you can see, the intensity will have a max. of 1 when the distance is 0. - * The coefficient flareCoeff will determine the falloff speed with increasing distance. - */ - - factor = distance + size * sqrt(flareCoeff); - - intensity = flareCoeff * size * size / (factor * factor); - - VectorScale(f->color, f->drawIntensity * intensity, color); - -// Calculations for fogging - if(tr.world && f->fogNum < tr.world->numfogs) - { - tess.numVertexes = 1; - VectorCopy(f->origin, tess.xyz[0]); - tess.fogNum = f->fogNum; - - RB_CalcModulateColorsByFog(fogFactors); - - // We don't need to render the flare if colors are 0 anyways. - if(!(fogFactors[0] || fogFactors[1] || fogFactors[2])) - return; - } - - iColor[0] = color[0] * fogFactors[0]; - iColor[1] = color[1] * fogFactors[1]; - iColor[2] = color[2] * fogFactors[2]; - - RB_BeginSurface( tr.flareShader, f->fogNum ); - - // FIXME: use quadstamp? - tess.xyz[tess.numVertexes][0] = f->windowX - size; - tess.xyz[tess.numVertexes][1] = f->windowY - size; - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f; - tess.vertexColors[tess.numVertexes][3] = 1.0f; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = f->windowX - size; - tess.xyz[tess.numVertexes][1] = f->windowY + size; - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f; - tess.vertexColors[tess.numVertexes][3] = 1.0f; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = f->windowX + size; - tess.xyz[tess.numVertexes][1] = f->windowY + size; - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f; - tess.vertexColors[tess.numVertexes][3] = 1.0f; - tess.numVertexes++; - - tess.xyz[tess.numVertexes][0] = f->windowX + size; - tess.xyz[tess.numVertexes][1] = f->windowY - size; - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f; - tess.vertexColors[tess.numVertexes][3] = 1.0f; - 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(); -} - -/* -================== -RB_RenderFlares - -Because flares are simulating an occular effect, they should be drawn after -everything (all views) in the entire frame has been drawn. - -Because of the way portals use the depth buffer to mark off areas, the -needed information would be lost after each view, so we are forced to draw -flares after each view. - -The resulting artifact is that flares in mirrors or portals don't dim properly -when occluded by something in the main view, and portal flares that should -extend past the portal edge will be overwritten. -================== -*/ -void RB_RenderFlares (void) { - flare_t *f; - flare_t **prev; - qboolean draw; - matrix_t oldmodelview, oldprojection, matrix; - - if ( !r_flares->integer ) { - return; - } - - if(r_flareCoeff->modified) - { - if(r_flareCoeff->value == 0.0f) - flareCoeff = atof(FLARE_STDCOEFF); - else - flareCoeff = r_flareCoeff->value; - - r_flareCoeff->modified = qfalse; - } - - // Reset currentEntity to world so that any previously referenced entities - // don't have influence on the rendering of these flares (i.e. RF_ renderer flags). - backEnd.currentEntity = &tr.worldEntity; - backEnd.or = backEnd.viewParms.world; - -// RB_AddDlightFlares(); - - // perform z buffer readback on each flare in this view - draw = qfalse; - prev = &r_activeFlares; - while ( ( f = *prev ) != NULL ) { - // throw out any flares that weren't added last frame - if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) { - *prev = f->next; - f->next = r_inactiveFlares; - r_inactiveFlares = f; - continue; - } - - // don't draw any here that aren't from this scene / portal - f->drawIntensity = 0; - if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum - && f->inPortal == backEnd.viewParms.isPortal ) { - RB_TestFlare( f ); - if ( f->drawIntensity ) { - draw = qtrue; - } else { - // this flare has completely faded out, so remove it from the chain - *prev = f->next; - f->next = r_inactiveFlares; - r_inactiveFlares = f; - continue; - } - } - - prev = &f->next; - } - - if ( !draw ) { - return; // none visible - } - - if ( backEnd.viewParms.isPortal ) { - qglDisable (GL_CLIP_PLANE0); - } - - Matrix16Copy(glState.projection, oldprojection); - Matrix16Copy(glState.modelview, oldmodelview); - Matrix16Identity(matrix); - GL_SetModelviewMatrix(matrix); - Matrix16Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, - backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, - -99999, 99999, matrix ); - GL_SetProjectionMatrix(matrix); - - for ( f = r_activeFlares ; f ; f = f->next ) { - if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum - && f->inPortal == backEnd.viewParms.isPortal - && f->drawIntensity ) { - RB_RenderFlare( f ); - } - } - - GL_SetProjectionMatrix(oldprojection); - GL_SetModelviewMatrix(oldmodelview); -} - - - - - diff --git a/code/renderergl2/tr_font.c b/code/renderergl2/tr_font.c deleted file mode 100644 index 5a3673a4..00000000 --- a/code/renderergl2/tr_font.c +++ /dev/null @@ -1,552 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_font.c -// -// -// The font system uses FreeType 2.x to render TrueType fonts for use within the game. -// As of this writing ( Nov, 2000 ) Team Arena uses these fonts for all of the ui and -// about 90% of the cgame presentation. A few areas of the CGAME were left uses the old -// fonts since the code is shared with standard Q3A. -// -// If you include this font rendering code in a commercial product you MUST include the -// following somewhere with your product, see www.freetype.org for specifics or changes. -// The Freetype code also uses some hinting techniques that MIGHT infringe on patents -// held by apple so be aware of that also. -// -// As of Q3A 1.25+ and Team Arena, we are shipping the game with the font rendering code -// disabled. This removes any potential patent issues and it keeps us from having to -// distribute an actual TrueTrype font which is 1. expensive to do and 2. seems to require -// an act of god to accomplish. -// -// What we did was pre-render the fonts using FreeType ( which is why we leave the FreeType -// credit in the credits ) and then saved off the glyph data and then hand touched up the -// font bitmaps so they scale a bit better in GL. -// -// There are limitations in the way fonts are saved and reloaded in that it is based on -// point size and not name. So if you pre-render Helvetica in 18 point and Impact in 18 point -// you will end up with a single 18 point data file and image set. Typically you will want to -// choose 3 sizes to best approximate the scaling you will be doing in the ui scripting system -// -// In the UI Scripting code, a scale of 1.0 is equal to a 48 point font. In Team Arena, we -// use three or four scales, most of them exactly equaling the specific rendered size. We -// rendered three sizes in Team Arena, 12, 16, and 20. -// -// To generate new font data you need to go through the following steps. -// 1. delete the fontImage_x_xx.tga files and fontImage_xx.dat files from the fonts path. -// 2. in a ui script, specificy a font, smallFont, and bigFont keyword with font name and -// point size. the original TrueType fonts must exist in fonts at this point. -// 3. run the game, you should see things normally. -// 4. Exit the game and there will be three dat files and at least three tga files. The -// tga's are in 256x256 pages so if it takes three images to render a 24 point font you -// will end up with fontImage_0_24.tga through fontImage_2_24.tga -// 5. In future runs of the game, the system looks for these images and data files when a s -// specific point sized font is rendered and loads them for use. -// 6. Because of the original beta nature of the FreeType code you will probably want to hand -// touch the font bitmaps. -// -// Currently a define in the project turns on or off the FreeType code which is currently -// defined out. To pre-render new fonts you need enable the define ( BUILD_FREETYPE ) and -// uncheck the exclude from build check box in the FreeType2 area of the Renderer project. - - -#include "tr_local.h" -#include "../qcommon/qcommon.h" - -#ifdef BUILD_FREETYPE -#include -#include FT_ERRORS_H -#include FT_SYSTEM_H -#include FT_IMAGE_H -#include FT_FREETYPE_H -#include FT_OUTLINE_H - -#define _FLOOR(x) ((x) & -64) -#define _CEIL(x) (((x)+63) & -64) -#define _TRUNC(x) ((x) >> 6) - -FT_Library ftLibrary = NULL; -#endif - -#define MAX_FONTS 6 -static int registeredFontCount = 0; -static fontInfo_t registeredFont[MAX_FONTS]; - -#ifdef BUILD_FREETYPE -void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) { - *left = _FLOOR( glyph->metrics.horiBearingX ); - *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); - *width = _TRUNC(*right - *left); - - *top = _CEIL( glyph->metrics.horiBearingY ); - *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); - *height = _TRUNC( *top - *bottom ); - *pitch = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 ); -} - - -FT_Bitmap *R_RenderGlyph(FT_GlyphSlot glyph, glyphInfo_t* glyphOut) { - FT_Bitmap *bit2; - int left, right, width, top, bottom, height, pitch, size; - - R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch); - - if ( glyph->format == ft_glyph_format_outline ) { - size = pitch*height; - - bit2 = ri.Malloc(sizeof(FT_Bitmap)); - - bit2->width = width; - bit2->rows = height; - bit2->pitch = pitch; - bit2->pixel_mode = ft_pixel_mode_grays; - //bit2->pixel_mode = ft_pixel_mode_mono; - bit2->buffer = ri.Malloc(pitch*height); - bit2->num_grays = 256; - - Com_Memset( bit2->buffer, 0, size ); - - FT_Outline_Translate( &glyph->outline, -left, -bottom ); - - FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 ); - - glyphOut->height = height; - glyphOut->pitch = pitch; - glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1; - glyphOut->bottom = bottom; - - return bit2; - } else { - ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n"); - } - return NULL; -} - -void WriteTGA (char *filename, byte *data, int width, int height) { - byte *buffer; - int i, c; - int row; - unsigned char *flip; - unsigned char *src, *dst; - - buffer = ri.Malloc(width*height*4 + 18); - Com_Memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type - buffer[12] = width&255; - buffer[13] = width>>8; - buffer[14] = height&255; - buffer[15] = height>>8; - buffer[16] = 32; // pixel size - - // swap rgb to bgr - c = 18 + width * height * 4; - for (i=18 ; iglyph, &glyph); - if (bitmap) { - glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1; - } else { - return &glyph; - } - - if (glyph.height > *maxHeight) { - *maxHeight = glyph.height; - } - - if (calcHeight) { - ri.Free(bitmap->buffer); - ri.Free(bitmap); - return &glyph; - } - -/* - // need to convert to power of 2 sizes so we do not get - // any scaling from the gl upload - for (scaled_width = 1 ; scaled_width < glyph.pitch ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < glyph.height ; scaled_height<<=1) - ; -*/ - - scaled_width = glyph.pitch; - scaled_height = glyph.height; - - // we need to make sure we fit - if (*xOut + scaled_width + 1 >= 255) { - *xOut = 0; - *yOut += *maxHeight + 1; - } - - if (*yOut + *maxHeight + 1 >= 255) { - *yOut = -1; - *xOut = -1; - ri.Free(bitmap->buffer); - ri.Free(bitmap); - return &glyph; - } - - - src = bitmap->buffer; - dst = imageOut + (*yOut * 256) + *xOut; - - if (bitmap->pixel_mode == ft_pixel_mode_mono) { - for (i = 0; i < glyph.height; i++) { - int j; - unsigned char *_src = src; - unsigned char *_dst = dst; - unsigned char mask = 0x80; - unsigned char val = *_src; - for (j = 0; j < glyph.pitch; j++) { - if (mask == 0x80) { - val = *_src++; - } - if (val & mask) { - *_dst = 0xff; - } - mask >>= 1; - - if ( mask == 0 ) { - mask = 0x80; - } - _dst++; - } - - src += glyph.pitch; - dst += 256; - } - } else { - for (i = 0; i < glyph.height; i++) { - Com_Memcpy(dst, src, glyph.pitch); - src += glyph.pitch; - dst += 256; - } - } - - // we now have an 8 bit per pixel grey scale bitmap - // that is width wide and pf->ftSize->metrics.y_ppem tall - - glyph.imageHeight = scaled_height; - glyph.imageWidth = scaled_width; - glyph.s = (float)*xOut / 256; - glyph.t = (float)*yOut / 256; - glyph.s2 = glyph.s + (float)scaled_width / 256; - glyph.t2 = glyph.t + (float)scaled_height / 256; - - *xOut += scaled_width + 1; - } - - ri.Free(bitmap->buffer); - ri.Free(bitmap); - - return &glyph; -} -#endif - -static int fdOffset; -static byte *fdFile; - -int readInt( void ) { - int i = fdFile[fdOffset]+(fdFile[fdOffset+1]<<8)+(fdFile[fdOffset+2]<<16)+(fdFile[fdOffset+3]<<24); - fdOffset += 4; - return i; -} - -typedef union { - byte fred[4]; - float ffred; -} poor; - -float readFloat( void ) { - poor me; -#if defined Q3_BIG_ENDIAN - me.fred[0] = fdFile[fdOffset+3]; - me.fred[1] = fdFile[fdOffset+2]; - me.fred[2] = fdFile[fdOffset+1]; - me.fred[3] = fdFile[fdOffset+0]; -#elif defined Q3_LITTLE_ENDIAN - me.fred[0] = fdFile[fdOffset+0]; - me.fred[1] = fdFile[fdOffset+1]; - me.fred[2] = fdFile[fdOffset+2]; - me.fred[3] = fdFile[fdOffset+3]; -#endif - fdOffset += 4; - return me.ffred; -} - -void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { -#ifdef BUILD_FREETYPE - FT_Face face; - int j, k, xOut, yOut, lastStart, imageNumber; - int scaledSize, newSize, maxHeight, left; - unsigned char *out, *imageBuff; - glyphInfo_t *glyph; - image_t *image; - qhandle_t h; - float max; -#endif - void *faceData; - int i, len; - char name[1024]; - float dpi = 72; // - float glyphScale = 72.0f / dpi; // change the scale to be relative to 1 based on 72 dpi ( so dpi of 144 means a scale of .5 ) - - - if (!fontName) { - ri.Printf(PRINT_ALL, "RE_RegisterFont: called with empty name\n"); - return; - } - - if (pointSize <= 0) { - pointSize = 12; - } - // we also need to adjust the scale based on point size relative to 48 points as the ui scaling is based on a 48 point font - glyphScale *= 48.0f / pointSize; - - // make sure the render thread is stopped - R_SyncRenderThread(); - - if (registeredFontCount >= MAX_FONTS) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: Too many fonts registered already.\n"); - return; - } - - Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize); - for (i = 0; i < registeredFontCount; i++) { - if (Q_stricmp(name, registeredFont[i].name) == 0) { - Com_Memcpy(font, ®isteredFont[i], sizeof(fontInfo_t)); - return; - } - } - - len = ri.FS_ReadFile(name, NULL); - if (len == sizeof(fontInfo_t)) { - ri.FS_ReadFile(name, &faceData); - fdOffset = 0; - fdFile = faceData; - for(i=0; iglyphs[i].height = readInt(); - font->glyphs[i].top = readInt(); - font->glyphs[i].bottom = readInt(); - font->glyphs[i].pitch = readInt(); - font->glyphs[i].xSkip = readInt(); - font->glyphs[i].imageWidth = readInt(); - font->glyphs[i].imageHeight = readInt(); - font->glyphs[i].s = readFloat(); - font->glyphs[i].t = readFloat(); - font->glyphs[i].s2 = readFloat(); - font->glyphs[i].t2 = readFloat(); - font->glyphs[i].glyph = readInt(); - Q_strncpyz(font->glyphs[i].shaderName, (const char *)&fdFile[fdOffset], sizeof(font->glyphs[i].shaderName)); - fdOffset += sizeof(font->glyphs[i].shaderName); - } - font->glyphScale = readFloat(); - Com_Memcpy(font->name, &fdFile[fdOffset], MAX_QPATH); - -// Com_Memcpy(font, faceData, sizeof(fontInfo_t)); - Q_strncpyz(font->name, name, sizeof(font->name)); - for (i = GLYPH_START; i < GLYPH_END; i++) { - font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName); - } - Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); - return; - } - -#ifndef BUILD_FREETYPE - ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType code not available\n"); -#else - if (ftLibrary == NULL) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType not initialized.\n"); - return; - } - - len = ri.FS_ReadFile(fontName, &faceData); - if (len <= 0) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: Unable to read font file '%s'\n", fontName); - return; - } - - // allocate on the stack first in case we fail - if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType, unable to allocate new face.\n"); - return; - } - - - if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType, unable to set face char size.\n"); - return; - } - - //*font = ®isteredFonts[registeredFontCount++]; - - // make a 256x256 image buffer, once it is full, register it, clean it and keep going - // until all glyphs are rendered - - out = ri.Malloc(1024*1024); - if (out == NULL) { - ri.Printf(PRINT_WARNING, "RE_RegisterFont: ri.Malloc failure during output image creation.\n"); - return; - } - Com_Memset(out, 0, 1024*1024); - - maxHeight = 0; - - for (i = GLYPH_START; i < GLYPH_END; i++) { - glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue); - } - - xOut = 0; - yOut = 0; - i = GLYPH_START; - lastStart = i; - imageNumber = 0; - - while ( i <= GLYPH_END ) { - - glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); - - if (xOut == -1 || yOut == -1 || i == GLYPH_END) { - // ran out of room - // we need to create an image from the bitmap, set all the handles in the glyphs to this point - // - - scaledSize = 256*256; - newSize = scaledSize * 4; - imageBuff = ri.Malloc(newSize); - left = 0; - max = 0; - for ( k = 0; k < (scaledSize) ; k++ ) { - if (max < out[k]) { - max = out[k]; - } - } - - if (max > 0) { - max = 255/max; - } - - for ( k = 0; k < (scaledSize) ; k++ ) { - imageBuff[left++] = 255; - imageBuff[left++] = 255; - imageBuff[left++] = 255; - - imageBuff[left++] = ((float)out[k] * max); - } - - Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i.tga", imageNumber++, pointSize); - if (r_saveFontData->integer) { - WriteTGA(name, imageBuff, 256, 256); - } - - //Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize); - image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP_TO_EDGE); - h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse); - for (j = lastStart; j < i; j++) { - font->glyphs[j].glyph = h; - Q_strncpyz(font->glyphs[j].shaderName, name, sizeof(font->glyphs[j].shaderName)); - } - lastStart = i; - Com_Memset(out, 0, 1024*1024); - xOut = 0; - yOut = 0; - ri.Free(imageBuff); - i++; - } else { - Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t)); - i++; - } - } - - registeredFont[registeredFontCount].glyphScale = glyphScale; - font->glyphScale = glyphScale; - Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); - - if (r_saveFontData->integer) { - ri.FS_WriteFile(va("fonts/fontImage_%i.dat", pointSize), font, sizeof(fontInfo_t)); - } - - ri.Free(out); - - ri.FS_FreeFile(faceData); -#endif -} - - - -void R_InitFreeType(void) { -#ifdef BUILD_FREETYPE - if (FT_Init_FreeType( &ftLibrary )) { - ri.Printf(PRINT_WARNING, "R_InitFreeType: Unable to initialize FreeType.\n"); - } -#endif - registeredFontCount = 0; -} - - -void R_DoneFreeType(void) { -#ifdef BUILD_FREETYPE - if (ftLibrary) { - FT_Done_FreeType( ftLibrary ); - ftLibrary = NULL; - } -#endif - registeredFontCount = 0; -} - diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c deleted file mode 100644 index 85fa9b06..00000000 --- a/code/renderergl2/tr_glsl.c +++ /dev/null @@ -1,2674 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006-2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_glsl.c -#include "tr_local.h" - -void GLSL_BindNullProgram(void); - -// FIXME: Do something that isn't this messy -static const char *fallbackGenericShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut" -"e vec4 attr_TexCoord1;\r\nattribute vec3 attr_Normal;\r\nattribute vec4 att" -"r_Color;\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute vec4 attr_Po" -"sition2;\r\nattribute vec3 attr_Normal2;\r\n#endif\r\n\r\nuniform mat4 u_" -"DiffuseTexMatrix;\r\nuniform vec3 u_ViewOrigin;\r\n\r\n#if defined(USE_TC" -"GEN)\r\nuniform int u_TCGen0;\r\nuniform vec3 u_TCGen0Vector0;\r\nunif" -"orm vec3 u_TCGen0Vector1;\r\n#endif\r\n\r\n#if defined(USE_FOG)\r\nunifor" -"m vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nuniform float u_F" -"ogEyeT;\r\nuniform vec4 u_FogColorMask;\r\n#endif\r\n\r\n#if defined(USE_" -"DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nuniform float u_DeformP" -"arams[5];\r\n#endif\r\n\r\nuniform float u_Time;\r\n\r\nuniform mat4 u_M" -"odelViewProjectionMatrix;\r\nuniform vec4 u_BaseColor;\r\nuniform vec4 " -"u_VertColor;\r\n\r\n#if defined(USE_RGBAGEN)\r\nuniform int u_ColorGen;" -"\r\nuniform int u_AlphaGen;\r\nuniform vec3 u_AmbientLight;\r\nuniform" -" vec3 u_DirectedLight;\r\nuniform vec4 u_LightOrigin;\r\nuniform float " -" u_PortalRange;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nunifo" -"rm float u_VertexLerp;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n" -"#if defined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvary" -"ing vec4 var_Color;\r\n\r\nvec2 DoTexMatrix(vec2 st, vec3 position, mat4 " -"texMatrix)\r\n{\r\n\tfloat amplitude = texMatrix[3][0];\r\n\tfloat phase = " -"texMatrix[3][1];\r\n\tvec2 st2 = (texMatrix * vec4(st, 1.0, 0.0)).st;\r\n\r" -"\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x += offsetPos.z" -";\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);" -"\r\n\t\r\n\treturn st2 + texOffset * amplitude;\r\n}\r\n\r\n#if defined(USE" -"_DEFORM_VERTEXES)\r\nfloat triangle(float x)\r\n{\r\n\treturn max(1.0 - abs" -"(x), 0);\r\n}\r\n\r\nfloat sawtooth(float x)\r\n{\r\n\treturn x - floor(x);" -"\r\n}\r\n\r\nvec4 DeformPosition(const vec4 pos, const vec3 normal, const v" -"ec2 st)\r\n{\r\n\tfloat base = u_DeformParams[0];\r\n\tfloat amplitude" -" = u_DeformParams[1];\r\n\tfloat phase = u_DeformParams[2];\r\n\tfloat " -"frequency = u_DeformParams[3];\r\n\tfloat spread = u_DeformParams[4];\r" -"\n\t\r\n\tif (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25" -" * st.x;\r\n\t}\r\n\telse // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)" -"\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r\n\r\n\tf" -"loat value = phase + (u_Time * frequency);\r\n\tfloat func;\r\n\r\n\tif (u_" -"DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = sin(value * 2.0 * M_PI);\r" -"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = s" -"ign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE" -"_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r\n\t}\r\n\telse if (u_Def" -"ormGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = sawtooth(value);\r\n\t}" -"\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfun" -"c = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE" -")\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\t\r\n\tvec4 deformed = pos;\r" -"\n\tdeformed.xyz += normal * (base + func * amplitude);\r\n\r\n\treturn def" -"ormed;\r\n}\r\n#endif\r\n\r\n#if defined(USE_TCGEN)\r\nvec2 GenTexCoords(in" -"t TCGen, vec4 position, vec3 normal, vec3 TCGenVector0, vec3 TCGenVector1)" -"\r\n{\r\n\tvec2 tex = attr_TexCoord0.st;\r\n\r\n\tif (TCGen == TCGEN_LIGHTM" -"AP)\r\n\t{\r\n\t\ttex = attr_TexCoord1.st;\r\n\t}\r\n\telse if (TCGen == TC" -"GEN_ENVIRONMENT_MAPPED)\r\n\t{\r\n\t\tvec3 viewer = normalize(u_ViewOrigin " -"- position.xyz);\r\n\t\tvec3 reflected = normal * 2.0 * dot(normal, viewer)" -" - viewer;\r\n\r\n\t\ttex = reflected.yz * vec2(0.5, -0.5) + 0.5;\r\n\t}\r" -"\n\telse if (TCGen == TCGEN_VECTOR)\r\n\t{\r\n\t\ttex = vec2(dot(position.x" -"yz, TCGenVector0), dot(position.xyz, TCGenVector1));\r\n\t}\r\n\t\r\n\tretu" -"rn tex;\r\n}\r\n#endif\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_VERTEX_AN" -"IMATION)\r\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLe" -"rp);\r\n\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLe" -"rp));\r\n#else\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = attr_" -"Normal;\r\n#endif\r\n\r\n#if defined(USE_DEFORM_VERTEXES)\r\n\tposition = D" -"eformPosition(position, normal, attr_TexCoord0.st);\r\n#endif\r\n\r\n\tgl_P" -"osition = u_ModelViewProjectionMatrix * position;\r\n\r\n#if defined(USE_TC" -"GEN)\r\n\tvec2 tex = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vecto" -"r0, u_TCGen0Vector1);\r\n#else\r\n\tvec2 tex = attr_TexCoord0.st;\r\n#endif" -"\r\n\tvar_DiffuseTex = DoTexMatrix(tex, position.xyz, u_DiffuseTexMatrix);" -"\r\n\r\n#if defined(USE_LIGHTMAP)\r\n\tvar_LightTex = attr_TexCoord1.st;\r" -"\n#endif\r\n\r\n\tvar_Color = u_VertColor * attr_Color + u_BaseColor;\r\n\r" -"\n#if defined(USE_RGBAGEN)\r\n\tif (u_ColorGen == CGEN_LIGHTING_DIFFUSE)\r" -"\n\t{\r\n\t\tfloat incoming = max(dot(normal, u_LightOrigin.xyz), 0.0);\r\n" -"\r\n\t\tvar_Color.rgb = min(u_DirectedLight * incoming + u_AmbientLight, 1." -"0);\r\n\t}\r\n\t\r\n\tvec3 toView = u_ViewOrigin - position.xyz;\r\n\r\n\ti" -"f (u_AlphaGen == AGEN_LIGHTING_SPECULAR)\r\n\t{\r\n\t\tvec3 lightDir = norm" -"alize(vec3(-960.0, -1980.0, 96.0) - position.xyz);\r\n\t\tvec3 viewer = nor" -"malize(toView);\r\n\t\tvec3 halfangle = normalize(lightDir + viewer);\r\n\t" -"\t\r\n\t\tvar_Color.a = pow(max(dot(normal, halfangle), 0.0), 8.0);\r\n\t}" -"\r\n\telse if (u_AlphaGen == AGEN_PORTAL)\r\n\t{\r\n\t\tfloat alpha = lengt" -"h(toView) / u_PortalRange;\r\n\r\n\t\tvar_Color.a = min(alpha, 1.0);\r\n\t}" -"\r\n\telse if (u_AlphaGen == AGEN_FRESNEL)\r\n\t{\r\n\t\tvec3 viewer = norm" -"alize(toView);\r\n\t\t\r\n\t\tvar_Color.a = 0.10 + 0.90 * pow(1.0 - dot(nor" -"mal, viewer), 5);\r\n\t}\r\n#endif\r\n\r\n#if defined (USE_FOG)\r\n\tfloat " -"s = dot(position, u_FogDistance);\r\n\tfloat t = dot(position, u_FogDepth);" -"\r\n\t\r\n\tif (t >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogEyeT, 0.0));" -"\r\n\t}\r\n\telse\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0.0);\r\n\t}" -"\r\n\t\r\n\ts = 1.0 - sqrt(clamp(s * 8.0, 0.0, 1.0));\r\n\t\r\n\tvar_Color " -"*= u_FogColorMask * s + (vec4(1.0) - u_FogColorMask);\r\n#endif\r\n}\r\n"; - -static const char *fallbackGenericShader_fp = -"uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform" -" sampler2D u_LightMap;\r\n#endif\r\n\r\nuniform int u_Texture1Env;\r" -"\n\r\nvarying vec2 var_DiffuseTex;\r\n\r\n#if defined(USE_LIGHTMAP)\r" -"\nvarying vec2 var_LightTex;\r\n#endif\r\n\r\nvarying vec4 var_Co" -"lor;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = texture2D(u_DiffuseMap," -" var_DiffuseTex);\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 color2 = texture2D" -"(u_LightMap, var_LightTex);\r\n #if defined(RGBE_LIGHTMAP)\r\n\tcolor2.rgb" -" *= exp2(color2.a * 255.0 - 128.0);\r\n\tcolor2.a = 1.0;\r\n #endif\r\n\r" -"\n\tif (u_Texture1Env == TEXENV_MODULATE)\r\n\t{\r\n\t\tcolor *= color2;\r" -"\n\t}\r\n\telse if (u_Texture1Env == TEXENV_ADD)\r\n\t{\r\n\t\tcolor += col" -"or2;\r\n\t}\r\n\telse if (u_Texture1Env == TEXENV_REPLACE)\r\n\t{\r\n\t\tco" -"lor = color2;\r\n\t}\r\n#endif\r\n\r\n\tgl_FragColor = color * var_Color;\r" -"\n}\r\n"; - -static const char *fallbackTextureColorShader_vp = -"#version 120\r\n\r\nattribute vec4 attr_Position;\r\nattribute vec4 attr_Te" -"xCoord0;\r\n\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying " -"vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelView" -"ProjectionMatrix * attr_Position;\r\n\tvar_Tex1 = attr_TexCoord0.st;\r\n}\r" -"\n"; - -static const char *fallbackTextureColorShader_fp = -"#version 120\r\n\r\nuniform sampler2D u_DiffuseMap;\r\nuniform vec4 u_" -"Color;\r\n\r\nvarying vec2 var_Tex1;\r\n\r\n\r\nvoid main()\r\n{\r" -"\n\tgl_FragColor = texture2D(u_DiffuseMap, var_Tex1) * u_Color;\r\n}\r\n"; - -static const char *fallbackFogPassShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute" -" vec4 attr_TexCoord0;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nattrib" -"ute vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n//#endif\r\n" -"\r\nuniform vec4 u_FogDistance;\r\nuniform vec4 u_FogDepth;\r\nunifor" -"m float u_FogEyeT;\r\n\r\n//#if defined(USE_DEFORM_VERTEXES)\r\nuniform i" -"nt u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n//#endif\r\n\r" -"\nuniform float u_Time;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r" -"\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLerp;" -"\r\n//#endif\r\n\r\nvarying float var_Scale;\r\n\r\n\r\nfloat triangle(fl" -"oat x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat sawtooth(fl" -"oat x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPosition(const" -" vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif (u_DeformGen == 0" -")\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = u_DeformParam" -"s[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat phase = u_De" -"formParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r\n\tfloat spread " -"= u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WAVE_INVERSE_S" -"AWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * spread;\r\n\t}\r" -"\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M_PI * 0.25 " -"* st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * frequency);\r\n\tfl" -"oat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n\t\tfunc = s" -"in(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SQUAR" -"E)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n\t}\r\n\telse if " -"(u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triangle(value);\r" -"\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r\n\t\tfunc =" -" sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_INVERSE_SAW" -"TOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n\telse if (u" -"_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n\t}\r\n\r\n\t" -"vec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base + func * amplitude" -");\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 pos" -"ition = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 normal " -"= normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));\r\n\r\n\tpositio" -"n = DeformPosition(position, normal, attr_TexCoord0.st);\r\n\r\n\tgl_Positi" -"on = u_ModelViewProjectionMatrix * position;\r\n\r\n\tfloat s = dot(positio" -"n, u_FogDistance);\r\n\tfloat t = dot(position, u_FogDepth);\r\n\r\n\tif (t" -" >= 1.0)\r\n\t{\r\n\t\ts *= t / (t - min(u_FogEyeT, 0.0));\r\n\t}\r\n\telse" -"\r\n\t{\r\n\t\ts *= max(t + sign(u_FogEyeT), 0.0);\r\n\t}\r\n\r\n\tvar_Scal" -"e = s * 8.0;\r\n}\r\n"; - -static const char *fallbackFogPassShader_fp = -"uniform vec4 u_Color;\r\n\r\nvarying float var_Scale;\r\n\r\nvoid main()\r" -"\n{\r\n\tgl_FragColor = u_Color;\r\n\tgl_FragColor.a *= sqrt(clamp(var_Scal" -"e, 0.0, 1.0));\r\n}\r\n"; - -static const char *fallbackDlightShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\nattribut" -"e vec3 attr_Normal;\r\n\r\nuniform vec4 u_DlightInfo;\r\n\r\nuniform int " -" u_DeformGen;\r\nuniform float u_DeformParams[5];\r\n\r\nuniform float " -"u_Time;\r\nuniform vec4 u_Color;\r\nuniform mat4 u_ModelViewProjectionM" -"atrix;\r\n\r\nvarying vec2 var_Tex1;\r\nvarying vec4 var_Color;\r\n\r\n" -"float triangle(float x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\n" -"float sawtooth(float x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 Def" -"ormPosition(const vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif " -"(u_DeformGen == 0)\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = " -" u_DeformParams[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat" -" phase = u_DeformParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r" -"\n\tfloat spread = u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DG" -"EN_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * " -"spread;\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase" -" *= M_PI * 0.25 * st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * fre" -"quency);\r\n\tfloat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{" -"\r\n\t\tfunc = sin(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen ==" -" DGEN_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n" -"\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = t" -"riangle(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n" -"\t{\r\n\t\tfunc = sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN" -"_WAVE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t" -"}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);" -"\r\n\t}\r\n\r\n\tvec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base +" -" func * amplitude);\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\nvoid main()\r" -"\n{\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = attr_Normal;\r\n" -"\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);\r\n\r" -"\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\t\t\r\n\tvec3" -" dist = u_DlightInfo.xyz - position.xyz;\t\r\n\r\n\tfloat diffz = abs(dist." -"z);\r\n\tfloat radius = 1.0 / u_DlightInfo.a;\r\n\r\n\tvec2 tex = vec2(0.5)" -" + dist.xy * u_DlightInfo.a;\r\n\tfloat dlightmod = max(sign(dot(dist, norm" -"al)), 0.0);\r\n\tdlightmod *= clamp(2.0 * (radius - diffz) * u_DlightInfo.a" -", 0.0, 1.0);\r\n\r\n\tvar_Tex1 = tex;\r\n\tvar_Color = u_Color;\r\n\tvar_Co" -"lor.rgb *= dlightmod;\r\n}\r\n"; - -static const char *fallbackDlightShader_fp = -"uniform sampler2D u_DiffuseMap;\r\n\r\nvarying vec2 var_Tex1;\r\nvaryi" -"ng vec4 var_Color;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 color = textu" -"re2D(u_DiffuseMap, var_Tex1);\r\n\r\n\tgl_FragColor = color * var_Color;\r" -"\n}\r\n"; - -static const char *fallbackLightallShader_vp = -"attribute vec4 attr_TexCoord0;\r\n#if defined(USE_LIGHTMAP)\r\nattribute ve" -"c4 attr_TexCoord1;\r\n#endif\r\nattribute vec4 attr_Color;\r\n\r\nattribute" -" vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\n#if defined(USE_" -"VERT_TANGENT_SPACE)\r\nattribute vec3 attr_Tangent;\r\nattribute vec3 attr_" -"Bitangent;\r\n#endif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nattribute " -"vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n #if defined(USE_V" -"ERT_TANGENT_SPACE)\r\nattribute vec3 attr_Tangent2;\r\nattribute vec3 attr_" -"Bitangent2;\r\n #endif\r\n#endif\r\n\r\n#if defined(USE_LIGHT) && !defined" -"(USE_LIGHT_VECTOR)\r\nattribute vec3 attr_LightDirection;\r\n#endif\r\n\r\n" -"#if defined(TCGEN_ENVIRONMENT) || defined(USE_NORMALMAP) || defined(USE_LIG" -"HT) && !defined(USE_FAST_LIGHT)\r\nuniform vec3 u_ViewOrigin;\r\n#endif\r" -"\n\r\nuniform mat4 u_DiffuseTexMatrix;\r\nuniform mat4 u_ModelViewProje" -"ctionMatrix;\r\nuniform vec4 u_BaseColor;\r\nuniform vec4 u_VertColor;" -"\r\n\r\n#if defined(USE_MODELMATRIX)\r\nuniform mat4 u_ModelMatrix;\r\n#e" -"ndif\r\n\r\n#if defined(USE_VERTEX_ANIMATION)\r\nuniform float u_VertexLer" -"p;\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec4 u_Light" -"Origin;\r\n #if defined(USE_FAST_LIGHT)\r\nuniform vec3 u_DirectedLight;" -"\r\nuniform vec3 u_AmbientLight;\r\nuniform float u_LightRadius;\r\n #e" -"ndif\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n\r\n#if defined(USE" -"_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\n\r\n#if defined(USE" -"_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)\r\nvarying ve" -"c3 var_SampleToView;\r\n#endif\r\n\r\nvarying vec4 var_Color;\r\nvaryin" -"g vec3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\n#if defined(USE" -"_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 var_B" -"itangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR) && defined(USE_FAS" -"T_LIGHT)\r\nvarying vec3 var_VectLight;\r\n#endif\r\n\r\n#if defined(USE_" -"LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying vec3 var_WorldLight;\r\n#end" -"if\r\n\r\nvarying vec4 var_ScreenPos;\r\n\r\nvec2 DoTexMatrix(vec2 st, ve" -"c3 position, mat4 texMatrix)\r\n{\r\n\tvec2 st2 = (texMatrix * vec4(st, 1, " -"0)).st;\r\n\r\n\tvec3 offsetPos = position.xyz / 1024.0;\r\n\toffsetPos.x +" -"= offsetPos.z;\r\n\r\n\tvec2 texOffset = sin((offsetPos.xy + vec2(texMatrix" -"[3][1])) * 2.0 * M_PI);\r\n\t\r\n\treturn st2 + texOffset * texMatrix[3][0]" -";\r\n}\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_VERTEX_ANIMATION)\r\n\tve" -"c4 position = mix(attr_Position, attr_Position2, u_VertexLerp);\r\n\tvec3 " -"normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));" -"\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\tvec3 tangent = normalize(m" -"ix(attr_Tangent, attr_Tangent2, u_VertexLerp));\r\n\tvec3 bitangent = n" -"ormalize(mix(attr_Bitangent, attr_Bitangent2, u_VertexLerp));\r\n #endif\r" -"\n#else\r\n\tvec4 position = attr_Position;\r\n\tvec3 normal = attr_Nor" -"mal;\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\tvec3 tangent = attr_Ta" -"ngent;\r\n\tvec3 bitangent = attr_Bitangent;\r\n #endif\r\n#endif\r\n\r\n" -"\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\tvar_ScreenPos " -"= gl_Position;\r\n\r\n#if (defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTE" -"X)) && !defined(USE_DELUXEMAP)\r\n\tvec3 worldLight = attr_LightDirection;" -"\r\n#endif\r\n\t\r\n#if defined(USE_MODELMATRIX)\r\n\tposition = u_ModelMa" -"trix * position;\r\n\tnormal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;" -"\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n\ttangent = (u_ModelMatrix *" -" vec4(tangent, 0.0)).xyz;\r\n\tbitangent = (u_ModelMatrix * vec4(bitangent," -" 0.0)).xyz;\r\n #endif\r\n\r\n #if defined(USE_LIGHTMAP) && !defined(USE_" -"DELUXEMAP)\r\n\tworldLight = (u_ModelMatrix * vec4(worldLight, 0.0)).xyz;\r" -"\n #endif\r\n#endif\r\n\r\n\tvar_Position = position.xyz;\r\n\r\n#if defin" -"ed(TCGEN_ENVIRONMENT) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !d" -"efined(USE_FAST_LIGHT)\r\n\tvec3 SampleToView = u_ViewOrigin - position.xyz" -";\r\n#endif\r\n\r\n#if defined(USE_NORMALMAP) || defined(USE_LIGHT) && !def" -"ined(USE_FAST_LIGHT)\r\n\tvar_SampleToView = SampleToView;\r\n#endif\r\n\r" -"\n#if defined(TCGEN_ENVIRONMENT)\r\n\tvec3 viewer = normalize(SampleToView)" -";\r\n\tvec3 reflected = normal * 2.0 * dot(normal, viewer) - viewer;\r\n\r" -"\n\tvec2 tex = reflected.yz * vec2(0.5, -0.5) + 0.5;\r\n#else\r\n\tvec2 tex" -" = attr_TexCoord0.st;\r\n#endif\r\n\r\n\tvar_DiffuseTex = DoTexMatrix(tex, " -"position.xyz, u_DiffuseTexMatrix);\r\n\r\n#if defined(USE_LIGHTMAP)\r\n\tva" -"r_LightTex = attr_TexCoord1.st;\r\n#endif\r\n\r\n\tvar_Color = u_VertColor " -"* attr_Color + u_BaseColor;\r\n \r\n\tvar_Normal = normal;\r\n#if defined(" -"USE_VERT_TANGENT_SPACE)\r\n\tvar_Tangent = tangent;\r\n\tvar_Bitangent = bi" -"tangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)" -"\r\n #if defined(USE_LIGHT_VECTOR)\r\n\tvec3 worldLight = u_LightOrigin.xy" -"z - (position.xyz * u_LightOrigin.w);\r\n #endif\r\n\r\n\tworldLight += no" -"rmal * 0.0001;\r\n\tvar_WorldLight = worldLight;\r\n#endif\r\n\r\n#if defin" -"ed(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)\r\n #if defined(USE_INVSQR" -"LIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, worldLight);\r\n #else" -"\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, worldLight) / (u_Light" -"Radius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #endif\r\n\tfloat NL = cla" -"mp(dot(normal, normalize(worldLight)), 0.0, 1.0);\r\n\r\n\tvar_VectLight = " -"u_DirectedLight * intensity * NL + u_AmbientLight;\r\n#endif\r\n}\r\n"; - -static const char *fallbackLightallShader_fp = -"uniform sampler2D u_DiffuseMap;\r\n\r\n#if defined(USE_LIGHTMAP)\r\nuniform" -" sampler2D u_LightMap;\r\n#endif\r\n\r\n#if defined(USE_NORMALMAP)\r\nunifo" -"rm sampler2D u_NormalMap;\r\n#endif\r\n\r\n#if defined(USE_DELUXEMAP)\r\nun" -"iform sampler2D u_DeluxeMap;\r\n#endif\r\n\r\n#if defined(USE_SPECULARMAP)" -"\r\nuniform sampler2D u_SpecularMap;\r\n#endif\r\n\r\n#if defined(USE_SHADO" -"WMAP)\r\nuniform sampler2D u_ShadowMap;\r\n#endif\r\n\r\nuniform vec3 " -"u_ViewOrigin;\r\n\r\n#if defined(USE_LIGHT_VECTOR)\r\nuniform vec3 u_D" -"irectedLight;\r\nuniform vec3 u_AmbientLight;\r\nuniform float u_L" -"ightRadius;\r\n#endif\r\n\r\n#if defined(USE_LIGHT)\r\nuniform vec2 u_" -"MaterialInfo;\r\n#endif\r\n\r\nvarying vec2 var_DiffuseTex;\r\n#if def" -"ined(USE_LIGHTMAP)\r\nvarying vec2 var_LightTex;\r\n#endif\r\nvarying " -"vec4 var_Color;\r\nvarying vec3 var_Position;\r\n\r\nvarying vec3" -" var_SampleToView;\r\n\r\nvarying vec3 var_Normal;\r\n#if defined" -"(USE_VERT_TANGENT_SPACE)\r\nvarying vec3 var_Tangent;\r\nvarying vec3 " -" var_Bitangent;\r\n#endif\r\n\r\n#if defined(USE_LIGHT_VECTOR) && defin" -"ed(USE_FAST_LIGHT)\r\nvarying vec3 var_VectLight;\r\n#endif\r\n\r\n#if" -" defined(USE_LIGHT) && !defined(USE_DELUXEMAP)\r\nvarying vec3 var_Wor" -"ldLight;\r\n#endif\r\n\r\nvarying vec4 var_ScreenPos;\r\n\r\n#define EPSI" -"LON 0.00000001\r\n\r\n#if defined(USE_PARALLAXMAP)\r\nfloat SampleHeight(sa" -"mpler2D normalMap, vec2 t)\r\n{\r\n #if defined(SWIZZLE_NORMALMAP)\r\n\tre" -"turn texture2D(normalMap, t).r;\r\n #else\r\n\treturn texture2D(normalMap," -" t).a;\r\n #endif\r\n}\r\n\r\nfloat RayIntersectDisplaceMap(vec2 dp, vec2 " -"ds, sampler2D normalMap)\r\n{\r\n\tconst int linearSearchSteps = 16;\r\n\tc" -"onst int binarySearchSteps = 6;\r\n\r\n\tfloat depthStep = 1.0 / float(line" -"arSearchSteps);\r\n\r\n\t// current size of search window\r\n\tfloat size =" -" depthStep;\r\n\r\n\t// current depth position\r\n\tfloat depth = 0.0;\r\n" -"\r\n\t// best match found (starts with last position 1.0)\r\n\tfloat bestDe" -"pth = 1.0;\r\n\r\n\t// search front to back for first point inside object\r" -"\n\tfor(int i = 0; i < linearSearchSteps - 1; ++i)\r\n\t{\r\n\t\tdepth += s" -"ize;\r\n\t\t\r\n\t\tfloat t = 1.0 - SampleHeight(normalMap, dp + ds * depth" -");\r\n\t\t\r\n\t\tif(bestDepth > 0.996)\t\t// if no depth found yet\r\n\t\t" -"\tif(depth >= t)\r\n\t\t\t\tbestDepth = depth;\t// store best depth\r\n\t}" -"\r\n\r\n\tdepth = bestDepth;\r\n\t\r\n\t// recurse around first point (dept" -"h) for closest match\r\n\tfor(int i = 0; i < binarySearchSteps; ++i)\r\n\t{" -"\r\n\t\tsize *= 0.5;\r\n\r\n\t\tfloat t = 1.0 - SampleHeight(normalMap, dp " -"+ ds * depth);\r\n\t\t\r\n\t\tif(depth >= t)\r\n\t\t{\r\n\t\t\tbestDepth = " -"depth;\r\n\t\t\tdepth -= 2.0 * size;\r\n\t\t}\r\n\r\n\t\tdepth += size;\r\n" -"\t}\r\n\r\n\treturn bestDepth;\r\n}\r\n#endif\r\n\r\nfloat CalcDiffuse(vec3" -" N, vec3 L, vec3 E, float NE, float NL, float fzero, float shininess)\r\n{" -"\r\n #if defined(USE_OREN_NAYAR)\r\n\tfloat roughness = sqrt(2.0 / max(shi" -"niness, EPSILON));\r\n\r\n\tfloat gamma = dot(E - N * NE, L - N * NL);\r\n" -"\tfloat r_sq = roughness * roughness;\r\n\r\n\tfloat A = 1.0 - 0.5 * (r_sq " -"/ (r_sq + 0.57));\r\n\tfloat B = 0.45 * (r_sq / (r_sq + 0.09));\r\n\r\n\tfl" -"oat alpha = max(acos(NE), acos(NL));\r\n\tfloat beta = min(acos(NE), acos(" -"NL));\r\n\r\n\tfloat C = sin(alpha) * tan(beta);\r\n\r\n\treturn A + B * cl" -"amp(gamma, 0.0, 1.0) * C;\r\n #else\r\n\treturn 1.0 - fzero;\r\n #endif\r" -"\n}\r\n\r\n#if defined(USE_SPECULARMAP)\r\nfloat CalcSpecular(float NH, flo" -"at NL, float NE, float EH, float fzero, float shininess)\r\n{\r\n #if defi" -"ned(USE_BLINN) || defined(USE_TRIACE) || defined(USE_TORRANCE_SPARROW)\r\n" -"\tfloat blinn = pow(NH, shininess);\r\n #endif\r\n\r\n #if defined(USE_BL" -"INN)\r\n\treturn blinn;\r\n #endif\r\n\r\n #if defined(USE_COOK_TORRANCE)" -" || defined (USE_TRIACE) || defined (USE_TORRANCE_SPARROW)\r\n\tfloat fresn" -"el = fzero + (1.0 - fzero) * pow(1.0 - EH, 5);\r\n #endif\r\n\r\n #if def" -"ined(USE_COOK_TORRANCE) || defined(USE_TORRANCE_SPARROW)\r\n\tfloat geo = 2" -".0 * NH * min(NE, NL);\r\n\tgeo /= max(EH, geo);\r\n #endif \r\n\r\n #if" -" defined(USE_COOK_TORRANCE)\r\n\tfloat m = sqrt(2.0 / max(shininess, EPSILO" -"N));\r\n\r\n\tfloat m_sq = m * m;\r\n\tfloat NH_sq = NH * NH;\r\n\tfloat be" -"ckmann = exp((NH_sq - 1.0) / max(m_sq * NH_sq, EPSILON)) / max(4.0 * m_sq *" -" NH_sq * NH_sq, EPSILON);\r\n\r\n\treturn fresnel * geo * beckmann / max(NE" -", EPSILON);\r\n #endif\r\n\r\n #if defined(USE_TRIACE)\r\n\tfloat scale =" -" 0.1248582 * shininess + 0.2691817;\r\n\r\n\treturn fresnel * scale * blinn" -" / max(max(NL, NE), EPSILON);\r\n #endif\r\n \r\n #if defined(USE_TORRAN" -"CE_SPARROW)\r\n\tfloat scale = 0.125 * shininess + 1.0;\r\n\r\n\treturn fre" -"snel * geo * scale * blinn / max(NE, EPSILON);\r\n #endif\r\n}\r\n#endif\r" -"\n\r\nvoid main()\r\n{\r\n#if defined(USE_LIGHT) || defined(USE_NORMALMAP)" -"\r\n\tvec3 surfNormal = normalize(var_Normal);\r\n#endif\r\n\r\n#if defined" -"(USE_DELUXEMAP)\r\n\tvec3 worldLight = 2.0 * texture2D(u_DeluxeMap, var_Lig" -"htTex).xyz - vec3(1.0);\r\n\t//worldLight += var_WorldLight * 0.0001;\r\n#e" -"lif defined(USE_LIGHT)\r\n\tvec3 worldLight = var_WorldLight;\r\n#endif\r\n" -"\r\n#if defined(USE_LIGHTMAP)\r\n\tvec4 lightSample = texture2D(u_LightMap," -" var_LightTex).rgba;\r\n #if defined(RGBE_LIGHTMAP)\r\n\tlightSample.rgb *" -"= exp2(lightSample.a * 255.0 - 128.0);\r\n #endif\r\n\tvec3 directedLight " -"= lightSample.rgb;\r\n#elif defined(USE_LIGHT_VECTOR)\r\n #if defined(USE_" -"FAST_LIGHT)\r\n\tvec3 directedLight = var_VectLight;\r\n #else\r\n #if " -"defined(USE_INVSQRLIGHT)\r\n\tfloat intensity = 1.0 / dot(worldLight, world" -"Light);\r\n #else\r\n\tfloat intensity = clamp((1.0 - dot(worldLight, wo" -"rldLight) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);\r\n #end" -"if\r\n\r\n\tvec3 directedLight = u_DirectedLight * intensity;\r\n\tvec3 amb" -"ientLight = u_AmbientLight;\r\n #endif\r\n\r\n #if defined(USE_SHADOWMAP" -")\r\n\tvec2 shadowTex = var_ScreenPos.xy / var_ScreenPos.w * 0.5 + 0.5;\r\n" -"\tdirectedLight *= texture2D(u_ShadowMap, shadowTex).r;\r\n #endif\r\n#eli" -"f defined(USE_LIGHT_VERTEX)\r\n\tvec3 directedLight = var_Color.rgb;\r\n#en" -"dif\r\n\t\r\n#if defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(U" -"SE_FAST_LIGHT)\r\n\tvec3 SampleToView = normalize(var_SampleToView);\r\n#en" -"dif\r\n\tvec2 tex = var_DiffuseTex;\r\n\r\n\tfloat ambientDiff = 1.0;\r\n\r" -"\n#if defined(USE_NORMALMAP)\r\n #if defined(USE_VERT_TANGENT_SPACE)\r\n " -" vec3 tangent = normalize(var_Tangent);\r\n\tvec3 bitangent = normalize(" -"var_Bitangent);\r\n #else\r\n\tvec3 q0 = dFdx(var_Position);\r\n\tvec3 q1" -" = dFdy(var_Position);\r\n\tvec2 st0 = dFdx(tex);\r\n\tvec2 st1 = dFdy(tex" -");\r\n\tfloat dir = sign(st1.t * st0.s - st0.t * st1.s);\r\n\r\n\tvec3 ta" -"ngent = normalize( q0 * st1.t - q1 * st0.t) * dir;\r\n\tvec3 bitangent = -n" -"ormalize( q0 * st1.s - q1 * st0.s) * dir;\r\n #endif\r\n\r\n\tmat3 tangent" -"ToWorld = mat3(tangent, bitangent, surfNormal);\r\n\r\n #if defined(USE_PA" -"RALLAXMAP)\r\n\tvec3 offsetDir = normalize(SampleToView * tangentToWorld);" -"\r\n #if 0\r\n float height = SampleHeight(u_NormalMap, tex);\r\n\tfl" -"oat pdist = 0.05 * height - (0.05 / 2.0);\r\n #else\r\n\toffsetDir.xy *=" -" -0.05 / offsetDir.z;\r\n\tfloat pdist = RayIntersectDisplaceMap(tex, offse" -"tDir.xy, u_NormalMap);\r\n #endif\t\r\n\ttex += offsetDir.xy * pdist;\r" -"\n #endif\r\n #if defined(SWIZZLE_NORMALMAP)\r\n\tvec3 normal = 2.0 * tex" -"ture2D(u_NormalMap, tex).agb - 1.0;\r\n #else\r\n\tvec3 normal = 2.0 * tex" -"ture2D(u_NormalMap, tex).rgb - 1.0;\r\n #endif\r\n\tnormal.z = sqrt(clamp(" -"1.0 - dot(normal.xy, normal.xy), 0.0, 1.0));\r\n\tvec3 worldNormal = tangen" -"tToWorld * normal;\r\n #if defined(r_normalAmbient)\r\n\tambientDiff = 0.7" -"81341 * normal.z + 0.218659;\r\n #endif\r\n#elif defined(USE_LIGHT)\r\n\tv" -"ec3 worldNormal = surfNormal;\r\n#endif\r\n\r\n\tvec4 diffuse = texture2D(u" -"_DiffuseMap, tex);\r\n\r\n#if defined(USE_LIGHT) && defined(USE_FAST_LIGHT)" -"\r\n\tdiffuse.rgb *= directedLight;\r\n#elif defined(USE_LIGHT)\r\n\tworldN" -"ormal = normalize(worldNormal);\r\n\tworldLight = normalize(worldLight);\r" -"\n\r\n #if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)\r\n\tdirecte" -"dLight /= max(dot(surfNormal, worldLight), 0.004);\r\n\r\n #if defined(r" -"_normalAmbient)\r\n\tvec3 ambientLight = directedLight * r_normalAmbient;\r" -"\n\tdirectedLight -= ambientLight;\r\n #else\r\n\tvec3 ambientLight = ve" -"c3(0);\r\n #endif\r\n #endif\r\n\r\n\tfloat NL = clamp(dot(worldNormal," -" worldLight), 0.0, 1.0);\r\n\tfloat surfNL = clamp(dot(surfNormal, worl" -"dLight), 0.0, 1.0);\r\n\tNL = min(NL, surfNL * 2.0);\r\n\tfloat NE = clam" -"p(dot(worldNormal, SampleToView), 0.0, 1.0);\r\n\t\r\n\tfloat fzero = u_Ma" -"terialInfo.x;\r\n\tfloat shininess = u_MaterialInfo.y;\r\n #if defined(USE" -"_SPECULARMAP)\r\n\tvec4 specular = texture2D(u_SpecularMap, tex);\r\n\t//sp" -"ecular.rgb = clamp(specular.rgb - diffuse.rgb, 0.0, 1.0);\r\n\tshininess *=" -" specular.a;\r\n #endif\r\n\tfloat directedDiff = NL * CalcDiffuse(worldNo" -"rmal, worldLight, SampleToView, NE, NL, fzero, shininess);\r\n\tdiffuse.rgb" -" *= directedLight * directedDiff + ambientDiff * ambientLight;\r\n \r\n #" -"if defined(USE_SPECULARMAP)\r\n\tvec3 halfAngle = normalize(worldLight + Sa" -"mpleToView);\r\n\r\n\tfloat EH = clamp(dot(SampleToView, halfAngle), 0.0, 1" -".0);\r\n\tfloat NH = clamp(dot(worldNormal, halfAngle), 0.0, 1.0);\r\n\r\n" -"\tfloat directedSpec = NL * CalcSpecular(NH, NL, NE, EH, fzero, shininess);" -"\r\n \r\n #if defined(r_normalAmbient)\r\n\tvec3 ambientHalf = normaliz" -"e(surfNormal + SampleToView);\r\n\tfloat ambientSpec = max(dot(ambientHalf," -" worldNormal) + 0.5, 0.0);\r\n\tambientSpec *= ambientSpec * 0.44;\r\n\tamb" -"ientSpec = pow(ambientSpec, shininess) * fzero;\r\n\tspecular.rgb *= direct" -"edSpec * directedLight + ambientSpec * ambientLight;\r\n #else\r\n\tspec" -"ular.rgb *= directedSpec * directedLight;\r\n #endif\r\n #endif\r\n#end" -"if\r\n\r\n\tgl_FragColor = diffuse;\r\n\r\n#if defined(USE_SPECULARMAP) && " -"defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)\r\n\tgl_FragColor.rgb += spe" -"cular.rgb;\r\n#endif\r\n\r\n#if !defined(USE_LIGHT_VERTEX)\r\n\tgl_FragColo" -"r *= var_Color;\r\n#endif\r\n}\r\n"; - -static const char *fallbackShadowfillShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\nattribute" -" vec4 attr_TexCoord0;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nattrib" -"ute vec4 attr_Position2;\r\nattribute vec3 attr_Normal2;\r\n//#endif\r\n" -"\r\n//#if defined(USE_DEFORM_VERTEXES)\r\nuniform int u_DeformGen;\r\nu" -"niform float u_DeformParams[5];\r\n//#endif\r\n\r\nuniform float u_Tim" -"e;\r\nuniform mat4 u_ModelViewProjectionMatrix;\r\n\r\nuniform mat4 u_" -"ModelMatrix;\r\n\r\n//#if defined(USE_VERTEX_ANIMATION)\r\nuniform float " -"u_VertexLerp;\r\n//#endif\r\n\r\nvarying vec3 var_Position;\r\n\r\nfloat" -" triangle(float x)\r\n{\r\n\treturn max(1.0 - abs(x), 0);\r\n}\r\n\r\nfloat" -" sawtooth(float x)\r\n{\r\n\treturn x - floor(x);\r\n}\r\n\r\nvec4 DeformPo" -"sition(const vec4 pos, const vec3 normal, const vec2 st)\r\n{\r\n\tif (u_De" -"formGen == 0)\r\n\t{\r\n\t\treturn pos;\r\n\t}\r\n\r\n\tfloat base = u" -"_DeformParams[0];\r\n\tfloat amplitude = u_DeformParams[1];\r\n\tfloat phas" -"e = u_DeformParams[2];\r\n\tfloat frequency = u_DeformParams[3];\r\n\tf" -"loat spread = u_DeformParams[4];\r\n\t\t\r\n\tif (u_DeformGen <= DGEN_WA" -"VE_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tphase += (pos.x + pos.y + pos.z) * sprea" -"d;\r\n\t}\r\n\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tphase *= M" -"_PI * 0.25 * st.x;\r\n\t}\r\n\r\n\tfloat value = phase + (u_Time * frequenc" -"y);\r\n\tfloat func;\r\n\r\n\tif (u_DeformGen == DGEN_WAVE_SIN)\r\n\t{\r\n" -"\t\tfunc = sin(value * 2.0 * M_PI);\r\n\t}\r\n\telse if (u_DeformGen == DGE" -"N_WAVE_SQUARE)\r\n\t{\r\n\t\tfunc = sign(sin(value * 2.0 * M_PI));\r\n\t}\r" -"\n\telse if (u_DeformGen == DGEN_WAVE_TRIANGLE)\r\n\t{\r\n\t\tfunc = triang" -"le(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE_SAWTOOTH)\r\n\t{\r" -"\n\t\tfunc = sawtooth(value);\r\n\t}\r\n\telse if (u_DeformGen == DGEN_WAVE" -"_INVERSE_SAWTOOTH)\r\n\t{\r\n\t\tfunc = (1.0 - sawtooth(value));\r\n\t}\r\n" -"\telse if (u_DeformGen == DGEN_BULGE)\r\n\t{\r\n\t\tfunc = sin(value);\r\n" -"\t}\r\n\r\n\tvec4 deformed = pos;\r\n\tdeformed.xyz += normal * (base + fun" -"c * amplitude);\r\n\r\n\treturn deformed;\r\n\r\n}\r\n\r\n\r\nvoid main()\r" -"\n{\r\n\tvec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);" -"\r\n\tvec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp))" -";\r\n\r\n\tposition = DeformPosition(position, normal, attr_TexCoord0.st);" -"\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position;\r\n\t\r\n\t" -"var_Position = (u_ModelMatrix * position).xyz;\r\n}\r\n"; - -static const char *fallbackShadowfillShader_fp = -"uniform vec4 u_LightOrigin;\r\nuniform float u_LightRadius;\r\n\r\nvarying" -" vec3 var_Position;\r\n\r\nvoid main()\r\n{\r\n#if defined(USE_DEPTH)\r\n" -"\tfloat depth = length(u_LightOrigin.xyz - var_Position) / u_LightRadius;\r" -"\n #if 0\r\n\t// 32 bit precision\r\n\tconst vec4 bitSh = vec4( 256 * 256 *" -" 256, 256 * 256, 256, 1);\r\n\tconst vec4 bitMsk = vec4" -"( 0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);\r\n\t\r\n\tvec4 c" -"omp;\r\n\tcomp = depth * bitSh;\r\n\tcomp.xyz = fract(comp.xyz);\r\n\tcomp " -"-= comp.xxyz * bitMsk;\r\n\tgl_FragColor = comp;\r\n #endif\r\n\r\n #if 1\r" -"\n\t// 24 bit precision\r\n\tconst vec3 bitSh = vec3( 256 * 256, 25" -"6, 1);\r\n\tconst vec3 bitMsk = vec3( 0, 1.0 / 256.0, 1.0 " -"/ 256.0);\r\n\t\r\n\tvec3 comp;\r\n\tcomp = depth * bitSh;\r\n\tcomp.xy = f" -"ract(comp.xy);\r\n\tcomp -= comp.xxy * bitMsk;\r\n\tgl_FragColor = vec4(com" -"p, 1.0);\r\n #endif\r\n\r\n #if 0\r\n\t// 8 bit precision\r\n\tgl_FragColor" -" = vec4(depth, depth, depth, 1);\r\n #endif\r\n#else\r\n\tgl_FragColor = ve" -"c4(0, 0, 0, 1);\r\n#endif\r\n}\r\n"; - -static const char *fallbackPshadowShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec3 attr_Normal;\r\n\r\nuniform" -" mat4 u_ModelViewProjectionMatrix;\r\nvarying vec3 var_Position;\r\nvar" -"ying vec3 var_Normal;\r\n\r\n\r\nvoid main()\r\n{\r\n\tvec4 position = a" -"ttr_Position;\r\n\r\n\tgl_Position = u_ModelViewProjectionMatrix * position" -";\r\n\r\n\tvar_Position = position.xyz;\r\n\tvar_Normal = attr_Normal;" -"\r\n}\r\n"; - -static const char *fallbackPshadowShader_fp = -"uniform sampler2D u_ShadowMap;\r\n\r\nuniform vec3 u_LightForward;\r\n" -"uniform vec3 u_LightUp;\r\nuniform vec3 u_LightRight;\r\nuniform " -"vec4 u_LightOrigin;\r\nuniform float u_LightRadius;\r\nvarying vec" -"3 var_Position;\r\nvarying vec3 var_Normal;\r\n\r\nfloat sampleDi" -"stMap(sampler2D texMap, vec2 uv, float scale)\r\n{\r\n\tvec3 distv = textur" -"e2D(texMap, uv).xyz;\r\n\treturn dot(distv, vec3(1.0 / (256.0 * 256.0), 1.0" -" / 256.0, 1.0)) * scale;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec3 lightToPos " -"= var_Position - u_LightOrigin.xyz;\r\n\tvec2 st = vec2(-dot(u_LightRight, " -"lightToPos), dot(u_LightUp, lightToPos));\r\n\t\r\n\tfloat fade = length(st" -");\r\n\t\r\n#if defined(USE_DISCARD)\r\n\tif (fade >= 1.0)\r\n\t{\r\n\t\tdi" -"scard;\r\n\t}\r\n#endif\r\n\r\n\tfade = clamp(8.0 - fade * 8.0, 0.0, 1.0);" -"\r\n\t\r\n\tst = st * 0.5 + vec2(0.5);\r\n\r\n#if defined(USE_SOLID_PSHADOW" -"S)\r\n\tfloat intensity = max(sign(u_LightRadius - length(lightToPos)), 0.0" -");\r\n#else\r\n\tfloat intensity = clamp((1.0 - dot(lightToPos, lightToPos)" -" / (u_LightRadius * u_LightRadius)) * 2.0, 0.0, 1.0);\r\n#endif\r\n\t\r\n\t" -"float lightDist = length(lightToPos);\r\n\tfloat dist;\r\n\r\n#if defined(U" -"SE_DISCARD)\r\n\tif (dot(u_LightForward, lightToPos) <= 0.0)\r\n\t{\r\n\t\t" -"discard;\r\n\t}\r\n\r\n\tif (dot(var_Normal, lightToPos) > 0.0)\r\n\t{\r\n" -"\t\tdiscard;\r\n\t}\r\n#else\r\n\tintensity *= max(sign(dot(u_LightForward," -" lightToPos)), 0.0);\r\n\tintensity *= max(sign(-dot(var_Normal, lightToPos" -")), 0.0);\r\n#endif\r\n\r\n\tintensity *= fade;\r\n#if defined(USE_PCF)\r\n" -"\tfloat part;\r\n\t\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/5" -"12.0, -1.0/512.0), u_LightRadius);\r\n\tpart = max(sign(lightDist - dist)," -" 0.0);\r\n\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, -1." -"0/512.0), u_LightRadius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r" -"\n\r\n\tdist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, 1.0/512.0)" -", u_LightRadius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r\n\r\n\td" -"ist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, 1.0/512.0), u_Light" -"Radius);\r\n\tpart += max(sign(lightDist - dist), 0.0);\r\n\r\n #if define" -"d(USE_DISCARD)\r\n\tif (part <= 0.0)\r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n #en" -"dif\r\n\r\n\tintensity *= part * 0.25;\r\n#else\r\n\tdist = sampleDistMap(u" -"_ShadowMap, st, u_LightRadius);\r\n\r\n #if defined(USE_DISCARD)\r\n\tif (" -"lightDist - dist <= 0.0)\r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n #endif\r\n\t\t" -"\t\r\n\tintensity *= max(sign(lightDist - dist), 0.0);\r\n#endif\r\n\t\t\r" -"\n\tgl_FragColor.rgb = vec3(0);\r\n\tgl_FragColor.a = clamp(intensity, 0.0," -" 0.75);\r\n}\r\n"; - -static const char *fallbackDown4xShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif" -"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords" -";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri" -"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n"; - -static const char *fallbackDown4xShader_fp = -"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec2 u_InvTexRes;\r\nva" -"rying vec2 var_TexCoords;\r\n\r\nvoid main()\r\n{\r\n\tvec4 color;\r\n" -"\tvec2 tc;\r\n\t\r\n\ttc = var_TexCoords + u_InvTexRes * vec2(-1.5, -1.5); " -" color = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRe" -"s * vec2(-0.5, -1.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_" -"TexCoords + u_InvTexRes * vec2( 0.5, -1.5); color += texture2D(u_TextureMa" -"p, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 1.5, -1.5); color +=" -" texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * v" -"ec2(-1.5, -0.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoo" -"rds + u_InvTexRes * vec2(-0.5, -0.5); color += texture2D(u_TextureMap, tc);" -"\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 0.5, -0.5); color += texture" -"2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 1.5, -0" -".5); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_" -"InvTexRes * vec2(-1.5, 0.5); color += texture2D(u_TextureMap, tc);\r\n\ttc" -" = var_TexCoords + u_InvTexRes * vec2(-0.5, 0.5); color += texture2D(u_Tex" -"tureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( 0.5, 0.5); col" -"or += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * " -"vec2( 1.5, 0.5); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_T" -"exCoords + u_InvTexRes * vec2(-1.5, 1.5); color += texture2D(u_TextureMap" -", tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2(-0.5, 1.5); color += " -"texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( " -"0.5, 1.5); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords " -"+ u_InvTexRes * vec2( 1.5, 1.5); color += texture2D(u_TextureMap, tc);\r" -"\n\t\r\n\tcolor *= 0.0625;\r\n\t\r\n\tgl_FragColor = color;\r\n}\r\n"; - -static const char *fallbackBokehShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif" -"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords" -";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri" -"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n"; - -static const char *fallbackBokehShader_fp = -"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec4 u_Color;\r\n\r\nun" -"iform vec2 u_InvTexRes;\r\nvarying vec2 var_TexCoords;\r\n\r\nvoi" -"d main()\r\n{\r\n\tvec4 color;\r\n\tvec2 tc;\r\n\r\n#if 0\r\n\tfloat c[7] =" -" float[7](1.0, 0.9659258263, 0.8660254038, 0.7071067812, 0.5, 0.2588190451," -" 0.0);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[0], c[6]); co" -"lor = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *" -" vec2( c[1], c[5]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_" -"TexCoords + u_InvTexRes * vec2( c[2], c[4]); color += texture2D(u_Textur" -"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[3], c[3]); co" -"lor += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *" -" vec2( c[4], c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_" -"TexCoords + u_InvTexRes * vec2( c[5], c[1]); color += texture2D(u_Textur" -"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[6], c[0]); co" -"lor += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexR" -"es * vec2( c[1], -c[5]); color += texture2D(u_TextureMap, tc);\r\n\ttc = " -"var_TexCoords + u_InvTexRes * vec2( c[2], -c[4]); color += texture2D(u_Te" -"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[3], -c[3]);" -" color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexR" -"es * vec2( c[4], -c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = " -"var_TexCoords + u_InvTexRes * vec2( c[5], -c[1]); color += texture2D(u_Te" -"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[6], -c[0]);" -" color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_Inv" -"TexRes * vec2( -c[0], c[6]); color += texture2D(u_TextureMap, tc);\r\n\tt" -"c = var_TexCoords + u_InvTexRes * vec2( -c[1], c[5]); color += texture2D(" -"u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], c[" -"4]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_Inv" -"TexRes * vec2( -c[3], c[3]); color += texture2D(u_TextureMap, tc);\r\n\tt" -"c = var_TexCoords + u_InvTexRes * vec2( -c[4], c[2]); color += texture2D(" -"u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[5], c[" -"1]); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u" -"_InvTexRes * vec2( -c[1], -c[5]); color += texture2D(u_TextureMap, tc);\r" -"\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[4]); color += textu" -"re2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[3]" -", -c[3]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + " -"u_InvTexRes * vec2( -c[4], -c[2]); color += texture2D(u_TextureMap, tc);\r" -"\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[5], -c[1]); color += textu" -"re2D(u_TextureMap, tc);\r\n\t\r\n\tgl_FragColor = color * 0.04166667 * u_Co" -"lor;\r\n#endif\r\n\r\n\tfloat c[5] = float[5](1.0, 0.9238795325, 0.70710678" -"12, 0.3826834324, 0.0);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( " -"c[0], c[4]); color = texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoord" -"s + u_InvTexRes * vec2( c[1], c[3]); color += texture2D(u_TextureMap, tc" -");\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[2], c[2]); color += t" -"exture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( " -"c[3], c[1]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoord" -"s + u_InvTexRes * vec2( c[4], c[0]); color += texture2D(u_TextureMap, tc" -");\r\n\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[1], -c[3]); color " -"+= texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec" -"2( c[2], -c[2]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexC" -"oords + u_InvTexRes * vec2( c[3], -c[1]); color += texture2D(u_TextureMap" -", tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( c[4], -c[0]); color " -"+= texture2D(u_TextureMap, tc);\r\n\r\n\ttc = var_TexCoords + u_InvTexRes *" -" vec2( -c[0], c[4]); color += texture2D(u_TextureMap, tc);\r\n\ttc = var_" -"TexCoords + u_InvTexRes * vec2( -c[1], c[3]); color += texture2D(u_Textur" -"eMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], c[2]); co" -"lor += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes *" -" vec2( -c[3], c[1]); color += texture2D(u_TextureMap, tc);\r\n\r\n\ttc = " -"var_TexCoords + u_InvTexRes * vec2( -c[1], -c[3]); color += texture2D(u_Te" -"xtureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[2]);" -" color += texture2D(u_TextureMap, tc);\r\n\ttc = var_TexCoords + u_InvTexR" -"es * vec2( -c[3], -c[1]); color += texture2D(u_TextureMap, tc);\r\n\t\r\n" -"\tgl_FragColor = color * 0.0625 * u_Color;\r\n}\r\n"; - -static const char *fallbackToneMapShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif" -"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords" -";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri" -"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n"; - -static const char *fallbackToneMapShader_fp = -"#define AVG_MAP 1.0\r\n#define WHITE_LEVEL 2.0\r\n#define BLACK_LEVEL 0.1\r" -"\n\r\nuniform sampler2D u_TextureMap;\r\nuniform sampler2D u_LevelsMap;\r\n" -"\r\nuniform vec4 u_Color;\r\n\r\nuniform vec2 u_AutoExposureMinMa" -"x;\r\n\r\nvarying vec2 var_TexCoords;\r\n\r\nconst vec3 LUMINANCE_VEC" -"TOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0.587, 0.114);\r\n\r\nv" -"ec3 FilmicTonemap(vec3 x)\r\n{\r\n\tconst float SS = 0.22; // Shoulder Str" -"ength\r\n\tconst float LS = 0.30; // Linear Strength\r\n\tconst float LA " -"= 0.10; // Linear Angle\r\n\tconst float TS = 0.20; // Toe Strength\r\n\tc" -"onst float TAN = 0.01; // Toe Angle Numerator\r\n\tconst float TAD = 0.30; " -"// Toe Angle Denominator\r\n\t\r\n\tvec3 SSxx = SS * x * x;\r\n\tvec3 LSx =" -" LS * x;\r\n\tvec3 LALSx = LSx * LA;\r\n\t\r\n\treturn ((SSxx + LALSx + TS " -"* TAN) / (SSxx + LSx + TS * TAD)) - TAN / TAD;\r\n\r\n\t//return ((x*(SS*x+" -"LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD)) - TAN/TAD;\r\n\r\n}\r\n\r\nvoid main()" -"\r\n{\r\n\tvec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;\r" -"\n\tvec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;\r\n\tvec3 l" -"ogMinAvgMaxLum = clamp(minAvgMax * 20.0 - 10.0, -u_AutoExposureMinMax.y, -u" -"_AutoExposureMinMax.x);\r\n\t\t\r\n\tfloat avgLum = exp2(logMinAvgMaxLum.y)" -";\r\n\t//float maxLum = exp2(logMinAvgMaxLum.z);\r\n\t\r\n\tcolor.rgb *= AV" -"G_MAP / avgLum;\r\n\tcolor.rgb = max(vec3(0.0), color.rgb - vec3(BLACK_LEVE" -"L));\r\n\r\n\tvec3 fWhite = 1.0 / FilmicTonemap(vec3(WHITE_LEVEL - BLACK_LE" -"VEL));\r\n\tcolor.rgb = FilmicTonemap(color.rgb) * fWhite;\r\n\t\r\n#if def" -"ined(r_obbcorrect)\r\n\tcolor.rgb /= r_obbcorrect;\r\n#endif\r\n\t\r\n\tgl_" -"FragColor = color;\r\n}\r\n"; - -static const char *fallbackCalcLevels4xShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif" -"orm mat4 u_ModelViewProjectionMatrix;\r\n\r\nvarying vec2 var_TexCoords" -";\r\n\r\n\r\nvoid main()\r\n{\r\n\tgl_Position = u_ModelViewProjectionMatri" -"x * attr_Position;\r\n\tvar_TexCoords = attr_TexCoord0.st;\r\n}\r\n"; - -static const char *fallbackCalcLevels4xShader_fp = -"uniform sampler2D u_TextureMap;\r\n\r\nuniform vec4 u_Color;\r\n\r\nun" -"iform vec2 u_InvTexRes;\r\nvarying vec2 var_TexCoords;\r\n\r\ncon" -"st vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0" -".587, 0.114);\r\n\r\nvec3 GetValues(vec2 offset, vec3 current)\r\n{\r\n\tve" -"c3 minAvgMax;\r\n\tvec2 tc = var_TexCoords + u_InvTexRes * offset; minAvgMa" -"x = texture2D(u_TextureMap, tc).rgb;\r\n\r\n#ifdef FIRST_PASS\r\n\tfloat lu" -"mi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);\r\n\tfloat loglumi = " -"clamp(log2(lumi), -10.0, 10.0);\r\n\tminAvgMax = vec3(loglumi * 0.05 + 0.5)" -";\r\n#endif\r\n\r\n\treturn vec3(min(current.x, minAvgMax.x), current.y + m" -"inAvgMax.y, max(current.z, minAvgMax.z));\r\n}\r\n\r\nvoid main()\r\n{\r\n" -"\tvec3 current = vec3(1.0, 0.0, 0.0);\r\n\r\n#ifdef FIRST_PASS\r\n\tcurrent" -" = GetValues(vec2( 0.0, 0.0), current);\r\n#else\r\n\tcurrent = GetValues(" -"vec2(-1.5, -1.5), current);\r\n\tcurrent = GetValues(vec2(-0.5, -1.5), curr" -"ent);\r\n\tcurrent = GetValues(vec2( 0.5, -1.5), current);\r\n\tcurrent = G" -"etValues(vec2( 1.5, -1.5), current);\r\n\t\r\n\tcurrent = GetValues(vec2(-1" -".5, -0.5), current);\r\n\tcurrent = GetValues(vec2(-0.5, -0.5), current);\r" -"\n\tcurrent = GetValues(vec2( 0.5, -0.5), current);\r\n\tcurrent = GetValue" -"s(vec2( 1.5, -0.5), current);\r\n\t\r\n\tcurrent = GetValues(vec2(-1.5, 0." -"5), current);\r\n\tcurrent = GetValues(vec2(-0.5, 0.5), current);\r\n\tcur" -"rent = GetValues(vec2( 0.5, 0.5), current);\r\n\tcurrent = GetValues(vec2(" -" 1.5, 0.5), current);\r\n\r\n\tcurrent = GetValues(vec2(-1.5, 1.5), curre" -"nt);\r\n\tcurrent = GetValues(vec2(-0.5, 1.5), current);\r\n\tcurrent = Ge" -"tValues(vec2( 0.5, 1.5), current);\r\n\tcurrent = GetValues(vec2( 1.5, 1." -"5), current);\r\n\r\n\tcurrent.y *= 0.0625;\r\n#endif\r\n\r\n\tgl_FragColor" -" = vec4(current, 1.0f);\r\n}\r\n"; - -static const char *fallbackShadowmaskShader_vp = -"attribute vec4 attr_Position;\r\nattribute vec4 attr_TexCoord0;\r\n\r\nunif" -"orm vec3 u_ViewForward;\r\nuniform vec3 u_ViewLeft;\r\nuniform vec3 u" -"_ViewUp;\r\nuniform vec4 u_ViewInfo; // zfar / znear\r\n\r\nvarying vec2 " -" var_ScreenTex;\r\nvarying vec3 var_ViewDir;\r\n\r\nvoid main()\r\n{\r\n" -"\tgl_Position = attr_Position;\r\n\t//vec2 screenCoords = gl_Position.xy / " -"gl_Position.w;\r\n\t//var_ScreenTex = screenCoords * 0.5 + 0.5;\r\n\tvar_Sc" -"reenTex = attr_TexCoord0.xy;\r\n\tvec2 screenCoords = attr_TexCoord0.xy * 2" -".0 - 1.0;\r\n\tvar_ViewDir = u_ViewForward + u_ViewLeft * -screenCoords.x +" -" u_ViewUp * screenCoords.y;\r\n}\r\n"; - -static const char *fallbackShadowmaskShader_fp = -"uniform sampler2D u_ScreenDepthMap;\r\n\r\nuniform sampler2D u_ShadowMap;\r" -"\n#if 1 //defined(USE_SHADOW_CASCADE)\r\nuniform sampler2D u_ShadowMap2;\r" -"\nuniform sampler2D u_ShadowMap3;\r\n#endif\r\n\r\nuniform mat4 u_Shad" -"owMvp;\r\n#if 1 //defined(USE_SHADOW_CASCADE)\r\nuniform mat4 u_Shadow" -"Mvp2;\r\nuniform mat4 u_ShadowMvp3;\r\n#endif\r\n\r\nuniform vec3 u_" -"ViewOrigin;\r\nuniform vec4 u_ViewInfo; // zfar / znear, zfar\r\n\r\nvary" -"ing vec2 var_ScreenTex;\r\nvarying vec3 var_ViewDir;\r\n\r\n// Input: I" -"t uses texture coords as the random number seed.\r\n// Output: Random numbe" -"r: [0,1), that is between 0.0 and 0.999999... inclusive.\r\n// Author: Mich" -"ael Pohoreski\r\n// Copyright: Copyleft 2012 :-)\r\n// Source: http://stack" -"overflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixe" -"l-shader\r\n\r\nfloat random( vec2 p )\r\n{\r\n // We need irrationals for" -" pseudo randomness.\r\n // Most (all?) known transcendental numbers will (" -"generally) work.\r\n const vec2 r = vec2(\r\n 23.1406926327792690, // " -"e^pi (Gelfond's constant)\r\n 2.6651441426902251); // 2^sqrt(2) (Gelfon" -"d?chneider constant)\r\n //return fract( cos( mod( 123456789., 1e-7 + 256" -". * dot(p,r) ) ) );\r\n return mod( 123456789., 1e-7 + 256. * dot(p,r) ); " -" \r\n}\r\n\r\nfloat PCF(sampler2D shadowmap, vec2 st, float dist)\r\n{\r\n" -"\tfloat mult;\r\n\tfloat scale = 2.0 / r_shadowMapSize;\r\n\t\t\r\n#if defi" -"ned(USE_SHADOW_FILTER)\r\n\tfloat r = random(var_ScreenTex.xy);\r\n\tfloat " -"sinr = sin(r) * scale;\r\n\tfloat cosr = cos(r) * scale;\r\n\tmat2 rmat = m" -"at2(cosr, sinr, -sinr, cosr);\r\n\r\n\tmult = step(dist, texture2D(shadowma" -"p, st + rmat * vec2(-0.7055767, 0.196515)).r);\r\n\tmult += step(dist, text" -"ure2D(shadowmap, st + rmat * vec2(0.3524343, -0.7791386)).r);\r\n mult +" -"= step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 0.9189604)).r" -");\r\n #if defined(USE_SHADOW_FILTER2)\r\n\tmult += step(dist, texture2D(s" -"hadowmap, st + rmat * vec2(-0.07580382, -0.09224417)).r);\r\n\tmult += step" -"(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, -0.002528916)).r);" -"\r\n\tmult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 0." -"4064181)).r);\r\n\tmult += step(dist, texture2D(shadowmap, st + rmat * vec2" -"(-0.6335801, -0.5247476)).r);\r\n\tmult += step(dist, texture2D(shadowmap, " -"st + rmat * vec2(-0.5579782, 0.7491854)).r);\r\n\tmult += step(dist, textur" -"e2D(shadowmap, st + rmat * vec2(0.7320465, 0.6317794)).r);\r\n\r\n\tmult *=" -" 0.11111;\r\n #else\r\n mult *= 0.33333;\r\n #endif\r\n#else\r\n\tmult" -" = step(dist, texture2D(shadowmap, st).r);\r\n#endif\r\n\t\t\r\n\treturn mu" -"lt;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tconst float fadeTo = 0.5;\r\n\tfloat " -"result = fadeTo;\r\n\tfloat sampleZ_W = texture2D(u_ScreenDepthMap, var_Scr" -"eenTex).r;\r\n\r\n\tfloat depth = 1.0 / mix(u_ViewInfo.x, 1.0, sampleZ_W);" -"\r\n\tfloat sampleZ = u_ViewInfo.y * depth;\r\n\tvec4 biasPos = vec4(u_View" -"Origin + var_ViewDir * depth * 0.99, 1.0);\r\n\t\r\n #if defined(USE_SHADO" -"W_CASCADE)\r\n\tvec4 shadowpos = u_ShadowMvp * biasPos;\r\n\tshadowpos /= s" -"hadowpos.w;\r\n\r\n\tvec4 shadowpos2 = u_ShadowMvp2 * biasPos;\r\n\tshadowp" -"os2 /= shadowpos2.w;\r\n\r\n\tvec4 shadowpos3 = u_ShadowMvp3 * biasPos;\r\n" -"\tshadowpos3 /= shadowpos3.w;\r\n\t\r\n\tif (all(lessThan(abs(shadowpos.xyz" -"), vec3(1.0))))\r\n\t{\r\n\t\tshadowpos.xyz = shadowpos.xyz * 0.5 + 0.5;\r" -"\n\t\tresult = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z);\r\n\t}\r\n\tels" -"e if (all(lessThan(abs(shadowpos2.xyz), vec3(1.0))))\r\n\t{\r\n\t\tshadowpo" -"s2.xyz = shadowpos2.xyz * 0.5 + 0.5;\r\n\t\tresult = PCF(u_ShadowMap2, shad" -"owpos2.xy, shadowpos2.z);\r\n\t}\r\n\telse if (all(lessThan(abs(shadowpos3." -"xyz), vec3(1.0))))\r\n\t{\r\n\t\tshadowpos3.xyz = shadowpos3.xyz * 0.5 + 0." -"5;\r\n\t\tresult = PCF(u_ShadowMap3, shadowpos3.xy, shadowpos3.z);\r\n\r\n" -"\t\tfloat fade = clamp(sampleZ / r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0" -");\r\n\t\tresult = mix(result, fadeTo, fade);\r\n\t}\r\n\t\r\n #else\r\n\t" -"vec4 shadowpos = u_ShadowMvp * biasPos;\r\n\tshadowpos /= shadowpos.w;\r\n" -"\r\n\tfloat outside = dot(vec3(1.0), step(1.0, abs(shadowpos.xyz)));\r\n\r" -"\n\tshadowpos.xyz = shadowpos.xyz * 0.5 + 0.5;\r\n\tresult = clamp(PCF(u_Sh" -"adowMap, shadowpos.xy, shadowpos.z) - outside, 1.0, 0.0);\r\n #endif\r\n\t" -"\t\r\n\tgl_FragColor.rgba = vec4(vec3(result), 1.0);\r\n}"; - - - -static void GLSL_PrintInfoLog(GLhandleARB object, qboolean developerOnly) -{ - char *msg; - static char msgPart[1024]; - int maxLength = 0; - int i; - int printLevel = developerOnly ? PRINT_DEVELOPER : PRINT_ALL; - - qglGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength); - - if (maxLength <= 0) - { - ri.Printf(printLevel, "No compile log.\n"); - return; - } - - ri.Printf(printLevel, "compile log:\n"); - - if (maxLength < 1023) - { - qglGetInfoLogARB(object, maxLength, &maxLength, msgPart); - - msgPart[maxLength + 1] = '\0'; - - ri.Printf(printLevel, "%s\n", msgPart); - } - else - { - msg = ri.Malloc(maxLength); - - qglGetInfoLogARB(object, maxLength, &maxLength, msg); - - for(i = 0; i < maxLength; i += 1024) - { - Q_strncpyz(msgPart, msg + i, sizeof(msgPart)); - - ri.Printf(printLevel, "%s\n", msgPart); - } - - ri.Free(msg); - } -} - -static void GLSL_PrintShaderSource(GLhandleARB object) -{ - char *msg; - static char msgPart[1024]; - int maxLength = 0; - int i; - - qglGetObjectParameterivARB(object, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &maxLength); - - msg = ri.Malloc(maxLength); - - qglGetShaderSourceARB(object, maxLength, &maxLength, msg); - - for(i = 0; i < maxLength; i += 1024) - { - Q_strncpyz(msgPart, msg + i, sizeof(msgPart)); - ri.Printf(PRINT_ALL, "%s\n", msgPart); - } - - ri.Free(msg); -} - -static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, char *dest, int size ) -{ - float fbufWidthScale, fbufHeightScale; - - dest[0] = '\0'; - - // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones - if(glRefConfig.glslMajorVersion > 1 || (glRefConfig.glslMajorVersion == 1 && glRefConfig.glslMinorVersion >= 30)) - { - Q_strcat(dest, size, "#version 130\n"); - - if(shaderType == GL_VERTEX_SHADER_ARB) - { - Q_strcat(dest, size, "#define attribute in\n"); - Q_strcat(dest, size, "#define varying out\n"); - } - else - { - Q_strcat(dest, size, "#define varying in\n"); - - Q_strcat(dest, size, "out vec4 out_Color;\n"); - Q_strcat(dest, size, "#define gl_FragColor out_Color\n"); - } - } - else - { - Q_strcat(dest, size, "#version 120\n"); - } - - // HACK: add some macros to avoid extra uniforms and save speed and code maintenance - //Q_strcat(dest, size, - // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value)); - //Q_strcat(dest, size, - // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value)); - //Q_strcat(dest, size, - // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value)); - - - Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n"); - - //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS)); - - Q_strcat(dest, size, - va("#ifndef deformGen_t\n" - "#define deformGen_t\n" - "#define DGEN_WAVE_SIN %i\n" - "#define DGEN_WAVE_SQUARE %i\n" - "#define DGEN_WAVE_TRIANGLE %i\n" - "#define DGEN_WAVE_SAWTOOTH %i\n" - "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n" - "#define DGEN_BULGE %i\n" - "#define DGEN_MOVE %i\n" - "#endif\n", - DGEN_WAVE_SIN, - DGEN_WAVE_SQUARE, - DGEN_WAVE_TRIANGLE, - DGEN_WAVE_SAWTOOTH, - DGEN_WAVE_INVERSE_SAWTOOTH, - DGEN_BULGE, - DGEN_MOVE)); - - Q_strcat(dest, size, - va("#ifndef tcGen_t\n" - "#define tcGen_t\n" - "#define TCGEN_LIGHTMAP %i\n" - "#define TCGEN_TEXTURE %i\n" - "#define TCGEN_ENVIRONMENT_MAPPED %i\n" - "#define TCGEN_FOG %i\n" - "#define TCGEN_VECTOR %i\n" - "#endif\n", - TCGEN_LIGHTMAP, - TCGEN_TEXTURE, - TCGEN_ENVIRONMENT_MAPPED, - TCGEN_FOG, - TCGEN_VECTOR)); - - Q_strcat(dest, size, - va("#ifndef colorGen_t\n" - "#define colorGen_t\n" - "#define CGEN_LIGHTING_DIFFUSE %i\n" - "#endif\n", - CGEN_LIGHTING_DIFFUSE)); - - Q_strcat(dest, size, - va("#ifndef alphaGen_t\n" - "#define alphaGen_t\n" - "#define AGEN_LIGHTING_SPECULAR %i\n" - "#define AGEN_PORTAL %i\n" - "#define AGEN_FRESNEL %i\n" - "#endif\n", - AGEN_LIGHTING_SPECULAR, - AGEN_PORTAL, - AGEN_FRESNEL)); - - Q_strcat(dest, size, - va("#ifndef texenv_t\n" - "#define texenv_t\n" - "#define TEXENV_MODULATE %i\n" - "#define TEXENV_ADD %i\n" - "#define TEXENV_REPLACE %i\n" - "#endif\n", - GL_MODULATE, - GL_ADD, - GL_REPLACE)); - - fbufWidthScale = 1.0f / ((float)glConfig.vidWidth); - fbufHeightScale = 1.0f / ((float)glConfig.vidHeight); - Q_strcat(dest, size, - va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale)); - - Q_strcat(dest, size, - va("#ifndef r_obbcorrect\n#define r_obbcorrect %i\n#endif\n", (int)(pow(2, tr.overbrightBits)))); - - if (extra) - { - Q_strcat(dest, size, extra); - } - - // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line - // so we have to reset the line counting - Q_strcat(dest, size, "#line 0\n"); -} - -static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, const GLcharARB *buffer, int size, GLenum shaderType) -{ - GLint compiled; - GLhandleARB shader; - - shader = qglCreateShaderObjectARB(shaderType); - - qglShaderSourceARB(shader, 1, (const GLcharARB **)&buffer, &size); - - // compile shader - qglCompileShaderARB(shader); - - // check if shader compiled - qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); - if(!compiled) - { - GLSL_PrintShaderSource(shader); - GLSL_PrintInfoLog(shader, qfalse); - ri.Error(ERR_DROP, "Couldn't compile shader"); - return 0; - } - - //GLSL_PrintInfoLog(shader, qtrue); - //GLSL_PrintShaderSource(shader); - - if (*prevShader) - { - qglDetachObjectARB(program, *prevShader); - qglDeleteObjectARB(*prevShader); - } - - // attach shader to program - qglAttachObjectARB(program, shader); - - *prevShader = shader; - - return 1; -} - - -static void GLSL_DumpText(const char *shaderText, int size, const char *name, GLenum shaderType) -{ - int i, l, inc; - ri.Printf(PRINT_ALL, "static const char *fallback%sShader_%s =\n\"", name, shaderType == GL_VERTEX_SHADER_ARB ? "vp" : "fp"); - l = 0; - - for (i = 0; i < size; i++) - { - switch (shaderText[i]) - { - case '\a': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - case '\v': - case '"': - case '\\': - inc = 2; - break; - default: - inc = 1; - break; - } - - l += inc; - - if (l >= 76) - { - ri.Printf(PRINT_ALL, "\"\n\""); - l = inc; - } - - switch (shaderText[i]) - { - case '\a': - ri.Printf(PRINT_ALL, "\\a"); - break; - case '\b': - ri.Printf(PRINT_ALL, "\\b"); - break; - case '\f': - ri.Printf(PRINT_ALL, "\\f"); - break; - case '\n': - ri.Printf(PRINT_ALL, "\\n"); - break; - case '\r': - ri.Printf(PRINT_ALL, "\\r"); - break; - case '\t': - ri.Printf(PRINT_ALL, "\\t"); - break; - case '\v': - ri.Printf(PRINT_ALL, "\\v"); - break; - case '"': - ri.Printf(PRINT_ALL, "\\\""); - break; - case '\\': - ri.Printf(PRINT_ALL, "\\\\"); - break; - default: - ri.Printf(PRINT_ALL, "%c", shaderText[i]); - break; - } - } - ri.Printf(PRINT_ALL, "\";\n\n"); -} - -static int GLSL_LoadGPUShaderText(const char *name, const char *fallback, - GLenum shaderType, char *dest, int destSize, qboolean dump) -{ - char filename[MAX_QPATH]; - GLcharARB *buffer = NULL; - const GLcharARB *shaderText = NULL; - int size; - int result; - - if(shaderType == GL_VERTEX_SHADER_ARB) - { - Com_sprintf(filename, sizeof(filename), "glsl/%s_vp.glsl", name); - } - else - { - Com_sprintf(filename, sizeof(filename), "glsl/%s_fp.glsl", name); - } - - ri.Printf(PRINT_DEVELOPER, "...loading '%s'\n", filename); - size = ri.FS_ReadFile(filename, (void **)&buffer); - if(!buffer) - { - if (fallback) - { - ri.Printf(PRINT_DEVELOPER, "couldn't load, using fallback\n"); - shaderText = fallback; - size = strlen(shaderText); - } - else - { - ri.Printf(PRINT_DEVELOPER, "couldn't load!\n"); - return 0; - } - } - else - { - shaderText = buffer; - } - - if (dump) - GLSL_DumpText(shaderText, size, name, shaderType); - - if (size > destSize) - { - result = 0; - } - else - { - Q_strncpyz(dest, shaderText, size + 1); - result = 1; - } - - if (buffer) - { - ri.FS_FreeFile(buffer); - } - - return result; -} - -static void GLSL_LinkProgram(GLhandleARB program) -{ - GLint linked; - - qglLinkProgramARB(program); - - qglGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked); - if(!linked) - { - GLSL_PrintInfoLog(program, qfalse); - ri.Error(ERR_DROP, "\nshaders failed to link"); - } -} - -static void GLSL_ValidateProgram(GLhandleARB program) -{ - GLint validated; - - qglValidateProgramARB(program); - - qglGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated); - if(!validated) - { - GLSL_PrintInfoLog(program, qfalse); - ri.Error(ERR_DROP, "\nshaders failed to validate"); - } -} - -static void GLSL_ShowProgramUniforms(GLhandleARB program) -{ - int i, count, size; - GLenum type; - char uniformName[1000]; - - // install the executables in the program object as part of current state. - qglUseProgramObjectARB(program); - - // check for GL Errors - - // query the number of active uniforms - qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count); - - // Loop over each of the active uniforms, and set their value - for(i = 0; i < count; i++) - { - qglGetActiveUniformARB(program, i, sizeof(uniformName), NULL, &size, &type, uniformName); - - ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName); - } - - qglUseProgramObjectARB(0); -} - -static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode, int numUniforms) -{ - ri.Printf(PRINT_DEVELOPER, "------- GPU shader -------\n"); - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "GLSL_InitGPUShader2: \"%s\" is too long\n", name); - } - - Q_strncpyz(program->name, name, sizeof(program->name)); - - program->program = qglCreateProgramObjectARB(); - program->attribs = attribs; - - if (!(GLSL_CompileGPUShader(program->program, &program->vertexShader, vpCode, strlen(vpCode), GL_VERTEX_SHADER_ARB))) - { - ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name); - qglDeleteObjectARB(program->program); - return 0; - } - - if(fpCode) - { - if(!(GLSL_CompileGPUShader(program->program, &program->fragmentShader, fpCode, strlen(fpCode), GL_FRAGMENT_SHADER_ARB))) - { - ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name); - qglDeleteObjectARB(program->program); - return 0; - } - } - - if(attribs & ATTR_POSITION) - qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION, "attr_Position"); - - if(attribs & ATTR_TEXCOORD) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD0, "attr_TexCoord0"); - - if(attribs & ATTR_LIGHTCOORD) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD1, "attr_TexCoord1"); - -// if(attribs & ATTR_TEXCOORD2) -// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD2, "attr_TexCoord2"); - -// if(attribs & ATTR_TEXCOORD3) -// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD3, "attr_TexCoord3"); - -#ifdef USE_VERT_TANGENT_SPACE - if(attribs & ATTR_TANGENT) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent"); - - if(attribs & ATTR_BITANGENT) - qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT, "attr_Bitangent"); -#endif - - if(attribs & ATTR_NORMAL) - qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL, "attr_Normal"); - - if(attribs & ATTR_COLOR) - qglBindAttribLocationARB(program->program, ATTR_INDEX_COLOR, "attr_Color"); - - if(attribs & ATTR_PAINTCOLOR) - qglBindAttribLocationARB(program->program, ATTR_INDEX_PAINTCOLOR, "attr_PaintColor"); - - if(attribs & ATTR_LIGHTDIRECTION) - qglBindAttribLocationARB(program->program, ATTR_INDEX_LIGHTDIRECTION, "attr_LightDirection"); - - if(attribs & ATTR_POSITION2) - qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION2, "attr_Position2"); - - if(attribs & ATTR_NORMAL2) - qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL2, "attr_Normal2"); - -#ifdef USE_VERT_TANGENT_SPACE - if(attribs & ATTR_TANGENT2) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT2, "attr_Tangent2"); - - if(attribs & ATTR_BITANGENT2) - qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT2, "attr_Bitangent2"); -#endif - - GLSL_LinkProgram(program->program); - - program->numUniforms = numUniforms; - - { - int i, size; - - size = sizeof(*program->uniforms) * numUniforms; - program->uniforms = ri.Malloc(size); - for (i = 0; i < numUniforms; i++) - { - program->uniforms[i] = -1; - } - - size = sizeof(*program->uniformTypes) * numUniforms; - program->uniformTypes = ri.Malloc(size); - memset(program->uniformTypes, 0, size); - - size = sizeof(*program->uniformBufferOffsets) * numUniforms; - program->uniformBufferOffsets = ri.Malloc(size); - memset(program->uniformBufferOffsets, 0, size); - } - - return 1; -} - -static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name, - int attribs, qboolean fragmentShader, const GLcharARB *extra, qboolean addHeader, - const char *fallback_vp, const char *fallback_fp, int numUniforms) -{ - char vpCode[32000]; - char fpCode[32000]; - char *postHeader; - int size; - int result; - - size = sizeof(vpCode); - if (addHeader) - { - GLSL_GetShaderHeader(GL_VERTEX_SHADER_ARB, extra, vpCode, size); - postHeader = &vpCode[strlen(vpCode)]; - size -= strlen(vpCode); - } - else - { - postHeader = &vpCode[0]; - } - - if (!GLSL_LoadGPUShaderText(name, fallback_vp, GL_VERTEX_SHADER_ARB, postHeader, size, qfalse)) - { - return 0; - } - - if (fragmentShader) - { - size = sizeof(fpCode); - if (addHeader) - { - GLSL_GetShaderHeader(GL_FRAGMENT_SHADER_ARB, extra, fpCode, size); - postHeader = &fpCode[strlen(fpCode)]; - size -= strlen(fpCode); - } - else - { - postHeader = &fpCode[0]; - } - - if (!GLSL_LoadGPUShaderText(name, fallback_fp, GL_FRAGMENT_SHADER_ARB, postHeader, size, qfalse)) - { - return 0; - } - } - - result = GLSL_InitGPUShader2(program, name, attribs, vpCode, fragmentShader ? fpCode : NULL, numUniforms); - - return result; -} - -// intentionally deceiving the user here, not actually setting the names but getting their indexes. -void GLSL_AddUniform(shaderProgram_t *program, int uniformNum, const char *name, int type) -{ - GLint *uniforms = program->uniforms; - - uniforms[uniformNum] = qglGetUniformLocationARB(program->program, name); - program->uniformTypes[uniformNum] = type; -} - -void GLSL_EndUniforms(shaderProgram_t *program) -{ - if (program->numUniforms) - { - int i, size; - - size = 0; - for (i = 0; i < program->numUniforms; i++) - { - if (program->uniforms[i] != -1) - { - program->uniformBufferOffsets[i] = size; - - switch(program->uniformTypes[i]) - { - case GLSL_INT: - size += sizeof(GLint); - break; - case GLSL_FLOAT: - size += sizeof(GLfloat); - break; - case GLSL_FLOAT5: - size += sizeof(vec_t) * 5; - break; - case GLSL_VEC2: - size += sizeof(vec_t) * 2; - break; - case GLSL_VEC3: - size += sizeof(vec_t) * 3; - break; - case GLSL_VEC4: - size += sizeof(vec_t) * 4; - break; - case GLSL_MAT16: - size += sizeof(vec_t) * 16; - break; - default: - break; - } - } - } - - program->uniformBuffer = ri.Malloc(size); - - } -} - -void GLSL_FinishGPUShader(shaderProgram_t *program) -{ - GLSL_ValidateProgram(program->program); - GLSL_ShowProgramUniforms(program->program); - GL_CheckErrors(); -} - -void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value) -{ - GLint *uniforms = program->uniforms; - GLint *compare = (GLint *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_INT) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformInt: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (value == *compare) - { - return; - } - - *compare = value; - - qglUniform1iARB(uniforms[uniformNum], value); -} - -void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value) -{ - GLint *uniforms = program->uniforms; - GLfloat *compare = (GLfloat *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_FLOAT) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (value == *compare) - { - return; - } - - *compare = value; - - qglUniform1fARB(uniforms[uniformNum], value); -} - -void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v) -{ - GLint *uniforms = program->uniforms; - vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_VEC2) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec2: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (v[0] == compare[0] && v[1] == compare[1]) - { - return; - } - - compare[0] = v[0]; - compare[1] = v[1]; - - qglUniform2fARB(uniforms[uniformNum], v[0], v[1]); -} - -void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v) -{ - GLint *uniforms = program->uniforms; - vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_VEC3) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec3: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (VectorCompare(v, compare)) - { - return; - } - - VectorCopy(v, compare); - - qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]); -} - -void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v) -{ - GLint *uniforms = program->uniforms; - vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_VEC4) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec4: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (VectorCompare4(v, compare)) - { - return; - } - - VectorCopy4(v, compare); - - qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]); -} - -void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v) -{ - GLint *uniforms = program->uniforms; - vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - { - ri.Printf( PRINT_ALL, "well shit.\n"); - return; - } - - if (program->uniformTypes[uniformNum] != GLSL_FLOAT5) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat5: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (VectorCompare5(v, compare)) - { - return; - } - - VectorCopy5(v, compare); - - qglUniform1fvARB(uniforms[uniformNum], 5, v); -} - -void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix) -{ - GLint *uniforms = program->uniforms; - vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]); - - if (uniforms[uniformNum] == -1) - return; - - if (program->uniformTypes[uniformNum] != GLSL_MAT16) - { - ri.Printf( PRINT_WARNING, "GLSL_SetUniformMatrix16: wrong type for uniform %i in program %s\n", uniformNum, program->name); - return; - } - - if (Matrix16Compare(matrix, compare)) - { - return; - } - - Matrix16Copy(matrix, compare); - - qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix); -} - -void GLSL_DeleteGPUShader(shaderProgram_t *program) -{ - if(program->program) - { - if (program->vertexShader) - { - qglDetachObjectARB(program->program, program->vertexShader); - qglDeleteObjectARB(program->vertexShader); - } - - if (program->fragmentShader) - { - qglDetachObjectARB(program->program, program->fragmentShader); - qglDeleteObjectARB(program->fragmentShader); - } - - qglDeleteObjectARB(program->program); - - if (program->uniforms) - { - ri.Free(program->uniforms); - } - - if (program->uniformTypes) - { - ri.Free(program->uniformTypes); - } - - if (program->uniformBuffer) - { - ri.Free(program->uniformBuffer); - } - - if (program->uniformBufferOffsets) - { - ri.Free(program->uniformBufferOffsets); - } - - Com_Memset(program, 0, sizeof(*program)); - } -} - -void GLSL_InitGPUShaders(void) -{ - int startTime, endTime; - int i; - char extradefines[1024]; - int attribs; - int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0; - - ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n"); - - // make sure the render thread is stopped - R_SyncRenderThread(); - - startTime = ri.Milliseconds(); - - for (i = 0; i < GENERICDEF_COUNT; i++) - { - attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR; - extradefines[0] = '\0'; - - if (i & GENERICDEF_USE_DEFORM_VERTEXES) - Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); - - if (i & GENERICDEF_USE_TCGEN) - Q_strcat(extradefines, 1024, "#define USE_TCGEN\n"); - - if (i & GENERICDEF_USE_VERTEX_ANIMATION) - { - Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); - attribs |= ATTR_POSITION2 | ATTR_NORMAL2; - } - - if (i & GENERICDEF_USE_FOG) - Q_strcat(extradefines, 1024, "#define USE_FOG\n"); - - if (i & GENERICDEF_USE_RGBAGEN) - Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n"); - - if (i & GENERICDEF_USE_LIGHTMAP) - Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); - - if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) - Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n"); - - if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackGenericShader_vp, fallbackGenericShader_fp, GENERIC_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load generic shader!\n"); - } - - // There's actually no need to filter these out, since they'll - // redirect to -1 if nonexistent, but it's more understandable this way. - - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4); - - if (i & GENERICDEF_USE_RGBAGEN) - { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLORGEN, "u_ColorGen", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_ALPHAGEN, "u_AlphaGen", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_PORTALRANGE, "u_PortalRange", GLSL_FLOAT); - } - - if (i & GENERICDEF_USE_TCGEN) - { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0, "u_TCGen0", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR0, "u_TCGen0Vector0", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR1, "u_TCGen0Vector1", GLSL_VEC3); - } - - if (i & GENERICDEF_USE_FOG) - { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGCOLORMASK, "u_FogColorMask", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT); - } - - if (i & GENERICDEF_USE_DEFORM_VERTEXES) - { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5); - } - - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TEXTURE1ENV, "u_Texture1Env", GLSL_INT); - - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT); - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT); - - - if (i & GENERICDEF_USE_VERTEX_ANIMATION) - { - GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); - } - - GLSL_EndUniforms(&tr.genericShader[i]); - - qglUseProgramObjectARB(tr.genericShader[i].program); - GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); - GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.genericShader[i]); - - numGenShaders++; - } - - - attribs = ATTR_POSITION | ATTR_TEXCOORD; - - if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackTextureColorShader_vp, fallbackTextureColorShader_fp, TEXTURECOLOR_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load texturecolor shader!\n"); - } - - GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_DiffuseMap", GLSL_INT); - - GLSL_EndUniforms(&tr.textureColorShader); - - qglUseProgramObjectARB(tr.textureColorShader.program); - GLSL_SetUniformInt(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.textureColorShader); - - numEtcShaders++; - - - attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; - - if (!GLSL_InitGPUShader(&tr.fogShader, "fogpass", attribs, qtrue, NULL, qtrue, fallbackFogPassShader_vp, fallbackFogPassShader_fp, FOGPASS_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load fogpass shader!\n"); - } - - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_TIME, "u_Time", GLSL_FLOAT); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.fogShader, FOGPASS_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); - - GLSL_EndUniforms(&tr.fogShader); - GLSL_FinishGPUShader(&tr.fogShader); - - numEtcShaders++; - - - attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD; - - if (!GLSL_InitGPUShader(&tr.dlightallShader, "dlight", attribs, qtrue, NULL, qtrue, fallbackDlightShader_vp, fallbackDlightShader_fp, DLIGHT_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load dlight shader!\n"); - } - - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DLIGHTINFO, "u_DlightInfo", GLSL_VEC4); - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT); - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5); - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_TIME, "u_Time", GLSL_FLOAT); - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - GLSL_AddUniform(&tr.dlightallShader, DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - - GLSL_EndUniforms(&tr.dlightallShader); - - qglUseProgramObjectARB(tr.dlightallShader.program); - GLSL_SetUniformInt(&tr.dlightallShader, DLIGHT_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.dlightallShader); - - numEtcShaders++; - - - for (i = 0; i < LIGHTDEF_COUNT; i++) - { - // skip impossible combos - if ((i & LIGHTDEF_USE_NORMALMAP) && !r_normalMapping->integer) - continue; - - if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer) - continue; - - if ((i & LIGHTDEF_USE_SPECULARMAP) && !r_specularMapping->integer) - continue; - - if ((i & LIGHTDEF_USE_DELUXEMAP) && !r_deluxeMapping->integer) - continue; - - if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_USE_DELUXEMAP)) - continue; - - if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP)) - continue; - - if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHT_VECTOR)) - { - if (i & LIGHTDEF_USE_SHADOWMAP) - continue; - } - - attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL; - - extradefines[0] = '\0'; - - if (r_normalAmbient->value > 0.003f) - Q_strcat(extradefines, 1024, va("#define r_normalAmbient %f\n", r_normalAmbient->value)); - - if (r_dlightMode->integer >= 2) - Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); - - if (1) - { - Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); - } - - if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel)) - Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n"); - - if (i & LIGHTDEF_LIGHTTYPE_MASK) - { - Q_strcat(extradefines, 1024, "#define USE_LIGHT\n"); - - if (r_normalMapping->integer == 0 && r_specularMapping->integer == 0) - Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n"); - - switch (i & LIGHTDEF_LIGHTTYPE_MASK) - { - case LIGHTDEF_USE_LIGHTMAP: - Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); - attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION; - break; - case LIGHTDEF_USE_LIGHT_VECTOR: - Q_strcat(extradefines, 1024, "#define USE_LIGHT_VECTOR\n"); - break; - case LIGHTDEF_USE_LIGHT_VERTEX: - Q_strcat(extradefines, 1024, "#define USE_LIGHT_VERTEX\n"); - attribs |= ATTR_LIGHTDIRECTION; - break; - default: - break; - } - } - - if ((i & LIGHTDEF_USE_NORMALMAP) && r_normalMapping->integer) - { - Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n"); - - if (r_normalMapping->integer == 2) - Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n"); - -#ifdef USE_VERT_TANGENT_SPACE - Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n"); - attribs |= ATTR_TANGENT | ATTR_BITANGENT; -#endif - } - - if ((i & LIGHTDEF_USE_SPECULARMAP) && r_specularMapping->integer) - { - Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n"); - - switch (r_specularMapping->integer) - { - case 1: - default: - Q_strcat(extradefines, 1024, "#define USE_TRIACE\n"); - break; - - case 2: - Q_strcat(extradefines, 1024, "#define USE_BLINN\n"); - break; - - case 3: - Q_strcat(extradefines, 1024, "#define USE_COOK_TORRANCE\n"); - break; - - case 4: - Q_strcat(extradefines, 1024, "#define USE_TORRANCE_SPARROW\n"); - break; - } - } - - if ((i & LIGHTDEF_USE_DELUXEMAP) && r_deluxeMapping->integer) - Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n"); - - if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) - Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); - - if (i & LIGHTDEF_USE_SHADOWMAP) - Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); - - if (i & LIGHTDEF_TCGEN_ENVIRONMENT) - Q_strcat(extradefines, 1024, "#define TCGEN_ENVIRONMENT\n"); - - if (i & LIGHTDEF_ENTITY) - { - Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n"); - attribs |= ATTR_POSITION2 | ATTR_NORMAL2; - -#ifdef USE_VERT_TANGENT_SPACE - if (i & LIGHTDEF_USE_NORMALMAP && r_normalMapping->integer) - { - attribs |= ATTR_TANGENT2 | ATTR_BITANGENT2; - } -#endif - } - - if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackLightallShader_vp, fallbackLightallShader_fp, GENERIC_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load lightall shader!\n"); - } - - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_MAT16); - //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALTEXMATRIX, "u_NormalTexMatrix", GLSL_MAT16); - //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARTEXMATRIX, "u_SpecularTexMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3); - - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, "u_NormalMap", GLSL_INT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, "u_DeluxeMap", GLSL_INT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, "u_SpecularMap", GLSL_INT); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT); - - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT); - - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MATERIALINFO, "u_MaterialInfo", GLSL_VEC2); - - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4); - GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); - - GLSL_EndUniforms(&tr.lightallShader[i]); - - qglUseProgramObjectARB(tr.lightallShader[i].program); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, TB_NORMALMAP); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, TB_DELUXEMAP); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, TB_SPECULARMAP); - GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.lightallShader[i]); - - numLightShaders++; - } - - attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; - - extradefines[0] = '\0'; - - if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShadowfillShader_vp, fallbackShadowfillShader_fp, GENERIC_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load shadowfill shader!\n"); - } - - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT); - - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); - GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT); - - GLSL_EndUniforms(&tr.shadowmapShader); - GLSL_FinishGPUShader(&tr.shadowmapShader); - - numEtcShaders++; - - attribs = ATTR_POSITION | ATTR_NORMAL; - extradefines[0] = '\0'; - - Q_strcat(extradefines, 1024, "#define USE_PCF\n#define USE_DISCARD\n"); - - if (!GLSL_InitGPUShader(&tr.pshadowShader, "pshadow", attribs, qtrue, extradefines, qtrue, fallbackPshadowShader_vp, fallbackPshadowShader_fp, PSHADOW_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load pshadow shader!\n"); - } - - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTFORWARD, "u_LightForward", GLSL_VEC3); - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTUP, "u_LightUp", GLSL_VEC3); - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRIGHT, "u_LightRight", GLSL_VEC3); - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4); - GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT); - - GLSL_EndUniforms(&tr.pshadowShader); - - qglUseProgramObjectARB(tr.pshadowShader.program); - GLSL_SetUniformInt(&tr.pshadowShader, PSHADOW_UNIFORM_SHADOWMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.pshadowShader); - - numEtcShaders++; - - - attribs = ATTR_POSITION | ATTR_TEXCOORD; - extradefines[0] = '\0'; - - if (!GLSL_InitGPUShader(&tr.down4xShader, "down4x", attribs, qtrue, extradefines, qtrue, fallbackDown4xShader_vp, fallbackDown4xShader_fp, TEXTURECOLOR_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load down4x shader!\n"); - } - - GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2); - - GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT); - - GLSL_EndUniforms(&tr.down4xShader); - - qglUseProgramObjectARB(tr.down4xShader.program); - GLSL_SetUniformInt(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.down4xShader); - - numEtcShaders++; - - - attribs = ATTR_POSITION | ATTR_TEXCOORD; - extradefines[0] = '\0'; - - if (!GLSL_InitGPUShader(&tr.bokehShader, "bokeh", attribs, qtrue, extradefines, qtrue, fallbackBokehShader_vp, fallbackBokehShader_fp, TEXTURECOLOR_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load bokeh shader!\n"); - } - - GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2); - GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - - GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT); - - GLSL_EndUniforms(&tr.bokehShader); - - qglUseProgramObjectARB(tr.bokehShader.program); - GLSL_SetUniformInt(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.bokehShader); - - numEtcShaders++; - - - attribs = ATTR_POSITION | ATTR_TEXCOORD; - extradefines[0] = '\0'; - - if (!GLSL_InitGPUShader(&tr.tonemapShader, "tonemap", attribs, qtrue, extradefines, qtrue, fallbackToneMapShader_vp, fallbackToneMapShader_fp, TEXTURECOLOR_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load tonemap shader!\n"); - } - - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2); - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, "u_AutoExposureMinMax", GLSL_VEC2); - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT); - GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, "u_LevelsMap", GLSL_INT); - - GLSL_EndUniforms(&tr.tonemapShader); - - qglUseProgramObjectARB(tr.tonemapShader.program); - GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_COLORMAP); - GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, TB_LEVELSMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.tonemapShader); - - numEtcShaders++; - - - for (i = 0; i < 2; i++) - { - attribs = ATTR_POSITION | ATTR_TEXCOORD; - extradefines[0] = '\0'; - - if (!i) - Q_strcat(extradefines, 1024, "#define FIRST_PASS\n"); - - if (!GLSL_InitGPUShader(&tr.calclevels4xShader[i], "calclevels4x", attribs, qtrue, extradefines, qtrue, fallbackCalcLevels4xShader_vp, fallbackCalcLevels4xShader_fp, TEXTURECOLOR_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load calclevels4x shader!\n"); - } - - GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16); - GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2); - GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4); - - GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT); - - GLSL_EndUniforms(&tr.calclevels4xShader[i]); - - qglUseProgramObjectARB(tr.calclevels4xShader[i].program); - GLSL_SetUniformInt(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.calclevels4xShader[i]); - - numEtcShaders++; - } - - - attribs = ATTR_POSITION | ATTR_TEXCOORD; - extradefines[0] = '\0'; - - if (r_shadowFilter->integer >= 1) - Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER\n"); - - if (r_shadowFilter->integer >= 2) - Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n"); - - Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n"); - - Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", r_shadowMapSize->integer)); - Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value)); - - - if (!GLSL_InitGPUShader(&tr.shadowmaskShader, "shadowmask", attribs, qtrue, extradefines, qtrue, fallbackShadowmaskShader_vp, fallbackShadowmaskShader_fp, SHADOWMASK_UNIFORM_COUNT)) - { - ri.Error(ERR_FATAL, "Could not load shadowmask shader!\n"); - } - - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP, "u_ShadowMvp", GLSL_MAT16); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP2, "u_ShadowMvp2", GLSL_MAT16); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP3, "u_ShadowMvp3", GLSL_MAT16); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWFORWARD,"u_ViewForward", GLSL_VEC3); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWLEFT, "u_ViewLeft", GLSL_VEC3); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWUP, "u_ViewUp", GLSL_VEC3); - - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, "u_ShadowMap2", GLSL_INT); - GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, "u_ShadowMap3", GLSL_INT); - - GLSL_EndUniforms(&tr.shadowmaskShader); - - qglUseProgramObjectARB(tr.shadowmaskShader.program); - GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); - GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, TB_SHADOWMAP); - GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, TB_SHADOWMAP2); - GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, TB_SHADOWMAP3); - qglUseProgramObjectARB(0); - - GLSL_FinishGPUShader(&tr.shadowmaskShader); - - numEtcShaders++; - - - endTime = ri.Milliseconds(); - - ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n", - numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders, - numEtcShaders, (endTime - startTime) / 1000.0); - - if (0) - { - GLSL_LoadGPUShaderText("Generic", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Generic", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("TextureColor", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("TextureColor", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("FogPass", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("FogPass", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Dlight", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Dlight", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Lightall", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Lightall", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Shadowfill", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Pshadow", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Pshadow", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Down4x", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Down4x", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Bokeh", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Bokeh", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("ToneMap", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("ToneMap", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("CalcLevels4x", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("CalcLevels4x", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - - GLSL_LoadGPUShaderText("Shadowmask", NULL, GL_VERTEX_SHADER_ARB, NULL, 0, qtrue); - GLSL_LoadGPUShaderText("Shadowmask", NULL, GL_FRAGMENT_SHADER_ARB, NULL, 0, qtrue); - } - -} - -void GLSL_ShutdownGPUShaders(void) -{ - int i; - - ri.Printf(PRINT_ALL, "------- GLSL_ShutdownGPUShaders -------\n"); - - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL); -#ifdef USE_VERT_TANGENT_SPACE - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT); - qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT); -#endif - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); -#ifdef USE_VERT_TANGENT_SPACE - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); - qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2); -#endif - qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR); - qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); - GLSL_BindNullProgram(); - - for ( i = 0; i < GENERICDEF_COUNT; i++) - GLSL_DeleteGPUShader(&tr.genericShader[i]); - - GLSL_DeleteGPUShader(&tr.textureColorShader); - GLSL_DeleteGPUShader(&tr.fogShader); - GLSL_DeleteGPUShader(&tr.dlightallShader); - - for ( i = 0; i < LIGHTDEF_COUNT; i++) - GLSL_DeleteGPUShader(&tr.lightallShader[i]); - - GLSL_DeleteGPUShader(&tr.shadowmapShader); - GLSL_DeleteGPUShader(&tr.pshadowShader); - GLSL_DeleteGPUShader(&tr.down4xShader); - - for ( i = 0; i < 2; i++) - GLSL_DeleteGPUShader(&tr.calclevels4xShader[i]); - - glState.currentProgram = 0; - qglUseProgramObjectARB(0); -} - - -void GLSL_BindProgram(shaderProgram_t * program) -{ - if(!program) - { - GLSL_BindNullProgram(); - return; - } - - if(r_logFile->integer) - { - // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name)); - } - - if(glState.currentProgram != program) - { - qglUseProgramObjectARB(program->program); - glState.currentProgram = program; - backEnd.pc.c_glslShaderBinds++; - } -} - - -void GLSL_BindNullProgram(void) -{ - if(r_logFile->integer) - { - GLimp_LogComment("--- GL_BindNullProgram ---\n"); - } - - if(glState.currentProgram) - { - qglUseProgramObjectARB(0); - glState.currentProgram = NULL; - } -} - - -void GLSL_VertexAttribsState(uint32_t stateBits) -{ - uint32_t diff; - - GLSL_VertexAttribPointers(stateBits); - - diff = stateBits ^ glState.vertexAttribsState; - if(!diff) - { - return; - } - - if(diff & ATTR_POSITION) - { - if(stateBits & ATTR_POSITION) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION); - } - } - - if(diff & ATTR_TEXCOORD) - { - if(stateBits & ATTR_TEXCOORD) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - } - } - - if(diff & ATTR_LIGHTCOORD) - { - if(stateBits & ATTR_LIGHTCOORD) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - } - } - - if(diff & ATTR_NORMAL) - { - if(stateBits & ATTR_NORMAL) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL); - } - } - -#ifdef USE_VERT_TANGENT_SPACE - if(diff & ATTR_TANGENT) - { - if(stateBits & ATTR_TANGENT) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT); - } - } - - if(diff & ATTR_BITANGENT) - { - if(stateBits & ATTR_BITANGENT) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT); - } - } -#endif - - if(diff & ATTR_COLOR) - { - if(stateBits & ATTR_COLOR) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_COLOR); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR); - } - } - - if(diff & ATTR_LIGHTDIRECTION) - { - if(stateBits & ATTR_LIGHTDIRECTION) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); - } - } - - if(diff & ATTR_POSITION2) - { - if(stateBits & ATTR_POSITION2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - } - } - - if(diff & ATTR_NORMAL2) - { - if(stateBits & ATTR_NORMAL2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); - } - } - -#ifdef USE_VERT_TANGENT_SPACE - if(diff & ATTR_TANGENT2) - { - if(stateBits & ATTR_TANGENT2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); - } - } - - if(diff & ATTR_BITANGENT2) - { - if(stateBits & ATTR_BITANGENT2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2); - } - } -#endif - - glState.vertexAttribsState = stateBits; -} - -void GLSL_VertexAttribPointers(uint32_t attribBits) -{ - if(!glState.currentVBO) - { - ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound"); - return; - } - - // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", glState.currentVBO->name)); - - if((attribBits & ATTR_POSITION) && !(glState.vertexAttribPointersSet & ATTR_POSITION)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsNewFrame * glState.currentVBO->size_xyz)); - glState.vertexAttribPointersSet |= ATTR_POSITION; - } - - if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st)); - glState.vertexAttribPointersSet |= ATTR_TEXCOORD; - } - - if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, glState.currentVBO->stride_lightmap, BUFFER_OFFSET(glState.currentVBO->ofs_lightmap)); - glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD; - } - - if((attribBits & ATTR_NORMAL) && !(glState.vertexAttribPointersSet & ATTR_NORMAL)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); - glState.vertexAttribPointersSet |= ATTR_NORMAL; - } - -#ifdef USE_VERT_TANGENT_SPACE - if((attribBits & ATTR_TANGENT) && !(glState.vertexAttribPointersSet & ATTR_TANGENT)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_TANGENT; - } - - if((attribBits & ATTR_BITANGENT) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_BITANGENT; - } -#endif - - if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, glState.currentVBO->stride_vertexcolor, BUFFER_OFFSET(glState.currentVBO->ofs_vertexcolor)); - glState.vertexAttribPointersSet |= ATTR_COLOR; - } - - if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 3, GL_FLOAT, 0, glState.currentVBO->stride_lightdir, BUFFER_OFFSET(glState.currentVBO->ofs_lightdir)); - glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION; - } - - if((attribBits & ATTR_POSITION2) && !(glState.vertexAttribPointersSet & ATTR_POSITION2)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsOldFrame * glState.currentVBO->size_xyz)); - glState.vertexAttribPointersSet |= ATTR_POSITION2; - } - - if((attribBits & ATTR_NORMAL2) && !(glState.vertexAttribPointersSet & ATTR_NORMAL2)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); - glState.vertexAttribPointersSet |= ATTR_NORMAL2; - } - -#ifdef USE_VERT_TANGENT_SPACE - if((attribBits & ATTR_TANGENT2) && !(glState.vertexAttribPointersSet & ATTR_TANGENT2)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_TANGENT2; - } - - if((attribBits & ATTR_BITANGENT2) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT2)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_BITANGENT2; - } -#endif - -} - -shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) -{ - shaderStage_t *pStage = tess.xstages[stage]; - int shaderAttribs = 0; - - if (tess.fogNum && pStage->adjustColorsForFog) - { - shaderAttribs |= GENERICDEF_USE_FOG; - } - - if (pStage->bundle[1].image[0] && tess.shader->multitextureEnv) - { - shaderAttribs |= GENERICDEF_USE_LIGHTMAP; - } - - switch (pStage->rgbGen) - { - case CGEN_LIGHTING_DIFFUSE: - shaderAttribs |= GENERICDEF_USE_RGBAGEN; - break; - default: - break; - } - - switch (pStage->alphaGen) - { - case AGEN_LIGHTING_SPECULAR: - case AGEN_PORTAL: - case AGEN_FRESNEL: - shaderAttribs |= GENERICDEF_USE_RGBAGEN; - break; - default: - break; - } - - if (pStage->bundle[0].tcGen != TCGEN_TEXTURE) - { - shaderAttribs |= GENERICDEF_USE_TCGEN; - } - - if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader)) - { - shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; - } - - if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) - { - shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; - } - - return &tr.genericShader[shaderAttribs]; -} diff --git a/code/renderergl2/tr_image.c b/code/renderergl2/tr_image.c deleted file mode 100644 index 25caf1f3..00000000 --- a/code/renderergl2/tr_image.c +++ /dev/null @@ -1,3419 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_image.c -#include "tr_local.h" - -static byte s_intensitytable[256]; -static unsigned char s_gammatable[256]; - -int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; -int gl_filter_max = GL_LINEAR; - -#define FILE_HASH_SIZE 1024 -static image_t* hashTable[FILE_HASH_SIZE]; - -/* -** R_GammaCorrect -*/ -void R_GammaCorrect( byte *buffer, int bufSize ) { - int i; - - for ( i = 0; i < bufSize; i++ ) { - buffer[i] = s_gammatable[buffer[i]]; - } -} - -typedef struct { - char *name; - int minimize, maximize; -} textureMode_t; - -textureMode_t modes[] = { - {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, - {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} -}; - -/* -================ -return a hash value for the filename -================ -*/ -static long generateHashValue( const char *fname ) { - int i; - long hash; - char letter; - - hash = 0; - i = 0; - while (fname[i] != '\0') { - letter = tolower(fname[i]); - if (letter =='.') break; // don't include extension - if (letter =='\\') letter = '/'; // damn path names - hash+=(long)(letter)*(i+119); - i++; - } - hash &= (FILE_HASH_SIZE-1); - return hash; -} - -/* -=============== -GL_TextureMode -=============== -*/ -void GL_TextureMode( const char *string ) { - int i; - image_t *glt; - - for ( i=0 ; i< 6 ; i++ ) { - if ( !Q_stricmp( modes[i].name, string ) ) { - break; - } - } - - // hack to prevent trilinear from being set on voodoo, - // because their driver freaks... - if ( i == 5 && glConfig.hardwareType == GLHW_3DFX_2D3D ) { - ri.Printf( PRINT_ALL, "Refusing to set trilinear on a voodoo.\n" ); - i = 3; - } - - - if ( i == 6 ) { - ri.Printf (PRINT_ALL, "bad filter name\n"); - return; - } - - gl_filter_min = modes[i].minimize; - gl_filter_max = modes[i].maximize; - - // change all the existing mipmap texture objects - for ( i = 0 ; i < tr.numImages ; i++ ) { - glt = tr.images[ i ]; - if ( glt->flags & IMGFLAG_MIPMAP ) { - GL_Bind (glt); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - } -} - -/* -=============== -R_SumOfUsedImages -=============== -*/ -int R_SumOfUsedImages( void ) { - int total; - int i; - - total = 0; - for ( i = 0; i < tr.numImages; i++ ) { - if ( tr.images[i]->frameUsed == tr.frameCount ) { - total += tr.images[i]->uploadWidth * tr.images[i]->uploadHeight; - } - } - - return total; -} - -/* -=============== -R_ImageList_f -=============== -*/ -void R_ImageList_f( void ) { -#if 1 - int i; - int estTotalSize = 0; - - ri.Printf(PRINT_ALL, "\n -w-- -h-- type -size- --name-------\n"); - - for ( i = 0 ; i < tr.numImages ; i++ ) - { - image_t *image = tr.images[i]; - char *format = "???? "; - char *sizeSuffix; - int estSize; - int displaySize; - - estSize = image->uploadHeight * image->uploadWidth; - - switch(image->internalFormat) - { - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - format = "sDXT1"; - // 64 bits per 16 pixels, so 4 bits per pixel - estSize /= 2; - break; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - format = "sDXT5"; - // 128 bits per 16 pixels, so 1 byte per pixel - break; - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: - format = "sBPTC"; - // 128 bits per 16 pixels, so 1 byte per pixel - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - format = "LATC "; - // 128 bits per 16 pixels, so 1 byte per pixel - break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - format = "DXT1 "; - // 64 bits per 16 pixels, so 4 bits per pixel - estSize /= 2; - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - format = "DXT5 "; - // 128 bits per 16 pixels, so 1 byte per pixel - break; - case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: - format = "BPTC "; - // 128 bits per 16 pixels, so 1 byte per pixel - break; - case GL_RGB4_S3TC: - format = "S3TC "; - // same as DXT1? - estSize /= 2; - break; - case GL_RGBA4: - case GL_RGBA8: - case GL_RGBA: - format = "RGBA "; - // 4 bytes per pixel - estSize *= 4; - break; - case GL_LUMINANCE8: - case GL_LUMINANCE16: - case GL_LUMINANCE: - format = "L "; - // 1 byte per pixel? - break; - case GL_RGB5: - case GL_RGB8: - case GL_RGB: - format = "RGB "; - // 3 bytes per pixel? - estSize *= 3; - break; - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE16_ALPHA16: - case GL_LUMINANCE_ALPHA: - format = "LA "; - // 2 bytes per pixel? - estSize *= 2; - break; - case GL_SRGB_EXT: - case GL_SRGB8_EXT: - format = "sRGB "; - // 3 bytes per pixel? - estSize *= 3; - break; - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - format = "sRGBA"; - // 4 bytes per pixel? - estSize *= 4; - break; - case GL_SLUMINANCE_EXT: - case GL_SLUMINANCE8_EXT: - format = "sL "; - // 1 byte per pixel? - break; - case GL_SLUMINANCE_ALPHA_EXT: - case GL_SLUMINANCE8_ALPHA8_EXT: - format = "sLA "; - // 2 byte per pixel? - estSize *= 2; - break; - } - - // mipmap adds about 50% - if (image->flags & IMGFLAG_MIPMAP) - estSize += estSize / 2; - - sizeSuffix = "b "; - displaySize = estSize; - - if (displaySize > 1024) - { - displaySize /= 1024; - sizeSuffix = "kb"; - } - - if (displaySize > 1024) - { - displaySize /= 1024; - sizeSuffix = "Mb"; - } - - if (displaySize > 1024) - { - displaySize /= 1024; - sizeSuffix = "Gb"; - } - - ri.Printf(PRINT_ALL, "%4i: %4ix%4i %s %4i%s %s\n", i, image->uploadWidth, image->uploadHeight, format, displaySize, sizeSuffix, image->imgName); - estTotalSize += estSize; - } - - ri.Printf (PRINT_ALL, " ---------\n"); - ri.Printf (PRINT_ALL, " approx %i bytes\n", estTotalSize); - ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages ); -#else - int i; - image_t *image; - int texels; - const char *yesno[] = { - "no ", "yes" - }; - - ri.Printf (PRINT_ALL, "\n -w-- -h-- -mm- -TMU- -if-- wrap --name-------\n"); - texels = 0; - - for ( i = 0 ; i < tr.numImages ; i++ ) { - image = tr.images[ i ]; - - texels += image->uploadWidth*image->uploadHeight; - ri.Printf (PRINT_ALL, "%4i: %4i %4i %s %d ", - i, image->uploadWidth, image->uploadHeight, yesno[(image->flags & IMGFLAG_MIPMAP) ? 1 : 0], image->TMU ); - switch ( image->internalFormat ) { - case 1: - ri.Printf( PRINT_ALL, "I " ); - break; - case 2: - ri.Printf( PRINT_ALL, "IA " ); - break; - case 3: - ri.Printf( PRINT_ALL, "RGB " ); - break; - case 4: - ri.Printf( PRINT_ALL, "RGBA " ); - break; - case GL_RGBA8: - ri.Printf( PRINT_ALL, "RGBA8" ); - break; - case GL_RGB8: - ri.Printf( PRINT_ALL, "RGB8" ); - break; - case GL_RGB4_S3TC: - ri.Printf( PRINT_ALL, "S3TC " ); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - ri.Printf( PRINT_ALL, "DXT1 " ); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - ri.Printf( PRINT_ALL, "DXT5 " ); - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - ri.Printf( PRINT_ALL, "LATC " ); - break; - case GL_RGBA4: - ri.Printf( PRINT_ALL, "RGBA4" ); - break; - case GL_RGB5: - ri.Printf( PRINT_ALL, "RGB5 " ); - break; - case GL_SRGB_EXT: - ri.Printf( PRINT_ALL, "sRGB " ); - break; - case GL_SRGB8_EXT: - ri.Printf( PRINT_ALL, "sRGB8" ); - break; - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - ri.Printf( PRINT_ALL, "sRGBA" ); - break; - /* - case GL_SLUMINANCE_EXT: - break; - case GL_SLUMINANCE8_EXT: - break; - case GL_SLUMINANCE_ALPHA_EXT: - break; - case GL_SLUMINANCE8_ALPHA8_EXT: - break; - */ - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - ri.Printf( PRINT_ALL, "sDXT1" ); - break; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - ri.Printf( PRINT_ALL, "sDXT5" ); - break; - case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: - ri.Printf( PRINT_ALL, "BPTC " ); - break; - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: - ri.Printf( PRINT_ALL, "sBPTC" ); - break; - default: - ri.Printf( PRINT_ALL, "???? " ); - } - - if (image->flags & IMGFLAG_CLAMPTOEDGE) - ri.Printf( PRINT_ALL, "clmp " ); - else - ri.Printf( PRINT_ALL, "rept " ); - - ri.Printf( PRINT_ALL, " %s\n", image->imgName ); - } - ri.Printf (PRINT_ALL, " ---------\n"); - ri.Printf (PRINT_ALL, " %i total texels (not including mipmaps)\n", texels); - ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages ); -#endif -} - -//======================================================================= - -/* -================ -ResampleTexture - -Used to resample images in a more general than quartering fashion. - -This will only be filtered properly if the resampled size -is greater than half the original size. - -If a larger shrinking is needed, use the mipmap function -before or after. -================ -*/ -static void ResampleTexture( byte *in, int inwidth, int inheight, byte *out, - int outwidth, int outheight ) { - int i, j; - byte *inrow, *inrow2; - int frac, fracstep; - int p1[2048], p2[2048]; - byte *pix1, *pix2, *pix3, *pix4; - - if (outwidth>2048) - ri.Error(ERR_DROP, "ResampleTexture: max width"); - - fracstep = inwidth*0x10000/outwidth; - - frac = fracstep>>2; - for ( i=0 ; i>16); - frac += fracstep; - } - frac = 3*(fracstep>>2); - for ( i=0 ; i>16); - frac += fracstep; - } - - for (i=0 ; i> 1; - for (j=0 ; j>2; - *out++ = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2; - *out++ = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2; - *out++ = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2; - } - } -} - -static void RGBAtoYCoCgA(const byte *in, byte *out, int width, int height) -{ - int x, y; - - for (y = 0; y < height; y++) - { - const byte *inbyte = in + y * width * 4; - byte *outbyte = out + y * width * 4; - - for (x = 0; x < width; x++) - { - byte r, g, b, a, rb2; - - r = *inbyte++; - g = *inbyte++; - b = *inbyte++; - a = *inbyte++; - rb2 = (r + b) >> 1; - - *outbyte++ = (g + rb2) >> 1; // Y = R/4 + G/2 + B/4 - *outbyte++ = (r - b + 256) >> 1; // Co = R/2 - B/2 - *outbyte++ = (g - rb2 + 256) >> 1; // Cg = -R/4 + G/2 - B/4 - *outbyte++ = a; - } - } -} - -static void YCoCgAtoRGBA(const byte *in, byte *out, int width, int height) -{ - int x, y; - - for (y = 0; y < height; y++) - { - const byte *inbyte = in + y * width * 4; - byte *outbyte = out + y * width * 4; - - for (x = 0; x < width; x++) - { - byte _Y, Co, Cg, a; - - _Y = *inbyte++; - Co = *inbyte++; - Cg = *inbyte++; - a = *inbyte++; - - *outbyte++ = CLAMP(_Y + Co - Cg, 0, 255); // R = Y + Co - Cg - *outbyte++ = CLAMP(_Y + Cg - 128, 0, 255); // G = Y + Cg - *outbyte++ = CLAMP(_Y - Co - Cg + 256, 0, 255); // B = Y - Co - Cg - *outbyte++ = a; - } - } -} - - -// uses a sobel filter to change a texture to a normal map -static void RGBAtoNormal(const byte *in, byte *out, int width, int height, qboolean clampToEdge) -{ - int x, y, max; - - // convert to heightmap, storing in alpha - // same as converting to Y in YCoCg - max = 1; - for (y = 0; y < height; y++) - { - const byte *inbyte = in + y * width * 4; - byte *outbyte = out + y * width * 4 + 3; - - for (x = 0; x < width; x++) - { - *outbyte = (inbyte[0] >> 2) + (inbyte[1] >> 1) + (inbyte[2] >> 2); - max = MAX(max, *outbyte); - outbyte += 4; - inbyte += 4; - } - } - - // level out heights - if (max < 255) - { - for (y = 0; y < height; y++) - { - byte *outbyte = out + y * width * 4 + 3; - - for (x = 0; x < width; x++) - { - *outbyte = *outbyte + (255 - max); - outbyte += 4; - } - } - } - - - // now run sobel filter over height values to generate X and Y - // then normalize - for (y = 0; y < height; y++) - { - byte *outbyte = out + y * width * 4; - - for (x = 0; x < width; x++) - { - // 0 1 2 - // 3 4 5 - // 6 7 8 - - byte s[9]; - int x2, y2, i; - vec3_t normal; - - i = 0; - for (y2 = -1; y2 <= 1; y2++) - { - int src_y = y + y2; - - if (clampToEdge) - { - src_y = CLAMP(src_y, 0, height - 1); - } - else - { - src_y = (src_y + height) % height; - } - - - for (x2 = -1; x2 <= 1; x2++) - { - int src_x = x + x2; - - if (clampToEdge) - { - src_x = CLAMP(src_x, 0, height - 1); - } - else - { - src_x = (src_x + height) % height; - } - - s[i++] = *(out + (src_y * width + src_x) * 4 + 3); - } - } - - normal[0] = s[0] - s[2] - + 2 * s[3] - 2 * s[5] - + s[6] - s[8]; - - normal[1] = s[0] + 2 * s[1] + s[2] - - - s[6] - 2 * s[7] - s[8]; - - normal[2] = s[4] * 4; - - if (!VectorNormalize2(normal, normal)) - { - VectorSet(normal, 0, 0, 1); - } - - *outbyte++ = FloatToOffsetByte(normal[0]); - *outbyte++ = FloatToOffsetByte(normal[1]); - *outbyte++ = FloatToOffsetByte(normal[2]); - outbyte++; - } - } -} - -#define COPYSAMPLE(a,b) *(unsigned int *)(a) = *(unsigned int *)(b) - -// based on Fast Curve Based Interpolation -// from Fast Artifacts-Free Image Interpolation (http://www.andreagiachetti.it/icbi/) -// assumes data has a 2 pixel thick border of clamped or wrapped data -// expects data to be a grid with even (0, 0), (2, 0), (0, 2), (2, 2) etc pixels filled -// only performs FCBI on specified component -static void DoFCBI(byte *in, byte *out, int width, int height, int component) -{ - int x, y; - byte *outbyte, *inbyte; - - // copy in to out - for (y = 2; y < height - 2; y += 2) - { - inbyte = in + (y * width + 2) * 4 + component; - outbyte = out + (y * width + 2) * 4 + component; - - for (x = 2; x < width - 2; x += 2) - { - *outbyte = *inbyte; - outbyte += 8; - inbyte += 8; - } - } - - for (y = 3; y < height - 3; y += 2) - { - // diagonals - // - // NWp - northwest interpolated pixel - // NEp - northeast interpolated pixel - // NWd - northwest first derivative - // NEd - northeast first derivative - // NWdd - northwest second derivative - // NEdd - northeast second derivative - // - // Uses these samples: - // - // 0 - // - - a - b - - - // - - - - - - - - // c - d - e - f - // 0 - - - - - - - - // g - h - i - j - // - - - - - - - - // - - k - l - - - // - // x+2 uses these samples: - // - // 0 - // - - - - a - b - - - // - - - - - - - - - - // - - c - d - e - f - // 0 - - - - - - - - - - // - - g - h - i - j - // - - - - - - - - - - // - - - - k - l - - - // - // so we can reuse 8 of them on next iteration - // - // a=b, c=d, d=e, e=f, g=h, h=i, i=j, k=l - // - // only b, f, j, and l need to be sampled on next iteration - - byte sa, sb, sc, sd, se, sf, sg, sh, si, sj, sk, sl; - byte *line1, *line2, *line3, *line4; - - x = 3; - - // optimization one - // SAMPLE2(sa, x-1, y-3); - //SAMPLE2(sc, x-3, y-1); SAMPLE2(sd, x-1, y-1); SAMPLE2(se, x+1, y-1); - //SAMPLE2(sg, x-3, y+1); SAMPLE2(sh, x-1, y+1); SAMPLE2(si, x+1, y+1); - // SAMPLE2(sk, x-1, y+3); - - // optimization two - line1 = in + ((y - 3) * width + (x - 1)) * 4 + component; - line2 = in + ((y - 1) * width + (x - 3)) * 4 + component; - line3 = in + ((y + 1) * width + (x - 3)) * 4 + component; - line4 = in + ((y + 3) * width + (x - 1)) * 4 + component; - - // COPYSAMPLE(sa, line1); line1 += 8; - //COPYSAMPLE(sc, line2); line2 += 8; COPYSAMPLE(sd, line2); line2 += 8; COPYSAMPLE(se, line2); line2 += 8; - //COPYSAMPLE(sg, line3); line3 += 8; COPYSAMPLE(sh, line3); line3 += 8; COPYSAMPLE(si, line3); line3 += 8; - // COPYSAMPLE(sk, line4); line4 += 8; - - sa = *line1; line1 += 8; - sc = *line2; line2 += 8; sd = *line2; line2 += 8; se = *line2; line2 += 8; - sg = *line3; line3 += 8; sh = *line3; line3 += 8; si = *line3; line3 += 8; - sk = *line4; line4 += 8; - - outbyte = out + (y * width + x) * 4 + component; - - for ( ; x < width - 3; x += 2) - { - int NWd, NEd, NWp, NEp; - - // original - // SAMPLE2(sa, x-1, y-3); SAMPLE2(sb, x+1, y-3); - //SAMPLE2(sc, x-3, y-1); SAMPLE2(sd, x-1, y-1); SAMPLE2(se, x+1, y-1); SAMPLE2(sf, x+3, y-1); - //SAMPLE2(sg, x-3, y+1); SAMPLE2(sh, x-1, y+1); SAMPLE2(si, x+1, y+1); SAMPLE2(sj, x+3, y+1); - // SAMPLE2(sk, x-1, y+3); SAMPLE2(sl, x+1, y+3); - - // optimization one - //SAMPLE2(sb, x+1, y-3); - //SAMPLE2(sf, x+3, y-1); - //SAMPLE2(sj, x+3, y+1); - //SAMPLE2(sl, x+1, y+3); - - // optimization two - //COPYSAMPLE(sb, line1); line1 += 8; - //COPYSAMPLE(sf, line2); line2 += 8; - //COPYSAMPLE(sj, line3); line3 += 8; - //COPYSAMPLE(sl, line4); line4 += 8; - - sb = *line1; line1 += 8; - sf = *line2; line2 += 8; - sj = *line3; line3 += 8; - sl = *line4; line4 += 8; - - NWp = sd + si; - NEp = se + sh; - NWd = abs(sd - si); - NEd = abs(se - sh); - - if (NWd > 100 || NEd > 100 || abs(NWp-NEp) > 200) - { - if (NWd < NEd) - *outbyte = NWp >> 1; - else - *outbyte = NEp >> 1; - } - else - { - int NWdd, NEdd; - - //NEdd = abs(sg + sd + sb - 3 * (se + sh) + sk + si + sf); - //NWdd = abs(sa + se + sj - 3 * (sd + si) + sc + sh + sl); - NEdd = abs(sg + sb - 3 * NEp + sk + sf + NWp); - NWdd = abs(sa + sj - 3 * NWp + sc + sl + NEp); - - if (NWdd > NEdd) - *outbyte = NWp >> 1; - else - *outbyte = NEp >> 1; - } - - outbyte += 8; - - // COPYSAMPLE(sa, sb); - //COPYSAMPLE(sc, sd); COPYSAMPLE(sd, se); COPYSAMPLE(se, sf); - //COPYSAMPLE(sg, sh); COPYSAMPLE(sh, si); COPYSAMPLE(si, sj); - // COPYSAMPLE(sk, sl); - - sa = sb; - sc = sd; sd = se; se = sf; - sg = sh; sh = si; si = sj; - sk = sl; - } - } - - // hack: copy out to in again - for (y = 3; y < height - 3; y += 2) - { - inbyte = out + (y * width + 3) * 4 + component; - outbyte = in + (y * width + 3) * 4 + component; - - for (x = 3; x < width - 3; x += 2) - { - *outbyte = *inbyte; - outbyte += 8; - inbyte += 8; - } - } - - for (y = 2; y < height - 3; y++) - { - // horizontal & vertical - // - // hp - horizontally interpolated pixel - // vp - vertically interpolated pixel - // hd - horizontal first derivative - // vd - vertical first derivative - // hdd - horizontal second derivative - // vdd - vertical second derivative - // Uses these samples: - // - // 0 - // - a - b - - // c - d - e - // 0 - f - g - - // h - i - j - // - k - l - - // - // x+2 uses these samples: - // - // 0 - // - - - a - b - - // - - c - d - e - // 0 - - - f - g - - // - - h - i - j - // - - - k - l - - // - // so we can reuse 7 of them on next iteration - // - // a=b, c=d, d=e, f=g, h=i, i=j, k=l - // - // only b, e, g, j, and l need to be sampled on next iteration - - byte sa, sb, sc, sd, se, sf, sg, sh, si, sj, sk, sl; - byte *line1, *line2, *line3, *line4, *line5; - - //x = (y + 1) % 2; - x = (y + 1) % 2 + 2; - - // optimization one - // SAMPLE2(sa, x-1, y-2); - //SAMPLE2(sc, x-2, y-1); SAMPLE2(sd, x, y-1); - // SAMPLE2(sf, x-1, y ); - //SAMPLE2(sh, x-2, y+1); SAMPLE2(si, x, y+1); - // SAMPLE2(sk, x-1, y+2); - - line1 = in + ((y - 2) * width + (x - 1)) * 4 + component; - line2 = in + ((y - 1) * width + (x - 2)) * 4 + component; - line3 = in + ((y ) * width + (x - 1)) * 4 + component; - line4 = in + ((y + 1) * width + (x - 2)) * 4 + component; - line5 = in + ((y + 2) * width + (x - 1)) * 4 + component; - - // COPYSAMPLE(sa, line1); line1 += 8; - //COPYSAMPLE(sc, line2); line2 += 8; COPYSAMPLE(sd, line2); line2 += 8; - // COPYSAMPLE(sf, line3); line3 += 8; - //COPYSAMPLE(sh, line4); line4 += 8; COPYSAMPLE(si, line4); line4 += 8; - // COPYSAMPLE(sk, line5); line5 += 8; - - sa = *line1; line1 += 8; - sc = *line2; line2 += 8; sd = *line2; line2 += 8; - sf = *line3; line3 += 8; - sh = *line4; line4 += 8; si = *line4; line4 += 8; - sk = *line5; line5 += 8; - - outbyte = out + (y * width + x) * 4 + component; - - for ( ; x < width - 3; x+=2) - { - int hd, vd, hp, vp; - - // SAMPLE2(sa, x-1, y-2); SAMPLE2(sb, x+1, y-2); - //SAMPLE2(sc, x-2, y-1); SAMPLE2(sd, x, y-1); SAMPLE2(se, x+2, y-1); - // SAMPLE2(sf, x-1, y ); SAMPLE2(sg, x+1, y ); - //SAMPLE2(sh, x-2, y+1); SAMPLE2(si, x, y+1); SAMPLE2(sj, x+2, y+1); - // SAMPLE2(sk, x-1, y+2); SAMPLE2(sl, x+1, y+2); - - // optimization one - //SAMPLE2(sb, x+1, y-2); - //SAMPLE2(se, x+2, y-1); - //SAMPLE2(sg, x+1, y ); - //SAMPLE2(sj, x+2, y+1); - //SAMPLE2(sl, x+1, y+2); - - //COPYSAMPLE(sb, line1); line1 += 8; - //COPYSAMPLE(se, line2); line2 += 8; - //COPYSAMPLE(sg, line3); line3 += 8; - //COPYSAMPLE(sj, line4); line4 += 8; - //COPYSAMPLE(sl, line5); line5 += 8; - - sb = *line1; line1 += 8; - se = *line2; line2 += 8; - sg = *line3; line3 += 8; - sj = *line4; line4 += 8; - sl = *line5; line5 += 8; - - hp = sf + sg; - vp = sd + si; - hd = abs(sf - sg); - vd = abs(sd - si); - - if (hd > 100 || vd > 100 || abs(hp-vp) > 200) - { - if (hd < vd) - *outbyte = hp >> 1; - else - *outbyte = vp >> 1; - } - else - { - int hdd, vdd; - - //hdd = abs(sc[i] + sd[i] + se[i] - 3 * (sf[i] + sg[i]) + sh[i] + si[i] + sj[i]); - //vdd = abs(sa[i] + sf[i] + sk[i] - 3 * (sd[i] + si[i]) + sb[i] + sg[i] + sl[i]); - - hdd = abs(sc + se - 3 * hp + sh + sj + vp); - vdd = abs(sa + sk - 3 * vp + sb + sl + hp); - - if (hdd > vdd) - *outbyte = hp >> 1; - else - *outbyte = vp >> 1; - } - - outbyte += 8; - - // COPYSAMPLE(sa, sb); - //COPYSAMPLE(sc, sd); COPYSAMPLE(sd, se); - // COPYSAMPLE(sf, sg); - //COPYSAMPLE(sh, si); COPYSAMPLE(si, sj); - // COPYSAMPLE(sk, sl); - sa = sb; - sc = sd; sd = se; - sf = sg; - sh = si; si = sj; - sk = sl; - } - } -} - -// Similar to FCBI, but throws out the second order derivatives for speed -static void DoFCBIQuick(byte *in, byte *out, int width, int height, int component) -{ - int x, y; - byte *outbyte, *inbyte; - - // copy in to out - for (y = 2; y < height - 2; y += 2) - { - inbyte = in + (y * width + 2) * 4 + component; - outbyte = out + (y * width + 2) * 4 + component; - - for (x = 2; x < width - 2; x += 2) - { - *outbyte = *inbyte; - outbyte += 8; - inbyte += 8; - } - } - - for (y = 3; y < height - 4; y += 2) - { - byte sd, se, sh, si; - byte *line2, *line3; - - x = 3; - - line2 = in + ((y - 1) * width + (x - 1)) * 4 + component; - line3 = in + ((y + 1) * width + (x - 1)) * 4 + component; - - sd = *line2; line2 += 8; - sh = *line3; line3 += 8; - - outbyte = out + (y * width + x) * 4 + component; - - for ( ; x < width - 4; x += 2) - { - int NWd, NEd, NWp, NEp; - - se = *line2; line2 += 8; - si = *line3; line3 += 8; - - NWp = sd + si; - NEp = se + sh; - NWd = abs(sd - si); - NEd = abs(se - sh); - - if (NWd < NEd) - *outbyte = NWp >> 1; - else - *outbyte = NEp >> 1; - - outbyte += 8; - - sd = se; - sh = si; - } - } - - // hack: copy out to in again - for (y = 3; y < height - 3; y += 2) - { - inbyte = out + (y * width + 3) * 4 + component; - outbyte = in + (y * width + 3) * 4 + component; - - for (x = 3; x < width - 3; x += 2) - { - *outbyte = *inbyte; - outbyte += 8; - inbyte += 8; - } - } - - for (y = 2; y < height - 3; y++) - { - byte sd, sf, sg, si; - byte *line2, *line3, *line4; - - x = (y + 1) % 2 + 2; - - line2 = in + ((y - 1) * width + (x )) * 4 + component; - line3 = in + ((y ) * width + (x - 1)) * 4 + component; - line4 = in + ((y + 1) * width + (x )) * 4 + component; - - outbyte = out + (y * width + x) * 4 + component; - - sf = *line3; line3 += 8; - - for ( ; x < width - 3; x+=2) - { - int hd, vd, hp, vp; - - sd = *line2; line2 += 8; - sg = *line3; line3 += 8; - si = *line4; line4 += 8; - - hp = sf + sg; - vp = sd + si; - hd = abs(sf - sg); - vd = abs(sd - si); - - if (hd < vd) - *outbyte = hp >> 1; - else - *outbyte = vp >> 1; - - outbyte += 8; - - sf = sg; - } - } -} - -// Similar to DoFCBIQuick, but just takes the average instead of checking derivatives -// as well, this operates on all four components -static void DoLinear(byte *in, byte *out, int width, int height) -{ - int x, y, i; - byte *outbyte, *inbyte; - - // copy in to out - for (y = 2; y < height - 2; y += 2) - { - x = 2; - - inbyte = in + (y * width + x) * 4; - outbyte = out + (y * width + x) * 4; - - for ( ; x < width - 2; x += 2) - { - COPYSAMPLE(outbyte, inbyte); - outbyte += 8; - inbyte += 8; - } - } - - for (y = 1; y < height - 1; y += 2) - { - byte sd[4], se[4], sh[4], si[4]; - byte *line2, *line3; - - x = 1; - - line2 = in + ((y - 1) * width + (x - 1)) * 4; - line3 = in + ((y + 1) * width + (x - 1)) * 4; - - COPYSAMPLE(sd, line2); line2 += 8; - COPYSAMPLE(sh, line3); line3 += 8; - - outbyte = out + (y * width + x) * 4; - - for ( ; x < width - 1; x += 2) - { - COPYSAMPLE(se, line2); line2 += 8; - COPYSAMPLE(si, line3); line3 += 8; - - for (i = 0; i < 4; i++) - { - *outbyte++ = (sd[i] + si[i] + se[i] + sh[i]) >> 2; - } - - outbyte += 4; - - COPYSAMPLE(sd, se); - COPYSAMPLE(sh, si); - } - } - - // hack: copy out to in again - for (y = 1; y < height - 1; y += 2) - { - x = 1; - - inbyte = out + (y * width + x) * 4; - outbyte = in + (y * width + x) * 4; - - for ( ; x < width - 1; x += 2) - { - COPYSAMPLE(outbyte, inbyte); - outbyte += 8; - inbyte += 8; - } - } - - for (y = 1; y < height - 1; y++) - { - byte sd[4], sf[4], sg[4], si[4]; - byte *line2, *line3, *line4; - - x = y % 2 + 1; - - line2 = in + ((y - 1) * width + (x )) * 4; - line3 = in + ((y ) * width + (x - 1)) * 4; - line4 = in + ((y + 1) * width + (x )) * 4; - - COPYSAMPLE(sf, line3); line3 += 8; - - outbyte = out + (y * width + x) * 4; - - for ( ; x < width - 1; x += 2) - { - COPYSAMPLE(sd, line2); line2 += 8; - COPYSAMPLE(sg, line3); line3 += 8; - COPYSAMPLE(si, line4); line4 += 8; - - for (i = 0; i < 4; i++) - { - *outbyte++ = (sf[i] + sg[i] + sd[i] + si[i]) >> 2; - } - - outbyte += 4; - - COPYSAMPLE(sf, sg); - } - } -} - - -static void ExpandHalfTextureToGrid( byte *data, int width, int height) -{ - int x, y; - - for (y = height / 2; y > 0; y--) - { - byte *outbyte = data + ((y * 2 - 1) * (width) - 2) * 4; - byte *inbyte = data + (y * (width / 2) - 1) * 4; - - for (x = width / 2; x > 0; x--) - { - COPYSAMPLE(outbyte, inbyte); - - outbyte -= 8; - inbyte -= 4; - } - } -} - -static void FillInNormalizedZ(const byte *in, byte *out, int width, int height) -{ - int x, y; - - for (y = 0; y < height; y++) - { - const byte *inbyte = in + y * width * 4; - byte *outbyte = out + y * width * 4; - - for (x = 0; x < width; x++) - { - byte nx, ny, nz, h; - float fnx, fny, fll, fnz; - - nx = *inbyte++; - ny = *inbyte++; - inbyte++; - h = *inbyte++; - - fnx = OffsetByteToFloat(nx); - fny = OffsetByteToFloat(ny); - fll = 1.0f - fnx * fnx - fny * fny; - if (fll >= 0.0f) - fnz = (float)sqrt(fll); - else - fnz = 0.0f; - - nz = FloatToOffsetByte(fnz); - - *outbyte++ = nx; - *outbyte++ = ny; - *outbyte++ = nz; - *outbyte++ = h; - } - } -} - - -// size must be even -#define WORKBLOCK_SIZE 128 -#define WORKBLOCK_BORDER 4 -#define WORKBLOCK_REALSIZE (WORKBLOCK_SIZE + WORKBLOCK_BORDER * 2) - -// assumes that data has already been expanded into a 2x2 grid -static void FCBIByBlock(byte *data, int width, int height, qboolean clampToEdge, qboolean normalized) -{ - byte workdata[WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4]; - byte outdata[WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4]; - byte *inbyte, *outbyte; - int x, y; - int srcx, srcy; - - ExpandHalfTextureToGrid(data, width, height); - - for (y = 0; y < height; y += WORKBLOCK_SIZE) - { - for (x = 0; x < width; x += WORKBLOCK_SIZE) - { - int x2, y2; - int workwidth, workheight, fullworkwidth, fullworkheight; - - workwidth = MIN(WORKBLOCK_SIZE, width - x); - workheight = MIN(WORKBLOCK_SIZE, height - y); - - fullworkwidth = workwidth + WORKBLOCK_BORDER * 2; - fullworkheight = workheight + WORKBLOCK_BORDER * 2; - - //memset(workdata, 0, WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4); - - // fill in work block - for (y2 = 0; y2 < fullworkheight; y2 += 2) - { - srcy = y + y2 - WORKBLOCK_BORDER; - - if (clampToEdge) - { - srcy = CLAMP(srcy, 0, height - 2); - } - else - { - srcy = (srcy + height) % height; - } - - outbyte = workdata + y2 * fullworkwidth * 4; - inbyte = data + srcy * width * 4; - - for (x2 = 0; x2 < fullworkwidth; x2 += 2) - { - srcx = x + x2 - WORKBLOCK_BORDER; - - if (clampToEdge) - { - srcx = CLAMP(srcx, 0, width - 2); - } - else - { - srcx = (srcx + width) % width; - } - - COPYSAMPLE(outbyte, inbyte + srcx * 4); - outbyte += 8; - } - } - - // submit work block - DoLinear(workdata, outdata, fullworkwidth, fullworkheight); - - if (!normalized) - { - switch (r_imageUpsampleType->integer) - { - case 0: - break; - case 1: - DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 0); - break; - case 2: - default: - DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 0); - break; - } - } - else - { - switch (r_imageUpsampleType->integer) - { - case 0: - break; - case 1: - DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 0); - DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 1); - break; - case 2: - default: - DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 0); - DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 1); - break; - } - } - - // copy back work block - for (y2 = 0; y2 < workheight; y2++) - { - inbyte = outdata + ((y2 + WORKBLOCK_BORDER) * fullworkwidth + WORKBLOCK_BORDER) * 4; - outbyte = data + ((y + y2) * width + x) * 4; - for (x2 = 0; x2 < workwidth; x2++) - { - COPYSAMPLE(outbyte, inbyte); - outbyte += 4; - inbyte += 4; - } - } - } - } -} -#undef COPYSAMPLE - -/* -================ -R_LightScaleTexture - -Scale up the pixel values in a texture to increase the -lighting range -================ -*/ -void R_LightScaleTexture (byte *in, int inwidth, int inheight, qboolean only_gamma ) -{ - if ( only_gamma ) - { - if ( !glConfig.deviceSupportsGamma ) - { - int i, c; - byte *p; - - p = in; - - c = inwidth*inheight; - for (i=0 ; i> 1; - outHeight = inHeight >> 1; - temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); - - inWidthMask = inWidth - 1; - inHeightMask = inHeight - 1; - - for ( i = 0 ; i < outHeight ; i++ ) { - for ( j = 0 ; j < outWidth ; j++ ) { - outpix = (byte *) ( temp + i * outWidth + j ); - for ( k = 0 ; k < 4 ; k++ ) { - total = - 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k]; - outpix[k] = total / 36; - } - } - } - - Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); -} - - -static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) -{ - int i, j, k; - int outWidth, outHeight; - byte *temp; - - outWidth = inWidth >> 1; - outHeight = inHeight >> 1; - temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); - - for ( i = 0 ; i < outHeight ; i++ ) { - byte *outbyte = temp + ( i * outWidth ) * 4; - byte *inbyte1 = in + ( i * 2 * inWidth ) * 4; - byte *inbyte2 = in + ( (i * 2 + 1) * inWidth ) * 4; - for ( j = 0 ; j < outWidth ; j++ ) { - for ( k = 0 ; k < 3 ; k++ ) { - float total, current; - - current = ByteToFloat(inbyte1[0]); total = sRGBtoRGB(current); - current = ByteToFloat(inbyte1[4]); total += sRGBtoRGB(current); - current = ByteToFloat(inbyte2[0]); total += sRGBtoRGB(current); - current = ByteToFloat(inbyte2[4]); total += sRGBtoRGB(current); - - total *= 0.25f; - - inbyte1++; - inbyte2++; - - current = RGBtosRGB(total); - *outbyte++ = FloatToByte(current); - } - *outbyte++ = (inbyte1[0] + inbyte1[4] + inbyte2[0] + inbyte2[4]) >> 2; - inbyte1 += 5; - inbyte2 += 5; - } - } - - Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); -} - -/* -================ -R_MipMap - -Operates in place, quartering the size of the texture -================ -*/ -static void R_MipMap (byte *in, int width, int height) { - int i, j; - byte *out; - int row; - - if ( !r_simpleMipMaps->integer ) { - R_MipMap2( in, width, height ); - return; - } - - if ( width == 1 && height == 1 ) { - return; - } - - row = width * 4; - out = in; - width >>= 1; - height >>= 1; - - if ( width == 0 || height == 0 ) { - width += height; // get largest - for (i=0 ; i>1; - out[1] = ( in[1] + in[5] )>>1; - out[2] = ( in[2] + in[6] )>>1; - out[3] = ( in[3] + in[7] )>>1; - } - return; - } - - for (i=0 ; i>2; - out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2; - out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2; - out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2; - } - } -} - - -static void R_MipMapLuminanceAlpha (const byte *in, byte *out, int width, int height) -{ - int i, j, row; - - if ( width == 1 && height == 1 ) { - return; - } - - row = width * 4; - width >>= 1; - height >>= 1; - - if ( width == 0 || height == 0 ) { - width += height; // get largest - for (i=0 ; i> 1; - out[3] = (in[3] + in[7]) >> 1; - } - return; - } - - for (i=0 ; i> 2; - out[3] = (in[3] + in[7] + in[row+3] + in[row+7]) >> 2; - } - } - -} - - -static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int height, qboolean swizzle) -{ - int i, j; - int row; - int sx = swizzle ? 3 : 0; - int sa = swizzle ? 0 : 3; - - if ( width == 1 && height == 1 ) { - return; - } - - row = width * 4; - width >>= 1; - height >>= 1; - - for (i=0 ; i> 9; - data[1] = ( data[1] * inverseAlpha + premult[1] ) >> 9; - data[2] = ( data[2] * inverseAlpha + premult[2] ) >> 9; - } -} - -byte mipBlendColors[16][4] = { - {0,0,0,0}, - {255,0,0,128}, - {0,255,0,128}, - {0,0,255,128}, - {255,0,0,128}, - {0,255,0,128}, - {0,0,255,128}, - {255,0,0,128}, - {0,255,0,128}, - {0,0,255,128}, - {255,0,0,128}, - {0,255,0,128}, - {0,0,255,128}, - {255,0,0,128}, - {0,255,0,128}, - {0,0,255,128}, -}; - -static void RawImage_SwizzleRA( byte *data, int width, int height ) -{ - int i; - byte *ptr = data, swap; - - for (i=0; iinteger && scaled_width > width ) - scaled_width >>= 1; - if ( r_roundImagesDown->integer && scaled_height > height ) - scaled_height >>= 1; - - if ( picmip && data && resampledBuffer && r_imageUpsample->integer && - scaled_width < r_imageUpsampleMaxSize->integer && scaled_height < r_imageUpsampleMaxSize->integer) - { - int finalwidth, finalheight; - //int startTime, endTime; - - //startTime = ri.Milliseconds(); - - finalwidth = scaled_width << r_imageUpsample->integer; - finalheight = scaled_height << r_imageUpsample->integer; - - while ( finalwidth > r_imageUpsampleMaxSize->integer - || finalheight > r_imageUpsampleMaxSize->integer ) { - finalwidth >>= 1; - finalheight >>= 1; - } - - while ( finalwidth > glConfig.maxTextureSize - || finalheight > glConfig.maxTextureSize ) { - finalwidth >>= 1; - finalheight >>= 1; - } - - *resampledBuffer = ri.Hunk_AllocateTempMemory( finalwidth * finalheight * 4 ); - - if (scaled_width != width || scaled_height != height) - { - ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height); - } - else - { - byte *inbyte, *outbyte; - int i; - - inbyte = *data; - outbyte = *resampledBuffer; - - for (i = width * height * 4; i > 0; i--) - { - *outbyte++ = *inbyte++; - } - } - - if (type == IMGTYPE_COLORALPHA) - RGBAtoYCoCgA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); - - while (scaled_width < finalwidth || scaled_height < finalheight) - { - scaled_width <<= 1; - scaled_height <<= 1; - - FCBIByBlock(*resampledBuffer, scaled_width, scaled_height, clampToEdge, (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)); - } - - if (type == IMGTYPE_COLORALPHA) - { - YCoCgAtoRGBA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); - } - else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { - FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); - } - - - //endTime = ri.Milliseconds(); - - //ri.Printf(PRINT_ALL, "upsampled %dx%d to %dx%d in %dms\n", width, height, scaled_width, scaled_height, endTime - startTime); - - *data = *resampledBuffer; - width = scaled_width; - height = scaled_height; - } - else if ( scaled_width != width || scaled_height != height ) { - if (data && resampledBuffer) - { - *resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); - ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height); - *data = *resampledBuffer; - } - width = scaled_width; - height = scaled_height; - } - - // - // perform optional picmip operation - // - if ( picmip ) { - scaled_width >>= r_picmip->integer; - scaled_height >>= r_picmip->integer; - } - - // - // clamp to minimum size - // - if (scaled_width < 1) { - scaled_width = 1; - } - if (scaled_height < 1) { - scaled_height = 1; - } - - // - // clamp to the current upper OpenGL limit - // scale both axis down equally so we don't have to - // deal with a half mip resampling - // - while ( scaled_width > glConfig.maxTextureSize - || scaled_height > glConfig.maxTextureSize ) { - scaled_width >>= 1; - scaled_height >>= 1; - } - - *inout_width = width; - *inout_height = height; - *inout_scaled_width = scaled_width; - *inout_scaled_height = scaled_height; -} - - -static qboolean RawImage_HasAlpha(const byte *scan, int numPixels) -{ - int i; - - if (!scan) - return qtrue; - - for ( i = 0; i < numPixels; i++ ) - { - if ( scan[i*4 + 3] != 255 ) - { - return qtrue; - } - } - - return qfalse; -} - -static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags) -{ - int samples = 3; - GLenum internalFormat = GL_RGB; - qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION); - qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT); - - if(normalmap) - { - if ((!RawImage_HasAlpha(data, numPixels) || (type == IMGTYPE_NORMAL)) && !forceNoCompression && (glRefConfig.textureCompression & TCR_LATC)) - { - internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; - } - else - { - if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) - { - internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - } - else if ( r_texturebits->integer == 16 ) - { - internalFormat = GL_RGBA4; - } - else if ( r_texturebits->integer == 32 ) - { - internalFormat = GL_RGBA8; - } - else - { - internalFormat = GL_RGBA; - } - } - } - else if(lightMap) - { - samples = 4; - if(r_greyscale->integer) - internalFormat = GL_LUMINANCE; - else - internalFormat = GL_RGBA; - } - else - { - if (RawImage_HasAlpha(data, numPixels)) - { - samples = 4; - } - - // select proper internal format - if ( samples == 3 ) - { - if(r_greyscale->integer) - { - if(r_texturebits->integer == 16) - internalFormat = GL_LUMINANCE8; - else if(r_texturebits->integer == 32) - internalFormat = GL_LUMINANCE16; - else - internalFormat = GL_LUMINANCE; - } - else - { - if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) ) - { - internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; - } - else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) - { - internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - } - else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC ) - { - internalFormat = GL_RGB4_S3TC; - } - else if ( r_texturebits->integer == 16 ) - { - internalFormat = GL_RGB5; - } - else if ( r_texturebits->integer == 32 ) - { - internalFormat = GL_RGB8; - } - else - { - internalFormat = GL_RGB; - } - } - } - else if ( samples == 4 ) - { - if(r_greyscale->integer) - { - if(r_texturebits->integer == 16) - internalFormat = GL_LUMINANCE8_ALPHA8; - else if(r_texturebits->integer == 32) - internalFormat = GL_LUMINANCE16_ALPHA16; - else - internalFormat = GL_LUMINANCE_ALPHA; - } - else - { - if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) ) - { - internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; - } - else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) - { - internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - } - else if ( r_texturebits->integer == 16 ) - { - internalFormat = GL_RGBA4; - } - else if ( r_texturebits->integer == 32 ) - { - internalFormat = GL_RGBA8; - } - else - { - internalFormat = GL_RGBA; - } - } - } - - if (glRefConfig.texture_srgb && (flags & IMGFLAG_SRGB)) - { - switch(internalFormat) - { - case GL_RGB: - internalFormat = GL_SRGB_EXT; - break; - - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - internalFormat = GL_SRGB8_EXT; - break; - - case GL_RGBA: - internalFormat = GL_SRGB_ALPHA_EXT; - break; - - case GL_RGBA4: - case GL_RGBA8: - internalFormat = GL_SRGB8_ALPHA8_EXT; - break; - - case GL_LUMINANCE: - internalFormat = GL_SLUMINANCE_EXT; - break; - - case GL_LUMINANCE8: - case GL_LUMINANCE16: - internalFormat = GL_SLUMINANCE8_EXT; - break; - - case GL_LUMINANCE_ALPHA: - internalFormat = GL_SLUMINANCE_ALPHA_EXT; - break; - - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE16_ALPHA16: - internalFormat = GL_SLUMINANCE8_ALPHA8_EXT; - break; - - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; - break; - - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; - break; - - case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: - internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB; - break; - } - } - } - - return internalFormat; -} - - -static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) -{ - int dataFormat, dataType; - - switch(internalFormat) - { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16_ARB: - case GL_DEPTH_COMPONENT24_ARB: - case GL_DEPTH_COMPONENT32_ARB: - dataFormat = GL_DEPTH_COMPONENT; - dataType = GL_UNSIGNED_BYTE; - break; - case GL_RGBA16F_ARB: - dataFormat = GL_RGBA; - dataType = GL_HALF_FLOAT_ARB; - break; - default: - dataFormat = GL_RGBA; - dataType = GL_UNSIGNED_BYTE; - break; - } - - if ( subtexture ) - qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); - else - qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data ); - - if (flags & IMGFLAG_MIPMAP) - { - int miplevel; - - miplevel = 0; - while (width > 1 || height > 1) - { - if (data) - { - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } - } - else if (flags & IMGFLAG_SRGB) - { - R_MipMapsRGB( data, width, height ); - } - else - { - R_MipMap( data, width, height ); - } - } - - width >>= 1; - height >>= 1; - if (width < 1) - width = 1; - if (height < 1) - height = 1; - miplevel++; - - if ( data && r_colorMipLevels->integer ) - R_BlendOverTexture( (byte *)data, width * height, mipBlendColors[miplevel] ); - - if ( subtexture ) - { - x >>= 1; - y >>= 1; - qglTexSubImage2D( GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data ); - } - else - { - qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data ); - } - } - } -} - - -/* -=============== -Upload32 - -=============== -*/ -extern qboolean charSet; -static void Upload32( byte *data, int width, int height, imgType_t type, imgFlags_t flags, - qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight) -{ - byte *scaledBuffer = NULL; - byte *resampledBuffer = NULL; - int scaled_width, scaled_height; - int i, c; - byte *scan; - - RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, type, flags, &resampledBuffer); - - scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); - - // - // scan the texture for each channel's max values - // and verify if the alpha channel is being used or not - // - c = width*height; - scan = data; - - if( r_greyscale->integer ) - { - for ( i = 0; i < c; i++ ) - { - byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]); - scan[i*4] = luma; - scan[i*4 + 1] = luma; - scan[i*4 + 2] = luma; - } - } - else if( r_greyscale->value ) - { - for ( i = 0; i < c; i++ ) - { - float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]); - scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value); - scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value); - scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value); - } - } - - // normals are always swizzled - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { - RawImage_SwizzleRA(data, width, height); - } - - // LATC2 is only used for normals - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - byte *in = data; - int c = width * height; - while (c--) - { - in[0] = in[1]; - in[2] = in[1]; - in += 4; - } - } - - // copy or resample data as appropriate for first MIP level - if ( ( scaled_width == width ) && - ( scaled_height == height ) ) { - if (!(flags & IMGFLAG_MIPMAP)) - { - RawImage_UploadTexture( data, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse ); - //qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; - - goto done; - } - Com_Memcpy (scaledBuffer, data, width*height*4); - } - else - { - // use the normal mip-mapping function to go down from here - while ( width > scaled_width || height > scaled_height ) { - - if (flags & IMGFLAG_SRGB) - { - R_MipMapsRGB( (byte *)data, width, height ); - } - else - { - R_MipMap( (byte *)data, width, height ); - } - - width >>= 1; - height >>= 1; - if ( width < 1 ) { - width = 1; - } - if ( height < 1 ) { - height = 1; - } - } - Com_Memcpy( scaledBuffer, data, width * height * 4 ); - } - - if (!(flags & IMGFLAG_NOLIGHTSCALE)) - R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(flags & IMGFLAG_MIPMAP) ); - - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; - - RawImage_UploadTexture(scaledBuffer, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse); - -done: - - if (flags & IMGFLAG_MIPMAP) - { - if ( textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) ); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - if ( textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - - GL_CheckErrors(); - - if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); - if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); -} - - -static void EmptyTexture( int width, int height, imgType_t type, imgFlags_t flags, - qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight ) -{ - int scaled_width, scaled_height; - - RawImage_ScaleToPower2(NULL, &width, &height, &scaled_width, &scaled_height, type, flags, NULL); - - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; - - RawImage_UploadTexture(NULL, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse); - - if (flags & IMGFLAG_MIPMAP) - { - if ( textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) ); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - if ( textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - - // Fix for sampling depth buffer on old nVidia cards - // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844 - switch(internalFormat) - { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16_ARB: - case GL_DEPTH_COMPONENT24_ARB: - case GL_DEPTH_COMPONENT32_ARB: - qglTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - break; - default: - break; - } - - GL_CheckErrors(); -} - - -/* -================ -R_CreateImage - -This is the only way any image_t are created -================ -*/ -image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) { - image_t *image; - qboolean isLightmap = qfalse; - long hash; - int glWrapClampMode; - - if (strlen(name) >= MAX_QPATH ) { - ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long", name); - } - if ( !strncmp( name, "*lightmap", 9 ) ) { - isLightmap = qtrue; - } - - if ( tr.numImages == MAX_DRAWIMAGES ) { - ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit"); - } - - image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low ); - image->texnum = 1024 + tr.numImages; - tr.numImages++; - - image->type = type; - image->flags = flags; - - strcpy (image->imgName, name); - - image->width = width; - image->height = height; - if (flags & IMGFLAG_CLAMPTOEDGE) - glWrapClampMode = GL_CLAMP_TO_EDGE; - else - glWrapClampMode = GL_REPEAT; - - if (!internalFormat) - { - if (image->flags & IMGFLAG_CUBEMAP) - internalFormat = GL_RGBA8; - else - internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags); - } - - image->internalFormat = internalFormat; - - - // lightmaps are always allocated on TMU 1 - if ( qglActiveTextureARB && isLightmap ) { - image->TMU = 1; - } else { - image->TMU = 0; - } - - if ( qglActiveTextureARB ) { - GL_SelectTexture( image->TMU ); - } - - if (image->flags & IMGFLAG_CUBEMAP) - { - GL_BindCubemap(image); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - - image->uploadWidth = width; - image->uploadHeight = height; - } - else - { - GL_Bind(image); - - if (pic) - { - Upload32( pic, image->width, image->height, image->type, image->flags, - isLightmap, image->internalFormat, &image->uploadWidth, - &image->uploadHeight ); - } - else - { - EmptyTexture(image->width, image->height, image->type, image->flags, - isLightmap, image->internalFormat, &image->uploadWidth, - &image->uploadHeight ); - } - - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); - } - - GL_SelectTexture( 0 ); - - hash = generateHashValue(name); - image->next = hashTable[hash]; - hashTable[hash] = image; - - return image; -} - -void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ) -{ - byte *scaledBuffer = NULL; - byte *resampledBuffer = NULL; - int scaled_width, scaled_height, scaled_x, scaled_y; - byte *data = pic; - - // normals are always swizzled - if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) - { - RawImage_SwizzleRA(pic, width, height); - } - - // LATC2 is only used for normals - if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - byte *in = data; - int c = width * height; - while (c--) - { - in[0] = in[1]; - in[2] = in[1]; - in += 4; - } - } - - - RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer); - - scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); - - if ( qglActiveTextureARB ) { - GL_SelectTexture( image->TMU ); - } - - GL_Bind(image); - - // copy or resample data as appropriate for first MIP level - if ( ( scaled_width == width ) && - ( scaled_height == height ) ) { - if (!(image->flags & IMGFLAG_MIPMAP)) - { - scaled_x = x * scaled_width / width; - scaled_y = y * scaled_height / height; - RawImage_UploadTexture( data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue ); - //qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data ); - - GL_CheckErrors(); - goto done; - } - Com_Memcpy (scaledBuffer, data, width*height*4); - } - else - { - // use the normal mip-mapping function to go down from here - while ( width > scaled_width || height > scaled_height ) { - - if (image->flags & IMGFLAG_SRGB) - { - R_MipMapsRGB( (byte *)data, width, height ); - } - else - { - R_MipMap( (byte *)data, width, height ); - } - - width >>= 1; - height >>= 1; - x >>= 1; - y >>= 1; - if ( width < 1 ) { - width = 1; - } - if ( height < 1 ) { - height = 1; - } - } - Com_Memcpy( scaledBuffer, data, width * height * 4 ); - } - - if (!(image->flags & IMGFLAG_NOLIGHTSCALE)) - R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(image->flags & IMGFLAG_MIPMAP) ); - - scaled_x = x * scaled_width / width; - scaled_y = y * scaled_height / height; - RawImage_UploadTexture( (byte *)data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue ); - -done: - - GL_SelectTexture( 0 ); - - GL_CheckErrors(); - - if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); - if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); -} - -//=================================================================== - -typedef struct -{ - char *ext; - void (*ImageLoader)( const char *, unsigned char **, int *, int * ); -} imageExtToLoaderMap_t; - -// Note that the ordering indicates the order of preference used -// when there are multiple images of different formats available -static imageExtToLoaderMap_t imageLoaders[ ] = -{ - { "tga", R_LoadTGA }, - { "jpg", R_LoadJPG }, - { "jpeg", R_LoadJPG }, - { "png", R_LoadPNG }, - { "pcx", R_LoadPCX }, - { "bmp", R_LoadBMP } -}; - -static int numImageLoaders = ARRAY_LEN( imageLoaders ); - -/* -================= -R_LoadImage - -Loads any of the supported image types into a cannonical -32 bit format. -================= -*/ -void R_LoadImage( const char *name, byte **pic, int *width, int *height ) -{ - qboolean orgNameFailed = qfalse; - int orgLoader = -1; - int i; - char localName[ MAX_QPATH ]; - const char *ext; - char *altName; - - *pic = NULL; - *width = 0; - *height = 0; - - Q_strncpyz( localName, name, MAX_QPATH ); - - ext = COM_GetExtension( localName ); - - if( *ext ) - { - // Look for the correct loader and use it - for( i = 0; i < numImageLoaders; i++ ) - { - if( !Q_stricmp( ext, imageLoaders[ i ].ext ) ) - { - // Load - imageLoaders[ i ].ImageLoader( localName, pic, width, height ); - break; - } - } - - // A loader was found - if( i < numImageLoaders ) - { - if( *pic == NULL ) - { - // Loader failed, most likely because the file isn't there; - // try again without the extension - orgNameFailed = qtrue; - orgLoader = i; - COM_StripExtension( name, localName, MAX_QPATH ); - } - else - { - // Something loaded - return; - } - } - } - - // Try and find a suitable match using all - // the image formats supported - for( i = 0; i < numImageLoaders; i++ ) - { - if (i == orgLoader) - continue; - - altName = va( "%s.%s", localName, imageLoaders[ i ].ext ); - - // Load - imageLoaders[ i ].ImageLoader( altName, pic, width, height ); - - if( *pic ) - { - if( orgNameFailed ) - { - ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n", - name, altName ); - } - - break; - } - } -} - - -/* -=============== -R_FindImageFile - -Finds or loads the given image. -Returns NULL if it fails, not a default image. -============== -*/ -image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) -{ - image_t *image; - int width, height; - byte *pic; - long hash; - - if (!name) { - return NULL; - } - - hash = generateHashValue(name); - - // - // see if the image is already loaded - // - for (image=hashTable[hash]; image; image=image->next) { - if ( !strcmp( name, image->imgName ) ) { - // the white image can be used with any set of parms, but other mismatches are errors - if ( strcmp( name, "*white" ) ) { - if ( image->flags != flags ) { - ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed flags (%i vs %i)\n", name, image->flags, flags ); - } - } - return image; - } - } - - // - // load the pic from disk - // - R_LoadImage( name, &pic, &width, &height ); - if ( pic == NULL ) { - return NULL; - } - - if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) - { - char normalName[MAX_QPATH]; - image_t *normalImage; - int normalWidth, normalHeight; - imgFlags_t normalFlags; - - normalFlags = (flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE; - - COM_StripExtension(name, normalName, MAX_QPATH); - Q_strcat(normalName, MAX_QPATH, "_n"); - - // find normalmap in case it's there - normalImage = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags); - - // if not, generate it - if (normalImage == NULL) - { - byte *normalPic; - int x, y; - - normalWidth = width; - normalHeight = height; - normalPic = ri.Malloc(width * height * 4); - RGBAtoNormal(pic, normalPic, width, height, flags & IMGFLAG_CLAMPTOEDGE); - - // Brighten up the original image to work with the normal map - RGBAtoYCoCgA(pic, pic, width, height); - for (y = 0; y < height; y++) - { - byte *picbyte = pic + y * width * 4; - byte *normbyte = normalPic + y * width * 4; - for (x = 0; x < width; x++) - { - int div = MAX(normbyte[2] - 127, 16); - picbyte[0] = CLAMP(picbyte[0] * 128 / div, 0, 255); - picbyte += 4; - normbyte += 4; - } - } - YCoCgAtoRGBA(pic, pic, width, height); - - R_CreateImage( normalName, normalPic, normalWidth, normalHeight, IMGTYPE_NORMAL, normalFlags, 0 ); - ri.Free( normalPic ); - } - } - - image = R_CreateImage( ( char * ) name, pic, width, height, type, flags, 0 ); - ri.Free( pic ); - return image; -} - - -/* -================ -R_CreateDlightImage -================ -*/ -#define DLIGHT_SIZE 16 -static void R_CreateDlightImage( void ) { - int x,y; - byte data[DLIGHT_SIZE][DLIGHT_SIZE][4]; - int b; - - // make a centered inverse-square falloff blob for dynamic lighting - for (x=0 ; x 255) { - b = 255; - } else if ( b < 75 ) { - b = 0; - } - data[y][x][0] = - data[y][x][1] = - data[y][x][2] = b; - data[y][x][3] = 255; - } - } - tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 ); -} - - -/* -================= -R_InitFogTable -================= -*/ -void R_InitFogTable( void ) { - int i; - float d; - float exp; - - exp = 0.5; - - for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) { - d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp ); - - tr.fogTable[i] = d; - } -} - -/* -================ -R_FogFactor - -Returns a 0.0 to 1.0 fog density value -This is called for each texel of the fog texture on startup -and for each vertex of transparent shaders in fog dynamically -================ -*/ -float R_FogFactor( float s, float t ) { - float d; - - s -= 1.0/512; - if ( s < 0 ) { - return 0; - } - if ( t < 1.0/32 ) { - return 0; - } - if ( t < 31.0/32 ) { - s *= (t - 1.0f/32.0f) / (30.0f/32.0f); - } - - // we need to leave a lot of clamp range - s *= 8; - - if ( s > 1.0 ) { - s = 1.0; - } - - d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ]; - - return d; -} - -/* -================ -R_CreateFogImage -================ -*/ -#define FOG_S 256 -#define FOG_T 32 -static void R_CreateFogImage( void ) { - int x,y; - byte *data; - float d; - float borderColor[4]; - - data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); - - // S is distance, T is depth - for (x=0 ; xinteger >= 2) - { - for( x = 0; x < MAX_DLIGHTS; x++) - { - tr.shadowCubemaps[x] = R_CreateImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE | IMGFLAG_CUBEMAP, 0); - } - } - - // with overbright bits active, we need an image which is some fraction of full color, - // for default lightmaps, etc - for (x=0 ; xinteger && glRefConfig.framebufferObject && glRefConfig.textureFloat) - hdrFormat = GL_RGB16F_ARB; - - tr.renderImage = R_CreateImage("_render", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); -#ifdef REACTION - tr.godRaysImage = R_CreateImage("*godRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); -#endif - - { - int format; - - if (glRefConfig.texture_srgb && glRefConfig.framebuffer_srgb) - format = GL_SRGB8_ALPHA8_EXT; - else - format = GL_RGBA8; - - tr.screenScratchImage = R_CreateImage("*screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, format); - } - - if (glRefConfig.framebufferObject) - { - tr.renderDepthImage = R_CreateImage("*renderdepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); - tr.textureDepthImage = R_CreateImage("*texturedepth", NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); - } - - { - unsigned short sdata[4]; - void *p; - - if (hdrFormat == GL_RGB16F_ARB) - { - sdata[0] = FloatToHalf(0.0f); - sdata[1] = FloatToHalf(0.45f); - sdata[2] = FloatToHalf(1.0f); - sdata[3] = FloatToHalf(1.0f); - p = &sdata[0]; - } - else - { - data[0][0][0] = 0; - data[0][0][1] = 0.45f * 255; - data[0][0][2] = 255; - data[0][0][3] = 255; - p = data; - } - - tr.calcLevelsImage = R_CreateImage("*calcLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); - tr.targetLevelsImage = R_CreateImage("*targetLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); - tr.fixedLevelsImage = R_CreateImage("*fixedLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); - } - - for (x = 0; x < 2; x++) - { - tr.textureScratchImage[x] = R_CreateImage(va("*textureScratch%d", x), NULL, 256, 256, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - } - for (x = 0; x < 2; x++) - { - tr.quarterImage[x] = R_CreateImage(va("*quarter%d", x), NULL, 512, 512, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - } - - tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - } - - for( x = 0; x < MAX_DRAWN_PSHADOWS; x++) - { - tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - } - - //tr.sunShadowImage = R_CreateImage("*sunshadowmap", NULL, SUNSHADOW_MAP_SIZE, SUNSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - for ( x = 0; x < 3; x++) - { - tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); - } -} - - -/* -=============== -R_SetColorMappings -=============== -*/ -void R_SetColorMappings( void ) { - int i, j; - float g; - int inf; - int shift; - - // setup the overbright lighting - tr.overbrightBits = r_overBrightBits->integer; - if ( !glConfig.deviceSupportsGamma ) { - tr.overbrightBits = 0; // need hardware gamma for overbright - } - - // never overbright in windowed mode - if ( 0 /* !glConfig.isFullscreen */ ) - { - tr.overbrightBits = 0; - } - - // allow 2 overbright bits in 24 bit, but only 1 in 16 bit - if ( glConfig.colorBits > 16 ) { - if ( tr.overbrightBits > 2 ) { - tr.overbrightBits = 2; - } - } else { - if ( tr.overbrightBits > 1 ) { - tr.overbrightBits = 1; - } - } - if ( tr.overbrightBits < 0 ) { - tr.overbrightBits = 0; - } - - tr.identityLight = 1.0f / ( 1 << tr.overbrightBits ); - tr.identityLightByte = 255 * tr.identityLight; - - - if ( r_intensity->value <= 1 ) { - ri.Cvar_Set( "r_intensity", "1" ); - } - - if ( r_gamma->value < 0.5f ) { - ri.Cvar_Set( "r_gamma", "0.5" ); - } else if ( r_gamma->value > 3.0f ) { - ri.Cvar_Set( "r_gamma", "3.0" ); - } - - g = r_gamma->value; - - shift = tr.overbrightBits; - - if (glRefConfig.framebufferObject) - shift = 0; - - for ( i = 0; i < 256; i++ ) { - if ( g == 1 ) { - inf = i; - } else { - inf = 255 * pow ( i/255.0f, 1.0f / g ) + 0.5f; - } - inf <<= shift; - if (inf < 0) { - inf = 0; - } - if (inf > 255) { - inf = 255; - } - s_gammatable[i] = inf; - } - - for (i=0 ; i<256 ; i++) { - j = i * r_intensity->value; - if (j > 255) { - j = 255; - } - s_intensitytable[i] = j; - } - - if ( glConfig.deviceSupportsGamma ) - { - GLimp_SetGamma( s_gammatable, s_gammatable, s_gammatable ); - } -} - -/* -=============== -R_InitImages -=============== -*/ -void R_InitImages( void ) { - Com_Memset(hashTable, 0, sizeof(hashTable)); - // build brightness translation tables - R_SetColorMappings(); - - // create default texture and white texture - R_CreateBuiltinImages(); -} - -/* -=============== -R_DeleteTextures -=============== -*/ -void R_DeleteTextures( void ) { - int i; - - for ( i=0; itexnum ); - } - Com_Memset( tr.images, 0, sizeof( tr.images ) ); - - tr.numImages = 0; - - Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) ); - if ( qglActiveTextureARB ) { - GL_SelectTexture( 1 ); - qglBindTexture( GL_TEXTURE_2D, 0 ); - GL_SelectTexture( 0 ); - qglBindTexture( GL_TEXTURE_2D, 0 ); - } else { - qglBindTexture( GL_TEXTURE_2D, 0 ); - } -} - -/* -============================================================================ - -SKINS - -============================================================================ -*/ - -/* -================== -CommaParse - -This is unfortunate, but the skin files aren't -compatable 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 = *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) - { - com_token[len] = c; - len++; - } - } - } - - // parse a regular word - do - { - if (len < MAX_TOKEN_CHARS) - { - com_token[len] = c; - len++; - } - data++; - c = *data; - } while (c>32 && c != ',' ); - - if (len == MAX_TOKEN_CHARS) - { -// ri.Printf (PRINT_DEVELOPER, "Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS); - len = 0; - } - com_token[len] = 0; - - *data_p = ( char * ) data; - return com_token; -} - - -/* -=============== -RE_RegisterSkin - -=============== -*/ -qhandle_t RE_RegisterSkin( const char *name ) { - qhandle_t hSkin; - skin_t *skin; - skinSurface_t *surf; - union { - char *c; - void *v; - } text; - char *text_p; - char *token; - char surfName[MAX_QPATH]; - - if ( !name || !name[0] ) { - ri.Printf( PRINT_DEVELOPER, "Empty name passed to RE_RegisterSkin\n" ); - return 0; - } - - if ( strlen( name ) >= MAX_QPATH ) { - ri.Printf( PRINT_DEVELOPER, "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; - } - } - - // allocate a new skin - if ( tr.numSkins == MAX_SKINS ) { - ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name ); - return 0; - } - tr.numSkins++; - skin = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); - tr.skins[hSkin] = skin; - Q_strncpyz( skin->name, name, sizeof( skin->name ) ); - skin->numSurfaces = 0; - - // make sure the render thread is stopped - R_SyncRenderThread(); - - // If not a .skin file, load as a single shader - if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { - skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); - skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); - return hSkin; - } - - // load and parse the skin file - ri.FS_ReadFile( name, &text.v ); - if ( !text.c ) { - return 0; - } - - text_p = text.c; - 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 ( strstr( token, "tag_" ) ) { - continue; - } - - // parse the shader name - token = CommaParse( &text_p ); - - surf = skin->surfaces[ skin->numSurfaces ] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); - Q_strncpyz( surf->name, surfName, sizeof( surf->name ) ); - surf->shader = R_FindShader( token, LIGHTMAP_NONE, qtrue ); - skin->numSurfaces++; - } - - ri.FS_FreeFile( text.v ); - - - // never let a skin have 0 shaders - if ( skin->numSurfaces == 0 ) { - return 0; // use default skin - } - - 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] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); - Q_strncpyz( skin->name, "", sizeof( skin->name ) ); - skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); - 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"); -} - - diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c deleted file mode 100644 index f2fc9c3d..00000000 --- a/code/renderergl2/tr_init.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_init.c -- functions that are not called every frame - -#include "tr_local.h" - -glconfig_t glConfig; -glRefConfig_t glRefConfig; -qboolean textureFilterAnisotropic = qfalse; -int maxAnisotropy = 0; -float displayAspect = 0.0f; - -glstate_t glState; - -static void GfxInfo_f( void ); -static void GfxMemInfo_f( void ); - -#ifdef USE_RENDERER_DLOPEN -cvar_t *com_altivec; -#endif - -cvar_t *r_flareSize; -cvar_t *r_flareFade; -cvar_t *r_flareCoeff; - -cvar_t *r_railWidth; -cvar_t *r_railCoreWidth; -cvar_t *r_railSegmentLength; - -cvar_t *r_verbose; -cvar_t *r_ignore; - -cvar_t *r_detailTextures; - -cvar_t *r_znear; -cvar_t *r_zproj; -cvar_t *r_stereoSeparation; - -cvar_t *r_smp; -cvar_t *r_showSmp; -cvar_t *r_skipBackEnd; - -cvar_t *r_stereoEnabled; -cvar_t *r_anaglyphMode; - -cvar_t *r_greyscale; - -cvar_t *r_ignorehwgamma; -cvar_t *r_measureOverdraw; - -cvar_t *r_inGameVideo; -cvar_t *r_fastsky; -cvar_t *r_drawSun; -cvar_t *r_dynamiclight; -cvar_t *r_dlightBacks; - -cvar_t *r_lodbias; -cvar_t *r_lodscale; - -cvar_t *r_norefresh; -cvar_t *r_drawentities; -cvar_t *r_drawworld; -cvar_t *r_speeds; -cvar_t *r_fullbright; -cvar_t *r_novis; -cvar_t *r_nocull; -cvar_t *r_facePlaneCull; -cvar_t *r_showcluster; -cvar_t *r_nocurves; - -cvar_t *r_allowExtensions; - -cvar_t *r_ext_compressed_textures; -cvar_t *r_ext_multitexture; -cvar_t *r_ext_compiled_vertex_array; -cvar_t *r_ext_texture_env_add; -cvar_t *r_ext_texture_filter_anisotropic; -cvar_t *r_ext_max_anisotropy; - -cvar_t *r_ext_draw_range_elements; -cvar_t *r_ext_multi_draw_arrays; -cvar_t *r_ext_framebuffer_object; -cvar_t *r_ext_texture_float; -cvar_t *r_arb_half_float_pixel; -cvar_t *r_ext_framebuffer_multisample; - -cvar_t *r_mergeMultidraws; -cvar_t *r_mergeLeafSurfaces; - -cvar_t *r_cameraExposure; -cvar_t *r_hdr; -cvar_t *r_postProcess; -cvar_t *r_toneMap; -cvar_t *r_autoExposure; - -cvar_t *r_srgb; -cvar_t *r_depthPrepass; - -cvar_t *r_normalMapping; -cvar_t *r_specularMapping; -cvar_t *r_deluxeMapping; -cvar_t *r_parallaxMapping; -cvar_t *r_normalAmbient; -cvar_t *r_recalcMD3Normals; -cvar_t *r_mergeLightmaps; -cvar_t *r_dlightMode; -cvar_t *r_pshadowDist; -cvar_t *r_imageUpsample; -cvar_t *r_imageUpsampleMaxSize; -cvar_t *r_imageUpsampleType; -cvar_t *r_genNormalMaps; -cvar_t *r_forceSun; -cvar_t *r_forceSunMapLightScale; -cvar_t *r_forceSunLightScale; -cvar_t *r_forceSunAmbientScale; -cvar_t *r_sunShadows; -cvar_t *r_shadowFilter; -cvar_t *r_shadowMapSize; -cvar_t *r_shadowCascadeZNear; -cvar_t *r_shadowCascadeZFar; -cvar_t *r_shadowCascadeZBias; - -cvar_t *r_ignoreGLErrors; -cvar_t *r_logFile; - -cvar_t *r_stencilbits; -cvar_t *r_depthbits; -cvar_t *r_colorbits; -cvar_t *r_texturebits; -cvar_t *r_ext_multisample; - -cvar_t *r_drawBuffer; -cvar_t *r_lightmap; -cvar_t *r_vertexLight; -cvar_t *r_uiFullScreen; -cvar_t *r_shadows; -cvar_t *r_flares; -cvar_t *r_mode; -cvar_t *r_nobind; -cvar_t *r_singleShader; -cvar_t *r_roundImagesDown; -cvar_t *r_colorMipLevels; -cvar_t *r_picmip; -cvar_t *r_showtris; -cvar_t *r_showsky; -cvar_t *r_shownormals; -cvar_t *r_finish; -cvar_t *r_clear; -cvar_t *r_swapInterval; -cvar_t *r_textureMode; -cvar_t *r_offsetFactor; -cvar_t *r_offsetUnits; -cvar_t *r_gamma; -cvar_t *r_intensity; -cvar_t *r_lockpvs; -cvar_t *r_noportals; -cvar_t *r_portalOnly; - -cvar_t *r_subdivisions; -cvar_t *r_lodCurveError; - -cvar_t *r_fullscreen; -cvar_t *r_noborder; - -cvar_t *r_customwidth; -cvar_t *r_customheight; -cvar_t *r_customPixelAspect; - -cvar_t *r_overBrightBits; -cvar_t *r_mapOverBrightBits; - -cvar_t *r_debugSurface; -cvar_t *r_simpleMipMaps; - -cvar_t *r_showImages; - -cvar_t *r_ambientScale; -cvar_t *r_directedScale; -cvar_t *r_debugLight; -cvar_t *r_debugSort; -cvar_t *r_printShaders; -cvar_t *r_saveFontData; - -cvar_t *r_marksOnTriangleMeshes; - -cvar_t *r_aviMotionJpegQuality; -cvar_t *r_screenshotJpegQuality; - -cvar_t *r_maxpolys; -int max_polys; -cvar_t *r_maxpolyverts; -int max_polyverts; - -/* -** InitOpenGL -** -** This function is responsible for initializing a valid OpenGL subsystem. This -** is done by calling GLimp_Init (which gives us a working OGL subsystem) then -** setting variables, checking GL constants, and reporting the gfx system config -** to the user. -*/ -static void InitOpenGL( void ) -{ - char renderer_buffer[1024]; - - // - // initialize OS specific portions of the renderer - // - // GLimp_Init directly or indirectly references the following cvars: - // - r_fullscreen - // - r_mode - // - r_(color|depth|stencil)bits - // - r_ignorehwgamma - // - r_gamma - // - - if ( glConfig.vidWidth == 0 ) - { - GLint temp; - - GLimp_Init(); - GLimp_InitExtraExtensions(); - - strcpy( renderer_buffer, glConfig.renderer_string ); - Q_strlwr( renderer_buffer ); - - // OpenGL driver constants - qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp ); - glConfig.maxTextureSize = temp; - - // stubbed or broken drivers may have reported 0... - if ( glConfig.maxTextureSize <= 0 ) - { - glConfig.maxTextureSize = 0; - } - } - - // init command buffers and SMP - R_InitCommandBuffers(); - - // print info - GfxInfo_f(); - - // set default state - GL_SetDefaultState(); -} - -/* -================== -GL_CheckErrors -================== -*/ -void GL_CheckErrs( char *file, int line ) { - int err; - char s[64]; - - err = qglGetError(); - if ( err == GL_NO_ERROR ) { - return; - } - if ( r_ignoreGLErrors->integer ) { - return; - } - switch( err ) { - case GL_INVALID_ENUM: - strcpy( s, "GL_INVALID_ENUM" ); - break; - case GL_INVALID_VALUE: - strcpy( s, "GL_INVALID_VALUE" ); - break; - case GL_INVALID_OPERATION: - strcpy( s, "GL_INVALID_OPERATION" ); - break; - case GL_STACK_OVERFLOW: - strcpy( s, "GL_STACK_OVERFLOW" ); - break; - case GL_STACK_UNDERFLOW: - strcpy( s, "GL_STACK_UNDERFLOW" ); - break; - case GL_OUT_OF_MEMORY: - strcpy( s, "GL_OUT_OF_MEMORY" ); - break; - default: - Com_sprintf( s, sizeof(s), "%i", err); - break; - } - - ri.Error( ERR_FATAL, "GL_CheckErrors: %s in %s at line %d", s , file, line); -} - - -/* -** R_GetModeInfo -*/ -typedef struct vidmode_s -{ - const char *description; - int width, height; - float pixelAspect; // pixel width / height -} vidmode_t; - -vidmode_t r_vidModes[] = -{ - { "Mode 0: 320x240", 320, 240, 1 }, - { "Mode 1: 400x300", 400, 300, 1 }, - { "Mode 2: 512x384", 512, 384, 1 }, - { "Mode 3: 640x480", 640, 480, 1 }, - { "Mode 4: 800x600", 800, 600, 1 }, - { "Mode 5: 960x720", 960, 720, 1 }, - { "Mode 6: 1024x768", 1024, 768, 1 }, - { "Mode 7: 1152x864", 1152, 864, 1 }, - { "Mode 8: 1280x1024", 1280, 1024, 1 }, - { "Mode 9: 1600x1200", 1600, 1200, 1 }, - { "Mode 10: 2048x1536", 2048, 1536, 1 }, - { "Mode 11: 856x480 (wide)",856, 480, 1 } -}; -static int s_numVidModes = ARRAY_LEN( r_vidModes ); - -qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ) { - vidmode_t *vm; - float pixelAspect; - - if ( mode < -1 ) { - return qfalse; - } - if ( mode >= s_numVidModes ) { - return qfalse; - } - - if ( mode == -1 ) { - *width = r_customwidth->integer; - *height = r_customheight->integer; - pixelAspect = r_customPixelAspect->value; - } else { - vm = &r_vidModes[mode]; - - *width = vm->width; - *height = vm->height; - pixelAspect = vm->pixelAspect; - } - - *windowAspect = (float)*width / ( *height * pixelAspect ); - - return qtrue; -} - -/* -** R_ModeList_f -*/ -static void R_ModeList_f( void ) -{ - int i; - - ri.Printf( PRINT_ALL, "\n" ); - for ( i = 0; i < s_numVidModes; i++ ) - { - ri.Printf( PRINT_ALL, "%s\n", r_vidModes[i].description ); - } - ri.Printf( PRINT_ALL, "\n" ); -} - - -/* -============================================================================== - - SCREEN SHOTS - -NOTE TTimo -some thoughts about the screenshots system: -screenshots get written in fs_homepath + fs_gamedir -vanilla q3 .. baseq3/screenshots/ *.tga -team arena .. missionpack/screenshots/ *.tga - -two commands: "screenshot" and "screenshotJPEG" -we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available -(with FS_FileExists / FS_FOpenFileWrite calls) -FIXME: the statics don't get a reinit between fs_game changes - -============================================================================== -*/ - -/* -================== -RB_ReadPixels - -Reads an image but takes care of alignment issues for reading RGB images. - -Reads a minimum offset for where the RGB data starts in the image from -integer stored at pointer offset. When the function has returned the actual -offset was written back to address offset. This address will always have an -alignment of packAlign to ensure efficient copying. - -Stores the length of padding after a line of pixels to address padlen - -Return value must be freed with ri.Hunk_FreeTempMemory() -================== -*/ - -byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen) -{ - byte *buffer, *bufstart; - int padwidth, linelen; - GLint packAlign; - - qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); - - linelen = width * 3; - padwidth = PAD(linelen, packAlign); - - // Allocate a few more bytes so that we can choose an alignment we like - buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1); - - bufstart = PADP((intptr_t) buffer + *offset, packAlign); - qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart); - - *offset = bufstart - buffer; - *padlen = padwidth - linelen; - - return buffer; -} - -/* -================== -RB_TakeScreenshot -================== -*/ -void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName) -{ - byte *allbuf, *buffer; - byte *srcptr, *destptr; - byte *endline, *endmem; - byte temp; - - int linelen, padlen; - size_t offset = 18, memcount; - - allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen); - buffer = allbuf + offset - 18; - - Com_Memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type - buffer[12] = width & 255; - buffer[13] = width >> 8; - buffer[14] = height & 255; - buffer[15] = height >> 8; - buffer[16] = 24; // pixel size - - // swap rgb to bgr and remove padding from line endings - linelen = width * 3; - - srcptr = destptr = allbuf + offset; - endmem = srcptr + (linelen + padlen) * height; - - while(srcptr < endmem) - { - endline = srcptr + linelen; - - while(srcptr < endline) - { - temp = srcptr[0]; - *destptr++ = srcptr[2]; - *destptr++ = srcptr[1]; - *destptr++ = temp; - - srcptr += 3; - } - - // Skip the pad - srcptr += padlen; - } - - memcount = linelen * height; - - // gamma correct - if(glConfig.deviceSupportsGamma) - R_GammaCorrect(allbuf + offset, memcount); - - ri.FS_WriteFile(fileName, buffer, memcount + 18); - - ri.Hunk_FreeTempMemory(allbuf); -} - -/* -================== -RB_TakeScreenshotJPEG -================== -*/ - -void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName) -{ - byte *buffer; - size_t offset = 0, memcount; - int padlen; - - buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen); - memcount = (width * 3 + padlen) * height; - - // gamma correct - if(glConfig.deviceSupportsGamma) - R_GammaCorrect(buffer + offset, memcount); - - RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, buffer + offset, padlen); - ri.Hunk_FreeTempMemory(buffer); -} - -/* -================== -RB_TakeScreenshotCmd -================== -*/ -const void *RB_TakeScreenshotCmd( const void *data ) { - const screenshotCommand_t *cmd; - - cmd = (const screenshotCommand_t *)data; - - if (cmd->jpeg) - RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); - else - RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); - - return (const void *)(cmd + 1); -} - -/* -================== -R_TakeScreenshot -================== -*/ -void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) { - static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame? - screenshotCommand_t *cmd; - - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; - } - cmd->commandId = RC_SCREENSHOT; - - cmd->x = x; - cmd->y = y; - cmd->width = width; - cmd->height = height; - Q_strncpyz( fileName, name, sizeof(fileName) ); - cmd->fileName = fileName; - cmd->jpeg = jpeg; -} - -/* -================== -R_ScreenshotFilename -================== -*/ -void R_ScreenshotFilename( int lastNumber, char *fileName ) { - int a,b,c,d; - - if ( lastNumber < 0 || lastNumber > 9999 ) { - Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" ); - return; - } - - a = lastNumber / 1000; - lastNumber -= a*1000; - b = lastNumber / 100; - lastNumber -= b*100; - c = lastNumber / 10; - lastNumber -= c*10; - d = lastNumber; - - Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga" - , a, b, c, d ); -} - -/* -================== -R_ScreenshotFilename -================== -*/ -void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) { - int a,b,c,d; - - if ( lastNumber < 0 || lastNumber > 9999 ) { - Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" ); - return; - } - - a = lastNumber / 1000; - lastNumber -= a*1000; - b = lastNumber / 100; - lastNumber -= b*100; - c = lastNumber / 10; - lastNumber -= c*10; - d = lastNumber; - - Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg" - , a, b, c, d ); -} - -/* -==================== -R_LevelShot - -levelshots are specialized 128*128 thumbnails for -the menu system, sampled down from full screen distorted images -==================== -*/ -void R_LevelShot( void ) { - char checkname[MAX_OSPATH]; - byte *buffer; - byte *source, *allsource; - byte *src, *dst; - size_t offset = 0; - int padlen; - int x, y; - int r, g, b; - float xScale, yScale; - int xx, yy; - - Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName); - - allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen); - source = allsource + offset; - - buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18); - Com_Memset (buffer, 0, 18); - buffer[2] = 2; // uncompressed type - buffer[12] = 128; - buffer[14] = 128; - buffer[16] = 24; // pixel size - - // resample from source - xScale = glConfig.vidWidth / 512.0f; - yScale = glConfig.vidHeight / 384.0f; - for ( y = 0 ; y < 128 ; y++ ) { - for ( x = 0 ; x < 128 ; x++ ) { - r = g = b = 0; - for ( yy = 0 ; yy < 3 ; yy++ ) { - for ( xx = 0 ; xx < 4 ; xx++ ) { - src = source + (3 * glConfig.vidWidth + padlen) * (int)((y*3 + yy) * yScale) + - 3 * (int) ((x*4 + xx) * xScale); - r += src[0]; - g += src[1]; - b += src[2]; - } - } - dst = buffer + 18 + 3 * ( y * 128 + x ); - dst[0] = b / 12; - dst[1] = g / 12; - dst[2] = r / 12; - } - } - - // gamma correct - if ( glConfig.deviceSupportsGamma ) { - R_GammaCorrect( buffer + 18, 128 * 128 * 3 ); - } - - ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 ); - - ri.Hunk_FreeTempMemory(buffer); - ri.Hunk_FreeTempMemory(allsource); - - ri.Printf( PRINT_ALL, "Wrote %s\n", checkname ); -} - -/* -================== -R_ScreenShot_f - -screenshot -screenshot [silent] -screenshot [levelshot] -screenshot [filename] - -Doesn't print the pacifier message if there is a second arg -================== -*/ -void R_ScreenShot_f (void) { - char checkname[MAX_OSPATH]; - static int lastNumber = -1; - qboolean silent; - - if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { - R_LevelShot(); - return; - } - - if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) { - silent = qtrue; - } else { - silent = qfalse; - } - - if ( ri.Cmd_Argc() == 2 && !silent ) { - // explicit filename - Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) ); - } else { - // scan for a free filename - - // if we have saved a previous screenshot, don't scan - // again, because recording demo avis can involve - // thousands of shots - if ( lastNumber == -1 ) { - lastNumber = 0; - } - // scan for a free number - for ( ; lastNumber <= 9999 ; lastNumber++ ) { - R_ScreenshotFilename( lastNumber, checkname ); - - if (!ri.FS_FileExists( checkname )) - { - break; // file doesn't exist - } - } - - if ( lastNumber >= 9999 ) { - ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); - return; - } - - lastNumber++; - } - - R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse ); - - if ( !silent ) { - ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); - } -} - -void R_ScreenShotJPEG_f (void) { - char checkname[MAX_OSPATH]; - static int lastNumber = -1; - qboolean silent; - - if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { - R_LevelShot(); - return; - } - - if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) { - silent = qtrue; - } else { - silent = qfalse; - } - - if ( ri.Cmd_Argc() == 2 && !silent ) { - // explicit filename - Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) ); - } else { - // scan for a free filename - - // if we have saved a previous screenshot, don't scan - // again, because recording demo avis can involve - // thousands of shots - if ( lastNumber == -1 ) { - lastNumber = 0; - } - // scan for a free number - for ( ; lastNumber <= 9999 ; lastNumber++ ) { - R_ScreenshotFilenameJPEG( lastNumber, checkname ); - - if (!ri.FS_FileExists( checkname )) - { - break; // file doesn't exist - } - } - - if ( lastNumber == 10000 ) { - ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); - return; - } - - lastNumber++; - } - - R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue ); - - if ( !silent ) { - ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); - } -} - -//============================================================================ - -/* -================== -RB_TakeVideoFrameCmd -================== -*/ -const void *RB_TakeVideoFrameCmd( const void *data ) -{ - const videoFrameCommand_t *cmd; - byte *cBuf; - size_t memcount, linelen; - int padwidth, avipadwidth, padlen, avipadlen; - GLint packAlign; - - cmd = (const videoFrameCommand_t *)data; - - qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); - - linelen = cmd->width * 3; - - // Alignment stuff for glReadPixels - padwidth = PAD(linelen, packAlign); - padlen = padwidth - linelen; - // AVI line padding - avipadwidth = PAD(linelen, AVI_LINE_PADDING); - avipadlen = avipadwidth - linelen; - - cBuf = PADP(cmd->captureBuffer, packAlign); - - qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB, - GL_UNSIGNED_BYTE, cBuf); - - memcount = padwidth * cmd->height; - - // gamma correct - if(glConfig.deviceSupportsGamma) - R_GammaCorrect(cBuf, memcount); - - if(cmd->motionJpeg) - { - memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height, - r_aviMotionJpegQuality->integer, - cmd->width, cmd->height, cBuf, padlen); - ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount); - } - else - { - byte *lineend, *memend; - byte *srcptr, *destptr; - - srcptr = cBuf; - destptr = cmd->encodeBuffer; - memend = srcptr + memcount; - - // swap R and B and remove line paddings - while(srcptr < memend) - { - lineend = srcptr + linelen; - while(srcptr < lineend) - { - *destptr++ = srcptr[2]; - *destptr++ = srcptr[1]; - *destptr++ = srcptr[0]; - srcptr += 3; - } - - Com_Memset(destptr, '\0', avipadlen); - destptr += avipadlen; - - srcptr += padlen; - } - - ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height); - } - - return (const void *)(cmd + 1); -} - -//============================================================================ - -/* -** GL_SetDefaultState -*/ -void GL_SetDefaultState( void ) -{ - qglClearDepth( 1.0f ); - - qglCullFace(GL_FRONT); - - qglColor4f (1,1,1,1); - - // initialize downstream texture unit if we're running - // in a multitexture environment - if ( qglActiveTextureARB ) { - GL_SelectTexture( 1 ); - GL_TextureMode( r_textureMode->string ); - GL_TexEnv( GL_MODULATE ); - qglDisable( GL_TEXTURE_2D ); - GL_SelectTexture( 0 ); - } - - qglEnable(GL_TEXTURE_2D); - GL_TextureMode( r_textureMode->string ); - GL_TexEnv( GL_MODULATE ); - - //qglShadeModel( GL_SMOOTH ); - qglDepthFunc( GL_LEQUAL ); - - // - // make sure our GL state vector is set correctly - // - glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; - - glState.vertexAttribsState = 0; - glState.vertexAttribPointersSet = 0; - glState.currentProgram = 0; - qglUseProgramObjectARB(0); - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - glState.currentVBO = NULL; - glState.currentIBO = NULL; - - if (glRefConfig.framebuffer_srgb) - { - qglEnable(GL_FRAMEBUFFER_SRGB_EXT); - } - - qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - qglDepthMask( GL_TRUE ); - qglDisable( GL_DEPTH_TEST ); - qglEnable( GL_SCISSOR_TEST ); - qglDisable( GL_CULL_FACE ); - qglDisable( GL_BLEND ); -} - - -/* -================ -GfxInfo_f -================ -*/ -void GfxInfo_f( void ) -{ - const char *enablestrings[] = - { - "disabled", - "enabled" - }; - const char *fsstrings[] = - { - "windowed", - "fullscreen" - }; - - ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string ); - ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string ); - ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string ); - // this was really bugging me - if (strlen(glConfig.extensions_string) > 1008) - { - char buffer[1024]; - char *p; - int size = strlen(glConfig.extensions_string); - ri.Printf( PRINT_ALL, "GL_EXTENSIONS: "); - - p = glConfig.extensions_string; - while(size > 0) - { - Q_strncpyz(buffer, p, 1024); - ri.Printf( PRINT_ALL, "%s", buffer ); - p += 1023; - size -= 1023; - } - ri.Printf( PRINT_ALL, "\n" ); - } - else - { - ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string ); - } - ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize ); - ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits ); - ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); - ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] ); - if ( glConfig.displayFrequency ) - { - ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency ); - } - else - { - ri.Printf( PRINT_ALL, "N/A\n" ); - } - if ( glConfig.deviceSupportsGamma ) - { - ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits ); - } - else - { - ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits ); - } - - ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string ); - ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer ); - ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer ); - ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] ); - ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] ); - ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] ); - ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] ); - if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) - { - ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" ); - } - if ( glConfig.hardwareType == GLHW_RAGEPRO ) - { - ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" ); - } - if ( glConfig.hardwareType == GLHW_RIVA128 ) - { - ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" ); - } - if ( glConfig.smpActive ) { - ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" ); - } - if ( r_finish->integer ) { - ri.Printf( PRINT_ALL, "Forcing glFinish\n" ); - } -} - -/* -================ -GfxMemInfo_f -================ -*/ -void GfxMemInfo_f( void ) -{ - switch (glRefConfig.memInfo) - { - case MI_NONE: - { - ri.Printf(PRINT_ALL, "No extension found for GPU memory info.\n"); - } - break; - case MI_NVX: - { - int value; - - qglGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &value); - ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX: %ikb\n", value); - - qglGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &value); - ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX: %ikb\n", value); - - qglGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &value); - ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX: %ikb\n", value); - - qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX, &value); - ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTION_COUNT_NVX: %i\n", value); - - qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX, &value); - ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTED_MEMORY_NVX: %ikb\n", value); - } - break; - case MI_ATI: - { - // GL_ATI_meminfo - int value[4]; - - qglGetIntegerv(GL_VBO_FREE_MEMORY_ATI, &value[0]); - ri.Printf(PRINT_ALL, "VBO_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); - - qglGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &value[0]); - ri.Printf(PRINT_ALL, "TEXTURE_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); - - qglGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, &value[0]); - ri.Printf(PRINT_ALL, "RENDERBUFFER_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); - } - break; - } -} - -/* -=============== -R_Register -=============== -*/ -void R_Register( void ) -{ - #ifdef USE_RENDERER_DLOPEN - com_altivec = ri.Cvar_Get("com_altivec", "1", CVAR_ARCHIVE); - #endif - - // - // latched and archived variables - // - r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH); - - r_ext_draw_range_elements = ri.Cvar_Get( "r_ext_draw_range_elements", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_ext_multi_draw_arrays = ri.Cvar_Get( "r_ext_multi_draw_arrays", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH); - r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH); - - r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", - "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH ); - - r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH ); - ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue ); - r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH ); - r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH ); - ri.Cvar_CheckRange( r_ext_multisample, 0, 4, qtrue ); - r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH); - r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH ); - r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE ); - r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE); - r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH ); - r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH ); - r_customPixelAspect = ri.Cvar_Get( "r_customPixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0); - r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH); - r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH); - r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH); - r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH); - ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); - - r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); - r_toneMap = ri.Cvar_Get( "r_toneMap", "2", CVAR_ARCHIVE ); - r_autoExposure = ri.Cvar_Get( "r_autoExposure", "2", CVAR_ARCHIVE ); - r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT ); - - r_srgb = ri.Cvar_Get( "r_srgb", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE ); - - r_normalMapping = ri.Cvar_Get( "r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_normalAmbient = ri.Cvar_Get( "r_normalAmbient", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE ); - r_recalcMD3Normals = ri.Cvar_Get( "r_recalcMD3Normals", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_imageUpsample = ri.Cvar_Get( "r_imageUpsample", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_imageUpsampleMaxSize = ri.Cvar_Get( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); - r_imageUpsampleType = ri.Cvar_Get( "r_imageUpsampleType", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH ); - - r_forceSun = ri.Cvar_Get( "r_forceSun", "0", CVAR_CHEAT ); - r_forceSunMapLightScale = ri.Cvar_Get( "r_forceSunMapLightScale", "0.5", CVAR_CHEAT ); - r_forceSunLightScale = ri.Cvar_Get( "r_forceSunLightScale", "0.5", CVAR_CHEAT ); - r_forceSunAmbientScale = ri.Cvar_Get( "r_forceSunAmbientScale", "0.2", CVAR_CHEAT ); - r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", CVAR_ARCHIVE | CVAR_LATCH ); - - // - // temporary latched variables that can only change over a restart - // - r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT ); - r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH ); - r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH ); - r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); - - // - // archived variables that can change at any time - // - r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT ); - r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE ); - r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE ); - r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT ); - ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse ); - r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE ); - r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE ); - r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE ); - r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE ); - r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE ); - r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE ); - r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE ); - r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE ); - r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE); - r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE ); - r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", - CVAR_ARCHIVE | CVAR_LATCH ); - r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE ); - r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE ); - - r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE ); - r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE ); - r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE ); - - r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT ); - r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT ); - - r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE); - r_mergeMultidraws = ri.Cvar_Get("r_mergeMultidraws", "1", CVAR_ARCHIVE); - r_mergeLeafSurfaces = ri.Cvar_Get("r_mergeLeafSurfaces", "1", CVAR_ARCHIVE); - - // - // temporary variables that can change at any time - // - r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP ); - - r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP ); - r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT ); - r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 ); - r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 ); - - r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT ); - r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT ); - r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 ); - r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT ); - - r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT); - r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT); - r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT); - - r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT); - r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT); - - r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT ); - r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT ); - r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT); - r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT ); - r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT ); - r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT); - r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT); - r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT); - r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT); - r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT ); - r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT ); - r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT); - r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT); - r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT); - r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT); - r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT); - r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT); - r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT ); - r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT ); - r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", 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", "1", 0 ); - - r_marksOnTriangleMeshes = ri.Cvar_Get("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE); - - r_aviMotionJpegQuality = ri.Cvar_Get("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE); - r_screenshotJpegQuality = ri.Cvar_Get("r_screenshotJpegQuality", "90", CVAR_ARCHIVE); - - r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0); - r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0); - - // make sure all the commands added here are also - // removed in R_Shutdown - ri.Cmd_AddCommand( "imagelist", R_ImageList_f ); - ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f ); - ri.Cmd_AddCommand( "skinlist", R_SkinList_f ); - ri.Cmd_AddCommand( "modellist", R_Modellist_f ); - ri.Cmd_AddCommand( "modelist", R_ModeList_f ); - ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f ); - ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f ); - ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f ); - ri.Cmd_AddCommand( "minimize", GLimp_Minimize ); - ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f ); -} - -void R_InitQueries(void) -{ - if (!glRefConfig.occlusionQuery) - return; - -#ifdef REACTION - qglGenQueriesARB(ARRAY_SIZE(tr.sunFlareQuery), tr.sunFlareQuery); -#endif -} - -void R_ShutDownQueries(void) -{ - if (!glRefConfig.occlusionQuery) - return; - -#ifdef REACTION - qglDeleteQueriesARB(ARRAY_SIZE(tr.sunFlareQuery), tr.sunFlareQuery); -#endif -} - -/* -=============== -R_Init -=============== -*/ -void R_Init( void ) { - int err; - int i; - byte *ptr; - - ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); - - // clear all our internal state - Com_Memset( &tr, 0, sizeof( tr ) ); - Com_Memset( &backEnd, 0, sizeof( backEnd ) ); - Com_Memset( &tess, 0, sizeof( tess ) ); - - if(sizeof(glconfig_t) != 11332) - ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t)); - -// Swap_Init(); - - if ( (intptr_t)tess.xyz & 15 ) { - ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" ); - } - //Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); - - // - // init function tables - // - for ( i = 0; i < FUNCTABLE_SIZE; i++ ) - { - tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); - tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; - tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; - tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; - - if ( i < FUNCTABLE_SIZE / 2 ) - { - if ( i < FUNCTABLE_SIZE / 4 ) - { - tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); - } - else - { - tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; - } - } - else - { - tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; - } - } - - R_InitFogTable(); - - R_NoiseInit(); - - R_Register(); - - max_polys = r_maxpolys->integer; - if (max_polys < MAX_POLYS) - max_polys = MAX_POLYS; - - max_polyverts = r_maxpolyverts->integer; - if (max_polyverts < MAX_POLYVERTS) - max_polyverts = MAX_POLYVERTS; - - ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); - backEndData[0] = (backEndData_t *) ptr; - backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] )); - backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys); - if ( r_smp->integer ) { - ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); - backEndData[1] = (backEndData_t *) ptr; - backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] )); - backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys); - } else { - backEndData[1] = NULL; - } - R_ToggleSmpFrame(); - - InitOpenGL(); - - R_InitImages(); - - FBO_Init(); - - GLSL_InitGPUShaders(); - - R_InitVBOs(); - - R_InitShaders(); - - R_InitSkins(); - - R_ModelInit(); - - R_InitFreeType(); - - R_InitQueries(); - - - err = qglGetError(); - if ( err != GL_NO_ERROR ) - ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); - - ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); -} - -/* -=============== -RE_Shutdown -=============== -*/ -void RE_Shutdown( qboolean destroyWindow ) { - - ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow ); - - ri.Cmd_RemoveCommand ("modellist"); - ri.Cmd_RemoveCommand ("screenshotJPEG"); - ri.Cmd_RemoveCommand ("screenshot"); - ri.Cmd_RemoveCommand ("imagelist"); - ri.Cmd_RemoveCommand ("shaderlist"); - ri.Cmd_RemoveCommand ("skinlist"); - ri.Cmd_RemoveCommand ("gfxinfo"); - ri.Cmd_RemoveCommand("minimize"); - ri.Cmd_RemoveCommand( "modelist" ); - ri.Cmd_RemoveCommand( "shaderstate" ); - - - if ( tr.registered ) { - R_SyncRenderThread(); - R_ShutdownCommandBuffers(); - R_ShutDownQueries(); - FBO_Shutdown(); - R_DeleteTextures(); - R_ShutdownVBOs(); - GLSL_ShutdownGPUShaders(); - } - - R_DoneFreeType(); - - // shut down platform specific OpenGL stuff - if ( destroyWindow ) { - GLimp_Shutdown(); - } - - tr.registered = qfalse; -} - - -/* -============= -RE_EndRegistration - -Touch all images to make sure they are resident -============= -*/ -void RE_EndRegistration( void ) { - R_SyncRenderThread(); - if (!ri.Sys_LowPhysicalMemory()) { - RB_ShowImages(); - } -} - - -/* -@@@@@@@@@@@@@@@@@@@@@ -GetRefAPI - -@@@@@@@@@@@@@@@@@@@@@ -*/ -#ifdef USE_RENDERER_DLOPEN -Q_EXPORT refexport_t QDECL *GetRefAPI ( int apiVersion, refimport_t *rimp ) { -#else -refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) { -#endif - - static refexport_t re; - - ri = *rimp; - - Com_Memset( &re, 0, sizeof( re ) ); - - if ( apiVersion != REF_API_VERSION ) { - ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n", - REF_API_VERSION, apiVersion ); - return NULL; - } - - // the RE_ functions are Renderer Entry points - - re.Shutdown = RE_Shutdown; - - re.BeginRegistration = RE_BeginRegistration; - re.RegisterModel = RE_RegisterModel; - re.RegisterSkin = RE_RegisterSkin; - re.RegisterShader = RE_RegisterShader; - re.RegisterShaderNoMip = RE_RegisterShaderNoMip; - re.LoadWorld = RE_LoadWorldMap; - re.SetWorldVisData = RE_SetWorldVisData; - re.EndRegistration = RE_EndRegistration; - - re.BeginFrame = RE_BeginFrame; - re.EndFrame = RE_EndFrame; - - re.MarkFragments = R_MarkFragments; - re.LerpTag = R_LerpTag; - re.ModelBounds = R_ModelBounds; - - re.ClearScene = RE_ClearScene; - re.AddRefEntityToScene = RE_AddRefEntityToScene; - re.AddPolyToScene = RE_AddPolyToScene; - re.LightForPoint = R_LightForPoint; - re.AddLightToScene = RE_AddLightToScene; - re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene; - re.RenderScene = RE_RenderScene; - - re.SetColor = RE_SetColor; - re.DrawStretchPic = RE_StretchPic; - re.DrawStretchRaw = RE_StretchRaw; - re.UploadCinematic = RE_UploadCinematic; - - re.RegisterFont = RE_RegisterFont; - re.RemapShader = R_RemapShader; - re.GetEntityToken = R_GetEntityToken; - re.inPVS = R_inPVS; - - re.TakeVideoFrame = RE_TakeVideoFrame; - - return &re; -} diff --git a/code/renderergl2/tr_light.c b/code/renderergl2/tr_light.c deleted file mode 100644 index cec6b295..00000000 --- a/code/renderergl2/tr_light.c +++ /dev/null @@ -1,455 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_light.c - -#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 *or) { - int i; - vec3_t temp; - - for ( i = 0 ; i < count ; i++, dl++ ) { - VectorSubtract( dl->origin, or->origin, temp ); - dl->transformed[0] = DotProduct( temp, or->axis[0] ); - dl->transformed[1] = DotProduct( temp, or->axis[1] ); - dl->transformed[2] = DotProduct( temp, or->axis[2] ); - } -} - -/* -============= -R_DlightBmodel - -Determine which dynamic lights may effect this bmodel -============= -*/ -void R_DlightBmodel( bmodel_t *bmodel ) { - 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.or ); - - mask = 0; - for ( i=0 ; itransformed[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 = (mask != 0); - - // set the dlight bits in all the surfaces - for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { - surf = tr.world->surfaces + bmodel->firstSurface + i; - - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = 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, world_t *world ) { - vec3_t lightOrigin; - int pos[3]; - int i, j; - byte *gridData; - float frac[3]; - int gridStep[3]; - vec3_t direction; - float totalFactor; - - 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 ); - } - - VectorSubtract( lightOrigin, world->lightGridOrigin, lightOrigin ); - for ( i = 0 ; i < 3 ; i++ ) { - float v; - - v = lightOrigin[i]*world->lightGridInverseSize[i]; - pos[i] = floor( v ); - frac[i] = v - pos[i]; - if ( pos[i] < 0 ) { - pos[i] = 0; - } else if ( pos[i] >= world->lightGridBounds[i] - 1 ) { - pos[i] = world->lightGridBounds[i] - 1; - } - } - - VectorClear( ent->ambientLight ); - VectorClear( ent->directedLight ); - VectorClear( direction ); - - assert( world->lightGridData ); // NULL with -nolight maps - - // trilerp the light value - gridStep[0] = 8; - gridStep[1] = 8 * world->lightGridBounds[0]; - gridStep[2] = 8 * world->lightGridBounds[0] * world->lightGridBounds[1]; - gridData = world->lightGridData + pos[0] * gridStep[0] - + pos[1] * gridStep[1] + pos[2] * gridStep[2]; - - totalFactor = 0; - for ( i = 0 ; i < 8 ; i++ ) { - float factor; - byte *data; - int lat, lng; - vec3_t normal; - qboolean ignore; - #if idppc - float d0, d1, d2, d3, d4, d5; - #endif - factor = 1.0; - data = gridData; - ignore = qfalse; - for ( j = 0 ; j < 3 ; j++ ) { - if ( i & (1<= world->lightGridBounds[j] - 1) - { - ignore = qtrue; // ignore values outside lightgrid - } - factor *= frac[j]; - data += gridStep[j]; - } else { - factor *= (1.0f - frac[j]); - } - } - - if ( ignore ) - continue; - - if (world->hdrLightGrid) - { - float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6; - if (!(hdrData[0]+hdrData[1]+hdrData[2]+hdrData[3]+hdrData[4]+hdrData[5]) ) { - continue; // ignore samples in walls - } - } - else - { - if (!(data[0]+data[1]+data[2]+data[3]+data[4]+data[5]) ) { - continue; // ignore samples in walls - } - } - totalFactor += factor; - #if idppc - d0 = data[0]; d1 = data[1]; d2 = data[2]; - d3 = data[3]; d4 = data[4]; d5 = data[5]; - - ent->ambientLight[0] += factor * d0; - ent->ambientLight[1] += factor * d1; - ent->ambientLight[2] += factor * d2; - - ent->directedLight[0] += factor * d3; - ent->directedLight[1] += factor * d4; - ent->directedLight[2] += factor * d5; - #else - if (world->hdrLightGrid) - { - // FIXME: this is hideous - float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6; - - ent->ambientLight[0] += factor * hdrData[0]; - ent->ambientLight[1] += factor * hdrData[1]; - ent->ambientLight[2] += factor * hdrData[2]; - - ent->directedLight[0] += factor * hdrData[3]; - ent->directedLight[1] += factor * hdrData[4]; - ent->directedLight[2] += factor * hdrData[5]; - } - else - { - ent->ambientLight[0] += factor * data[0]; - ent->ambientLight[1] += factor * data[1]; - ent->ambientLight[2] += factor * data[2]; - - ent->directedLight[0] += factor * data[3]; - ent->directedLight[1] += factor * data[4]; - ent->directedLight[2] += factor * data[5]; - } - #endif - lat = data[7]; - lng = data[6]; - 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 ( totalFactor > 0 && totalFactor < 0.99 ) { - totalFactor = 1.0f / 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 = ent->ambientLight[0]; - if ( ent->ambientLight[1] > max1 ) { - max1 = ent->ambientLight[1]; - } else if ( ent->ambientLight[2] > max1 ) { - max1 = ent->ambientLight[2]; - } - - 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\n", max1, max2 ); -} - -/* -================= -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, tr.world ); - } 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 ( !r_hdr->integer /* ent->e.renderfx & RF_MINLIGHT */ ) { - // 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 - if ( !r_hdr->integer ) - { - 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] = ri.ftol(ent->ambientLight[0]); - ((byte *)&ent->ambientLightInt)[1] = ri.ftol(ent->ambientLight[1]); - ((byte *)&ent->ambientLightInt)[2] = ri.ftol(ent->ambientLight[2]); - ((byte *)&ent->ambientLightInt)[3] = 0xff; - - // transform the direction to local space - // no need to do this if using lightentity glsl shader - VectorNormalize( lightDir ); - VectorCopy(lightDir, ent->lightDir); -} - -/* -================= -R_LightForPoint -================= -*/ -int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ) -{ - trRefEntity_t ent; - - if ( tr.world->lightGridData == NULL ) - return qfalse; - - Com_Memset(&ent, 0, sizeof(ent)); - VectorCopy( point, ent.e.origin ); - R_SetupEntityLightingGrid( &ent, tr.world ); - VectorCopy(ent.ambientLight, ambientLight); - VectorCopy(ent.directedLight, directedLight); - VectorCopy(ent.lightDir, lightDir); - - return qtrue; -} - - -int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ) -{ - trRefEntity_t ent; - - if ( world->lightGridData == NULL ) - return qfalse; - - Com_Memset(&ent, 0, sizeof(ent)); - VectorCopy( point, ent.e.origin ); - R_SetupEntityLightingGrid( &ent, world ); - - if ((DotProduct(ent.lightDir, ent.lightDir) < 0.9f) || (DotProduct(ent.lightDir, normal) < 0.1f)) - { - VectorCopy(normal, lightDir); - } - else - { - VectorCopy(ent.lightDir, lightDir); - } - - return qtrue; -} \ No newline at end of file diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h deleted file mode 100644 index a6153b9a..00000000 --- a/code/renderergl2/tr_local.h +++ /dev/null @@ -1,2819 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - - -#ifndef TR_LOCAL_H -#define TR_LOCAL_H - -#include "../qcommon/q_shared.h" -#include "../qcommon/qfiles.h" -#include "../qcommon/qcommon.h" -#include "../renderer/tr_public.h" -#include "tr_extratypes.h" -#include "tr_extramath.h" -#include "tr_fbo.h" -#include "tr_postprocess.h" -#include "qgl.h" -#include "../renderer/iqm.h" - -#define GL_INDEX_TYPE GL_UNSIGNED_INT -typedef unsigned int glIndex_t; - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) -#endif - -// everything that is needed by the backend needs -// to be double buffered to allow it to run in -// parallel on a dual cpu machine -#define SMP_FRAMES 2 - -// 14 bits -// can't be increased without changing bit packing for drawsurfs -// see QSORT_SHADERNUM_SHIFT -#define SHADERNUM_BITS 14 -#define MAX_SHADERS (1<or.origin in local coordinates - float modelMatrix[16]; - float transformMatrix[16]; -} orientationr_t; - -typedef enum -{ - IMGTYPE_COLORALPHA, // for color, lightmap, diffuse, and specular - IMGTYPE_NORMAL, - IMGTYPE_NORMALHEIGHT, - IMGTYPE_DELUXE, // normals are swizzled, deluxe are not -} imgType_t; - -typedef enum -{ - IMGFLAG_NONE = 0x0000, - IMGFLAG_MIPMAP = 0x0001, - IMGFLAG_PICMIP = 0x0002, - IMGFLAG_CUBEMAP = 0x0004, - IMGFLAG_NO_COMPRESSION = 0x0010, - IMGFLAG_NOLIGHTSCALE = 0x0020, - IMGFLAG_CLAMPTOEDGE = 0x0040, - IMGFLAG_SRGB = 0x0080, - IMGFLAG_GENNORMALMAP = 0x0100, -} imgFlags_t; - -typedef struct image_s { - char imgName[MAX_QPATH]; // game path, including extension - int width, height; // source image - int uploadWidth, uploadHeight; // after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE - GLuint texnum; // gl texture binding - - int frameUsed; // for texture usage in frame statistics - - int internalFormat; - int TMU; // only needed for voodoo2 - - imgType_t type; - imgFlags_t flags; - - struct image_s* next; -} image_t; - -typedef enum -{ - VBO_USAGE_STATIC, - VBO_USAGE_DYNAMIC -} vboUsage_t; - -typedef struct VBO_s -{ - char name[MAX_QPATH]; - - uint32_t vertexesVBO; - int vertexesSize; // amount of memory data allocated for all vertices in bytes - uint32_t ofs_xyz; - uint32_t ofs_normal; - uint32_t ofs_st; - uint32_t ofs_lightmap; - uint32_t ofs_vertexcolor; - uint32_t ofs_lightdir; -#ifdef USE_VERT_TANGENT_SPACE - uint32_t ofs_tangent; - uint32_t ofs_bitangent; -#endif - uint32_t stride_xyz; - uint32_t stride_normal; - uint32_t stride_st; - uint32_t stride_lightmap; - uint32_t stride_vertexcolor; - uint32_t stride_lightdir; -#ifdef USE_VERT_TANGENT_SPACE - uint32_t stride_tangent; - uint32_t stride_bitangent; -#endif - uint32_t size_xyz; - uint32_t size_normal; - - int attribs; -} VBO_t; - -typedef struct IBO_s -{ - char name[MAX_QPATH]; - - uint32_t indexesVBO; - int indexesSize; // amount of memory data allocated for all triangles in bytes -// uint32_t ofsIndexes; -} IBO_t; - -//=============================================================================== - -typedef enum { - SS_BAD, - SS_PORTAL, // mirrors, portals, viewscreens - SS_ENVIRONMENT, // sky box - SS_OPAQUE, // opaque - - SS_DECAL, // scorch marks, etc. - SS_SEE_THROUGH, // ladders, grates, grills that may have small blended edges - // in addition to alpha test - SS_BANNER, - - SS_FOG, - - SS_UNDERWATER, // for items that should be drawn in front of the water plane - - SS_BLEND0, // regular transparency and filters - SS_BLEND1, // generally only used for additive type effects - SS_BLEND2, - SS_BLEND3, - - SS_BLEND6, - SS_STENCIL_SHADOW, - SS_ALMOST_NEAREST, // gun smoke puffs - - SS_NEAREST // blood blobs -} shaderSort_t; - - -#define MAX_SHADER_STAGES 8 - -typedef enum { - GF_NONE, - - GF_SIN, - GF_SQUARE, - GF_TRIANGLE, - GF_SAWTOOTH, - GF_INVERSE_SAWTOOTH, - - GF_NOISE - -} genFunc_t; - - -typedef enum { - DEFORM_NONE, - DEFORM_WAVE, - DEFORM_NORMALS, - DEFORM_BULGE, - DEFORM_MOVE, - DEFORM_PROJECTION_SHADOW, - DEFORM_AUTOSPRITE, - DEFORM_AUTOSPRITE2, - DEFORM_TEXT0, - DEFORM_TEXT1, - DEFORM_TEXT2, - DEFORM_TEXT3, - DEFORM_TEXT4, - DEFORM_TEXT5, - DEFORM_TEXT6, - DEFORM_TEXT7 -} deform_t; - -// deformVertexes types that can be handled by the GPU -typedef enum -{ - // do not edit: same as genFunc_t - - DGEN_NONE, - DGEN_WAVE_SIN, - DGEN_WAVE_SQUARE, - DGEN_WAVE_TRIANGLE, - DGEN_WAVE_SAWTOOTH, - DGEN_WAVE_INVERSE_SAWTOOTH, - DGEN_WAVE_NOISE, - - // do not edit until this line - - DGEN_BULGE, - DGEN_MOVE -} deformGen_t; - -typedef enum { - AGEN_IDENTITY, - AGEN_SKIP, - AGEN_ENTITY, - AGEN_ONE_MINUS_ENTITY, - AGEN_VERTEX, - AGEN_ONE_MINUS_VERTEX, - AGEN_LIGHTING_SPECULAR, - AGEN_WAVEFORM, - AGEN_PORTAL, - AGEN_CONST, - AGEN_FRESNEL -} alphaGen_t; - -typedef enum { - CGEN_BAD, - CGEN_IDENTITY_LIGHTING, // tr.identityLight - CGEN_IDENTITY, // always (1,1,1,1) - CGEN_ENTITY, // grabbed from entity's modulate field - CGEN_ONE_MINUS_ENTITY, // grabbed from 1 - entity.modulate - CGEN_EXACT_VERTEX, // tess.vertexColors - CGEN_VERTEX, // tess.vertexColors * tr.identityLight - CGEN_EXACT_VERTEX_LIT, // like CGEN_EXACT_VERTEX but takes a light direction from the lightgrid - CGEN_VERTEX_LIT, // like CGEN_VERTEX but takes a light direction from the lightgrid - CGEN_ONE_MINUS_VERTEX, - CGEN_WAVEFORM, // programmatically generated - CGEN_LIGHTING_DIFFUSE, - CGEN_FOG, // standard fog - CGEN_CONST // fixed color -} colorGen_t; - -typedef enum { - TCGEN_BAD, - TCGEN_IDENTITY, // clear to 0,0 - TCGEN_LIGHTMAP, - TCGEN_TEXTURE, - TCGEN_ENVIRONMENT_MAPPED, - TCGEN_FOG, - TCGEN_VECTOR // S and T from world coordinates -} texCoordGen_t; - -typedef enum { - ACFF_NONE, - ACFF_MODULATE_RGB, - ACFF_MODULATE_RGBA, - ACFF_MODULATE_ALPHA -} acff_t; - -typedef struct { - genFunc_t func; - - float base; - float amplitude; - float phase; - float frequency; -} waveForm_t; - -#define TR_MAX_TEXMODS 4 - -typedef enum { - TMOD_NONE, - TMOD_TRANSFORM, - TMOD_TURBULENT, - TMOD_SCROLL, - TMOD_SCALE, - TMOD_STRETCH, - TMOD_ROTATE, - TMOD_ENTITY_TRANSLATE -} texMod_t; - -#define MAX_SHADER_DEFORMS 3 -typedef struct { - deform_t deformation; // vertex coordinate modification type - - vec3_t moveVector; - waveForm_t deformationWave; - float deformationSpread; - - float bulgeWidth; - float bulgeHeight; - float bulgeSpeed; -} deformStage_t; - - -typedef struct { - texMod_t type; - - // used for TMOD_TURBULENT and TMOD_STRETCH - waveForm_t wave; - - // used for TMOD_TRANSFORM - float matrix[2][2]; // s' = s * m[0][0] + t * m[1][0] + trans[0] - float translate[2]; // t' = s * m[0][1] + t * m[0][1] + trans[1] - - // used for TMOD_SCALE - float scale[2]; // s *= scale[0] - // t *= scale[1] - - // used for TMOD_SCROLL - float scroll[2]; // s' = s + scroll[0] * time - // t' = t + scroll[1] * time - - // + = clockwise - // - = counterclockwise - float rotateSpeed; - -} texModInfo_t; - - -#define MAX_IMAGE_ANIMATIONS 8 - -typedef struct { - image_t *image[MAX_IMAGE_ANIMATIONS]; - int numImageAnimations; - float imageAnimationSpeed; - - texCoordGen_t tcGen; - vec3_t tcGenVectors[2]; - - int numTexMods; - texModInfo_t *texMods; - - int videoMapHandle; - qboolean isLightmap; - qboolean vertexLightmap; - qboolean isVideoMap; -} textureBundle_t; - -enum -{ - TB_COLORMAP = 0, - TB_DIFFUSEMAP = 0, - TB_LIGHTMAP = 1, - TB_LEVELSMAP = 1, - TB_SHADOWMAP = 1, - TB_NORMALMAP = 2, - TB_DELUXEMAP = 3, - TB_SHADOWMAP2 = 3, - TB_SPECULARMAP = 4, - TB_SHADOWMAP3 = 5, - NUM_TEXTURE_BUNDLES = 6 -}; - -typedef enum -{ - // material shader stage types - ST_COLORMAP = 0, // vanilla Q3A style shader treatening - ST_DIFFUSEMAP = 0, // treat color and diffusemap the same - ST_NORMALMAP, - ST_NORMALPARALLAXMAP, - ST_SPECULARMAP, - ST_GLSL -} stageType_t; - -typedef struct { - qboolean active; - - textureBundle_t bundle[NUM_TEXTURE_BUNDLES]; - - waveForm_t rgbWave; - colorGen_t rgbGen; - - waveForm_t alphaWave; - alphaGen_t alphaGen; - - byte constantColor[4]; // for CGEN_CONST and AGEN_CONST - - unsigned stateBits; // GLS_xxxx mask - - acff_t adjustColorsForFog; - - qboolean isDetail; - - stageType_t type; - struct shaderProgram_s *glslShaderGroup; - int glslShaderIndex; - vec2_t materialInfo; -} shaderStage_t; - -struct shaderCommands_s; - -// any change in the LIGHTMAP_* defines here MUST be reflected in -// R_FindShader() in tr_bsp.c -#define LIGHTMAP_2D -4 // shader is for 2D rendering -#define LIGHTMAP_BY_VERTEX -3 // pre-lit triangle models -#define LIGHTMAP_WHITEIMAGE -2 -#define LIGHTMAP_NONE -1 - -typedef enum { - CT_FRONT_SIDED, - CT_BACK_SIDED, - CT_TWO_SIDED -} cullType_t; - -typedef enum { - FP_NONE, // surface is translucent and will just be adjusted properly - FP_EQUAL, // surface is opaque but possibly alpha tested - FP_LE // surface is trnaslucent, but still needs a fog pass (fog surface) -} fogPass_t; - -typedef struct { - float cloudHeight; - image_t *outerbox[6], *innerbox[6]; -} skyParms_t; - -typedef struct { - vec3_t color; - float depthForOpaque; -} fogParms_t; - - -typedef struct shader_s { - char name[MAX_QPATH]; // game path, including extension - int lightmapIndex; // for a shader to match, both name and lightmapIndex must match - - int index; // this shader == tr.shaders[index] - int sortedIndex; // this shader == tr.sortedShaders[sortedIndex] - - float sort; // lower numbered shaders draw before higher numbered - - qboolean defaultShader; // we want to return index 0 if the shader failed to - // load for some reason, but R_FindShader should - // still keep a name allocated for it, so if - // something calls RE_RegisterShader again with - // the same name, we don't try looking for it again - - qboolean explicitlyDefined; // found in a .shader file - - int surfaceFlags; // if explicitlyDefined, this will have SURF_* flags - int contentFlags; - - qboolean entityMergable; // merge across entites optimizable (smoke, blood) - - qboolean isSky; - skyParms_t sky; - fogParms_t fogParms; - - float portalRange; // distance to fog out at - qboolean isPortal; - - int multitextureEnv; // 0, GL_MODULATE, GL_ADD (FIXME: put in stage) - - cullType_t cullType; // CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED - qboolean polygonOffset; // set for decals and other items that must be offset - qboolean noMipMaps; // for console fonts, 2D elements, etc. - qboolean noPicMip; // for images that must always be full resolution - - fogPass_t fogPass; // draw a blended pass, possibly with depth test equals - - int vertexAttribs; // not all shaders will need all data to be gathered - - int numDeforms; - deformStage_t deforms[MAX_SHADER_DEFORMS]; - - int numUnfoggedPasses; - shaderStage_t *stages[MAX_SHADER_STAGES]; - - void (*optimalStageIteratorFunc)( void ); - - float clampTime; // time this shader is clamped to - float timeOffset; // current time offset for this shader - - int numStates; // if non-zero this is a state shader - struct shader_s *currentShader; // current state if this is a state shader - struct shader_s *parentShader; // current state if this is a state shader - int currentState; // current state index for cycle purposes - long expireTime; // time in milliseconds this expires - - struct shader_s *remappedShader; // current shader this one is remapped too - - int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states - - struct shader_s *next; -} shader_t; - -static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader) -{ - if(shader->numDeforms) - { - const deformStage_t *ds = &shader->deforms[0]; - - if (shader->numDeforms > 1) - return qtrue; - - switch (ds->deformation) - { - case DEFORM_WAVE: - case DEFORM_BULGE: - return qfalse; - - default: - return qtrue; - } - } - - return qfalse; -} - -typedef struct shaderState_s { - char shaderName[MAX_QPATH]; // name of shader this state belongs to - char name[MAX_STATE_NAME]; // name of this state - char stateShader[MAX_QPATH]; // shader this name invokes - int cycleTime; // time this cycle lasts, <= 0 is forever - shader_t *shader; -} shaderState_t; - -enum -{ - ATTR_INDEX_POSITION = 0, - ATTR_INDEX_TEXCOORD0 = 1, - ATTR_INDEX_TEXCOORD1 = 2, - ATTR_INDEX_TANGENT = 3, - ATTR_INDEX_BITANGENT = 4, - ATTR_INDEX_NORMAL = 5, - ATTR_INDEX_COLOR = 6, - ATTR_INDEX_PAINTCOLOR = 7, - ATTR_INDEX_LIGHTDIRECTION = 8, - ATTR_INDEX_BONE_INDEXES = 9, - ATTR_INDEX_BONE_WEIGHTS = 10, - - // GPU vertex animations - ATTR_INDEX_POSITION2 = 11, - ATTR_INDEX_TANGENT2 = 12, - ATTR_INDEX_BITANGENT2 = 13, - ATTR_INDEX_NORMAL2 = 14 -}; - -enum -{ - GLS_SRCBLEND_ZERO = (1 << 0), - GLS_SRCBLEND_ONE = (1 << 1), - GLS_SRCBLEND_DST_COLOR = (1 << 2), - GLS_SRCBLEND_ONE_MINUS_DST_COLOR = (1 << 3), - GLS_SRCBLEND_SRC_ALPHA = (1 << 4), - GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA = (1 << 5), - GLS_SRCBLEND_DST_ALPHA = (1 << 6), - GLS_SRCBLEND_ONE_MINUS_DST_ALPHA = (1 << 7), - GLS_SRCBLEND_ALPHA_SATURATE = (1 << 8), - - GLS_SRCBLEND_BITS = GLS_SRCBLEND_ZERO - | GLS_SRCBLEND_ONE - | GLS_SRCBLEND_DST_COLOR - | GLS_SRCBLEND_ONE_MINUS_DST_COLOR - | GLS_SRCBLEND_SRC_ALPHA - | GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA - | GLS_SRCBLEND_DST_ALPHA - | GLS_SRCBLEND_ONE_MINUS_DST_ALPHA - | GLS_SRCBLEND_ALPHA_SATURATE, - - GLS_DSTBLEND_ZERO = (1 << 9), - GLS_DSTBLEND_ONE = (1 << 10), - GLS_DSTBLEND_SRC_COLOR = (1 << 11), - GLS_DSTBLEND_ONE_MINUS_SRC_COLOR = (1 << 12), - GLS_DSTBLEND_SRC_ALPHA = (1 << 13), - GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA = (1 << 14), - GLS_DSTBLEND_DST_ALPHA = (1 << 15), - GLS_DSTBLEND_ONE_MINUS_DST_ALPHA = (1 << 16), - - GLS_DSTBLEND_BITS = GLS_DSTBLEND_ZERO - | GLS_DSTBLEND_ONE - | GLS_DSTBLEND_SRC_COLOR - | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR - | GLS_DSTBLEND_SRC_ALPHA - | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA - | GLS_DSTBLEND_DST_ALPHA - | GLS_DSTBLEND_ONE_MINUS_DST_ALPHA, - - GLS_DEPTHMASK_TRUE = (1 << 17), - - GLS_POLYMODE_LINE = (1 << 18), - - GLS_DEPTHTEST_DISABLE = (1 << 19), - - GLS_DEPTHFUNC_LESS = (1 << 20), - GLS_DEPTHFUNC_EQUAL = (1 << 21), - - GLS_DEPTHFUNC_BITS = GLS_DEPTHFUNC_LESS - | GLS_DEPTHFUNC_EQUAL, - - GLS_ATEST_GT_0 = (1 << 22), - GLS_ATEST_LT_128 = (1 << 23), - GLS_ATEST_GE_128 = (1 << 24), -// GLS_ATEST_GE_CUSTOM = (1 << 25), - - GLS_ATEST_BITS = GLS_ATEST_GT_0 - | GLS_ATEST_LT_128 - | GLS_ATEST_GE_128, -// | GLS_ATEST_GT_CUSTOM, - - GLS_REDMASK_FALSE = (1 << 26), - GLS_GREENMASK_FALSE = (1 << 27), - GLS_BLUEMASK_FALSE = (1 << 28), - GLS_ALPHAMASK_FALSE = (1 << 29), - - GLS_COLORMASK_BITS = GLS_REDMASK_FALSE - | GLS_GREENMASK_FALSE - | GLS_BLUEMASK_FALSE - | GLS_ALPHAMASK_FALSE, - - GLS_STENCILTEST_ENABLE = (1 << 30), - - GLS_DEFAULT = GLS_DEPTHMASK_TRUE -}; - -enum -{ - ATTR_POSITION = 0x0001, - ATTR_TEXCOORD = 0x0002, - ATTR_LIGHTCOORD = 0x0004, - ATTR_TANGENT = 0x0008, - ATTR_BITANGENT = 0x0010, - ATTR_NORMAL = 0x0020, - ATTR_COLOR = 0x0040, - ATTR_PAINTCOLOR = 0x0080, - ATTR_LIGHTDIRECTION = 0x0100, - ATTR_BONE_INDEXES = 0x0200, - ATTR_BONE_WEIGHTS = 0x0400, - - // for .md3 interpolation - ATTR_POSITION2 = 0x0800, - ATTR_TANGENT2 = 0x1000, - ATTR_BITANGENT2 = 0x2000, - ATTR_NORMAL2 = 0x4000, - - ATTR_DEFAULT = ATTR_POSITION, - ATTR_BITS = ATTR_POSITION | - ATTR_TEXCOORD | - ATTR_LIGHTCOORD | - ATTR_TANGENT | - ATTR_BITANGENT | - ATTR_NORMAL | - ATTR_COLOR | - ATTR_PAINTCOLOR | - ATTR_LIGHTDIRECTION | - ATTR_BONE_INDEXES | - ATTR_BONE_WEIGHTS | - ATTR_POSITION2 | - ATTR_TANGENT2 | - ATTR_BITANGENT2 | - ATTR_NORMAL2 -}; - -enum -{ - GENERICDEF_USE_DEFORM_VERTEXES = 0x0001, - GENERICDEF_USE_TCGEN = 0x0002, - GENERICDEF_USE_VERTEX_ANIMATION = 0x0004, - GENERICDEF_USE_FOG = 0x0008, - GENERICDEF_USE_RGBAGEN = 0x0010, - GENERICDEF_USE_LIGHTMAP = 0x0020, - GENERICDEF_ALL = 0x003F, - GENERICDEF_COUNT = 0x0040, -}; - -enum -{ - LIGHTDEF_USE_LIGHTMAP = 0x0001, - LIGHTDEF_USE_LIGHT_VECTOR = 0x0002, - LIGHTDEF_USE_LIGHT_VERTEX = 0x0003, - LIGHTDEF_LIGHTTYPE_MASK = 0x0003, - LIGHTDEF_USE_NORMALMAP = 0x0004, - LIGHTDEF_USE_SPECULARMAP = 0x0008, - LIGHTDEF_USE_DELUXEMAP = 0x0010, - LIGHTDEF_USE_PARALLAXMAP = 0x0020, - LIGHTDEF_USE_SHADOWMAP = 0x0040, - LIGHTDEF_TCGEN_ENVIRONMENT = 0x0080, - LIGHTDEF_ENTITY = 0x0100, - LIGHTDEF_ALL = 0x01FF, - LIGHTDEF_COUNT = 0x0200 -}; - -enum -{ - GLSL_INT, - GLSL_FLOAT, - GLSL_FLOAT5, - GLSL_VEC2, - GLSL_VEC3, - GLSL_VEC4, - GLSL_MAT16 -}; - -// Tr3B - shaderProgram_t represents a pair of one -// GLSL vertex and one GLSL fragment shader -typedef struct shaderProgram_s -{ - char name[MAX_QPATH]; - - GLhandleARB program; - GLhandleARB vertexShader; - GLhandleARB fragmentShader; - uint32_t attribs; // vertex array attributes - - // uniform parameters - int numUniforms; - GLint *uniforms; - GLint *uniformTypes; - int *uniformBufferOffsets; - char *uniformBuffer; -} shaderProgram_t; - - -enum -{ - TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX = 0, - TEXTURECOLOR_UNIFORM_INVTEXRES, - TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, - TEXTURECOLOR_UNIFORM_TEXTUREMAP, - TEXTURECOLOR_UNIFORM_LEVELSMAP, - TEXTURECOLOR_UNIFORM_COLOR, - TEXTURECOLOR_UNIFORM_COUNT -}; - - -enum -{ - FOGPASS_UNIFORM_FOGDISTANCE = 0, - FOGPASS_UNIFORM_FOGDEPTH, - FOGPASS_UNIFORM_FOGEYET, - FOGPASS_UNIFORM_DEFORMGEN, - FOGPASS_UNIFORM_DEFORMPARAMS, - FOGPASS_UNIFORM_TIME, - FOGPASS_UNIFORM_COLOR, - FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, - FOGPASS_UNIFORM_VERTEXLERP, - FOGPASS_UNIFORM_COUNT -}; - - -enum -{ - DLIGHT_UNIFORM_DIFFUSEMAP = 0, - DLIGHT_UNIFORM_DLIGHTINFO, - DLIGHT_UNIFORM_DEFORMGEN, - DLIGHT_UNIFORM_DEFORMPARAMS, - DLIGHT_UNIFORM_TIME, - DLIGHT_UNIFORM_COLOR, - DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, - DLIGHT_UNIFORM_VERTEXLERP, - DLIGHT_UNIFORM_COUNT -}; - - -enum -{ - PSHADOW_UNIFORM_SHADOWMAP = 0, - PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, - PSHADOW_UNIFORM_LIGHTFORWARD, - PSHADOW_UNIFORM_LIGHTUP, - PSHADOW_UNIFORM_LIGHTRIGHT, - PSHADOW_UNIFORM_LIGHTORIGIN, - PSHADOW_UNIFORM_LIGHTRADIUS, - PSHADOW_UNIFORM_COUNT -}; - - -enum -{ - GENERIC_UNIFORM_DIFFUSEMAP = 0, - GENERIC_UNIFORM_LIGHTMAP, - GENERIC_UNIFORM_NORMALMAP, - GENERIC_UNIFORM_DELUXEMAP, - GENERIC_UNIFORM_SPECULARMAP, - GENERIC_UNIFORM_SHADOWMAP, - GENERIC_UNIFORM_DIFFUSETEXMATRIX, - //GENERIC_UNIFORM_NORMALTEXMATRIX, - //GENERIC_UNIFORM_SPECULARTEXMATRIX, - GENERIC_UNIFORM_TEXTURE1ENV, - GENERIC_UNIFORM_VIEWORIGIN, - GENERIC_UNIFORM_TCGEN0, - GENERIC_UNIFORM_TCGEN0VECTOR0, - GENERIC_UNIFORM_TCGEN0VECTOR1, - GENERIC_UNIFORM_DEFORMGEN, - GENERIC_UNIFORM_DEFORMPARAMS, - GENERIC_UNIFORM_COLORGEN, - GENERIC_UNIFORM_ALPHAGEN, - GENERIC_UNIFORM_BASECOLOR, - GENERIC_UNIFORM_VERTCOLOR, - GENERIC_UNIFORM_AMBIENTLIGHT, - GENERIC_UNIFORM_DIRECTEDLIGHT, - GENERIC_UNIFORM_LIGHTORIGIN, - GENERIC_UNIFORM_LIGHTRADIUS, - GENERIC_UNIFORM_PORTALRANGE, - GENERIC_UNIFORM_FOGDISTANCE, - GENERIC_UNIFORM_FOGDEPTH, - GENERIC_UNIFORM_FOGEYET, - GENERIC_UNIFORM_FOGCOLORMASK, - GENERIC_UNIFORM_MODELMATRIX, - GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, - GENERIC_UNIFORM_TIME, - GENERIC_UNIFORM_VERTEXLERP, - GENERIC_UNIFORM_MATERIALINFO, - GENERIC_UNIFORM_COUNT -}; - -enum -{ - SHADOWMASK_UNIFORM_SCREENDEPTHMAP = 0, - SHADOWMASK_UNIFORM_SHADOWMAP, - SHADOWMASK_UNIFORM_SHADOWMAP2, - SHADOWMASK_UNIFORM_SHADOWMAP3, - SHADOWMASK_UNIFORM_SHADOWMVP, - SHADOWMASK_UNIFORM_SHADOWMVP2, - SHADOWMASK_UNIFORM_SHADOWMVP3, - SHADOWMASK_UNIFORM_VIEWORIGIN, - SHADOWMASK_UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2 - SHADOWMASK_UNIFORM_VIEWFORWARD, - SHADOWMASK_UNIFORM_VIEWLEFT, - SHADOWMASK_UNIFORM_VIEWUP, - SHADOWMASK_UNIFORM_COUNT -}; - -// -// Tr3B: these are fire wall functions to avoid expensive redundant glUniform* calls -//#define USE_UNIFORM_FIREWALL 1 -//#define LOG_GLSL_UNIFORMS 1 - -// trRefdef_t holds everything that comes in refdef_t, -// as well as the locally generated scene information -typedef struct { - int x, y, width, height; - float fov_x, fov_y; - vec3_t vieworg; - vec3_t viewaxis[3]; // transformation matrix - - stereoFrame_t stereoFrame; - - int time; // time in milliseconds for shader effects and other time dependent rendering issues - int rdflags; // RDF_NOWORLDMODEL, etc - - // 1 bits will prevent the associated area from rendering at all - byte areamask[MAX_MAP_AREA_BYTES]; - qboolean areamaskModified; // qtrue if areamask changed since last scene - - float floatTime; // tr.refdef.time / 1000.0 - - float blurFactor; - - // text messages for deform text shaders - char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; - - int num_entities; - trRefEntity_t *entities; - - int num_dlights; - struct dlight_s *dlights; - - int numPolys; - struct srfPoly_s *polys; - - int numDrawSurfs; - struct drawSurf_s *drawSurfs; - - unsigned int dlightMask; - int num_pshadows; - struct pshadow_s *pshadows; - - float sunShadowMvp[3][16]; - float sunDir[4]; - float sunCol[4]; - float sunAmbCol[4]; - float colorScale; -} trRefdef_t; - - -//================================================================================= - -// skins allow models to be retextured without modifying the model file -typedef struct { - char name[MAX_QPATH]; - shader_t *shader; -} skinSurface_t; - -typedef struct skin_s { - char name[MAX_QPATH]; // game path, including extension - int numSurfaces; - skinSurface_t *surfaces[MD3_MAX_SURFACES]; -} skin_t; - - -typedef struct { - int originalBrushNumber; - vec3_t bounds[2]; - - unsigned colorInt; // in packed byte format - float tcScale; // texture coordinate vector scales - fogParms_t parms; - - // for clipping distance in fog when outside - qboolean hasSurface; - float surface[4]; -} fog_t; - -typedef enum { - VPF_NONE = 0x00, - VPF_SHADOWMAP = 0x01, - VPF_DEPTHSHADOW = 0x02, - VPF_DEPTHCLAMP = 0x04, - VPF_ORTHOGRAPHIC = 0x08, - VPF_USESUNLIGHT = 0x10, -} viewParmFlags_t; - -typedef struct { - orientationr_t or; - orientationr_t world; - vec3_t pvsOrigin; // may be different than or.origin for portals - qboolean isPortal; // true if this view is through a portal - qboolean isMirror; // the portal is a mirror, invert the face culling - viewParmFlags_t flags; - int frameSceneNum; // copied from tr.frameSceneNum - int frameCount; // copied from tr.frameCount - cplane_t portalPlane; // clip anything behind this if mirroring - int viewportX, viewportY, viewportWidth, viewportHeight; - FBO_t *targetFbo; - float fovX, fovY; - float projectionMatrix[16]; - cplane_t frustum[5]; - vec3_t visBounds[2]; - float zFar; - float zNear; - stereoFrame_t stereoFrame; -} viewParms_t; - - -/* -============================================================================== - -SURFACES - -============================================================================== -*/ -typedef byte color4ub_t[4]; - -// any changes in surfaceType must be mirrored in rb_surfaceTable[] -typedef enum { - SF_BAD, - SF_SKIP, // ignore - SF_FACE, - SF_GRID, - SF_TRIANGLES, - SF_POLY, - SF_MDV, - SF_MD4, -#ifdef RAVENMD4 - SF_MDR, -#endif - SF_IQM, - SF_FLARE, - SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity - SF_DISPLAY_LIST, - SF_VBO_MESH, - SF_VBO_MDVMESH, - - SF_NUM_SURFACE_TYPES, - SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int ) -} surfaceType_t; - -typedef struct drawSurf_s { - unsigned sort; // bit combination for fast compares - surfaceType_t *surface; // any of surface*_t -} drawSurf_t; - -#define MAX_FACE_POINTS 64 - -#define MAX_PATCH_SIZE 32 // max dimensions of a patch mesh in map file -#define MAX_GRID_SIZE 65 // max dimensions of a grid mesh in memory - -// when cgame directly specifies a polygon, it becomes a srfPoly_t -// as soon as it is called -typedef struct srfPoly_s { - surfaceType_t surfaceType; - qhandle_t hShader; - int fogIndex; - int numVerts; - polyVert_t *verts; -} srfPoly_t; - -typedef struct srfDisplayList_s { - surfaceType_t surfaceType; - int listNum; -} srfDisplayList_t; - - -typedef struct srfFlare_s { - surfaceType_t surfaceType; - vec3_t origin; - vec3_t normal; - vec3_t color; -} srfFlare_t; - -typedef struct -{ - vec3_t xyz; - vec2_t st; - vec2_t lightmap; - vec3_t normal; -#ifdef USE_VERT_TANGENT_SPACE - vec3_t tangent; - vec3_t bitangent; -#endif - vec3_t lightdir; - vec4_t vertexColors; - -#if DEBUG_OPTIMIZEVERTICES - unsigned int id; -#endif -} srfVert_t; - -#ifdef USE_VERT_TANGENT_SPACE -#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}} -#else -#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}} -#endif - -typedef struct -{ - int indexes[3]; - int neighbors[3]; - vec4_t plane; - qboolean facingLight; - qboolean degenerated; -} srfTriangle_t; - - -typedef struct srfGridMesh_s -{ - surfaceType_t surfaceType; - - // dynamic lighting information - int dlightBits[SMP_FRAMES]; - int pshadowBits[SMP_FRAMES]; - - // culling information - vec3_t meshBounds[2]; - vec3_t localOrigin; - float meshRadius; - - // lod information, which may be different - // than the culling information to allow for - // groups of curves that LOD as a unit - vec3_t lodOrigin; - float lodRadius; - int lodFixed; - int lodStitched; - - // vertexes - int width, height; - float *widthLodError; - float *heightLodError; - - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfGridMesh_t; - - -typedef struct -{ - surfaceType_t surfaceType; - - // dynamic lighting information - int dlightBits[SMP_FRAMES]; - int pshadowBits[SMP_FRAMES]; - - // culling information - cplane_t plane; -// vec3_t bounds[2]; - - // triangle definitions - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfSurfaceFace_t; - - -// misc_models in maps are turned into direct geometry by xmap -typedef struct -{ - surfaceType_t surfaceType; - - // dynamic lighting information - int dlightBits[SMP_FRAMES]; - int pshadowBits[SMP_FRAMES]; - - // culling information -// vec3_t bounds[2]; - - // triangle definitions - int numTriangles; - srfTriangle_t *triangles; - - int numVerts; - srfVert_t *verts; - - // BSP VBO offsets - int firstVert; - int firstIndex; - - // static render data - VBO_t *vbo; // points to bsp model VBO - IBO_t *ibo; -} srfTriangles_t; - -// inter-quake-model -typedef struct { - int num_vertexes; - int num_triangles; - int num_frames; - int num_surfaces; - int num_joints; - struct srfIQModel_s *surfaces; - - float *positions; - float *texcoords; - float *normals; - float *tangents; - byte *blendIndexes; - byte *blendWeights; - byte *colors; - int *triangles; - - int *jointParents; - float *poseMats; - float *bounds; - char *names; -} iqmData_t; - -// inter-quake-model surface -typedef struct srfIQModel_s { - surfaceType_t surfaceType; - char name[MAX_QPATH]; - shader_t *shader; - iqmData_t *data; - int first_vertex, num_vertexes; - int first_triangle, num_triangles; -} srfIQModel_t; - -typedef struct srfVBOMesh_s -{ - surfaceType_t surfaceType; - - struct shader_s *shader; // FIXME move this to somewhere else - int fogIndex; - - // dynamic lighting information - int dlightBits[SMP_FRAMES]; - int pshadowBits[SMP_FRAMES]; - - // culling information - vec3_t bounds[2]; - - // backEnd stats - int numIndexes; - int numVerts; - int firstIndex; - - // static render data - VBO_t *vbo; - IBO_t *ibo; -} srfVBOMesh_t; - -typedef struct srfVBOMDVMesh_s -{ - surfaceType_t surfaceType; - - struct mdvModel_s *mdvModel; - struct mdvSurface_s *mdvSurface; - - // backEnd stats - int numIndexes; - int numVerts; - - // static render data - VBO_t *vbo; - IBO_t *ibo; -} srfVBOMDVMesh_t; - -extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *); - -/* -============================================================================== - -SHADOWS - -============================================================================== -*/ - -typedef struct pshadow_s -{ - float sort; - - int numEntities; - int entityNums[8]; - vec3_t entityOrigins[8]; - float entityRadiuses[8]; - - float viewRadius; - vec3_t viewOrigin; - - vec3_t lightViewAxis[3]; - vec3_t lightOrigin; - float lightRadius; - cplane_t cullPlane; -} pshadow_t; - - -/* -============================================================================== - -BRUSH MODELS - -============================================================================== -*/ - - -// -// in memory representation -// - -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 - -#define CULLINFO_NONE 0 -#define CULLINFO_BOX 1 -#define CULLINFO_SPHERE 2 -#define CULLINFO_PLANE 4 - -typedef struct cullinfo_s { - int type; - vec3_t bounds[2]; - vec3_t localOrigin; - float radius; - cplane_t plane; -} cullinfo_t; - -typedef struct msurface_s { - //int viewCount; // if == tr.viewCount, already added - struct shader_s *shader; - int fogIndex; - cullinfo_t cullinfo; - - surfaceType_t *data; // any of srf*_t -} msurface_t; - - -#define CONTENTS_NODE -1 -typedef struct mnode_s { - // common with leaf and node - int contents; // -1 for nodes, to differentiate from leafs - int visCounts[MAX_VISCOUNTS]; // node needs to be traversed if current - vec3_t mins, maxs; // for bounding box culling - struct mnode_s *parent; - - // node specific - cplane_t *plane; - struct mnode_s *children[2]; - - // leaf specific - int cluster; - int area; - - int firstmarksurface; - int nummarksurfaces; -} mnode_t; - -typedef struct { - vec3_t bounds[2]; // for culling - int firstSurface; - int numSurfaces; -} bmodel_t; - -typedef struct { - char name[MAX_QPATH]; // ie: maps/tim_dm2.bsp - char baseName[MAX_QPATH]; // ie: tim_dm2 - - int dataSize; - - int numShaders; - dshader_t *shaders; - - int numBModels; - bmodel_t *bmodels; - - int numplanes; - cplane_t *planes; - - int numnodes; // includes leafs - int numDecisionNodes; - mnode_t *nodes; - - VBO_t *vbo; - IBO_t *ibo; - - int numWorldSurfaces; - - int numsurfaces; - msurface_t *surfaces; - int *surfacesViewCount; - int *surfacesDlightBits; - int *surfacesPshadowBits; - - int numMergedSurfaces; - msurface_t *mergedSurfaces; - int *mergedSurfacesViewCount; - int *mergedSurfacesDlightBits; - int *mergedSurfacesPshadowBits; - - int nummarksurfaces; - int *marksurfaces; - int *viewSurfaces; - - int numfogs; - fog_t *fogs; - - vec3_t lightGridOrigin; - vec3_t lightGridSize; - vec3_t lightGridInverseSize; - int lightGridBounds[3]; - byte *lightGridData; - float *hdrLightGrid; - - - int numClusters; - int clusterBytes; - const byte *vis; // may be passed in by CM_LoadMap to save space - - byte *novis; // clusterBytes of 0xff - - char *entityString; - char *entityParsePoint; -} world_t; - - -/* -============================================================================== -MDV MODELS - meta format for vertex animation models like .md2, .md3, .mdc -============================================================================== -*/ -typedef struct -{ - float bounds[2][3]; - float localOrigin[3]; - float radius; -} mdvFrame_t; - -typedef struct -{ - float origin[3]; - float axis[3][3]; -} mdvTag_t; - -typedef struct -{ - char name[MAX_QPATH]; // tag name -} mdvTagName_t; - -typedef struct -{ - vec3_t xyz; - vec3_t normal; -#ifdef USE_VERT_TANGENT_SPACE - vec3_t tangent; - vec3_t bitangent; -#endif -} mdvVertex_t; - -typedef struct -{ - float st[2]; -} mdvSt_t; - -typedef struct mdvSurface_s -{ - surfaceType_t surfaceType; - - char name[MAX_QPATH]; // polyset name - - int numShaderIndexes; - int *shaderIndexes; - - int numVerts; - mdvVertex_t *verts; - mdvSt_t *st; - - int numTriangles; - srfTriangle_t *triangles; - - struct mdvModel_s *model; -} mdvSurface_t; - -typedef struct mdvModel_s -{ - int numFrames; - mdvFrame_t *frames; - - int numTags; - mdvTag_t *tags; - mdvTagName_t *tagNames; - - int numSurfaces; - mdvSurface_t *surfaces; - - int numVBOSurfaces; - srfVBOMDVMesh_t *vboSurfaces; - - int numSkins; -} mdvModel_t; - - -//====================================================================== - -typedef enum { - MOD_BAD, - MOD_BRUSH, - MOD_MESH, - MOD_MD4, -#ifdef RAVENMD4 - MOD_MDR, -#endif - MOD_IQM -} modtype_t; - -typedef struct model_s { - char name[MAX_QPATH]; - modtype_t type; - int index; // model = tr.models[model->index] - - int dataSize; // just for listing purposes - bmodel_t *bmodel; // only if type == MOD_BRUSH - mdvModel_t *mdv[MD3_MAX_LODS]; // only if type == MOD_MESH - void *modelData; // only if type == (MOD_MD4 | MOD_MDR | MOD_IQM) - - int numLods; -} model_t; - - -#define MAX_MOD_KNOWN 1024 - -void R_ModelInit (void); -model_t *R_GetModelByHandle( qhandle_t hModel ); -int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, - float frac, const char *tagName ); -void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ); - -void R_Modellist_f (void); - -//==================================================== -extern refimport_t ri; - -#define MAX_DRAWIMAGES 2048 -#define MAX_SKINS 1024 - - -#define MAX_DRAWSURFS 0x10000 -#define DRAWSURF_MASK (MAX_DRAWSURFS-1) - -/* - -the drawsurf sort data is packed into a single 32 bit value so it can be -compared quickly during the qsorting process - -the bits are allocated as follows: - -0 - 1 : dlightmap index -//2 : used to be clipped flag REMOVED - 03.21.00 rad -2 - 6 : fog index -11 - 20 : entity index -21 - 31 : sorted shader index - - TTimo - 1.32 -0-1 : dlightmap index -2-6 : fog index -7-16 : entity index -17-30 : sorted shader index - - SmileTheory - for pshadows -17-31 : sorted shader index -7-16 : entity index -2-6 : fog index -1 : pshadow flag -0 : dlight flag -*/ -#define QSORT_FOGNUM_SHIFT 2 -#define QSORT_ENTITYNUM_SHIFT 7 -#define QSORT_SHADERNUM_SHIFT (QSORT_ENTITYNUM_SHIFT+ENTITYNUM_BITS) -#if (QSORT_SHADERNUM_SHIFT+SHADERNUM_BITS) > 32 - #error "Need to update sorting, too many bits." -#endif -#define QSORT_PSHADOW_SHIFT 1 - -extern int gl_filter_min, gl_filter_max; - -/* -** performanceCounters_t -*/ -typedef struct { - int c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out; - int c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out; - int c_sphere_cull_md3_in, c_sphere_cull_md3_clip, c_sphere_cull_md3_out; - int c_box_cull_md3_in, c_box_cull_md3_clip, c_box_cull_md3_out; - - int c_leafs; - int c_dlightSurfaces; - int c_dlightSurfacesCulled; -} frontEndCounters_t; - -#define FOG_TABLE_SIZE 256 -#define FUNCTABLE_SIZE 1024 -#define FUNCTABLE_SIZE2 10 -#define FUNCTABLE_MASK (FUNCTABLE_SIZE-1) - - -// the renderer front end should never modify glstate_t -typedef struct { - int currenttextures[NUM_TEXTURE_BUNDLES]; - int currenttmu; - qboolean finishCalled; - int texEnv[2]; - int faceCulling; - unsigned long glStateBits; - uint32_t vertexAttribsState; - uint32_t vertexAttribPointersSet; - uint32_t vertexAttribsNewFrame; - uint32_t vertexAttribsOldFrame; - float vertexAttribsInterpolation; - shaderProgram_t *currentProgram; - FBO_t *currentFBO; - VBO_t *currentVBO; - IBO_t *currentIBO; - matrix_t modelview; - matrix_t projection; - matrix_t modelviewProjection; -} glstate_t; - -typedef enum { - MI_NONE, - MI_NVX, - MI_ATI -} memInfo_t; - -typedef enum { - TCR_NONE = 0x0000, - TCR_LATC = 0x0001, - TCR_BPTC = 0x0002, -} textureCompressionRef_t; - -// We can't change glConfig_t without breaking DLL/vms compatibility, so -// store extensions we have here. -typedef struct { - qboolean drawRangeElements; - qboolean multiDrawArrays; - qboolean occlusionQuery; - - int glslMajorVersion; - int glslMinorVersion; - - memInfo_t memInfo; - - qboolean framebufferObject; - int maxRenderbufferSize; - int maxColorAttachments; - - qboolean textureNonPowerOfTwo; - qboolean textureFloat; - qboolean halfFloatPixel; - qboolean packedDepthStencil; - textureCompressionRef_t textureCompression; - - qboolean framebufferMultisample; - qboolean framebufferBlit; - - qboolean texture_srgb; - qboolean framebuffer_srgb; - - qboolean depthClamp; -} glRefConfig_t; - - -typedef struct { - int c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes; - int c_surfBatches; - float c_overDraw; - - int c_vboVertexBuffers; - int c_vboIndexBuffers; - int c_vboVertexes; - int c_vboIndexes; - - int c_staticVboDraws; - int c_dynamicVboDraws; - - int c_multidraws; - int c_multidrawsMerged; - - int c_dlightVertexes; - int c_dlightIndexes; - - int c_flareAdds; - int c_flareTests; - int c_flareRenders; - - int c_glslShaderBinds; - int c_genericDraws; - int c_lightallDraws; - int c_fogDraws; - int c_dlightDraws; - - int msec; // total msec for backend run -} backEndCounters_t; - -// all state modified by the back end is seperated -// from the front end state -typedef struct { - int smpFrame; - trRefdef_t refdef; - viewParms_t viewParms; - orientationr_t or; - backEndCounters_t pc; - qboolean isHyperspace; - trRefEntity_t *currentEntity; - qboolean skyRenderedThisView; // flag for drawing sun - -#ifdef REACTION - vec3_t sunFlarePos; - qboolean viewHasSunFlare; - qboolean frameHasSunFlare; -#endif - - qboolean projection2D; // if qtrue, drawstretchpic doesn't need to change modes - byte color2D[4]; - qboolean vertexes2D; // shader needs to be finished - trRefEntity_t entity2D; // currentEntity will point at this when doing 2D rendering - - FBO_t *last2DFBO; - qboolean colorMask[4]; - qboolean framePostProcessed; - qboolean depthFill; -} backEndState_t; - -/* -** trGlobals_t -** -** Most renderer globals are defined here. -** backend functions should never modify any of these fields, -** but may read fields that aren't dynamically modified -** by the frontend. -*/ -typedef struct { - qboolean registered; // cleared at shutdown, set at beginRegistration - - int visIndex; - int visClusters[MAX_VISCOUNTS]; - int visCounts[MAX_VISCOUNTS]; // incremented every time a new vis cluster is entered - - int frameCount; // incremented every frame - int sceneCount; // incremented every scene - int viewCount; // incremented every view (twice a scene if portaled) - // and every R_MarkFragments call - - int smpFrame; // toggles from 0 to 1 every endFrame - - int frameSceneNum; // zeroed at RE_BeginFrame - - qboolean worldMapLoaded; - qboolean worldDeluxeMapping; - qboolean autoExposure; - vec2_t autoExposureMinMax; - world_t *world; - - const byte *externalVisData; // from RE_SetWorldVisData, shared with CM_Load - - image_t *defaultImage; - image_t *scratchImage[32]; - image_t *fogImage; - image_t *dlightImage; // inverse-quare highlight for projective adding - image_t *flareImage; - image_t *whiteImage; // full of 0xff - image_t *identityLightImage; // full of tr.identityLightByte - - image_t *shadowCubemaps[MAX_DLIGHTS]; - - - image_t *renderImage; - image_t *godRaysImage; - image_t *renderDepthImage; - image_t *pshadowMaps[MAX_DRAWN_PSHADOWS]; - image_t *textureScratchImage[2]; - image_t *screenScratchImage; - image_t *quarterImage[2]; - image_t *calcLevelsImage; - image_t *targetLevelsImage; - image_t *fixedLevelsImage; - image_t *sunShadowDepthImage[3]; - image_t *screenShadowImage; - - image_t *textureDepthImage; - - FBO_t *renderFbo; - FBO_t *msaaResolveFbo; - FBO_t *godRaysFbo; - FBO_t *depthFbo; - FBO_t *pshadowFbos[MAX_DRAWN_PSHADOWS]; - FBO_t *textureScratchFbo[2]; - FBO_t *screenScratchFbo; - FBO_t *quarterFbo[2]; - FBO_t *calcLevelsFbo; - FBO_t *targetLevelsFbo; - FBO_t *sunShadowFbo[3]; - FBO_t *screenShadowFbo; - - shader_t *defaultShader; - shader_t *shadowShader; - shader_t *projectionShadowShader; - - shader_t *flareShader; - shader_t *sunShader; - - int numLightmaps; - int lightmapSize; - image_t **lightmaps; - image_t **deluxemaps; - - int fatLightmapSize; - int fatLightmapStep; - - trRefEntity_t *currentEntity; - trRefEntity_t worldEntity; // point currentEntity at this when rendering world - int currentEntityNum; - int shiftedEntityNum; // currentEntityNum << QSORT_ENTITYNUM_SHIFT - model_t *currentModel; - - // - // GPU shader programs - // - shaderProgram_t genericShader[GENERICDEF_COUNT]; - shaderProgram_t textureColorShader; - shaderProgram_t fogShader; - shaderProgram_t dlightallShader; - shaderProgram_t lightallShader[LIGHTDEF_COUNT]; - shaderProgram_t shadowmapShader; - shaderProgram_t pshadowShader; - shaderProgram_t down4xShader; - shaderProgram_t bokehShader; - shaderProgram_t tonemapShader; - shaderProgram_t calclevels4xShader[2]; - shaderProgram_t shadowmaskShader; - - - // ----------------------------------------- - - viewParms_t viewParms; - - float identityLight; // 1.0 / ( 1 << overbrightBits ) - int identityLightByte; // identityLight * 255 - int overbrightBits; // r_overbrightBits->integer, but set to 0 if no hw gamma - - orientationr_t or; // for current entity - - trRefdef_t refdef; - - int viewCluster; - - float mapLightScale; - - qboolean sunShadows; - vec3_t sunLight; // from the sky shader for this level - vec3_t sunAmbient; - vec3_t sunDirection; - - frontEndCounters_t pc; - int frontEndMsec; // not in pc due to clearing issue - - // - // put large tables at the end, so most elements will be - // within the +/32K indexed range on risc processors - // - model_t *models[MAX_MOD_KNOWN]; - int numModels; - - int numImages; - image_t *images[MAX_DRAWIMAGES]; - - int numFBOs; - FBO_t *fbos[MAX_FBOS]; - - int numVBOs; - VBO_t *vbos[MAX_VBOS]; - - int numIBOs; - IBO_t *ibos[MAX_IBOS]; - - // shader indexes from other modules will be looked up in tr.shaders[] - // shader indexes from drawsurfs will be looked up in sortedShaders[] - // lower indexed sortedShaders must be rendered first (opaque surfaces before translucent) - int numShaders; - shader_t *shaders[MAX_SHADERS]; - shader_t *sortedShaders[MAX_SHADERS]; - - int numSkins; - skin_t *skins[MAX_SKINS]; - -#ifdef REACTION - GLuint sunFlareQuery[2]; - int sunFlareQueryIndex; - qboolean sunFlareQueryActive[2]; -#endif - - float sinTable[FUNCTABLE_SIZE]; - float squareTable[FUNCTABLE_SIZE]; - float triangleTable[FUNCTABLE_SIZE]; - float sawToothTable[FUNCTABLE_SIZE]; - float inverseSawToothTable[FUNCTABLE_SIZE]; - float fogTable[FOG_TABLE_SIZE]; -} trGlobals_t; - -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 glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init - -// These three variables should live inside glConfig but can't because of compatibility issues to the original ID vms. -// If you release a stand-alone game and your mod uses tr_types.h from this build you can safely move them to -// the glconfig_t struct. -extern qboolean textureFilterAnisotropic; -extern int maxAnisotropy; -extern glRefConfig_t glRefConfig; -extern float displayAspect; - - -// -// cvars -// -extern cvar_t *r_flareSize; -extern cvar_t *r_flareFade; -// coefficient for the flare intensity falloff function. -#define FLARE_STDCOEFF "150" -extern cvar_t *r_flareCoeff; - -extern cvar_t *r_railWidth; -extern cvar_t *r_railCoreWidth; -extern cvar_t *r_railSegmentLength; - -extern cvar_t *r_ignore; // used for debugging anything -extern cvar_t *r_verbose; // used for verbose debug spew - -extern cvar_t *r_znear; // near Z clip plane -extern cvar_t *r_zproj; // z distance of projection plane -extern cvar_t *r_stereoSeparation; // separation of cameras for stereo rendering - -extern cvar_t *r_stencilbits; // number of desired stencil bits -extern cvar_t *r_depthbits; // number of desired depth bits -extern cvar_t *r_colorbits; // number of desired color bits, only relevant for fullscreen -extern cvar_t *r_texturebits; // number of desired texture bits -extern cvar_t *r_ext_multisample; - // 0 = use framebuffer depth - // 16 = use 16-bit textures - // 32 = use 32-bit textures - // all else = error - -extern cvar_t *r_measureOverdraw; // enables stencil buffer overdraw measurement - -extern cvar_t *r_lodbias; // push/pull LOD transitions -extern cvar_t *r_lodscale; - -extern cvar_t *r_inGameVideo; // controls whether in game video should be draw -extern cvar_t *r_fastsky; // controls whether sky should be cleared or drawn -extern cvar_t *r_drawSun; // controls drawing of sun quad -extern cvar_t *r_dynamiclight; // dynamic lights enabled/disabled -extern cvar_t *r_dlightBacks; // dlight non-facing surfaces for continuity - -extern cvar_t *r_norefresh; // bypasses the ref rendering -extern cvar_t *r_drawentities; // disable/enable entity rendering -extern cvar_t *r_drawworld; // disable/enable world rendering -extern cvar_t *r_speeds; // various levels of information display -extern cvar_t *r_detailTextures; // enables/disables detail texturing stages -extern cvar_t *r_novis; // disable/enable usage of PVS -extern cvar_t *r_nocull; -extern cvar_t *r_facePlaneCull; // enables culling of planar surfaces with back side test -extern cvar_t *r_nocurves; -extern cvar_t *r_showcluster; - -extern cvar_t *r_mode; // video mode -extern cvar_t *r_fullscreen; -extern cvar_t *r_noborder; -extern cvar_t *r_gamma; -extern cvar_t *r_ignorehwgamma; // overrides hardware gamma capabilities - -extern cvar_t *r_allowExtensions; // global enable/disable of OpenGL extensions -extern cvar_t *r_ext_compressed_textures; // these control use of specific extensions -extern cvar_t *r_ext_multitexture; -extern cvar_t *r_ext_compiled_vertex_array; -extern cvar_t *r_ext_texture_env_add; - -extern cvar_t *r_ext_texture_filter_anisotropic; -extern cvar_t *r_ext_max_anisotropy; - -extern cvar_t *r_ext_draw_range_elements; -extern cvar_t *r_ext_multi_draw_arrays; -extern cvar_t *r_ext_framebuffer_object; -extern cvar_t *r_ext_texture_float; -extern cvar_t *r_arb_half_float_pixel; -extern cvar_t *r_ext_framebuffer_multisample; - -extern cvar_t *r_nobind; // turns off binding to appropriate textures -extern cvar_t *r_singleShader; // make most world faces use default shader -extern cvar_t *r_roundImagesDown; -extern cvar_t *r_colorMipLevels; // development aid to see texture mip usage -extern cvar_t *r_picmip; // controls picmip values -extern cvar_t *r_finish; -extern cvar_t *r_drawBuffer; -extern cvar_t *r_swapInterval; -extern cvar_t *r_textureMode; -extern cvar_t *r_offsetFactor; -extern cvar_t *r_offsetUnits; - -extern cvar_t *r_fullbright; // avoid lightmap pass -extern cvar_t *r_lightmap; // render lightmaps only -extern cvar_t *r_vertexLight; // vertex lighting mode for better performance -extern cvar_t *r_uiFullScreen; // ui is running fullscreen - -extern cvar_t *r_logFile; // number of frames to emit GL logs -extern cvar_t *r_showtris; // enables wireframe rendering of the world -extern cvar_t *r_showsky; // forces sky in front of all surfaces -extern cvar_t *r_shownormals; // draws wireframe normals -extern cvar_t *r_clear; // force screen clear every frame - -extern cvar_t *r_shadows; // controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection -extern cvar_t *r_flares; // light flares - -extern cvar_t *r_intensity; - -extern cvar_t *r_lockpvs; -extern cvar_t *r_noportals; -extern cvar_t *r_portalOnly; - -extern cvar_t *r_subdivisions; -extern cvar_t *r_lodCurveError; -extern cvar_t *r_smp; -extern cvar_t *r_showSmp; -extern cvar_t *r_skipBackEnd; - -extern cvar_t *r_stereoEnabled; -extern cvar_t *r_anaglyphMode; - -extern cvar_t *r_mergeMultidraws; -extern cvar_t *r_mergeLeafSurfaces; - -extern cvar_t *r_hdr; -extern cvar_t *r_postProcess; -extern cvar_t *r_toneMap; -extern cvar_t *r_autoExposure; -extern cvar_t *r_cameraExposure; - -extern cvar_t *r_srgb; -extern cvar_t *r_depthPrepass; - -extern cvar_t *r_normalMapping; -extern cvar_t *r_specularMapping; -extern cvar_t *r_deluxeMapping; -extern cvar_t *r_parallaxMapping; -extern cvar_t *r_normalAmbient; -extern cvar_t *r_dlightMode; -extern cvar_t *r_pshadowDist; -extern cvar_t *r_recalcMD3Normals; -extern cvar_t *r_mergeLightmaps; -extern cvar_t *r_imageUpsample; -extern cvar_t *r_imageUpsampleMaxSize; -extern cvar_t *r_imageUpsampleType; -extern cvar_t *r_genNormalMaps; -extern cvar_t *r_forceSun; -extern cvar_t *r_forceSunMapLightScale; -extern cvar_t *r_forceSunLightScale; -extern cvar_t *r_forceSunAmbientScale; -extern cvar_t *r_sunShadows; -extern cvar_t *r_shadowFilter; -extern cvar_t *r_shadowMapSize; -extern cvar_t *r_shadowCascadeZNear; -extern cvar_t *r_shadowCascadeZFar; -extern cvar_t *r_shadowCascadeZBias; - -extern cvar_t *r_greyscale; - -extern cvar_t *r_ignoreGLErrors; - -extern cvar_t *r_overBrightBits; -extern cvar_t *r_mapOverBrightBits; - -extern cvar_t *r_debugSurface; -extern cvar_t *r_simpleMipMaps; - -extern cvar_t *r_showImages; -extern cvar_t *r_debugSort; - -extern cvar_t *r_printShaders; -extern cvar_t *r_saveFontData; - -extern cvar_t *r_marksOnTriangleMeshes; - -//==================================================================== - -float R_NoiseGet4f( float x, float y, float z, float t ); -void R_NoiseInit( void ); - -void R_SwapBuffers( int ); - -void R_RenderView( viewParms_t *parms ); -void R_RenderDlightCubemaps(const refdef_t *fd); -void R_RenderPshadowMaps(const refdef_t *fd); -void R_RenderSunShadowMaps(const refdef_t *fd, int level); - -void R_AddMD3Surfaces( trRefEntity_t *e ); -void R_AddNullModelSurfaces( trRefEntity_t *e ); -void R_AddBeamSurfaces( trRefEntity_t *e ); -void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater ); -void R_AddLightningBoltSurfaces( trRefEntity_t *e ); - -void R_AddPolygonSurfaces( void ); - -void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, - int *fogNum, int *dlightMap, int *pshadowMap ); - -void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, - int fogIndex, int dlightMap, int pshadowMap ); - -void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2); -qboolean R_CalcTangentVectors(srfVert_t * dv[3]); -void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles); -void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts); - -#define CULL_IN 0 // completely unclipped -#define CULL_CLIP 1 // clipped by one or more planes -#define CULL_OUT 2 // completely outside the clipping planes -void R_LocalNormalToWorld (const vec3_t local, vec3_t world); -void R_LocalPointToWorld (const vec3_t local, vec3_t world); -int R_CullBox (vec3_t bounds[2]); -int R_CullLocalBox (vec3_t bounds[2]); -int R_CullPointAndRadiusEx( const vec3_t origin, float radius, const cplane_t* frustum, int numPlanes ); -int R_CullPointAndRadius( const vec3_t origin, float radius ); -int R_CullLocalPointAndRadius( const vec3_t origin, float radius ); - -void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum); -void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or ); - -/* -** GL wrapper/helper functions -*/ -void GL_Bind( image_t *image ); -void GL_BindCubemap( image_t *image ); -void GL_BindToTMU( image_t *image, int tmu ); -void GL_SetDefaultState (void); -void GL_SelectTexture( int unit ); -void GL_TextureMode( const char *string ); -void GL_CheckErrs( char *file, int line ); -#define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__) -void GL_State( unsigned long stateVector ); -void GL_SetProjectionMatrix(matrix_t matrix); -void GL_SetModelviewMatrix(matrix_t matrix); -void GL_TexEnv( int env ); -void GL_Cull( int cullType ); - -#define GLS_SRCBLEND_ZERO 0x00000001 -#define GLS_SRCBLEND_ONE 0x00000002 -#define GLS_SRCBLEND_DST_COLOR 0x00000003 -#define GLS_SRCBLEND_ONE_MINUS_DST_COLOR 0x00000004 -#define GLS_SRCBLEND_SRC_ALPHA 0x00000005 -#define GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA 0x00000006 -#define GLS_SRCBLEND_DST_ALPHA 0x00000007 -#define GLS_SRCBLEND_ONE_MINUS_DST_ALPHA 0x00000008 -#define GLS_SRCBLEND_ALPHA_SATURATE 0x00000009 -#define GLS_SRCBLEND_BITS 0x0000000f - -#define GLS_DSTBLEND_ZERO 0x00000010 -#define GLS_DSTBLEND_ONE 0x00000020 -#define GLS_DSTBLEND_SRC_COLOR 0x00000030 -#define GLS_DSTBLEND_ONE_MINUS_SRC_COLOR 0x00000040 -#define GLS_DSTBLEND_SRC_ALPHA 0x00000050 -#define GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA 0x00000060 -#define GLS_DSTBLEND_DST_ALPHA 0x00000070 -#define GLS_DSTBLEND_ONE_MINUS_DST_ALPHA 0x00000080 -#define GLS_DSTBLEND_BITS 0x000000f0 - -#define GLS_DEPTHMASK_TRUE 0x00000100 - -#define GLS_POLYMODE_LINE 0x00001000 - -#define GLS_DEPTHTEST_DISABLE 0x00010000 -#define GLS_DEPTHFUNC_EQUAL 0x00020000 -#define GLS_DEPTHFUNC_GREATER 0x00040000 -#define GLS_DEPTHFUNC_BITS 0x00060000 - -#define GLS_ATEST_GT_0 0x10000000 -#define GLS_ATEST_LT_80 0x20000000 -#define GLS_ATEST_GE_80 0x40000000 -#define GLS_ATEST_BITS 0x70000000 - -#define GLS_DEFAULT GLS_DEPTHMASK_TRUE - -void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); -void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); - -void RE_BeginFrame( stereoFrame_t stereoFrame ); -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 ); -qhandle_t RE_RegisterSkin( const char *name ); -void RE_Shutdown( qboolean destroyWindow ); - -qboolean R_GetEntityToken( char *buffer, int size ); - -model_t *R_AllocModel( void ); - -void R_Init( void ); -image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ); -image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ); -void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ); -qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode ); - -void R_SetColorMappings( void ); -void R_GammaCorrect( byte *buffer, int bufSize ); - -void R_ImageList_f( void ); -void R_SkinList_f( void ); -// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516 -const void *RB_TakeScreenshotCmd( const void *data ); -void R_ScreenShot_f( void ); - -void R_InitFogTable( void ); -float R_FogFactor( float s, float t ); -void R_InitImages( void ); -void R_DeleteTextures( void ); -int R_SumOfUsedImages( void ); -void R_InitSkins( void ); -skin_t *R_GetSkinByHandle( qhandle_t hSkin ); - -int R_ComputeLOD( trRefEntity_t *ent ); - -const void *RB_TakeVideoFrameCmd( const void *data ); - -// -// tr_shader.c -// -qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ); -qhandle_t RE_RegisterShader( const char *name ); -qhandle_t RE_RegisterShaderNoMip( const char *name ); -qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage); - -shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ); -shader_t *R_GetShaderByHandle( qhandle_t hShader ); -shader_t *R_GetShaderByState( int index, long *cycleTime ); -shader_t *R_FindShaderByName( const char *name ); -void R_InitShaders( void ); -void R_ShaderList_f( void ); -void R_RemapShader(const char *oldShader, const char *newShader, const char *timeOffset); - -/* -==================================================================== - -IMPLEMENTATION SPECIFIC FUNCTIONS - -==================================================================== -*/ - -void GLimp_Init( void ); -void GLimp_Shutdown( void ); -void GLimp_EndFrame( void ); - -qboolean GLimp_SpawnRenderThread( void (*function)( void ) ); -void *GLimp_RendererSleep( void ); -void GLimp_FrontEndSleep( void ); -void GLimp_WakeRenderer( void *data ); - -void GLimp_LogComment( char *comment ); -void GLimp_Minimize(void); - -// NOTE TTimo linux works with float gamma value, not the gamma table -// the params won't be used, getting the r_gamma cvar directly -void GLimp_SetGamma( unsigned char red[256], - unsigned char green[256], - unsigned char blue[256] ); - - -void GLimp_InitExtraExtensions( void ); -/* -==================================================================== - -TESSELATOR/SHADER DECLARATIONS - -==================================================================== -*/ - -typedef struct stageVars -{ - color4ub_t colors[SHADER_MAX_VERTEXES]; - vec2_t texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES]; -} stageVars_t; - -#define MAX_MULTIDRAW_PRIMITIVES 16384 - -typedef struct shaderCommands_s -{ - glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16); - vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16); - vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16); -#ifdef USE_VERT_TANGENT_SPACE - vec4_t tangent[SHADER_MAX_VERTEXES] QALIGN(16); - vec4_t bitangent[SHADER_MAX_VERTEXES] QALIGN(16); -#endif - vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16); - vec4_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16); - vec4_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16); - //int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16); - - VBO_t *vbo; - IBO_t *ibo; - qboolean useInternalVBO; - - stageVars_t svars QALIGN(16); - - //color4ub_t constantColor255[SHADER_MAX_VERTEXES] QALIGN(16); - - shader_t *shader; - float shaderTime; - int fogNum; - - int dlightBits; // or together of all vertexDlightBits - int pshadowBits; - - int firstIndex; - int numIndexes; - int numVertexes; - - int multiDrawPrimitives; - GLsizei multiDrawNumIndexes[MAX_MULTIDRAW_PRIMITIVES]; - GLvoid * multiDrawFirstIndex[MAX_MULTIDRAW_PRIMITIVES]; - GLvoid * multiDrawLastIndex[MAX_MULTIDRAW_PRIMITIVES]; - - // info extracted from current shader - int numPasses; - void (*currentStageIteratorFunc)( void ); - shaderStage_t **xstages; -} shaderCommands_t; - -extern shaderCommands_t tess; - -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);} - -void R_DrawElementsVBO( int numIndexes, int firstIndex ); -void RB_StageIteratorGeneric( void ); -void RB_StageIteratorSky( void ); -void RB_StageIteratorVertexLitTexture( void ); -void RB_StageIteratorLightmappedMultitexture( void ); - -void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, float color[4] ); -void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ); -void RB_InstantQuad( vec4_t quadVerts[4] ); -//void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4], vec4_t color, shaderProgram_t *sp, vec2_t invTexRes); -void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4]); - -void RB_ShowImages( void ); - - -/* -============================================================ - -WORLD MAP - -============================================================ -*/ - -void R_AddBrushModelSurfaces( trRefEntity_t *e ); -void R_AddWorldSurfaces( void ); -qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ); - - -/* -============================================================ - -FLARES - -============================================================ -*/ - -void R_ClearFlares( void ); - -void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ); -void RB_AddDlightFlares( void ); -void RB_RenderFlares (void); - -/* -============================================================ - -LIGHTS - -============================================================ -*/ - -void R_DlightBmodel( bmodel_t *bmodel ); -void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ); -void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or ); -int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ); -int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ); - - -/* -============================================================ - -SHADOWS - -============================================================ -*/ - -void RB_ShadowTessEnd( void ); -void RB_ShadowFinish( void ); -void RB_ProjectionShadowDeform( void ); - -/* -============================================================ - -SKIES - -============================================================ -*/ - -void R_BuildCloudData( shaderCommands_t *shader ); -void R_InitSkyTexCoords( float cloudLayerHeight ); -void R_DrawSkyBox( shaderCommands_t *shader ); -void RB_DrawSun( void ); -void RB_ClipSkyPolygons( shaderCommands_t *shader ); - -/* -============================================================ - -CURVE TESSELATION - -============================================================ -*/ - -#define PATCH_STITCHING - -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, - srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ); -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ); -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ); -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ); - -/* -============================================================ - -MARKERS, POLYGON PROJECTION ON WORLD POLYGONS - -============================================================ -*/ - -int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, - int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ); - - -/* -============================================================ - -VERTEX BUFFER OBJECTS - -============================================================ -*/ -VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage); -VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes, uint32_t stateBits, vboUsage_t usage); - -IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage); -IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage); - -void R_BindVBO(VBO_t * vbo); -void R_BindNullVBO(void); - -void R_BindIBO(IBO_t * ibo); -void R_BindNullIBO(void); - -void R_InitVBOs(void); -void R_ShutdownVBOs(void); -void R_VBOList_f(void); - -void RB_UpdateVBOs(unsigned int attribBits); - - -/* -============================================================ - -GLSL - -============================================================ -*/ - -void GLSL_InitGPUShaders(void); -void GLSL_ShutdownGPUShaders(void); -void GLSL_VertexAttribsState(uint32_t stateBits); -void GLSL_VertexAttribPointers(uint32_t attribBits); -void GLSL_BindProgram(shaderProgram_t * program); -void GLSL_BindNullProgram(void); - -void GLSL_SetNumUniforms(shaderProgram_t *program, int numUniforms); -void GLSL_SetUniformName(shaderProgram_t *program, int uniformNum, const char *name); -void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value); -void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value); -void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v); -void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v); -void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v); -void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v); -void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix); - -shaderProgram_t *GLSL_GetGenericShaderProgram(int stage); - -/* -============================================================ - -SCENE GENERATION - -============================================================ -*/ - -void R_ToggleSmpFrame( void ); - -void RE_ClearScene( void ); -void RE_AddRefEntityToScene( const refEntity_t *ent ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); -void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ); -void RE_RenderScene( const refdef_t *fd ); - -#ifdef RAVENMD4 -/* -============================================================= - -UNCOMPRESSING BONES - -============================================================= -*/ - -#define MC_BITS_X (16) -#define MC_BITS_Y (16) -#define MC_BITS_Z (16) -#define MC_BITS_VECT (16) - -#define MC_SCALE_X (1.0f/64) -#define MC_SCALE_Y (1.0f/64) -#define MC_SCALE_Z (1.0f/64) - -void MC_UnCompress(float mat[3][4],const unsigned char * comp); -#endif - -/* -============================================================= - -ANIMATED MODELS - -============================================================= -*/ - -// void R_MakeAnimModel( model_t *model ); haven't seen this one really, so not needed I guess. -void R_AddAnimSurfaces( trRefEntity_t *ent ); -void RB_SurfaceAnim( md4Surface_t *surfType ); -#ifdef RAVENMD4 -void R_MDRAddAnimSurfaces( trRefEntity_t *ent ); -void RB_MDRSurfaceAnim( md4Surface_t *surface ); -#endif -qboolean R_LoadIQM (model_t *mod, void *buffer, int filesize, const char *name ); -void R_AddIQMSurfaces( trRefEntity_t *ent ); -void RB_IQMSurfaceAnim( surfaceType_t *surface ); -int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, - int startFrame, int endFrame, - float frac, const char *tagName ); - -/* -============================================================= - -IMAGE LOADERS - -============================================================= -*/ - -void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); -void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); -void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); -void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); -void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); - -/* -============================================================= -============================================================= -*/ -void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix, - vec4_t eye, vec4_t dst ); -void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ); - -void RB_DeformTessGeometry( void ); - -void RB_CalcEnvironmentTexCoords( float *dstTexCoords ); -void RB_CalcFogTexCoords( float *dstTexCoords ); -void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords ); -void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords ); -void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords ); -void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords ); -void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords ); - -void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ); -void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ); -void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ); -void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix ); -void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ); -void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ); - -void RB_CalcModulateColorsByFog( unsigned char *dstColors ); -void RB_CalcModulateAlphasByFog( unsigned char *dstColors ); -void RB_CalcModulateRGBAsByFog( unsigned char *dstColors ); -void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ); -float RB_CalcWaveAlphaSingle( const waveForm_t *wf ); -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ); -float RB_CalcWaveColorSingle( const waveForm_t *wf ); -void RB_CalcAlphaFromEntity( unsigned char *dstColors ); -void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ); -void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords ); -void RB_CalcColorFromEntity( unsigned char *dstColors ); -void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ); -void RB_CalcSpecularAlpha( unsigned char *alphas ); -void RB_CalcDiffuseColor( unsigned char *colors ); - -/* -============================================================= - -RENDERER BACK END FUNCTIONS - -============================================================= -*/ - -void RB_RenderThread( void ); -void RB_ExecuteRenderCommands( const void *data ); - -/* -============================================================= - -RENDERER BACK END COMMAND QUEUE - -============================================================= -*/ - -#define MAX_RENDER_COMMANDS 0x40000 - -typedef struct { - byte cmds[MAX_RENDER_COMMANDS]; - int used; -} renderCommandList_t; - -typedef struct { - int commandId; - float color[4]; -} setColorCommand_t; - -typedef struct { - int commandId; - int buffer; -} drawBufferCommand_t; - -typedef struct { - int commandId; - image_t *image; - int width; - int height; - void *data; -} subImageCommand_t; - -typedef struct { - int commandId; -} swapBuffersCommand_t; - -typedef struct { - int commandId; - int buffer; -} endFrameCommand_t; - -typedef struct { - int commandId; - shader_t *shader; - float x, y; - float w, h; - float s1, t1; - float s2, t2; -} stretchPicCommand_t; - -typedef struct { - int commandId; - trRefdef_t refdef; - viewParms_t viewParms; - drawSurf_t *drawSurfs; - int numDrawSurfs; -} drawSurfsCommand_t; - -typedef struct { - int commandId; - int x; - int y; - int width; - int height; - char *fileName; - qboolean jpeg; -} screenshotCommand_t; - -typedef struct { - int commandId; - int width; - int height; - byte *captureBuffer; - byte *encodeBuffer; - qboolean motionJpeg; -} videoFrameCommand_t; - -typedef struct -{ - int commandId; - - GLboolean rgba[4]; -} colorMaskCommand_t; - -typedef struct -{ - int commandId; -} clearDepthCommand_t; - -typedef struct { - int commandId; - int map; - int cubeSide; -} capShadowmapCommand_t; - -typedef struct { - int commandId; - trRefdef_t refdef; - viewParms_t viewParms; -} postProcessCommand_t; - -typedef enum { - RC_END_OF_LIST, - RC_SET_COLOR, - RC_STRETCH_PIC, - RC_DRAW_SURFS, - RC_DRAW_BUFFER, - RC_SWAP_BUFFERS, - RC_SCREENSHOT, - RC_VIDEOFRAME, - RC_COLORMASK, - RC_CLEARDEPTH, - RC_CAPSHADOWMAP, - RC_POSTPROCESS -} renderCommand_t; - - -// these are sort of arbitrary limits. -// the limits apply to the sum of all scenes in a frame -- -// the main view, all the 3D icons, etc -#define MAX_POLYS 600 -#define MAX_POLYVERTS 3000 - -// all of the information needed by the back end must be -// contained in a backEndData_t. This entire structure is -// duplicated so the front and back end can run in parallel -// on an SMP machine -typedef struct { - drawSurf_t drawSurfs[MAX_DRAWSURFS]; - dlight_t dlights[MAX_DLIGHTS]; - trRefEntity_t entities[MAX_ENTITIES]; - srfPoly_t *polys;//[MAX_POLYS]; - polyVert_t *polyVerts;//[MAX_POLYVERTS]; - pshadow_t pshadows[MAX_CALC_PSHADOWS]; - renderCommandList_t commands; -} backEndData_t; - -extern int max_polys; -extern int max_polyverts; - -extern backEndData_t *backEndData[SMP_FRAMES]; // the second one may not be allocated - -extern volatile renderCommandList_t *renderCommandList; - -extern volatile qboolean renderThreadActive; - - -void *R_GetCommandBuffer( int bytes ); -void RB_ExecuteRenderCommands( const void *data ); - -void R_InitCommandBuffers( void ); -void R_ShutdownCommandBuffers( void ); - -void R_SyncRenderThread( void ); - -void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ); -void R_AddCapShadowmapCmd( int dlight, int cubeSide ); -void R_AddPostProcessCmd (void); - -void RE_SetColor( const float *rgba ); -void RE_StretchPic ( float x, float y, float w, float h, - float s1, float t1, float s2, float t2, qhandle_t hShader ); -void RE_BeginFrame( stereoFrame_t stereoFrame ); -void RE_EndFrame( int *frontEndMsec, int *backEndMsec ); -void RE_SaveJPG(char * filename, int quality, int image_width, int image_height, - unsigned char *image_buffer, int padding); -size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality, - int image_width, int image_height, byte *image_buffer, int padding); -void RE_TakeVideoFrame( int width, int height, - byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ); - -// font stuff -void R_InitFreeType( void ); -void R_DoneFreeType( void ); -void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font); - - -#endif //TR_LOCAL_H diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c deleted file mode 100644 index cda2a6ce..00000000 --- a/code/renderergl2/tr_main.c +++ /dev/null @@ -1,2878 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_main.c -- main control flow for each frame - -#include "tr_local.h" - -#include // memcpy - -trGlobals_t tr; - -static float s_flipMatrix[16] = { - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - 0, 0, -1, 0, - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 1 -}; - - -refimport_t ri; - -// entities that will have procedurally generated surfaces will just -// point at this for their sorting surface -surfaceType_t entitySurface = SF_ENTITY; - -/* -================ -R_CompareVert -================ -*/ -qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST) -{ - int i; - - for(i = 0; i < 3; i++) - { - if(floor(v1->xyz[i] + 0.1) != floor(v2->xyz[i] + 0.1)) - { - return qfalse; - } - - if(checkST && ((v1->st[0] != v2->st[0]) || (v1->st[1] != v2->st[1]))) - { - return qfalse; - } - } - - return qtrue; -} - -/* -============= -R_CalcNormalForTriangle -============= -*/ -void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2) -{ - vec3_t udir, vdir; - - // compute the face normal based on vertex points - VectorSubtract(v2, v0, udir); - VectorSubtract(v1, v0, vdir); - CrossProduct(udir, vdir, normal); - - VectorNormalize(normal); -} - -/* -============= -R_CalcTangentsForTriangle -http://members.rogers.com/deseric/tangentspace.htm -============= -*/ -void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent, - const vec3_t v0, const vec3_t v1, const vec3_t v2, - const vec2_t t0, const vec2_t t1, const vec2_t t2) -{ - int i; - vec3_t planes[3]; - vec3_t u, v; - - for(i = 0; i < 3; i++) - { - VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]); - VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]); - - VectorNormalize(u); - VectorNormalize(v); - - CrossProduct(u, v, planes[i]); - } - - //So your tangent space will be defined by this : - //Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product, - // you have to make sure the normal points in the right direction) - //Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az ) - //Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az ) - - // tangent... - tangent[0] = -planes[0][1] / planes[0][0]; - tangent[1] = -planes[1][1] / planes[1][0]; - tangent[2] = -planes[2][1] / planes[2][0]; - VectorNormalize(tangent); - - // bitangent... - bitangent[0] = -planes[0][2] / planes[0][0]; - bitangent[1] = -planes[1][2] / planes[1][0]; - bitangent[2] = -planes[2][2] / planes[2][0]; - VectorNormalize(bitangent); -} - - - - -/* -============= -R_CalcTangentSpace -============= -*/ -void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2) -{ - vec3_t cp, u, v; - vec3_t faceNormal; - - VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]); - VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]); - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[0] = -cp[1] / cp[0]; - bitangent[0] = -cp[2] / cp[0]; - } - - u[0] = v1[1] - v0[1]; - v[0] = v2[1] - v0[1]; - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[1] = -cp[1] / cp[0]; - bitangent[1] = -cp[2] / cp[0]; - } - - u[0] = v1[2] - v0[2]; - v[0] = v2[2] - v0[2]; - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[2] = -cp[1] / cp[0]; - bitangent[2] = -cp[2] / cp[0]; - } - - VectorNormalize(tangent); - VectorNormalize(bitangent); - - // compute the face normal based on vertex points - if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f ) - { - VectorSubtract(v2, v0, u); - VectorSubtract(v1, v0, v); - CrossProduct(u, v, faceNormal); - } - else - { - VectorCopy(normal, faceNormal); - } - - VectorNormalize(faceNormal); - -#if 1 - // Gram-Schmidt orthogonalize - //tangent[a] = (t - n * Dot(n, t)).Normalize(); - VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent); - VectorNormalize(tangent); - - // compute the cross product B=NxT - //CrossProduct(normal, tangent, bitangent); -#else - // normal, compute the cross product N=TxB - CrossProduct(tangent, bitangent, normal); - VectorNormalize(normal); - - if(DotProduct(normal, faceNormal) < 0) - { - //VectorInverse(normal); - //VectorInverse(tangent); - //VectorInverse(bitangent); - - // compute the cross product T=BxN - CrossProduct(bitangent, faceNormal, tangent); - - // compute the cross product B=NxT - //CrossProduct(normal, tangent, bitangent); - } -#endif - - VectorCopy(faceNormal, normal); -} - -void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2) -{ - vec3_t cp, u, v; - vec3_t faceNormal; - - VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]); - VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]); - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[0] = -cp[1] / cp[0]; - bitangent[0] = -cp[2] / cp[0]; - } - - u[0] = v1[1] - v0[1]; - v[0] = v2[1] - v0[1]; - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[1] = -cp[1] / cp[0]; - bitangent[1] = -cp[2] / cp[0]; - } - - u[0] = v1[2] - v0[2]; - v[0] = v2[2] - v0[2]; - - CrossProduct(u, v, cp); - if(fabs(cp[0]) > 10e-6) - { - tangent[2] = -cp[1] / cp[0]; - bitangent[2] = -cp[2] / cp[0]; - } - - VectorNormalizeFast(tangent); - VectorNormalizeFast(bitangent); - - // compute the face normal based on vertex points - VectorSubtract(v2, v0, u); - VectorSubtract(v1, v0, v); - CrossProduct(u, v, faceNormal); - - VectorNormalizeFast(faceNormal); - -#if 0 - // normal, compute the cross product N=TxB - CrossProduct(tangent, bitangent, normal); - VectorNormalizeFast(normal); - - if(DotProduct(normal, faceNormal) < 0) - { - VectorInverse(normal); - //VectorInverse(tangent); - //VectorInverse(bitangent); - - CrossProduct(normal, tangent, bitangent); - } - - VectorCopy(faceNormal, normal); -#else - // Gram-Schmidt orthogonalize - //tangent[a] = (t - n * Dot(n, t)).Normalize(); - VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent); - VectorNormalizeFast(tangent); -#endif - - VectorCopy(faceNormal, normal); -} - -/* -http://www.terathon.com/code/tangent.html -*/ -void R_CalcTBN(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3) -{ - vec3_t u, v; - float x1, x2, y1, y2, z1, z2; - float s1, s2, t1, t2; - float r, dot; - - x1 = v2[0] - v1[0]; - x2 = v3[0] - v1[0]; - y1 = v2[1] - v1[1]; - y2 = v3[1] - v1[1]; - z1 = v2[2] - v1[2]; - z2 = v3[2] - v1[2]; - - s1 = w2[0] - w1[0]; - s2 = w3[0] - w1[0]; - t1 = w2[1] - w1[1]; - t2 = w3[1] - w1[1]; - - r = 1.0f / (s1 * t2 - s2 * t1); - - VectorSet(tangent, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - VectorSet(bitangent, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); - - // compute the face normal based on vertex points - VectorSubtract(v3, v1, u); - VectorSubtract(v2, v1, v); - CrossProduct(u, v, normal); - - VectorNormalize(normal); - - // Gram-Schmidt orthogonalize - //tangent[a] = (t - n * Dot(n, t)).Normalize(); - dot = DotProduct(normal, tangent); - VectorMA(tangent, -dot, normal, tangent); - VectorNormalize(tangent); - - // B=NxT - //CrossProduct(normal, tangent, bitangent); -} - -void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3) -{ - vec3_t v2v1; - vec3_t v3v1; - - float c2c1_T; - float c2c1_B; - - float c3c1_T; - float c3c1_B; - - float denominator; - float scale1, scale2; - - vec3_t T, B, N, C; - - - // Calculate the tangent basis for each vertex of the triangle - // UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has - // been removed as it was redundant (the entire TBN matrix was calculated three times - // instead of just one). - // - // Please note, that this function relies on the fact that the input geometry are triangles - // and the tangent basis for each vertex thus is identical! - // - - // Calculate the vectors from the current vertex to the two other vertices in the triangle - VectorSubtract(v2, v1, v2v1); - VectorSubtract(v3, v1, v3v1); - - // The equation presented in the article states that: - // c2c1_T = V2.texcoord.x – V1.texcoord.x - // c2c1_B = V2.texcoord.y – V1.texcoord.y - // c3c1_T = V3.texcoord.x – V1.texcoord.x - // c3c1_B = V3.texcoord.y – V1.texcoord.y - - // Calculate c2c1_T and c2c1_B - c2c1_T = t2[0] - t1[0]; - c2c1_B = t2[1] - t2[1]; - - // Calculate c3c1_T and c3c1_B - c3c1_T = t3[0] - t1[0]; - c3c1_B = t3[1] - t1[1]; - - denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B; - //if(ROUNDOFF(fDenominator) == 0.0f) - if(denominator == 0.0f) - { - // We won't risk a divide by zero, so set the tangent matrix to the identity matrix - VectorSet(tangent, 1, 0, 0); - VectorSet(bitangent, 0, 1, 0); - VectorSet(normal, 0, 0, 1); - } - else - { - // Calculate the reciprocal value once and for all (to achieve speed) - scale1 = 1.0f / denominator; - - // T and B are calculated just as the equation in the article states - VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1, - (c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1, - (c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1); - - VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1, - (-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1, - (-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1); - - // The normal N is calculated as the cross product between T and B - CrossProduct(T, B, N); - -#if 0 - VectorCopy(T, tangent); - VectorCopy(B, bitangent); - VectorCopy(N, normal); -#else - // Calculate the reciprocal value once and for all (to achieve speed) - scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) + - (B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) + - (N[0] * T[1] * B[2] - N[2] * T[1] * B[0])); - - // Calculate the inverse if the TBN matrix using the formula described in the article. - // We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix - CrossProduct(B, N, C); tangent[0] = C[0] * scale2; - CrossProduct(N, T, C); tangent[1] = -C[0] * scale2; - CrossProduct(T, B, C); tangent[2] = C[0] * scale2; - VectorNormalize(tangent); - - CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2; - CrossProduct(N, T, C); bitangent[1] = C[1] * scale2; - CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2; - VectorNormalize(bitangent); - - CrossProduct(B, N, C); normal[0] = C[2] * scale2; - CrossProduct(N, T, C); normal[1] = -C[2] * scale2; - CrossProduct(T, B, C); normal[2] = C[2] * scale2; - VectorNormalize(normal); -#endif - } -} - - -#ifdef USE_VERT_TANGENT_SPACE -qboolean R_CalcTangentVectors(srfVert_t * dv[3]) -{ - int i; - float bb, s, t; - vec3_t bary; - - - /* calculate barycentric basis for the triangle */ - bb = (dv[1]->st[0] - dv[0]->st[0]) * (dv[2]->st[1] - dv[0]->st[1]) - (dv[2]->st[0] - dv[0]->st[0]) * (dv[1]->st[1] - dv[0]->st[1]); - if(fabs(bb) < 0.00000001f) - return qfalse; - - /* do each vertex */ - for(i = 0; i < 3; i++) - { - // calculate s tangent vector - s = dv[i]->st[0] + 10.0f; - t = dv[i]->st[1]; - bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb; - bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb; - bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb; - - dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0]; - dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1]; - dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2]; - - VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent); - VectorNormalize(dv[i]->tangent); - - // calculate t tangent vector - s = dv[i]->st[0]; - t = dv[i]->st[1] + 10.0f; - bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb; - bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb; - bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb; - - dv[i]->bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0]; - dv[i]->bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1]; - dv[i]->bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2]; - - VectorSubtract(dv[i]->bitangent, dv[i]->xyz, dv[i]->bitangent); - VectorNormalize(dv[i]->bitangent); - - // debug code - //% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i, - //% stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] ); - } - - return qtrue; -} -#endif - - -/* -================= -R_FindSurfaceTriangleWithEdge -Tr3B - recoded from Q2E -================= -*/ -static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore) -{ - srfTriangle_t *tri; - int count, match; - int i; - - count = 0; - match = -1; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - if((tri->indexes[0] == start && tri->indexes[1] == end) || - (tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end)) - { - if(i != ignore) - { - match = i; - } - - count++; - } - else if((tri->indexes[1] == start && tri->indexes[0] == end) || - (tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end)) - { - count++; - } - } - - // detect edges shared by three triangles and make them seams - if(count > 2) - { - match = -1; - } - - return match; -} - - -/* -================= -R_CalcSurfaceTriangleNeighbors -Tr3B - recoded from Q2E -================= -*/ -void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles) -{ - int i; - srfTriangle_t *tri; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i); - tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i); - tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i); - } -} - -/* -================= -R_CalcSurfaceTrianglePlanes -================= -*/ -void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts) -{ - int i; - srfTriangle_t *tri; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - float *v1, *v2, *v3; - vec3_t d1, d2; - - v1 = verts[tri->indexes[0]].xyz; - v2 = verts[tri->indexes[1]].xyz; - v3 = verts[tri->indexes[2]].xyz; - - VectorSubtract(v2, v1, d1); - VectorSubtract(v3, v1, d2); - - CrossProduct(d2, d1, tri->plane); - tri->plane[3] = DotProduct(tri->plane, v1); - } -} - - -/* -================= -R_CullLocalBox - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -int R_CullLocalBox(vec3_t localBounds[2]) { -#if 0 - int i, j; - vec3_t transformed[8]; - float dists[8]; - vec3_t v; - cplane_t *frust; - int anyBack; - int front, back; - - if ( r_nocull->integer ) { - return CULL_CLIP; - } - - // transform into world space - for (i = 0 ; i < 8 ; i++) { - v[0] = bounds[i&1][0]; - v[1] = bounds[(i>>1)&1][1]; - v[2] = bounds[(i>>2)&1][2]; - - VectorCopy( tr.or.origin, transformed[i] ); - VectorMA( transformed[i], v[0], tr.or.axis[0], transformed[i] ); - VectorMA( transformed[i], v[1], tr.or.axis[1], transformed[i] ); - VectorMA( transformed[i], v[2], tr.or.axis[2], transformed[i] ); - } - - // check against frustum planes - anyBack = 0; - for (i = 0 ; i < 4 ; i++) { - frust = &tr.viewParms.frustum[i]; - - front = back = 0; - for (j = 0 ; j < 8 ; j++) { - dists[j] = DotProduct(transformed[j], frust->normal); - if ( dists[j] > frust->dist ) { - front = 1; - if ( back ) { - break; // a point is in front - } - } else { - back = 1; - } - } - if ( !front ) { - // all points were behind one of the planes - return CULL_OUT; - } - anyBack |= back; - } - - if ( !anyBack ) { - return CULL_IN; // completely inside frustum - } - - return CULL_CLIP; // partially clipped -#else - int j; - vec3_t transformed; - vec3_t v; - vec3_t worldBounds[2]; - - if(r_nocull->integer) - { - return CULL_CLIP; - } - - // transform into world space - ClearBounds(worldBounds[0], worldBounds[1]); - - for(j = 0; j < 8; j++) - { - v[0] = localBounds[j & 1][0]; - v[1] = localBounds[(j >> 1) & 1][1]; - v[2] = localBounds[(j >> 2) & 1][2]; - - R_LocalPointToWorld(v, transformed); - - AddPointToBounds(transformed, worldBounds[0], worldBounds[1]); - } - - return R_CullBox(worldBounds); -#endif -} - -/* -================= -R_CullBox - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -int R_CullBox(vec3_t worldBounds[2]) { - int i; - cplane_t *frust; - qboolean anyClip; - int r; - - // check against frustum planes - anyClip = qfalse; - for(i = 0; i < 4 /*FRUSTUM_PLANES*/; i++) - { - frust = &tr.viewParms.frustum[i]; - - r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], frust); - - if(r == 2) - { - // completely outside frustum - return CULL_OUT; - } - if(r == 3) - { - anyClip = qtrue; - } - } - - if(!anyClip) - { - // completely inside frustum - return CULL_IN; - } - - // partially clipped - return CULL_CLIP; -} - -/* -** R_CullLocalPointAndRadius -*/ -int R_CullLocalPointAndRadius( const vec3_t pt, float radius ) -{ - vec3_t transformed; - - R_LocalPointToWorld( pt, transformed ); - - return R_CullPointAndRadius( transformed, radius ); -} - -/* -** R_CullPointAndRadius -*/ -int R_CullPointAndRadiusEx( const vec3_t pt, float radius, const cplane_t* frustum, int numPlanes ) -{ - int i; - float dist; - const cplane_t *frust; - qboolean mightBeClipped = qfalse; - - if ( r_nocull->integer ) { - return CULL_CLIP; - } - - // check against frustum planes - for (i = 0 ; i < numPlanes ; i++) - { - frust = &frustum[i]; - - dist = DotProduct( pt, frust->normal) - frust->dist; - if ( dist < -radius ) - { - return CULL_OUT; - } - else if ( dist <= radius ) - { - mightBeClipped = qtrue; - } - } - - if ( mightBeClipped ) - { - return CULL_CLIP; - } - - return CULL_IN; // completely inside frustum -} - -/* -** R_CullPointAndRadius -*/ -int R_CullPointAndRadius( const vec3_t pt, float radius ) -{ - return R_CullPointAndRadiusEx(pt, radius, tr.viewParms.frustum, ARRAY_LEN(tr.viewParms.frustum)); -} - -/* -================= -R_LocalNormalToWorld - -================= -*/ -void R_LocalNormalToWorld (const vec3_t local, vec3_t world) { - world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0]; - world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1]; - world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2]; -} - -/* -================= -R_LocalPointToWorld - -================= -*/ -void R_LocalPointToWorld (const vec3_t local, vec3_t world) { - world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0] + tr.or.origin[0]; - world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1] + tr.or.origin[1]; - world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2] + tr.or.origin[2]; -} - -/* -================= -R_WorldToLocal - -================= -*/ -void R_WorldToLocal (const vec3_t world, vec3_t local) { - local[0] = DotProduct(world, tr.or.axis[0]); - local[1] = DotProduct(world, tr.or.axis[1]); - local[2] = DotProduct(world, tr.or.axis[2]); -} - -/* -========================== -R_TransformModelToClip - -========================== -*/ -void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix, - vec4_t eye, vec4_t dst ) { - int i; - - for ( i = 0 ; i < 4 ; i++ ) { - eye[i] = - src[0] * modelMatrix[ i + 0 * 4 ] + - src[1] * modelMatrix[ i + 1 * 4 ] + - src[2] * modelMatrix[ i + 2 * 4 ] + - 1 * modelMatrix[ i + 3 * 4 ]; - } - - for ( i = 0 ; i < 4 ; i++ ) { - dst[i] = - eye[0] * projectionMatrix[ i + 0 * 4 ] + - eye[1] * projectionMatrix[ i + 1 * 4 ] + - eye[2] * projectionMatrix[ i + 2 * 4 ] + - eye[3] * projectionMatrix[ i + 3 * 4 ]; - } -} - -/* -========================== -R_TransformClipToWindow - -========================== -*/ -void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ) { - normalized[0] = clip[0] / clip[3]; - normalized[1] = clip[1] / clip[3]; - normalized[2] = ( clip[2] + clip[3] ) / ( 2 * clip[3] ); - - window[0] = 0.5f * ( 1.0f + normalized[0] ) * view->viewportWidth; - window[1] = 0.5f * ( 1.0f + normalized[1] ) * view->viewportHeight; - window[2] = normalized[2]; - - window[0] = (int) ( window[0] + 0.5 ); - window[1] = (int) ( window[1] + 0.5 ); -} - - -/* -========================== -myGlMultMatrix - -========================== -*/ -void myGlMultMatrix( const float *a, const float *b, float *out ) { - int i, j; - - for ( i = 0 ; i < 4 ; i++ ) { - for ( j = 0 ; j < 4 ; j++ ) { - out[ i * 4 + j ] = - a [ i * 4 + 0 ] * b [ 0 * 4 + j ] - + a [ i * 4 + 1 ] * b [ 1 * 4 + j ] - + a [ i * 4 + 2 ] * b [ 2 * 4 + j ] - + a [ i * 4 + 3 ] * b [ 3 * 4 + j ]; - } - } -} - -/* -================= -R_RotateForEntity - -Generates an orientation for an entity and viewParms -Does NOT produce any GL calls -Called by both the front end and the back end -================= -*/ -void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, - orientationr_t *or ) { - float glMatrix[16]; - vec3_t delta; - float axisLength; - - if ( ent->e.reType != RT_MODEL ) { - *or = viewParms->world; - return; - } - - VectorCopy( ent->e.origin, or->origin ); - - VectorCopy( ent->e.axis[0], or->axis[0] ); - VectorCopy( ent->e.axis[1], or->axis[1] ); - VectorCopy( ent->e.axis[2], or->axis[2] ); - - glMatrix[0] = or->axis[0][0]; - glMatrix[4] = or->axis[1][0]; - glMatrix[8] = or->axis[2][0]; - glMatrix[12] = or->origin[0]; - - glMatrix[1] = or->axis[0][1]; - glMatrix[5] = or->axis[1][1]; - glMatrix[9] = or->axis[2][1]; - glMatrix[13] = or->origin[1]; - - glMatrix[2] = or->axis[0][2]; - glMatrix[6] = or->axis[1][2]; - glMatrix[10] = or->axis[2][2]; - glMatrix[14] = or->origin[2]; - - glMatrix[3] = 0; - glMatrix[7] = 0; - glMatrix[11] = 0; - glMatrix[15] = 1; - - Matrix16Copy(glMatrix, or->transformMatrix); - myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix ); - - // calculate the viewer origin in the model's space - // needed for fog, specular, and environment mapping - VectorSubtract( viewParms->or.origin, or->origin, delta ); - - // compensate for scale in the axes if necessary - if ( ent->e.nonNormalizedAxes ) { - axisLength = VectorLength( ent->e.axis[0] ); - if ( !axisLength ) { - axisLength = 0; - } else { - axisLength = 1.0f / axisLength; - } - } else { - axisLength = 1.0f; - } - - or->viewOrigin[0] = DotProduct( delta, or->axis[0] ) * axisLength; - or->viewOrigin[1] = DotProduct( delta, or->axis[1] ) * axisLength; - or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength; -} - -/* -================= -R_RotateForViewer - -Sets up the modelview matrix for a given viewParm -================= -*/ -void R_RotateForViewer (void) -{ - float viewerMatrix[16]; - vec3_t origin; - - Com_Memset (&tr.or, 0, sizeof(tr.or)); - tr.or.axis[0][0] = 1; - tr.or.axis[1][1] = 1; - tr.or.axis[2][2] = 1; - VectorCopy (tr.viewParms.or.origin, tr.or.viewOrigin); - - // transform by the camera placement - VectorCopy( tr.viewParms.or.origin, origin ); - - viewerMatrix[0] = tr.viewParms.or.axis[0][0]; - viewerMatrix[4] = tr.viewParms.or.axis[0][1]; - viewerMatrix[8] = tr.viewParms.or.axis[0][2]; - viewerMatrix[12] = -origin[0] * viewerMatrix[0] + -origin[1] * viewerMatrix[4] + -origin[2] * viewerMatrix[8]; - - viewerMatrix[1] = tr.viewParms.or.axis[1][0]; - viewerMatrix[5] = tr.viewParms.or.axis[1][1]; - viewerMatrix[9] = tr.viewParms.or.axis[1][2]; - viewerMatrix[13] = -origin[0] * viewerMatrix[1] + -origin[1] * viewerMatrix[5] + -origin[2] * viewerMatrix[9]; - - viewerMatrix[2] = tr.viewParms.or.axis[2][0]; - viewerMatrix[6] = tr.viewParms.or.axis[2][1]; - viewerMatrix[10] = tr.viewParms.or.axis[2][2]; - viewerMatrix[14] = -origin[0] * viewerMatrix[2] + -origin[1] * viewerMatrix[6] + -origin[2] * viewerMatrix[10]; - - viewerMatrix[3] = 0; - viewerMatrix[7] = 0; - viewerMatrix[11] = 0; - viewerMatrix[15] = 1; - - // convert from our coordinate system (looking down X) - // to OpenGL's coordinate system (looking down -Z) - myGlMultMatrix( viewerMatrix, s_flipMatrix, tr.or.modelMatrix ); - - tr.viewParms.world = tr.or; - -} - -/* -** SetFarClip -*/ -static void R_SetFarClip( void ) -{ - float farthestCornerDistance = 0; - int i; - - // if not rendering the world (icons, menus, etc) - // set a 2k far clip plane - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { - tr.viewParms.zFar = 2048; - return; - } - - // - // set far clipping planes dynamically - // - farthestCornerDistance = 0; - for ( i = 0; i < 8; i++ ) - { - vec3_t v; - vec3_t vecTo; - float distance; - - if ( i & 1 ) - { - v[0] = tr.viewParms.visBounds[0][0]; - } - else - { - v[0] = tr.viewParms.visBounds[1][0]; - } - - if ( i & 2 ) - { - v[1] = tr.viewParms.visBounds[0][1]; - } - else - { - v[1] = tr.viewParms.visBounds[1][1]; - } - - if ( i & 4 ) - { - v[2] = tr.viewParms.visBounds[0][2]; - } - else - { - v[2] = tr.viewParms.visBounds[1][2]; - } - - VectorSubtract( v, tr.viewParms.or.origin, vecTo ); - - distance = vecTo[0] * vecTo[0] + vecTo[1] * vecTo[1] + vecTo[2] * vecTo[2]; - - if ( distance > farthestCornerDistance ) - { - farthestCornerDistance = distance; - } - } - tr.viewParms.zFar = sqrt( farthestCornerDistance ); -} - -/* -================= -R_SetupFrustum - -Set up the culling frustum planes for the current view using the results we got from computing the first two rows of -the projection matrix. -================= -*/ -void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float zFar, float stereoSep) -{ - vec3_t ofsorigin; - float oppleg, adjleg, length; - int i; - - if(stereoSep == 0 && xmin == -xmax) - { - // symmetric case can be simplified - VectorCopy(dest->or.origin, ofsorigin); - - length = sqrt(xmax * xmax + zProj * zProj); - oppleg = xmax / length; - adjleg = zProj / length; - - VectorScale(dest->or.axis[0], oppleg, dest->frustum[0].normal); - VectorMA(dest->frustum[0].normal, adjleg, dest->or.axis[1], dest->frustum[0].normal); - - VectorScale(dest->or.axis[0], oppleg, dest->frustum[1].normal); - VectorMA(dest->frustum[1].normal, -adjleg, dest->or.axis[1], dest->frustum[1].normal); - } - else - { - // In stereo rendering, due to the modification of the projection matrix, dest->or.origin is not the - // actual origin that we're rendering so offset the tip of the view pyramid. - VectorMA(dest->or.origin, stereoSep, dest->or.axis[1], ofsorigin); - - oppleg = xmax + stereoSep; - length = sqrt(oppleg * oppleg + zProj * zProj); - VectorScale(dest->or.axis[0], oppleg / length, dest->frustum[0].normal); - VectorMA(dest->frustum[0].normal, zProj / length, dest->or.axis[1], dest->frustum[0].normal); - - oppleg = xmin + stereoSep; - length = sqrt(oppleg * oppleg + zProj * zProj); - VectorScale(dest->or.axis[0], -oppleg / length, dest->frustum[1].normal); - VectorMA(dest->frustum[1].normal, -zProj / length, dest->or.axis[1], dest->frustum[1].normal); - } - - length = sqrt(ymax * ymax + zProj * zProj); - oppleg = ymax / length; - adjleg = zProj / length; - - VectorScale(dest->or.axis[0], oppleg, dest->frustum[2].normal); - VectorMA(dest->frustum[2].normal, adjleg, dest->or.axis[2], dest->frustum[2].normal); - - VectorScale(dest->or.axis[0], oppleg, dest->frustum[3].normal); - VectorMA(dest->frustum[3].normal, -adjleg, dest->or.axis[2], dest->frustum[3].normal); - - for (i=0 ; i<4 ; i++) { - dest->frustum[i].type = PLANE_NON_AXIAL; - dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal); - SetPlaneSignbits( &dest->frustum[i] ); - } - - if (zFar != 0.0f) - { - vec3_t farpoint; - - VectorMA(ofsorigin, zFar, dest->or.axis[0], farpoint); - VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal); - - dest->frustum[4].type = PLANE_NON_AXIAL; - dest->frustum[4].dist = DotProduct (farpoint, dest->frustum[4].normal); - SetPlaneSignbits( &dest->frustum[4] ); - } -} - -/* -=============== -R_SetupProjection -=============== -*/ -void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum) -{ - float xmin, xmax, ymin, ymax; - float width, height, stereoSep = r_stereoSeparation->value; - - /* - * offset the view origin of the viewer for stereo rendering - * by setting the projection matrix appropriately. - */ - - if(stereoSep != 0) - { - if(dest->stereoFrame == STEREO_LEFT) - stereoSep = zProj / stereoSep; - else if(dest->stereoFrame == STEREO_RIGHT) - stereoSep = zProj / -stereoSep; - else - stereoSep = 0; - } - - ymax = zProj * tan(dest->fovY * M_PI / 360.0f); - ymin = -ymax; - - xmax = zProj * tan(dest->fovX * M_PI / 360.0f); - xmin = -xmax; - - width = xmax - xmin; - height = ymax - ymin; - - dest->projectionMatrix[0] = 2 * zProj / width; - dest->projectionMatrix[4] = 0; - dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width; - dest->projectionMatrix[12] = 2 * zProj * stereoSep / width; - - dest->projectionMatrix[1] = 0; - dest->projectionMatrix[5] = 2 * zProj / height; - dest->projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0 - dest->projectionMatrix[13] = 0; - - dest->projectionMatrix[3] = 0; - dest->projectionMatrix[7] = 0; - dest->projectionMatrix[11] = -1; - dest->projectionMatrix[15] = 0; - - // Now that we have all the data for the projection matrix we can also setup the view frustum. - if(computeFrustum) - R_SetupFrustum(dest, xmin, xmax, ymax, zProj, zFar, stereoSep); -} - -/* -=============== -R_SetupProjectionZ - -Sets the z-component transformation part in the projection matrix -=============== -*/ -void R_SetupProjectionZ(viewParms_t *dest) -{ - float zNear, zFar, depth; - - zNear = r_znear->value; - zFar = dest->zFar; - - depth = zFar - zNear; - - dest->projectionMatrix[2] = 0; - dest->projectionMatrix[6] = 0; - dest->projectionMatrix[10] = -( zFar + zNear ) / depth; - dest->projectionMatrix[14] = -2 * zFar * zNear / depth; - - if (dest->isPortal) - { - float plane[4]; - float plane2[4]; - vec4_t q, c; - - // transform portal plane into camera space - plane[0] = dest->portalPlane.normal[0]; - plane[1] = dest->portalPlane.normal[1]; - plane[2] = dest->portalPlane.normal[2]; - plane[3] = dest->portalPlane.dist; - - plane2[0] = -DotProduct (dest->or.axis[1], plane); - plane2[1] = DotProduct (dest->or.axis[2], plane); - plane2[2] = -DotProduct (dest->or.axis[0], plane); - plane2[3] = DotProduct (plane, dest->or.origin) - plane[3]; - - // Lengyel, Eric. “Modifying the Projection Matrix to Perform Oblique Near-plane Clipping”. - // Terathon Software 3D Graphics Library, 2004. http://www.terathon.com/code/oblique.html - q[0] = (SGN(plane2[0]) + dest->projectionMatrix[8]) / dest->projectionMatrix[0]; - q[1] = (SGN(plane2[1]) + dest->projectionMatrix[9]) / dest->projectionMatrix[5]; - q[2] = -1.0f; - q[3] = (1.0f + dest->projectionMatrix[10]) / dest->projectionMatrix[14]; - - VectorScale4(plane2, 2.0f / DotProduct4(plane2, q), c); - - dest->projectionMatrix[2] = c[0]; - dest->projectionMatrix[6] = c[1]; - dest->projectionMatrix[10] = c[2] + 1.0f; - dest->projectionMatrix[14] = c[3]; - - } - -} - -/* -=============== -R_SetupProjectionOrtho -=============== -*/ -void R_SetupProjectionOrtho(viewParms_t *dest, vec3_t viewBounds[2]) -{ - float xmin, xmax, ymin, ymax, znear, zfar; - //viewParms_t *dest = &tr.viewParms; - int i; - vec3_t pop; - - // Quake3: Projection: - // - // Z X Y Z - // | / | / - // |/ |/ - // Y--+ +--X - - xmin = viewBounds[0][1]; - xmax = viewBounds[1][1]; - ymin = -viewBounds[1][2]; - ymax = -viewBounds[0][2]; - znear = viewBounds[0][0]; - zfar = viewBounds[1][0]; - - dest->projectionMatrix[0] = 2 / (xmax - xmin); - dest->projectionMatrix[4] = 0; - dest->projectionMatrix[8] = 0; - dest->projectionMatrix[12] = (xmax + xmin) / (xmax - xmin); - - dest->projectionMatrix[1] = 0; - dest->projectionMatrix[5] = 2 / (ymax - ymin); - dest->projectionMatrix[9] = 0; - dest->projectionMatrix[13] = (ymax + ymin) / (ymax - ymin); - - dest->projectionMatrix[2] = 0; - dest->projectionMatrix[6] = 0; - dest->projectionMatrix[10] = -2 / (zfar - znear); - dest->projectionMatrix[14] = -(zfar + znear) / (zfar - znear); - - dest->projectionMatrix[3] = 0; - dest->projectionMatrix[7] = 0; - dest->projectionMatrix[11] = 0; - dest->projectionMatrix[15] = 1; - - VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal); - VectorMA(dest->or.origin, viewBounds[0][1], dest->frustum[0].normal, pop); - dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal); - - VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal); - VectorMA(dest->or.origin, -viewBounds[1][1], dest->frustum[1].normal, pop); - dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal); - - VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal); - VectorMA(dest->or.origin, viewBounds[0][2], dest->frustum[2].normal, pop); - dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal); - - VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal); - VectorMA(dest->or.origin, -viewBounds[1][2], dest->frustum[3].normal, pop); - dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal); - - VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal); - VectorMA(dest->or.origin, -viewBounds[1][0], dest->frustum[4].normal, pop); - dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal); - - for (i = 0; i < 5; i++) - { - dest->frustum[i].type = PLANE_NON_AXIAL; - SetPlaneSignbits (&dest->frustum[i]); - } -} - -/* -================= -R_MirrorPoint -================= -*/ -void R_MirrorPoint (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) { - int i; - vec3_t local; - vec3_t transformed; - float d; - - VectorSubtract( in, surface->origin, local ); - - VectorClear( transformed ); - for ( i = 0 ; i < 3 ; i++ ) { - d = DotProduct(local, surface->axis[i]); - VectorMA( transformed, d, camera->axis[i], transformed ); - } - - VectorAdd( transformed, camera->origin, out ); -} - -void R_MirrorVector (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) { - int i; - float d; - - VectorClear( out ); - for ( i = 0 ; i < 3 ; i++ ) { - d = DotProduct(in, surface->axis[i]); - VectorMA( out, d, camera->axis[i], out ); - } -} - - -/* -============= -R_PlaneForSurface -============= -*/ -void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) { - srfTriangles_t *tri; - srfPoly_t *poly; - srfVert_t *v1, *v2, *v3; - vec4_t plane4; - - if (!surfType) { - Com_Memset (plane, 0, sizeof(*plane)); - plane->normal[0] = 1; - return; - } - switch (*surfType) { - case SF_FACE: - *plane = ((srfSurfaceFace_t *)surfType)->plane; - return; - case SF_TRIANGLES: - tri = (srfTriangles_t *)surfType; - v1 = tri->verts + tri->triangles[0].indexes[0]; - v2 = tri->verts + tri->triangles[0].indexes[1]; - v3 = tri->verts + tri->triangles[0].indexes[2]; - PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz ); - VectorCopy( plane4, plane->normal ); - plane->dist = plane4[3]; - return; - case SF_POLY: - poly = (srfPoly_t *)surfType; - PlaneFromPoints( plane4, poly->verts[0].xyz, poly->verts[1].xyz, poly->verts[2].xyz ); - VectorCopy( plane4, plane->normal ); - plane->dist = plane4[3]; - return; - default: - Com_Memset (plane, 0, sizeof(*plane)); - plane->normal[0] = 1; - return; - } -} - -/* -================= -R_GetPortalOrientation - -entityNum is the entity that the portal surface is a part of, which may -be moving and rotating. - -Returns qtrue if it should be mirrored -================= -*/ -qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum, - orientation_t *surface, orientation_t *camera, - vec3_t pvsOrigin, qboolean *mirror ) { - int i; - cplane_t originalPlane, plane; - trRefEntity_t *e; - float d; - vec3_t transformed; - - // create plane axis for the portal we are seeing - R_PlaneForSurface( drawSurf->surface, &originalPlane ); - - // rotate the plane if necessary - if ( entityNum != ENTITYNUM_WORLD ) { - tr.currentEntityNum = entityNum; - tr.currentEntity = &tr.refdef.entities[entityNum]; - - // get the orientation of the entity - R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or ); - - // rotate the plane, but keep the non-rotated version for matching - // against the portalSurface entities - R_LocalNormalToWorld( originalPlane.normal, plane.normal ); - plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin ); - - // translate the original plane - originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin ); - } else { - plane = originalPlane; - } - - VectorCopy( plane.normal, surface->axis[0] ); - PerpendicularVector( surface->axis[1], surface->axis[0] ); - CrossProduct( surface->axis[0], surface->axis[1], surface->axis[2] ); - - // locate the portal entity closest to this plane. - // origin will be the origin of the portal, origin2 will be - // the origin of the camera - for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) { - e = &tr.refdef.entities[i]; - if ( e->e.reType != RT_PORTALSURFACE ) { - continue; - } - - d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist; - if ( d > 64 || d < -64) { - continue; - } - - // get the pvsOrigin from the entity - VectorCopy( e->e.oldorigin, pvsOrigin ); - - // if the entity is just a mirror, don't use as a camera point - if ( e->e.oldorigin[0] == e->e.origin[0] && - e->e.oldorigin[1] == e->e.origin[1] && - e->e.oldorigin[2] == e->e.origin[2] ) { - VectorScale( plane.normal, plane.dist, surface->origin ); - VectorCopy( surface->origin, camera->origin ); - VectorSubtract( vec3_origin, surface->axis[0], camera->axis[0] ); - VectorCopy( surface->axis[1], camera->axis[1] ); - VectorCopy( surface->axis[2], camera->axis[2] ); - - *mirror = qtrue; - return qtrue; - } - - // project the origin onto the surface plane to get - // an origin point we can rotate around - d = DotProduct( e->e.origin, plane.normal ) - plane.dist; - VectorMA( e->e.origin, -d, surface->axis[0], surface->origin ); - - // now get the camera origin and orientation - VectorCopy( e->e.oldorigin, camera->origin ); - AxisCopy( e->e.axis, camera->axis ); - VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] ); - VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] ); - - // optionally rotate - if ( e->e.oldframe ) { - // if a speed is specified - if ( e->e.frame ) { - // continuous rotate - d = (tr.refdef.time/1000.0f) * e->e.frame; - VectorCopy( camera->axis[1], transformed ); - RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); - CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); - } else { - // bobbing rotate, with skinNum being the rotation offset - d = sin( tr.refdef.time * 0.003f ); - d = e->e.skinNum + d * 4; - VectorCopy( camera->axis[1], transformed ); - RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); - CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); - } - } - else if ( e->e.skinNum ) { - d = e->e.skinNum; - VectorCopy( camera->axis[1], transformed ); - RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d ); - CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] ); - } - *mirror = qfalse; - return qtrue; - } - - // if we didn't locate a portal entity, don't render anything. - // We don't want to just treat it as a mirror, because without a - // portal entity the server won't have communicated a proper entity set - // in the snapshot - - // unfortunately, with local movement prediction it is easily possible - // to see a surface before the server has communicated the matching - // portal surface entity, so we don't want to print anything here... - - //ri.Printf( PRINT_ALL, "Portal surface without a portal entity\n" ); - - return qfalse; -} - -static qboolean IsMirror( const drawSurf_t *drawSurf, int entityNum ) -{ - int i; - cplane_t originalPlane, plane; - trRefEntity_t *e; - float d; - - // create plane axis for the portal we are seeing - R_PlaneForSurface( drawSurf->surface, &originalPlane ); - - // rotate the plane if necessary - if ( entityNum != ENTITYNUM_WORLD ) - { - tr.currentEntityNum = entityNum; - tr.currentEntity = &tr.refdef.entities[entityNum]; - - // get the orientation of the entity - R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or ); - - // rotate the plane, but keep the non-rotated version for matching - // against the portalSurface entities - R_LocalNormalToWorld( originalPlane.normal, plane.normal ); - plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin ); - - // translate the original plane - originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin ); - } - else - { - plane = originalPlane; - } - - // locate the portal entity closest to this plane. - // origin will be the origin of the portal, origin2 will be - // the origin of the camera - for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) - { - e = &tr.refdef.entities[i]; - if ( e->e.reType != RT_PORTALSURFACE ) { - continue; - } - - d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist; - if ( d > 64 || d < -64) { - continue; - } - - // if the entity is just a mirror, don't use as a camera point - if ( e->e.oldorigin[0] == e->e.origin[0] && - e->e.oldorigin[1] == e->e.origin[1] && - e->e.oldorigin[2] == e->e.origin[2] ) - { - return qtrue; - } - - return qfalse; - } - return qfalse; -} - -/* -** SurfIsOffscreen -** -** Determines if a surface is completely offscreen. -*/ -static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128] ) { - float shortest = 100000000; - int entityNum; - int numTriangles; - shader_t *shader; - int fogNum; - int dlighted; - int pshadowed; - vec4_t clip, eye; - int i; - unsigned int pointOr = 0; - unsigned int pointAnd = (unsigned int)~0; - - if ( glConfig.smpActive ) { // FIXME! we can't do RB_BeginSurface/RB_EndSurface stuff with smp! - return qfalse; - } - - R_RotateForViewer(); - - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); - RB_BeginSurface( shader, fogNum ); - rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface ); - - assert( tess.numVertexes < 128 ); - - for ( i = 0; i < tess.numVertexes; i++ ) - { - int j; - unsigned int pointFlags = 0; - - R_TransformModelToClip( tess.xyz[i], tr.or.modelMatrix, tr.viewParms.projectionMatrix, eye, clip ); - - for ( j = 0; j < 3; j++ ) - { - if ( clip[j] >= clip[3] ) - { - pointFlags |= (1 << (j*2)); - } - else if ( clip[j] <= -clip[3] ) - { - pointFlags |= ( 1 << (j*2+1)); - } - } - pointAnd &= pointFlags; - pointOr |= pointFlags; - } - - // trivially reject - if ( pointAnd ) - { - return qtrue; - } - - // determine if this surface is backfaced and also determine the distance - // to the nearest vertex so we can cull based on portal range. Culling - // based on vertex distance isn't 100% correct (we should be checking for - // range to the surface), but it's good enough for the types of portals - // we have in the game right now. - numTriangles = tess.numIndexes / 3; - - for ( i = 0; i < tess.numIndexes; i += 3 ) - { - vec3_t normal; - float len; - - VectorSubtract( tess.xyz[tess.indexes[i]], tr.viewParms.or.origin, normal ); - - len = VectorLengthSquared( normal ); // lose the sqrt - if ( len < shortest ) - { - shortest = len; - } - - if ( DotProduct( normal, tess.normal[tess.indexes[i]] ) >= 0 ) - { - numTriangles--; - } - } - if ( !numTriangles ) - { - return qtrue; - } - - // mirrors can early out at this point, since we don't do a fade over distance - // with them (although we could) - if ( IsMirror( drawSurf, entityNum ) ) - { - return qfalse; - } - - if ( shortest > (tess.shader->portalRange*tess.shader->portalRange) ) - { - return qtrue; - } - - return qfalse; -} - -/* -======================== -R_MirrorViewBySurface - -Returns qtrue if another view has been rendered -======================== -*/ -qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) { - vec4_t clipDest[128]; - viewParms_t newParms; - viewParms_t oldParms; - orientation_t surface, camera; - - // don't recursively mirror - if (tr.viewParms.isPortal) { - ri.Printf( PRINT_DEVELOPER, "WARNING: recursive mirror/portal found\n" ); - return qfalse; - } - - if ( r_noportals->integer || (r_fastsky->integer == 1) ) { - return qfalse; - } - - // trivially reject portal/mirror - if ( SurfIsOffscreen( drawSurf, clipDest ) ) { - return qfalse; - } - - // save old viewParms so we can return to it after the mirror view - oldParms = tr.viewParms; - - newParms = tr.viewParms; - newParms.isPortal = qtrue; - if ( !R_GetPortalOrientations( drawSurf, entityNum, &surface, &camera, - newParms.pvsOrigin, &newParms.isMirror ) ) { - return qfalse; // bad portal, no portalentity - } - - R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin ); - - VectorSubtract( vec3_origin, camera.axis[0], newParms.portalPlane.normal ); - newParms.portalPlane.dist = DotProduct( camera.origin, newParms.portalPlane.normal ); - - R_MirrorVector (oldParms.or.axis[0], &surface, &camera, newParms.or.axis[0]); - R_MirrorVector (oldParms.or.axis[1], &surface, &camera, newParms.or.axis[1]); - R_MirrorVector (oldParms.or.axis[2], &surface, &camera, newParms.or.axis[2]); - - // OPTIMIZE: restrict the viewport on the mirrored view - - // render the mirror view - R_RenderView (&newParms); - - tr.viewParms = oldParms; - - return qtrue; -} - -/* -================= -R_SpriteFogNum - -See if a sprite is inside a fog volume -================= -*/ -int R_SpriteFogNum( trRefEntity_t *ent ) { - int i, j; - fog_t *fog; - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { - return 0; - } - - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { - fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) { - break; - } - if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) { - break; - } - } - if ( j == 3 ) { - return i; - } - } - - return 0; -} - -/* -========================================================================================== - -DRAWSURF SORTING - -========================================================================================== -*/ - -/* -=============== -R_Radix -=============== -*/ -static ID_INLINE void R_Radix( int byte, int size, drawSurf_t *source, drawSurf_t *dest ) -{ - int count[ 256 ] = { 0 }; - int index[ 256 ]; - int i; - unsigned char *sortKey = NULL; - unsigned char *end = NULL; - - sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte; - end = sortKey + ( size * sizeof( drawSurf_t ) ); - for( ; sortKey < end; sortKey += sizeof( drawSurf_t ) ) - ++count[ *sortKey ]; - - index[ 0 ] = 0; - - for( i = 1; i < 256; ++i ) - index[ i ] = index[ i - 1 ] + count[ i - 1 ]; - - sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte; - for( i = 0; i < size; ++i, sortKey += sizeof( drawSurf_t ) ) - dest[ index[ *sortKey ]++ ] = source[ i ]; -} - -/* -=============== -R_RadixSort - -Radix sort with 4 byte size buckets -=============== -*/ -static void R_RadixSort( drawSurf_t *source, int size ) -{ - static drawSurf_t scratch[ MAX_DRAWSURFS ]; -#ifdef Q3_LITTLE_ENDIAN - R_Radix( 0, size, source, scratch ); - R_Radix( 1, size, scratch, source ); - R_Radix( 2, size, source, scratch ); - R_Radix( 3, size, scratch, source ); -#else - R_Radix( 3, size, source, scratch ); - R_Radix( 2, size, scratch, source ); - R_Radix( 1, size, source, scratch ); - R_Radix( 0, size, scratch, source ); -#endif //Q3_LITTLE_ENDIAN -} - -//========================================================================================== - -/* -================= -R_AddDrawSurf -================= -*/ -void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, - int fogIndex, int dlightMap, int pshadowMap ) { - int index; - - // instead of checking for overflow, we just mask the index - // so it wraps around - index = tr.refdef.numDrawSurfs & DRAWSURF_MASK; - // the sort data is packed into a single 32 bit value so it can be - // compared quickly during the qsorting process - tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT) - | tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT ) - | ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap; - tr.refdef.drawSurfs[index].surface = surface; - tr.refdef.numDrawSurfs++; -} - -/* -================= -R_DecomposeSort -================= -*/ -void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, - int *fogNum, int *dlightMap, int *pshadowMap ) { - *fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31; - *shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ]; - *entityNum = ( sort >> QSORT_ENTITYNUM_SHIFT ) & MAX_ENTITIES; - *pshadowMap = (sort & 2) >> 1; - *dlightMap = sort & 1; -} - -/* -================= -R_SortDrawSurfs -================= -*/ -void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { - shader_t *shader; - int fogNum; - int entityNum; - int dlighted; - int pshadowed; - int i; - - //ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs); - - // it is possible for some views to not have any surfaces - if ( numDrawSurfs < 1 ) { - // we still need to add it for hyperspace cases - R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); - return; - } - - // if we overflowed MAX_DRAWSURFS, the drawsurfs - // wrapped around in the buffer and we will be missing - // the first surfaces, not the last ones - if ( numDrawSurfs > MAX_DRAWSURFS ) { - numDrawSurfs = MAX_DRAWSURFS; - } - - // sort the drawsurfs by sort type, then orientation, then shader - R_RadixSort( drawSurfs, numDrawSurfs ); - - // skip pass through drawing if rendering a shadow map - if (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)) - { - R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); - return; - } - - // check for any pass through drawing, which - // may cause another view to be rendered first - for ( i = 0 ; i < numDrawSurfs ; i++ ) { - R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed ); - - if ( shader->sort > SS_PORTAL ) { - break; - } - - // no shader should ever have this sort type - if ( shader->sort == SS_BAD ) { - ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name ); - } - - // if the mirror was completely clipped away, we may need to check another surface - if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) { - // this is a debug option to see exactly what is being mirrored - if ( r_portalOnly->integer ) { - return; - } - break; // only one mirror view at a time - } - } - - R_AddDrawSurfCmd( drawSurfs, numDrawSurfs ); -} - -static void R_AddEntitySurface (int entityNum) -{ - trRefEntity_t *ent; - shader_t *shader; - - tr.currentEntityNum = entityNum; - - ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum]; - - ent->needDlights = qfalse; - - // preshift the value we are going to OR into the drawsurf sort - tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - - // - // the weapon model must be handled special -- - // we don't want the hacked weapon position showing in - // mirrors, because the true body position will already be drawn - // - if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.isPortal - || (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW))) ) { - return; - } - - // simple generated models, like sprites and beams, are not culled - switch ( ent->e.reType ) { - case RT_PORTALSURFACE: - break; // don't draw anything - case RT_SPRITE: - case RT_BEAM: - case RT_LIGHTNING: - case RT_RAIL_CORE: - case RT_RAIL_RINGS: - // self blood sprites, talk balloons, etc should not be drawn in the primary - // view. We can't just do this check for all entities, because md3 - // entities may still want to cast shadows from them - if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) { - return; - } - shader = R_GetShaderByHandle( ent->e.customShader ); - R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0, 0 ); - break; - - case RT_MODEL: - // we must set up parts of tr.or for model culling - R_RotateForEntity( ent, &tr.viewParms, &tr.or ); - - tr.currentModel = R_GetModelByHandle( ent->e.hModel ); - if (!tr.currentModel) { - R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 ); - } else { - switch ( tr.currentModel->type ) { - case MOD_MESH: - R_AddMD3Surfaces( ent ); - break; - case MOD_MD4: - R_AddAnimSurfaces( ent ); - break; -#ifdef RAVENMD4 - case MOD_MDR: - R_MDRAddAnimSurfaces( ent ); - break; -#endif - case MOD_IQM: - R_AddIQMSurfaces( ent ); - break; - case MOD_BRUSH: - R_AddBrushModelSurfaces( ent ); - break; - case MOD_BAD: // null model axis - if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) { - break; - } - R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 ); - break; - default: - ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" ); - break; - } - } - break; - default: - ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" ); - } -} - -/* -============= -R_AddEntitySurfaces -============= -*/ -void R_AddEntitySurfaces (void) { - int i; - - if ( !r_drawentities->integer ) { - return; - } - - for ( i = 0; i < tr.refdef.num_entities; i++) - R_AddEntitySurface(i); -} - - -/* -==================== -R_GenerateDrawSurfs -==================== -*/ -void R_GenerateDrawSurfs( void ) { - R_AddWorldSurfaces (); - - R_AddPolygonSurfaces(); - - // set the projection matrix with the minimum zfar - // now that we have the world bounded - // this needs to be done before entities are - // added, because they use the projection - // matrix for lod calculation - - // dynamically compute far clip plane distance - if (!(tr.viewParms.flags & VPF_SHADOWMAP)) - { - R_SetFarClip(); - } - - // we know the size of the clipping volume. Now set the rest of the projection matrix. - R_SetupProjectionZ (&tr.viewParms); - - R_AddEntitySurfaces (); -} - -/* -================ -R_DebugPolygon -================ -*/ -void R_DebugPolygon( int color, int numPoints, float *points ) { - // FIXME: implement this -#if 0 - int i; - - GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - // draw solid shade - - qglColor3f( color&1, (color>>1)&1, (color>>2)&1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); - } - qglEnd(); - - // draw wireframe outline - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - qglDepthRange( 0, 0 ); - qglColor3f( 1, 1, 1 ); - qglBegin( GL_POLYGON ); - for ( i = 0 ; i < numPoints ; i++ ) { - qglVertex3fv( points + i * 3 ); - } - qglEnd(); - qglDepthRange( 0, 1 ); -#endif -} - -/* -==================== -R_DebugGraphics - -Visualization aid for movement clipping debugging -==================== -*/ -void R_DebugGraphics( void ) { - if ( !r_debugSurface->integer ) { - return; - } - - // the render thread can't make callbacks to the main thread - R_SyncRenderThread(); - - GL_Bind( tr.whiteImage); - GL_Cull( CT_FRONT_SIDED ); - ri.CM_DrawDebugSurface( R_DebugPolygon ); -} - - -/* -================ -R_RenderView - -A view may be either the actual camera view, -or a mirror / remote location -================ -*/ -void R_RenderView (viewParms_t *parms) { - int firstDrawSurf; - - if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { - return; - } - - tr.viewCount++; - - tr.viewParms = *parms; - tr.viewParms.frameSceneNum = tr.frameSceneNum; - tr.viewParms.frameCount = tr.frameCount; - - firstDrawSurf = tr.refdef.numDrawSurfs; - - tr.viewCount++; - - // set viewParms.world - R_RotateForViewer (); - - R_SetupProjection(&tr.viewParms, r_zproj->value, tr.viewParms.zFar, qtrue); - - R_GenerateDrawSurfs(); - - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); - - // draw main system development information (surface outlines, etc) - R_DebugGraphics(); -} - - -void R_RenderDlightCubemaps(const refdef_t *fd) -{ - int i; - - for (i = 0; i < tr.refdef.num_dlights; i++) - { - viewParms_t shadowParms; - int j; - - // use previous frame to determine visible dlights - if ((1 << i) & tr.refdef.dlightMask) - continue; - - Com_Memset( &shadowParms, 0, sizeof( shadowParms ) ); - - shadowParms.viewportX = tr.refdef.x; - shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE ); - shadowParms.viewportWidth = PSHADOW_MAP_SIZE; - shadowParms.viewportHeight = PSHADOW_MAP_SIZE; - shadowParms.isPortal = qfalse; - shadowParms.isMirror = qtrue; // because it is - - shadowParms.fovX = 90; - shadowParms.fovY = 90; - - shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW; - shadowParms.zFar = tr.refdef.dlights[i].radius; - - VectorCopy( tr.refdef.dlights[i].origin, shadowParms.or.origin ); - - for (j = 0; j < 6; j++) - { - switch(j) - { - case 0: - // -X - VectorSet( shadowParms.or.axis[0], -1, 0, 0); - VectorSet( shadowParms.or.axis[1], 0, 0, -1); - VectorSet( shadowParms.or.axis[2], 0, 1, 0); - break; - case 1: - // +X - VectorSet( shadowParms.or.axis[0], 1, 0, 0); - VectorSet( shadowParms.or.axis[1], 0, 0, 1); - VectorSet( shadowParms.or.axis[2], 0, 1, 0); - break; - case 2: - // -Y - VectorSet( shadowParms.or.axis[0], 0, -1, 0); - VectorSet( shadowParms.or.axis[1], 1, 0, 0); - VectorSet( shadowParms.or.axis[2], 0, 0, -1); - break; - case 3: - // +Y - VectorSet( shadowParms.or.axis[0], 0, 1, 0); - VectorSet( shadowParms.or.axis[1], 1, 0, 0); - VectorSet( shadowParms.or.axis[2], 0, 0, 1); - break; - case 4: - // -Z - VectorSet( shadowParms.or.axis[0], 0, 0, -1); - VectorSet( shadowParms.or.axis[1], 1, 0, 0); - VectorSet( shadowParms.or.axis[2], 0, 1, 0); - break; - case 5: - // +Z - VectorSet( shadowParms.or.axis[0], 0, 0, 1); - VectorSet( shadowParms.or.axis[1], -1, 0, 0); - VectorSet( shadowParms.or.axis[2], 0, 1, 0); - break; - } - - R_RenderView(&shadowParms); - R_AddCapShadowmapCmd( i, j ); - } - } -} - - -void R_RenderPshadowMaps(const refdef_t *fd) -{ - viewParms_t shadowParms; - int i; - - // first, make a list of shadows - for ( i = 0; i < tr.refdef.num_entities; i++) - { - trRefEntity_t *ent = &tr.refdef.entities[i]; - - if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW))) - continue; - - //if((ent->e.renderfx & RF_THIRD_PERSON)) - //continue; - - if (ent->e.reType == RT_MODEL) - { - model_t *model = R_GetModelByHandle( ent->e.hModel ); - pshadow_t shadow; - float radius = 0.0f; - float scale = 1.0f; - vec3_t diff; - int j; - - if (!model) - continue; - - if (ent->e.nonNormalizedAxes) - { - scale = VectorLength( ent->e.axis[0] ); - } - - switch (model->type) - { - case MOD_MESH: - { - mdvFrame_t *frame = &model->mdv[0]->frames[ent->e.frame]; - - radius = frame->radius * scale; - } - break; - - case MOD_MD4: - { - // FIXME: actually calculate the radius and bounds, this is a horrible hack - radius = r_pshadowDist->value / 2.0f; - } - break; -#ifdef RAVENMD4 - case MOD_MDR: - { - // FIXME: never actually tested this - mdrHeader_t *header = model->modelData; - int frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] ); - mdrFrame_t *frame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); - - radius = frame->radius; - } - break; -#endif - case MOD_IQM: - { - // FIXME: never actually tested this - iqmData_t *data = model->modelData; - vec3_t diag; - float *framebounds; - - framebounds = data->bounds + 6*ent->e.frame; - VectorSubtract( framebounds+3, framebounds, diag ); - radius = 0.5f * VectorLength( diag ); - } - break; - - default: - break; - } - - if (!radius) - continue; - - // Cull entities that are behind the viewer by more than lightRadius - VectorSubtract(ent->e.origin, fd->vieworg, diff); - if (DotProduct(diff, fd->viewaxis[0]) < -r_pshadowDist->value) - continue; - - memset(&shadow, 0, sizeof(shadow)); - - shadow.numEntities = 1; - shadow.entityNums[0] = i; - shadow.viewRadius = radius; - shadow.lightRadius = r_pshadowDist->value; - VectorCopy(ent->e.origin, shadow.viewOrigin); - shadow.sort = DotProduct(diff, diff) / (radius * radius); - VectorCopy(ent->e.origin, shadow.entityOrigins[0]); - shadow.entityRadiuses[0] = radius; - - for (j = 0; j < MAX_CALC_PSHADOWS; j++) - { - pshadow_t swap; - - if (j + 1 > tr.refdef.num_pshadows) - { - tr.refdef.num_pshadows = j + 1; - tr.refdef.pshadows[j] = shadow; - break; - } - - // sort shadows by distance from camera divided by radius - // FIXME: sort better - if (tr.refdef.pshadows[j].sort <= shadow.sort) - continue; - - swap = tr.refdef.pshadows[j]; - tr.refdef.pshadows[j] = shadow; - shadow = swap; - } - } - } - - // next, merge touching pshadows - for ( i = 0; i < tr.refdef.num_pshadows; i++) - { - pshadow_t *ps1 = &tr.refdef.pshadows[i]; - int j; - - for (j = i + 1; j < tr.refdef.num_pshadows; j++) - { - pshadow_t *ps2 = &tr.refdef.pshadows[j]; - int k; - qboolean touch; - - if (ps1->numEntities == 8) - break; - - touch = qfalse; - if (SpheresIntersect(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius)) - { - for (k = 0; k < ps1->numEntities; k++) - { - if (SpheresIntersect(ps1->entityOrigins[k], ps1->entityRadiuses[k], ps2->viewOrigin, ps2->viewRadius)) - { - touch = qtrue; - break; - } - } - } - - if (touch) - { - vec3_t newOrigin; - float newRadius; - - BoundingSphereOfSpheres(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius, newOrigin, &newRadius); - VectorCopy(newOrigin, ps1->viewOrigin); - ps1->viewRadius = newRadius; - - ps1->entityNums[ps1->numEntities] = ps2->entityNums[0]; - VectorCopy(ps2->viewOrigin, ps1->entityOrigins[ps1->numEntities]); - ps1->entityRadiuses[ps1->numEntities] = ps2->viewRadius; - - ps1->numEntities++; - - for (k = j; k < tr.refdef.num_pshadows - 1; k++) - { - tr.refdef.pshadows[k] = tr.refdef.pshadows[k + 1]; - } - - j--; - tr.refdef.num_pshadows--; - } - } - } - - // cap number of drawn pshadows - if (tr.refdef.num_pshadows > MAX_DRAWN_PSHADOWS) - { - tr.refdef.num_pshadows = MAX_DRAWN_PSHADOWS; - } - - // next, fill up the rest of the shadow info - for ( i = 0; i < tr.refdef.num_pshadows; i++) - { - pshadow_t *shadow = &tr.refdef.pshadows[i]; - vec3_t up; - vec3_t ambientLight, directedLight, lightDir; - - VectorSet(lightDir, 0.57735f, 0.57735f, 0.57735f); -#if 1 - R_LightForPoint(shadow->viewOrigin, ambientLight, directedLight, lightDir); - - // sometimes there's no light - if (DotProduct(lightDir, lightDir) < 0.9f) - VectorSet(lightDir, 0.0f, 0.0f, 1.0f); -#endif - - if (shadow->viewRadius * 3.0f > shadow->lightRadius) - { - shadow->lightRadius = shadow->viewRadius * 3.0f; - } - - VectorMA(shadow->viewOrigin, shadow->viewRadius, lightDir, shadow->lightOrigin); - - // make up a projection, up doesn't matter - VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]); - VectorSet(up, 0, 0, -1); - - if ( abs(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f ) - { - VectorSet(up, -1, 0, 0); - } - - CrossProduct(shadow->lightViewAxis[0], up, shadow->lightViewAxis[1]); - VectorNormalize(shadow->lightViewAxis[1]); - CrossProduct(shadow->lightViewAxis[0], shadow->lightViewAxis[1], shadow->lightViewAxis[2]); - - VectorCopy(shadow->lightViewAxis[0], shadow->cullPlane.normal); - shadow->cullPlane.dist = DotProduct(shadow->cullPlane.normal, shadow->lightOrigin); - shadow->cullPlane.type = PLANE_NON_AXIAL; - SetPlaneSignbits(&shadow->cullPlane); - } - - // next, render shadowmaps - for ( i = 0; i < tr.refdef.num_pshadows; i++) - { - int firstDrawSurf; - pshadow_t *shadow = &tr.refdef.pshadows[i]; - int j; - - Com_Memset( &shadowParms, 0, sizeof( shadowParms ) ); - - if (glRefConfig.framebufferObject) - { - shadowParms.viewportX = 0; - shadowParms.viewportY = 0; - } - else - { - shadowParms.viewportX = tr.refdef.x; - shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE ); - } - shadowParms.viewportWidth = PSHADOW_MAP_SIZE; - shadowParms.viewportHeight = PSHADOW_MAP_SIZE; - shadowParms.isPortal = qfalse; - shadowParms.isMirror = qfalse; - - shadowParms.fovX = 90; - shadowParms.fovY = 90; - - if (glRefConfig.framebufferObject) - shadowParms.targetFbo = tr.pshadowFbos[i]; - - shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW; - shadowParms.zFar = shadow->lightRadius; - - VectorCopy(shadow->lightOrigin, shadowParms.or.origin); - - VectorCopy(shadow->lightViewAxis[0], shadowParms.or.axis[0]); - VectorCopy(shadow->lightViewAxis[1], shadowParms.or.axis[1]); - VectorCopy(shadow->lightViewAxis[2], shadowParms.or.axis[2]); - - { - tr.viewCount++; - - tr.viewParms = shadowParms; - tr.viewParms.frameSceneNum = tr.frameSceneNum; - tr.viewParms.frameCount = tr.frameCount; - - firstDrawSurf = tr.refdef.numDrawSurfs; - - tr.viewCount++; - - // set viewParms.world - R_RotateForViewer (); - - { - float xmin, xmax, ymin, ymax, znear, zfar; - viewParms_t *dest = &tr.viewParms; - vec3_t pop; - - xmin = ymin = -shadow->viewRadius; - xmax = ymax = shadow->viewRadius; - znear = 0; - zfar = shadow->lightRadius; - - dest->projectionMatrix[0] = 2 / (xmax - xmin); - dest->projectionMatrix[4] = 0; - dest->projectionMatrix[8] = (xmax + xmin) / (xmax - xmin); - dest->projectionMatrix[12] =0; - - dest->projectionMatrix[1] = 0; - dest->projectionMatrix[5] = 2 / (ymax - ymin); - dest->projectionMatrix[9] = ( ymax + ymin ) / (ymax - ymin); // normally 0 - dest->projectionMatrix[13] = 0; - - dest->projectionMatrix[2] = 0; - dest->projectionMatrix[6] = 0; - dest->projectionMatrix[10] = 2 / (zfar - znear); - dest->projectionMatrix[14] = 0; - - dest->projectionMatrix[3] = 0; - dest->projectionMatrix[7] = 0; - dest->projectionMatrix[11] = 0; - dest->projectionMatrix[15] = 1; - - VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal); - VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[0].normal, pop); - dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal); - - VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal); - VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[1].normal, pop); - dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal); - - VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal); - VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[2].normal, pop); - dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal); - - VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal); - VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[3].normal, pop); - dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal); - - VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal); - VectorMA(dest->or.origin, -shadow->lightRadius, dest->frustum[4].normal, pop); - dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal); - - for (j = 0; j < 5; j++) - { - dest->frustum[j].type = PLANE_NON_AXIAL; - SetPlaneSignbits (&dest->frustum[j]); - } - } - - for (j = 0; j < shadow->numEntities; j++) - { - R_AddEntitySurface(shadow->entityNums[j]); - } - - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); - - if (!glRefConfig.framebufferObject) - R_AddCapShadowmapCmd( i, -1 ); - } - } -} - -static float CalcSplit(float n, float f, float i, float m) -{ - return (n * pow(f / n, i / m) + (f - n) * i / m) / 2.0f; -} - - -void R_RenderSunShadowMaps(const refdef_t *fd, int level) -{ - viewParms_t shadowParms; - vec4_t lightDir, lightCol; - vec3_t lightViewAxis[3]; - vec3_t lightOrigin; - float splitZNear, splitZFar, splitBias; - float viewZNear, viewZFar; - vec3_t lightviewBounds[2]; - qboolean lightViewIndependentOfCameraView = qfalse; - - if (r_forceSun->integer == 2) - { - int scale = 32768; - float angle = (fd->time % scale) / (float)scale * M_PI; - lightDir[0] = cos(angle); - lightDir[1] = sin(35.0f * M_PI / 180.0f); - lightDir[2] = sin(angle) * cos(35.0f * M_PI / 180.0f); - lightDir[3] = 0.0f; - - if (1) //((fd->time % (scale * 2)) < scale) - { - lightCol[0] = - lightCol[1] = - lightCol[2] = CLAMP(sin(angle) * 2.0f, 0.0f, 1.0f) * 2.0f; - lightCol[3] = 1.0f; - } - else - { - lightCol[0] = - lightCol[1] = - lightCol[2] = CLAMP(sin(angle) * 2.0f * 0.1f, 0.0f, 0.1f); - lightCol[3] = 1.0f; - } - - VectorCopy4(lightDir, tr.refdef.sunDir); - VectorCopy4(lightCol, tr.refdef.sunCol); - VectorScale4(lightCol, 0.2f, tr.refdef.sunAmbCol); - } - else - { - VectorCopy4(tr.refdef.sunDir, lightDir); - } - - viewZNear = r_shadowCascadeZNear->value; - viewZFar = r_shadowCascadeZFar->value; - splitBias = r_shadowCascadeZBias->value; - - switch(level) - { - case 0: - default: - //splitZNear = r_znear->value; - //splitZFar = 256; - splitZNear = viewZNear; - splitZFar = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias; - break; - case 1: - splitZNear = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias; - splitZFar = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias; - //splitZNear = 256; - //splitZFar = 896; - break; - case 2: - splitZNear = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias; - splitZFar = viewZFar; - //splitZNear = 896; - //splitZFar = 3072; - break; - } - - VectorCopy(fd->vieworg, lightOrigin); - - - // Make up a projection - VectorScale(lightDir, -1.0f, lightViewAxis[0]); - - if (lightViewIndependentOfCameraView) - { - // Use world up as light view up - VectorSet(lightViewAxis[2], 0, 0, 1); - } - else if (level == 0) - { - // Level 0 tries to use a diamond texture orientation relative to camera view - // Use halfway between camera view forward and left for light view up - VectorAdd(fd->viewaxis[0], fd->viewaxis[1], lightViewAxis[2]); - } - else - { - // Use camera view up as light view up - VectorCopy(fd->viewaxis[2], lightViewAxis[2]); - } - - // Check if too close to parallel to light direction - if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f) - { - if (lightViewIndependentOfCameraView) - { - // Use world left as light view up - VectorSet(lightViewAxis[2], 0, 1, 0); - } - else if (level == 0) - { - // Level 0 tries to use a diamond texture orientation relative to camera view - // Use halfway between camera view forward and up for light view up - VectorAdd(fd->viewaxis[0], fd->viewaxis[2], lightViewAxis[2]); - } - else - { - // Use camera view left as light view up - VectorCopy(fd->viewaxis[1], lightViewAxis[2]); - } - } - - // clean axes - CrossProduct(lightViewAxis[2], lightViewAxis[0], lightViewAxis[1]); - VectorNormalize(lightViewAxis[1]); - CrossProduct(lightViewAxis[0], lightViewAxis[1], lightViewAxis[2]); - - // Create bounds for light projection using slice of view projection - { - matrix_t lightViewMatrix; - vec4_t point, base, lightViewPoint; - float lx, ly; - - base[3] = 1; - point[3] = 1; - lightViewPoint[3] = 1; - - Matrix16View(lightViewAxis, lightOrigin, lightViewMatrix); - - ClearBounds(lightviewBounds[0], lightviewBounds[1]); - - // add view near plane - lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f); - ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f); - VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base); - - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - - // add view far plane - lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f); - ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f); - VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base); - - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Matrix16Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - - if (!glRefConfig.depthClamp) - lightviewBounds[0][0] = lightviewBounds[1][0] - 8192; - - // Moving the Light in Texel-Sized Increments - // from http://msdn.microsoft.com/en-us/library/windows/desktop/ee416324%28v=vs.85%29.aspx - // - if (lightViewIndependentOfCameraView) - { - float cascadeBound, worldUnitsPerTexel, invWorldUnitsPerTexel; - - cascadeBound = MAX(lightviewBounds[1][0] - lightviewBounds[0][0], lightviewBounds[1][1] - lightviewBounds[0][1]); - cascadeBound = MAX(cascadeBound, lightviewBounds[1][2] - lightviewBounds[0][2]); - worldUnitsPerTexel = cascadeBound / tr.sunShadowFbo[level]->width; - invWorldUnitsPerTexel = 1.0f / worldUnitsPerTexel; - - VectorScale(lightviewBounds[0], invWorldUnitsPerTexel, lightviewBounds[0]); - lightviewBounds[0][0] = floor(lightviewBounds[0][0]); - lightviewBounds[0][1] = floor(lightviewBounds[0][1]); - lightviewBounds[0][2] = floor(lightviewBounds[0][2]); - VectorScale(lightviewBounds[0], worldUnitsPerTexel, lightviewBounds[0]); - - VectorScale(lightviewBounds[1], invWorldUnitsPerTexel, lightviewBounds[1]); - lightviewBounds[1][0] = floor(lightviewBounds[1][0]); - lightviewBounds[1][1] = floor(lightviewBounds[1][1]); - lightviewBounds[1][2] = floor(lightviewBounds[1][2]); - VectorScale(lightviewBounds[1], worldUnitsPerTexel, lightviewBounds[1]); - } - - //ri.Printf(PRINT_ALL, "znear %f zfar %f\n", lightviewBounds[0][0], lightviewBounds[1][0]); - //ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax); - } - - - { - int firstDrawSurf; - - Com_Memset( &shadowParms, 0, sizeof( shadowParms ) ); - - if (glRefConfig.framebufferObject) - { - shadowParms.viewportX = 0; - shadowParms.viewportY = 0; - } - else - { - shadowParms.viewportX = tr.refdef.x; - shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.sunShadowFbo[level]->height ); - } - shadowParms.viewportWidth = tr.sunShadowFbo[level]->width; - shadowParms.viewportHeight = tr.sunShadowFbo[level]->height; - shadowParms.isPortal = qfalse; - shadowParms.isMirror = qfalse; - - shadowParms.fovX = 90; - shadowParms.fovY = 90; - - if (glRefConfig.framebufferObject) - shadowParms.targetFbo = tr.sunShadowFbo[level]; - - shadowParms.flags = VPF_DEPTHSHADOW | VPF_DEPTHCLAMP | VPF_ORTHOGRAPHIC; - shadowParms.zFar = lightviewBounds[1][0]; - - VectorCopy(lightOrigin, shadowParms.or.origin); - - VectorCopy(lightViewAxis[0], shadowParms.or.axis[0]); - VectorCopy(lightViewAxis[1], shadowParms.or.axis[1]); - VectorCopy(lightViewAxis[2], shadowParms.or.axis[2]); - - VectorCopy(lightOrigin, shadowParms.pvsOrigin ); - - { - tr.viewCount++; - - tr.viewParms = shadowParms; - tr.viewParms.frameSceneNum = tr.frameSceneNum; - tr.viewParms.frameCount = tr.frameCount; - - firstDrawSurf = tr.refdef.numDrawSurfs; - - tr.viewCount++; - - // set viewParms.world - R_RotateForViewer (); - - R_SetupProjectionOrtho(&tr.viewParms, lightviewBounds); - - R_AddWorldSurfaces (); - - R_AddPolygonSurfaces(); - - R_AddEntitySurfaces (); - - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); - } - - Matrix16Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]); - } -} diff --git a/code/renderergl2/tr_marks.c b/code/renderergl2/tr_marks.c deleted file mode 100644 index f24459e2..00000000 --- a/code/renderergl2/tr_marks.c +++ /dev/null @@ -1,466 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_marks.c -- polygon projection on the world polygons - -#include "tr_local.h" -//#include "assert.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]; - int sides[MAX_VERTS_ON_POLY+4]; - 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; - Com_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; - int *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 = tr.world->marksurfaces + node->firstmarksurface; - c = node->nummarksurfaces; - while (c--) { - int *surfViewCount; - // - if (*listlength >= listsize) break; - // - surfViewCount = &tr.world->surfacesViewCount[*mark]; - surf = tr.world->surfaces + *mark; - // check if the surface has NOIMPACT or NOMARKS set - if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) ) - || ( surf->shader->contentFlags & CONTENTS_FOG ) ) { - *surfViewCount = 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, &surf->cullinfo.plane ); - if (s == 1 || s == 2) { - *surfViewCount = tr.viewCount; - } else if (DotProduct(surf->cullinfo.plane.normal, dir) > -0.5) { - // don't add faces that make sharp angles with the projection direction - *surfViewCount = tr.viewCount; - } - } - else if (*(surf->data) != SF_GRID && - *(surf->data) != SF_TRIANGLES) - *surfViewCount = tr.viewCount; - // check the viewCount because the surface may have - // already been added if it spans multiple leafs - if (*surfViewCount != tr.viewCount) { - *surfViewCount = tr.viewCount; - list[*listlength] = 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; - Com_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]; - int numClipPoints; - float *v; - srfGridMesh_t *cv; - srfTriangle_t *tri; - srfVert_t *dv; - vec3_t normal; - vec3_t projectionDir; - vec3_t v1, v2; - - if (numPoints <= 0) { - return 0; - } - - //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) { - - 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. - - numClipPoints = 3; - - 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) { - - srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i]; - - // check the normal of this face - if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { - continue; - } - - for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++) - { - for(j = 0; j < 3; j++) - { - v = surf->verts[tri->indexes[j]].xyz; - 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 - } - } - } - else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) { - - srfTriangles_t *surf = (srfTriangles_t *) surfaces[i]; - - for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++) - { - for(j = 0; j < 3; j++) - { - v = surf->verts[tri->indexes[j]].xyz; - VectorMA(v, MARKER_OFFSET, surf->verts[tri->indexes[j]].normal, clipPoints[0][j]); - } - - // 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 - } - } - } - } - return returnedFragments; -} - - - - - diff --git a/code/renderergl2/tr_mesh.c b/code/renderergl2/tr_mesh.c deleted file mode 100644 index 4e9013d2..00000000 --- a/code/renderergl2/tr_mesh.c +++ /dev/null @@ -1,405 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_mesh.c: triangle model functions - -#include "tr_local.h" - -static float ProjectRadius( float r, vec3_t location ) -{ - float pr; - float dist; - float c; - vec3_t p; - float projected[4]; - - c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin ); - dist = DotProduct( tr.viewParms.or.axis[0], location ) - c; - - if ( dist <= 0 ) - return 0; - - p[0] = 0; - p[1] = fabs( r ); - p[2] = -dist; - - projected[0] = p[0] * tr.viewParms.projectionMatrix[0] + - p[1] * tr.viewParms.projectionMatrix[4] + - p[2] * tr.viewParms.projectionMatrix[8] + - tr.viewParms.projectionMatrix[12]; - - projected[1] = p[0] * tr.viewParms.projectionMatrix[1] + - p[1] * tr.viewParms.projectionMatrix[5] + - p[2] * tr.viewParms.projectionMatrix[9] + - tr.viewParms.projectionMatrix[13]; - - projected[2] = p[0] * tr.viewParms.projectionMatrix[2] + - p[1] * tr.viewParms.projectionMatrix[6] + - p[2] * tr.viewParms.projectionMatrix[10] + - tr.viewParms.projectionMatrix[14]; - - projected[3] = p[0] * tr.viewParms.projectionMatrix[3] + - p[1] * tr.viewParms.projectionMatrix[7] + - p[2] * tr.viewParms.projectionMatrix[11] + - tr.viewParms.projectionMatrix[15]; - - - pr = projected[1] / projected[3]; - - if ( pr > 1.0f ) - pr = 1.0f; - - return pr; -} - -/* -============= -R_CullModel -============= -*/ -static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) { - vec3_t bounds[2]; - mdvFrame_t *oldFrame, *newFrame; - int i; - - // compute frame pointers - newFrame = model->frames + ent->e.frame; - oldFrame = model->frames + 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; - } -} - - -/* -================= -R_ComputeLOD - -================= -*/ -int R_ComputeLOD( trRefEntity_t *ent ) { - float radius; - float flod, lodscale; - float projectedRadius; - mdvFrame_t *frame; -#ifdef RAVENMD4 - mdrHeader_t *mdr; - mdrFrame_t *mdrframe; -#endif - int lod; - - if ( tr.currentModel->numLods < 2 ) - { - // model has only 1 LOD level, skip computations and bias - lod = 0; - } - else - { - // multiple LODs exist, so compute projected bounding sphere - // and use that as a criteria for selecting LOD - -#ifdef RAVENMD4 - if(tr.currentModel->type == MOD_MDR) - { - int frameSize; - mdr = (mdrHeader_t *) tr.currentModel->modelData; - frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]); - - mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame); - - radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]); - } - else -#endif - { - //frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames ); - frame = tr.currentModel->mdv[0]->frames; - - frame += ent->e.frame; - - radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] ); - } - - if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 ) - { - lodscale = r_lodscale->value; - if (lodscale > 20) lodscale = 20; - flod = 1.0f - projectedRadius * lodscale; - } - else - { - // object intersects near view plane, e.g. view weapon - flod = 0; - } - - flod *= tr.currentModel->numLods; - lod = ri.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 - -================= -*/ -int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) { - int i, j; - fog_t *fog; - mdvFrame_t *mdvFrame; - vec3_t localOrigin; - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { - return 0; - } - - // FIXME: non-normalized axis issues - mdvFrame = model->frames + ent->e.frame; - VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin ); - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { - fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) { - break; - } - if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) { - break; - } - } - if ( j == 3 ) { - return i; - } - } - - return 0; -} - -/* -================= -R_AddMD3Surfaces - -================= -*/ -void R_AddMD3Surfaces( trRefEntity_t *ent ) { - int i; - mdvModel_t *model = NULL; - mdvSurface_t *surface = NULL; - shader_t *shader = NULL; - int cull; - int lod; - int fogNum; - qboolean personalModel; - - // don't add third_person objects if not in a portal - personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal - || (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW))); - - if ( ent->e.renderfx & RF_WRAP_FRAMES ) { - ent->e.frame %= tr.currentModel->mdv[0]->numFrames; - ent->e.oldframe %= tr.currentModel->mdv[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->mdv[0]->numFrames) - || (ent->e.frame < 0) - || (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames) - || (ent->e.oldframe < 0) ) { - ri.Printf( PRINT_DEVELOPER, "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 ); - - model = tr.currentModel->mdv[lod]; - - // - // cull the entire model if merged bounding box of both frames - // is outside the view frustum. - // - cull = R_CullModel ( model, 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( model, ent ); - - // - // draw all surfaces - // - surface = model->surfaces; - for ( i = 0 ; i < model->numSurfaces ; i++ ) { - - if ( ent->e.customShader ) { - shader = R_GetShaderByHandle( ent->e.customShader ); - } else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) { - skin_t *skin; - 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; - } - } - if (shader == tr.defaultShader) { - ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name); - } - else if (shader->defaultShader) { - ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name); - } - //} 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 ]; - shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ]; - } - - // don't add third_person objects if not viewing through a portal - if(!personalModel) - { - srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i]; - - R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse ); - } - - surface++; - } - -} - - - - - diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c deleted file mode 100644 index b269fdee..00000000 --- a/code/renderergl2/tr_model.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_models.c -- model loading and caching - -#include "tr_local.h" - -#define LL(x) x=LittleLong(x) - -static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName); -static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name ); -#ifdef RAVENMD4 -static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name ); -#endif - -/* -==================== -R_RegisterMD3 -==================== -*/ -qhandle_t R_RegisterMD3(const char *name, model_t *mod) -{ - union { - unsigned *u; - void *v; - } buf; - int size; - int lod; - int ident; - qboolean loaded = qfalse; - int numLoaded; - char filename[MAX_QPATH], namebuf[MAX_QPATH+20]; - char *fext, defex[] = "md3"; - - numLoaded = 0; - - strcpy(filename, name); - - fext = strchr(filename, '.'); - if(!fext) - fext = defex; - else - { - *fext = '\0'; - fext++; - } - - for (lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod--) - { - if(lod) - Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext); - else - Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext); - - size = ri.FS_ReadFile( namebuf, &buf.v ); - if(!buf.u) - continue; - - ident = LittleLong(* (unsigned *) buf.u); - if (ident == MD4_IDENT) - loaded = R_LoadMD4(mod, buf.u, name); - else - { - if (ident == MD3_IDENT) - loaded = R_LoadMD3(mod, lod, buf.u, size, name); - else - ri.Printf(PRINT_WARNING,"R_RegisterMD3: unknown fileid for %s\n", name); - } - - ri.FS_FreeFile(buf.v); - - if(loaded) - { - mod->numLods++; - numLoaded++; - } - else - break; - } - - if(numLoaded) - { - // duplicate into higher lod spots that weren't - // loaded, in case the user changes r_lodbias on the fly - for(lod--; lod >= 0; lod--) - { - mod->numLods++; - mod->mdv[lod] = mod->mdv[lod + 1]; - } - - return mod->index; - } - -#ifdef _DEBUG - ri.Printf(PRINT_WARNING,"R_RegisterMD3: couldn't load %s\n", name); -#endif - - mod->type = MOD_BAD; - return 0; -} - -#ifdef RAVENMD4 -/* -==================== -R_RegisterMDR -==================== -*/ -qhandle_t R_RegisterMDR(const char *name, model_t *mod) -{ - union { - unsigned *u; - void *v; - } buf; - int ident; - qboolean loaded = qfalse; - int filesize; - - filesize = ri.FS_ReadFile(name, (void **) &buf.v); - if(!buf.u) - { - mod->type = MOD_BAD; - return 0; - } - - ident = LittleLong(*(unsigned *)buf.u); - if(ident == MDR_IDENT) - loaded = R_LoadMDR(mod, buf.u, filesize, name); - - ri.FS_FreeFile (buf.v); - - if(!loaded) - { - ri.Printf(PRINT_WARNING,"R_RegisterMDR: couldn't load mdr file %s\n", name); - mod->type = MOD_BAD; - return 0; - } - - return mod->index; -} -#endif - -/* -==================== -R_RegisterIQM -==================== -*/ -qhandle_t R_RegisterIQM(const char *name, model_t *mod) -{ - union { - unsigned *u; - void *v; - } buf; - qboolean loaded = qfalse; - int filesize; - - filesize = ri.FS_ReadFile(name, (void **) &buf.v); - if(!buf.u) - { - mod->type = MOD_BAD; - return 0; - } - - loaded = R_LoadIQM(mod, buf.u, filesize, name); - - ri.FS_FreeFile (buf.v); - - if(!loaded) - { - ri.Printf(PRINT_WARNING,"R_RegisterIQM: couldn't load iqm file %s\n", name); - mod->type = MOD_BAD; - return 0; - } - - return mod->index; -} - - -typedef struct -{ - char *ext; - qhandle_t (*ModelLoader)( const char *, model_t * ); -} modelExtToLoaderMap_t; - -// Note that the ordering indicates the order of preference used -// when there are multiple models of different formats available -static modelExtToLoaderMap_t modelLoaders[ ] = -{ - { "iqm", R_RegisterIQM }, -#ifdef RAVENMD4 - { "mdr", R_RegisterMDR }, -#endif - { "md4", R_RegisterMD3 }, - { "md3", R_RegisterMD3 } -}; - -static int numModelLoaders = ARRAY_LEN(modelLoaders); - -//=============================================================================== - -/* -** R_GetModelByHandle -*/ -model_t *R_GetModelByHandle( qhandle_t index ) { - model_t *mod; - - // out of range gets the defualt model - if ( index < 1 || index >= tr.numModels ) { - return tr.models[0]; - } - - mod = tr.models[index]; - - return mod; -} - -//=============================================================================== - -/* -** R_AllocModel -*/ -model_t *R_AllocModel( void ) { - model_t *mod; - - if ( tr.numModels == MAX_MOD_KNOWN ) { - return NULL; - } - - mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low ); - mod->index = tr.numModels; - tr.models[tr.numModels] = mod; - tr.numModels++; - - return mod; -} - -/* -==================== -RE_RegisterModel - -Loads in a model for the given name - -Zero will be returned if the model fails to load. -An entry will be retained for failed models as an -optimization to prevent disk rescanning if they are -asked for again. -==================== -*/ -qhandle_t RE_RegisterModel( const char *name ) { - model_t *mod; - qhandle_t hModel; - qboolean orgNameFailed = qfalse; - int orgLoader = -1; - int i; - char localName[ MAX_QPATH ]; - const char *ext; - char altName[ MAX_QPATH ]; - - if ( !name || !name[0] ) { - ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" ); - return 0; - } - - if ( strlen( name ) >= MAX_QPATH ) { - ri.Printf( PRINT_ALL, "Model name exceeds MAX_QPATH\n" ); - return 0; - } - - // - // search the currently loaded models - // - for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) { - mod = tr.models[hModel]; - if ( !strcmp( mod->name, name ) ) { - if( mod->type == MOD_BAD ) { - return 0; - } - return hModel; - } - } - - // allocate a new model_t - - if ( ( mod = R_AllocModel() ) == NULL ) { - ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name); - return 0; - } - - // only set the name after the model has been successfully loaded - Q_strncpyz( mod->name, name, sizeof( mod->name ) ); - - - // make sure the render thread is stopped - R_SyncRenderThread(); - - mod->type = MOD_BAD; - mod->numLods = 0; - - // - // load the files - // - Q_strncpyz( localName, name, MAX_QPATH ); - - ext = COM_GetExtension( localName ); - - if( *ext ) - { - // Look for the correct loader and use it - for( i = 0; i < numModelLoaders; i++ ) - { - if( !Q_stricmp( ext, modelLoaders[ i ].ext ) ) - { - // Load - hModel = modelLoaders[ i ].ModelLoader( localName, mod ); - break; - } - } - - // A loader was found - if( i < numModelLoaders ) - { - if( !hModel ) - { - // Loader failed, most likely because the file isn't there; - // try again without the extension - orgNameFailed = qtrue; - orgLoader = i; - COM_StripExtension( name, localName, MAX_QPATH ); - } - else - { - // Something loaded - return mod->index; - } - } - } - - // Try and find a suitable match using all - // the model formats supported - for( i = 0; i < numModelLoaders; i++ ) - { - if (i == orgLoader) - continue; - - Com_sprintf( altName, sizeof (altName), "%s.%s", localName, modelLoaders[ i ].ext ); - - // Load - hModel = modelLoaders[ i ].ModelLoader( altName, mod ); - - if( hModel ) - { - if( orgNameFailed ) - { - ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n", - name, altName ); - } - - break; - } - } - - return hModel; -} - -/* -================= -R_LoadMD3 -================= -*/ -static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, const char *modName) -{ - int f, i, j, k; - - md3Header_t *md3Model; - md3Frame_t *md3Frame; - md3Surface_t *md3Surf; - md3Shader_t *md3Shader; - md3Triangle_t *md3Tri; - md3St_t *md3st; - md3XyzNormal_t *md3xyz; - md3Tag_t *md3Tag; - - mdvModel_t *mdvModel; - mdvFrame_t *frame; - mdvSurface_t *surf;//, *surface; - int *shaderIndex; - srfTriangle_t *tri; - mdvVertex_t *v; - mdvSt_t *st; - mdvTag_t *tag; - mdvTagName_t *tagName; - - int version; - int size; - - md3Model = (md3Header_t *) buffer; - - version = LittleLong(md3Model->version); - if(version != MD3_VERSION) - { - ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MD3_VERSION); - return qfalse; - } - - mod->type = MOD_MESH; - size = LittleLong(md3Model->ofsEnd); - mod->dataSize += size; - mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low); - -// Com_Memcpy(mod->md3[lod], buffer, LittleLong(md3Model->ofsEnd)); - - LL(md3Model->ident); - LL(md3Model->version); - LL(md3Model->numFrames); - LL(md3Model->numTags); - LL(md3Model->numSurfaces); - LL(md3Model->ofsFrames); - LL(md3Model->ofsTags); - LL(md3Model->ofsSurfaces); - LL(md3Model->ofsEnd); - - if(md3Model->numFrames < 1) - { - ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has no frames\n", modName); - return qfalse; - } - - // swap all the frames - mdvModel->numFrames = md3Model->numFrames; - mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low); - - md3Frame = (md3Frame_t *) ((byte *) md3Model + md3Model->ofsFrames); - for(i = 0; i < md3Model->numFrames; i++, frame++, md3Frame++) - { - frame->radius = LittleFloat(md3Frame->radius); - for(j = 0; j < 3; j++) - { - frame->bounds[0][j] = LittleFloat(md3Frame->bounds[0][j]); - frame->bounds[1][j] = LittleFloat(md3Frame->bounds[1][j]); - frame->localOrigin[j] = LittleFloat(md3Frame->localOrigin[j]); - } - } - - // swap all the tags - mdvModel->numTags = md3Model->numTags; - mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low); - - md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags); - for(i = 0; i < md3Model->numTags * md3Model->numFrames; i++, tag++, md3Tag++) - { - for(j = 0; j < 3; j++) - { - tag->origin[j] = LittleFloat(md3Tag->origin[j]); - tag->axis[0][j] = LittleFloat(md3Tag->axis[0][j]); - tag->axis[1][j] = LittleFloat(md3Tag->axis[1][j]); - tag->axis[2][j] = LittleFloat(md3Tag->axis[2][j]); - } - } - - - mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low); - - md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags); - for(i = 0; i < md3Model->numTags; i++, tagName++, md3Tag++) - { - Q_strncpyz(tagName->name, md3Tag->name, sizeof(tagName->name)); - } - - // swap all the surfaces - mdvModel->numSurfaces = md3Model->numSurfaces; - mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low); - - md3Surf = (md3Surface_t *) ((byte *) md3Model + md3Model->ofsSurfaces); - for(i = 0; i < md3Model->numSurfaces; i++) - { - LL(md3Surf->ident); - LL(md3Surf->flags); - LL(md3Surf->numFrames); - LL(md3Surf->numShaders); - LL(md3Surf->numTriangles); - LL(md3Surf->ofsTriangles); - LL(md3Surf->numVerts); - LL(md3Surf->ofsShaders); - LL(md3Surf->ofsSt); - LL(md3Surf->ofsXyzNormals); - LL(md3Surf->ofsEnd); - - if(md3Surf->numVerts > SHADER_MAX_VERTEXES) - { - ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i verts on a surface (%i)", - modName, SHADER_MAX_VERTEXES, md3Surf->numVerts); - return qfalse; - } - if(md3Surf->numTriangles * 3 > SHADER_MAX_INDEXES) - { - ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i triangles on a surface (%i)", - modName, SHADER_MAX_INDEXES / 3, md3Surf->numTriangles); - return qfalse; - } - - // change to surface identifier - surf->surfaceType = SF_MDV; - - // give pointer to model for Tess_SurfaceMDX - surf->model = mdvModel; - - // copy surface name - Q_strncpyz(surf->name, md3Surf->name, sizeof(surf->name)); - - // lowercase the surface name so skin compares are faster - Q_strlwr(surf->name); - - // strip off a trailing _1 or _2 - // this is a crutch for q3data being a mess - j = strlen(surf->name); - if(j > 2 && surf->name[j - 2] == '_') - { - surf->name[j - 2] = 0; - } - - // register the shaders - surf->numShaderIndexes = md3Surf->numShaders; - surf->shaderIndexes = shaderIndex = ri.Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low); - - md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders); - for(j = 0; j < md3Surf->numShaders; j++, shaderIndex++, md3Shader++) - { - shader_t *sh; - - sh = R_FindShader(md3Shader->name, LIGHTMAP_NONE, qtrue); - if(sh->defaultShader) - { - *shaderIndex = 0; - } - else - { - *shaderIndex = sh->index; - } - } - - // swap all the triangles - surf->numTriangles = md3Surf->numTriangles; - surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * md3Surf->numTriangles, h_low); - - md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles); - for(j = 0; j < md3Surf->numTriangles; j++, tri++, md3Tri++) - { - tri->indexes[0] = LittleLong(md3Tri->indexes[0]); - tri->indexes[1] = LittleLong(md3Tri->indexes[1]); - tri->indexes[2] = LittleLong(md3Tri->indexes[2]); - } - - R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles); - - // swap all the XyzNormals - surf->numVerts = md3Surf->numVerts; - surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low); - - md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals); - for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++) - { - unsigned lat, lng; - unsigned short normal; - - v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE; - v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE; - v->xyz[2] = LittleShort(md3xyz->xyz[2]) * MD3_XYZ_SCALE; - - normal = LittleShort(md3xyz->normal); - - lat = ( normal >> 8 ) & 0xff; - lng = ( normal & 0xff ); - 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 ) - - v->normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - v->normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - } - - // swap all the ST - surf->st = st = ri.Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low); - - md3st = (md3St_t *) ((byte *) md3Surf + md3Surf->ofsSt); - for(j = 0; j < md3Surf->numVerts; j++, md3st++, st++) - { - st->st[0] = LittleFloat(md3st->st[0]); - st->st[1] = LittleFloat(md3st->st[1]); - } - -#ifdef USE_VERT_TANGENT_SPACE - // calc tangent spaces - { - // Valgrind complaints: Conditional jump or move depends on uninitialised value(s) - // So lets Initialize them. - const float *v0 = NULL, *v1 = NULL, *v2 = NULL; - const float *t0 = NULL, *t1 = NULL, *t2 = NULL; - vec3_t tangent = { 0, 0, 0 }; - vec3_t bitangent = { 0, 0, 0 }; - vec3_t normal = { 0, 0, 0 }; - - for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++) - { - VectorClear(v->tangent); - VectorClear(v->bitangent); - if (r_recalcMD3Normals->integer) - VectorClear(v->normal); - } - - for(f = 0; f < mdvModel->numFrames; f++) - { - for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++) - { - v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz; - v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz; - v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz; - - t0 = surf->st[tri->indexes[0]].st; - t1 = surf->st[tri->indexes[1]].st; - t2 = surf->st[tri->indexes[2]].st; - - if (!r_recalcMD3Normals->integer) - VectorCopy(v->normal, normal); - else - VectorClear(normal); - - #if 1 - R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2); - #else - R_CalcNormalForTriangle(normal, v0, v1, v2); - R_CalcTangentsForTriangle(tangent, bitangent, v0, v1, v2, t0, t1, t2); - #endif - - for(k = 0; k < 3; k++) - { - float *v; - - v = surf->verts[surf->numVerts * f + tri->indexes[k]].tangent; - VectorAdd(v, tangent, v); - - v = surf->verts[surf->numVerts * f + tri->indexes[k]].bitangent; - VectorAdd(v, bitangent, v); - - if (r_recalcMD3Normals->integer) - { - v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal; - VectorAdd(v, normal, v); - } - } - } - } - - for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++) - { - VectorNormalize(v->tangent); - VectorNormalize(v->bitangent); - VectorNormalize(v->normal); - } - } -#endif - - // find the next surface - md3Surf = (md3Surface_t *) ((byte *) md3Surf + md3Surf->ofsEnd); - surf++; - } - - { - srfVBOMDVMesh_t *vboSurf; - - mdvModel->numVBOSurfaces = mdvModel->numSurfaces; - mdvModel->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low); - - vboSurf = mdvModel->vboSurfaces; - surf = mdvModel->surfaces; - for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++) - { - vec3_t *verts; - vec3_t *normals; - vec2_t *texcoords; -#ifdef USE_VERT_TANGENT_SPACE - vec3_t *tangents; - vec3_t *bitangents; -#endif - - byte *data; - int dataSize; - - int ofs_xyz, ofs_normal, ofs_st; -#ifdef USE_VERT_TANGENT_SPACE - int ofs_tangent, ofs_bitangent; -#endif - - dataSize = 0; - - ofs_xyz = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts); - - ofs_normal = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*normals); - -#ifdef USE_VERT_TANGENT_SPACE - ofs_tangent = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*tangents); - - ofs_bitangent = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*bitangents); -#endif - - ofs_st = dataSize; - dataSize += surf->numVerts * sizeof(*texcoords); - - data = ri.Malloc(dataSize); - - verts = (void *)(data + ofs_xyz); - normals = (void *)(data + ofs_normal); -#ifdef USE_VERT_TANGENT_SPACE - tangents = (void *)(data + ofs_tangent); - bitangents = (void *)(data + ofs_bitangent); -#endif - texcoords = (void *)(data + ofs_st); - - v = surf->verts; - for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ ) - { - VectorCopy(v->xyz, verts[j]); - VectorCopy(v->normal, normals[j]); -#ifdef USE_VERT_TANGENT_SPACE - VectorCopy(v->tangent, tangents[j]); - VectorCopy(v->bitangent, bitangents[j]); -#endif - } - - st = surf->st; - for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { - texcoords[j][0] = st->st[0]; - texcoords[j][1] = st->st[1]; - } - - vboSurf->surfaceType = SF_VBO_MDVMESH; - vboSurf->mdvModel = mdvModel; - vboSurf->mdvSurface = surf; - vboSurf->numIndexes = surf->numTriangles * 3; - vboSurf->numVerts = surf->numVerts; - vboSurf->vbo = R_CreateVBO(va("staticMD3Mesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); - - vboSurf->vbo->ofs_xyz = ofs_xyz; - vboSurf->vbo->ofs_normal = ofs_normal; -#ifdef USE_VERT_TANGENT_SPACE - vboSurf->vbo->ofs_tangent = ofs_tangent; - vboSurf->vbo->ofs_bitangent = ofs_bitangent; -#endif - vboSurf->vbo->ofs_st = ofs_st; - - vboSurf->vbo->stride_xyz = sizeof(*verts); - vboSurf->vbo->stride_normal = sizeof(*normals); -#ifdef USE_VERT_TANGENT_SPACE - vboSurf->vbo->stride_tangent = sizeof(*tangents); - vboSurf->vbo->stride_bitangent = sizeof(*bitangents); -#endif - vboSurf->vbo->stride_st = sizeof(*st); - - vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts; - vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts; - - ri.Free(data); - - vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC); - } - } - - return qtrue; -} - - -#ifdef RAVENMD4 - -/* -================= -R_LoadMDR -================= -*/ -static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name ) -{ - int i, j, k, l; - mdrHeader_t *pinmodel, *mdr; - mdrFrame_t *frame; - mdrLOD_t *lod, *curlod; - mdrSurface_t *surf, *cursurf; - mdrTriangle_t *tri, *curtri; - mdrVertex_t *v, *curv; - mdrWeight_t *weight, *curweight; - mdrTag_t *tag, *curtag; - int size; - shader_t *sh; - - pinmodel = (mdrHeader_t *)buffer; - - pinmodel->version = LittleLong(pinmodel->version); - if (pinmodel->version != MDR_VERSION) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION); - return qfalse; - } - - size = LittleLong(pinmodel->ofsEnd); - - if(size > filesize) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name); - return qfalse; - } - - mod->type = MOD_MDR; - - LL(pinmodel->numFrames); - LL(pinmodel->numBones); - LL(pinmodel->ofsFrames); - - // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame - // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4. - if(pinmodel->ofsFrames < 0) - { - // mdrFrame_t is larger than mdrCompFrame_t: - size += pinmodel->numFrames * sizeof(frame->name); - // now add enough space for the uncompressed bones. - size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t))); - } - - // simple bounds check - if(pinmodel->numBones < 0 || - sizeof(*mdr) + pinmodel->numFrames * (sizeof(*frame) + (pinmodel->numBones - 1) * sizeof(*frame->bones)) > size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - mod->dataSize += size; - mod->modelData = mdr = ri.Hunk_Alloc( size, h_low ); - - // Copy all the values over from the file and fix endian issues in the process, if necessary. - - mdr->ident = LittleLong(pinmodel->ident); - mdr->version = pinmodel->version; // Don't need to swap byte order on this one, we already did above. - Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name)); - mdr->numFrames = pinmodel->numFrames; - mdr->numBones = pinmodel->numBones; - mdr->numLODs = LittleLong(pinmodel->numLODs); - mdr->numTags = LittleLong(pinmodel->numTags); - // We don't care about the other offset values, we'll generate them ourselves while loading. - - mod->numLods = mdr->numLODs; - - if ( mdr->numFrames < 1 ) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name); - return qfalse; - } - - /* The first frame will be put into the first free space after the header */ - frame = (mdrFrame_t *)(mdr + 1); - mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr); - - if (pinmodel->ofsFrames < 0) - { - mdrCompFrame_t *cframe; - - // compressed model... - cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames); - - for(i = 0; i < mdr->numFrames; i++) - { - for(j = 0; j < 3; j++) - { - frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]); - frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]); - frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]); - } - - frame->radius = LittleFloat(cframe->radius); - frame->name[0] = '\0'; // No name supplied in the compressed version. - - for(j = 0; j < mdr->numBones; j++) - { - for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++) - { - // Do swapping for the uncompressing functions. They seem to use shorts - // values only, so I assume this will work. Never tested it on other - // platforms, though. - - ((unsigned short *)(cframe->bones[j].Comp))[k] = - LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] ); - } - - /* Now do the actual uncompressing */ - MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp); - } - - // Next Frame... - cframe = (mdrCompFrame_t *) &cframe->bones[j]; - frame = (mdrFrame_t *) &frame->bones[j]; - } - } - else - { - mdrFrame_t *curframe; - - // uncompressed model... - // - - curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames); - - // swap all the frames - for ( i = 0 ; i < mdr->numFrames ; i++) - { - for(j = 0; j < 3; j++) - { - frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]); - frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]); - frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]); - } - - frame->radius = LittleFloat(curframe->radius); - Q_strncpyz(frame->name, curframe->name, sizeof(frame->name)); - - for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++) - { - ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] ); - } - - curframe = (mdrFrame_t *) &curframe->bones[mdr->numBones]; - frame = (mdrFrame_t *) &frame->bones[mdr->numBones]; - } - } - - // frame should now point to the first free address after all frames. - lod = (mdrLOD_t *) frame; - mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr); - - curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs)); - - // swap all the LOD's - for ( l = 0 ; l < mdr->numLODs ; l++) - { - // simple bounds check - if((byte *) (lod + 1) > (byte *) mdr + size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - lod->numSurfaces = LittleLong(curlod->numSurfaces); - - // swap all the surfaces - surf = (mdrSurface_t *) (lod + 1); - lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod); - cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces)); - - for ( i = 0 ; i < lod->numSurfaces ; i++) - { - // simple bounds check - if((byte *) (surf + 1) > (byte *) mdr + size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - // first do some copying stuff - - surf->ident = SF_MDR; - Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name)); - Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader)); - - surf->ofsHeader = (byte *) mdr - (byte *) surf; - - surf->numVerts = LittleLong(cursurf->numVerts); - surf->numTriangles = LittleLong(cursurf->numTriangles); - // numBoneReferences and BoneReferences generally seem to be unused - - // now do the checks that may fail. - if ( surf->numVerts > SHADER_MAX_VERTEXES ) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i).\n", - mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); - return qfalse; - } - if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i).\n", - mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); - return qfalse; - } - // lowercase the surface name so skin compares are faster - Q_strlwr( surf->name ); - - // register the shaders - sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue); - if ( sh->defaultShader ) { - surf->shaderIndex = 0; - } else { - surf->shaderIndex = sh->index; - } - - // now copy the vertexes. - v = (mdrVertex_t *) (surf + 1); - surf->ofsVerts = (int)((byte *) v - (byte *) surf); - curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts)); - - for(j = 0; j < surf->numVerts; j++) - { - LL(curv->numWeights); - - // simple bounds check - if(curv->numWeights < 0 || (byte *) (v + 1) + (curv->numWeights - 1) * sizeof(*weight) > (byte *) mdr + size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - v->normal[0] = LittleFloat(curv->normal[0]); - v->normal[1] = LittleFloat(curv->normal[1]); - v->normal[2] = LittleFloat(curv->normal[2]); - - v->texCoords[0] = LittleFloat(curv->texCoords[0]); - v->texCoords[1] = LittleFloat(curv->texCoords[1]); - - v->numWeights = curv->numWeights; - weight = &v->weights[0]; - curweight = &curv->weights[0]; - - // Now copy all the weights - for(k = 0; k < v->numWeights; k++) - { - weight->boneIndex = LittleLong(curweight->boneIndex); - weight->boneWeight = LittleFloat(curweight->boneWeight); - - weight->offset[0] = LittleFloat(curweight->offset[0]); - weight->offset[1] = LittleFloat(curweight->offset[1]); - weight->offset[2] = LittleFloat(curweight->offset[2]); - - weight++; - curweight++; - } - - v = (mdrVertex_t *) weight; - curv = (mdrVertex_t *) curweight; - } - - // we know the offset to the triangles now: - tri = (mdrTriangle_t *) v; - surf->ofsTriangles = (int)((byte *) tri - (byte *) surf); - curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles)); - - // simple bounds check - if(surf->numTriangles < 0 || (byte *) (tri + surf->numTriangles) > (byte *) mdr + size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - for(j = 0; j < surf->numTriangles; j++) - { - tri->indexes[0] = LittleLong(curtri->indexes[0]); - tri->indexes[1] = LittleLong(curtri->indexes[1]); - tri->indexes[2] = LittleLong(curtri->indexes[2]); - - tri++; - curtri++; - } - - // tri now points to the end of the surface. - surf->ofsEnd = (byte *) tri - (byte *) surf; - surf = (mdrSurface_t *) tri; - - // find the next surface. - cursurf = (mdrSurface_t *) ((byte *) cursurf + LittleLong(cursurf->ofsEnd)); - } - - // surf points to the next lod now. - lod->ofsEnd = (int)((byte *) surf - (byte *) lod); - lod = (mdrLOD_t *) surf; - - // find the next LOD. - curlod = (mdrLOD_t *)((byte *) curlod + LittleLong(curlod->ofsEnd)); - } - - // lod points to the first tag now, so update the offset too. - tag = (mdrTag_t *) lod; - mdr->ofsTags = (int)((byte *) tag - (byte *) mdr); - curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags)); - - // simple bounds check - if(mdr->numTags < 0 || (byte *) (tag + mdr->numTags) > (byte *) mdr + size) - { - ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); - return qfalse; - } - - for (i = 0 ; i < mdr->numTags ; i++) - { - tag->boneIndex = LittleLong(curtag->boneIndex); - Q_strncpyz(tag->name, curtag->name, sizeof(tag->name)); - - tag++; - curtag++; - } - - // And finally we know the real offset to the end. - mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr); - - // phew! we're done. - - return qtrue; -} -#endif - -/* -================= -R_LoadMD4 -================= -*/ - -static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) { - int i, j, k, lodindex; - md4Header_t *pinmodel, *md4; - md4Frame_t *frame; - md4LOD_t *lod; - md4Surface_t *surf; - md4Triangle_t *tri; - md4Vertex_t *v; - int version; - int size; - shader_t *sh; - int frameSize; - - pinmodel = (md4Header_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != MD4_VERSION) { - ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n", - mod_name, version, MD4_VERSION); - return qfalse; - } - - mod->type = MOD_MD4; - size = LittleLong(pinmodel->ofsEnd); - mod->dataSize += size; - mod->modelData = md4 = ri.Hunk_Alloc( size, h_low ); - - Com_Memcpy(md4, buffer, size); - - LL(md4->ident); - LL(md4->version); - LL(md4->numFrames); - LL(md4->numBones); - LL(md4->numLODs); - LL(md4->ofsFrames); - LL(md4->ofsLODs); - md4->ofsEnd = size; - - if ( md4->numFrames < 1 ) { - ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name ); - return qfalse; - } - - // we don't need to swap tags in the renderer, they aren't used - - // swap all the frames - frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] ); - for ( i = 0 ; i < md4->numFrames ; i++) { - frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize ); - frame->radius = LittleFloat( frame->radius ); - for ( j = 0 ; j < 3 ; j++ ) { - frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); - frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); - frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); - } - for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) { - ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] ); - } - } - - // swap all the LOD's - lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs ); - for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) { - - // swap all the surfaces - surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces ); - for ( i = 0 ; i < lod->numSurfaces ; i++) { - LL(surf->ident); - LL(surf->numTriangles); - LL(surf->ofsTriangles); - LL(surf->numVerts); - LL(surf->ofsVerts); - LL(surf->ofsEnd); - - if ( surf->numVerts > SHADER_MAX_VERTEXES ) { - ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i verts on a surface (%i).\n", - mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); - return qfalse; - } - if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { - ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i triangles on a surface (%i).\n", - mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); - return qfalse; - } - - // change to surface identifier - surf->ident = SF_MD4; - - // lowercase the surface name so skin compares are faster - Q_strlwr( surf->name ); - - // register the shaders - sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue ); - if ( sh->defaultShader ) { - surf->shaderIndex = 0; - } else { - surf->shaderIndex = sh->index; - } - - // swap all the triangles - tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); - for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { - LL(tri->indexes[0]); - LL(tri->indexes[1]); - LL(tri->indexes[2]); - } - - // swap all the vertexes - // FIXME - // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left - // in for reference. - //v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12); - v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts); - for ( j = 0 ; j < surf->numVerts ; j++ ) { - v->normal[0] = LittleFloat( v->normal[0] ); - v->normal[1] = LittleFloat( v->normal[1] ); - v->normal[2] = LittleFloat( v->normal[2] ); - - v->texCoords[0] = LittleFloat( v->texCoords[0] ); - v->texCoords[1] = LittleFloat( v->texCoords[1] ); - - v->numWeights = LittleLong( v->numWeights ); - - for ( k = 0 ; k < v->numWeights ; k++ ) { - v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex ); - v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight ); - v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] ); - v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] ); - v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] ); - } - // FIXME - // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left - // in for reference. - //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 ); - v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]); - } - - // find the next surface - surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - - // find the next LOD - lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd ); - } - - return qtrue; -} - - - -//============================================================================= - -/* -** RE_BeginRegistration -*/ -void RE_BeginRegistration( glconfig_t *glconfigOut ) { - - R_Init(); - - *glconfigOut = glConfig; - - R_SyncRenderThread(); - - tr.visIndex = 0; - memset(tr.visClusters, -2, sizeof(tr.visClusters)); // force markleafs to regenerate - - R_ClearFlares(); - RE_ClearScene(); - - tr.registered = qtrue; - - // NOTE: this sucks, for some reason the first stretch pic is never drawn - // without this we'd see a white flash on a level load because the very - // first time the level shot would not be drawn -// RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0); -} - -//============================================================================= - -/* -=============== -R_ModelInit -=============== -*/ -void R_ModelInit( void ) { - model_t *mod; - - // leave a space for NULL model - tr.numModels = 0; - - mod = R_AllocModel(); - mod->type = MOD_BAD; -} - - -/* -================ -R_Modellist_f -================ -*/ -void R_Modellist_f( void ) { - int i, j; - model_t *mod; - int total; - int lods; - - total = 0; - for ( i = 1 ; i < tr.numModels; i++ ) { - mod = tr.models[i]; - lods = 1; - for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) { - if ( mod->mdv[j] && mod->mdv[j] != mod->mdv[j-1] ) { - lods++; - } - } - ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name ); - total += mod->dataSize; - } - ri.Printf( PRINT_ALL, "%8i : Total models\n", total ); - -#if 0 // not working right with new hunk - if ( tr.world ) { - ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name ); - } -#endif -} - - -//============================================================================= - - -/* -================ -R_GetTag -================ -*/ -static mdvTag_t *R_GetTag( mdvModel_t *mod, int frame, const char *_tagName ) { - int i; - mdvTag_t *tag; - mdvTagName_t *tagName; - - if ( frame >= mod->numFrames ) { - // it is possible to have a bad frame while changing models, so don't error - frame = mod->numFrames - 1; - } - - tag = mod->tags + frame * mod->numTags; - tagName = mod->tagNames; - for(i = 0; i < mod->numTags; i++, tag++, tagName++) - { - if(!strcmp(tagName->name, _tagName)) - { - return tag; - } - } - - return NULL; -} - -#ifdef RAVENMD4 -void R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, md3Tag_t * dest) -{ - int i, j, k; - int frameSize; - mdrFrame_t *frame; - mdrTag_t *tag; - - if ( framenum >= mod->numFrames ) - { - // it is possible to have a bad frame while changing models, so don't error - framenum = mod->numFrames - 1; - } - - tag = (mdrTag_t *)((byte *)mod + mod->ofsTags); - for ( i = 0 ; i < mod->numTags ; i++, tag++ ) - { - if ( !strcmp( tag->name, tagName ) ) - { - Q_strncpyz(dest->name, tag->name, sizeof(dest->name)); - - // uncompressed model... - // - frameSize = (intptr_t)( &((mdrFrame_t *)0)->bones[ mod->numBones ] ); - frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize ); - - for (j = 0; j < 3; j++) - { - for (k = 0; k < 3; k++) - dest->axis[j][k]=frame->bones[tag->boneIndex].matrix[k][j]; - } - - dest->origin[0]=frame->bones[tag->boneIndex].matrix[0][3]; - dest->origin[1]=frame->bones[tag->boneIndex].matrix[1][3]; - dest->origin[2]=frame->bones[tag->boneIndex].matrix[2][3]; - - return; - } - } - - AxisClear( dest->axis ); - VectorClear( dest->origin ); - strcpy(dest->name,""); -} -#endif - -/* -================ -R_LerpTag -================ -*/ -int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, - float frac, const char *tagName ) { - mdvTag_t *start, *end; -#ifdef RAVENMD4 - md3Tag_t start_space, end_space; -#endif - int i; - float frontLerp, backLerp; - model_t *model; - - model = R_GetModelByHandle( handle ); - if ( !model->mdv[0] ) - { -#ifdef RAVENMD4 - if(model->type == MOD_MDR) - { - start = &start_space; - end = &end_space; - R_GetAnimTag((mdrHeader_t *) model->modelData, startFrame, tagName, start); - R_GetAnimTag((mdrHeader_t *) model->modelData, endFrame, tagName, end); - } - else -#endif - if( model->type == MOD_IQM ) { - return R_IQMLerpTag( tag, model->modelData, - startFrame, endFrame, - frac, tagName ); - } else { - - AxisClear( tag->axis ); - VectorClear( tag->origin ); - return qfalse; - - } - } - else - { - start = R_GetTag( model->mdv[0], startFrame, tagName ); - end = R_GetTag( model->mdv[0], endFrame, tagName ); - if ( !start || !end ) { - AxisClear( tag->axis ); - VectorClear( tag->origin ); - return qfalse; - } - } - - frontLerp = frac; - backLerp = 1.0f - frac; - - for ( i = 0 ; i < 3 ; i++ ) { - tag->origin[i] = start->origin[i] * backLerp + end->origin[i] * frontLerp; - tag->axis[0][i] = start->axis[0][i] * backLerp + end->axis[0][i] * frontLerp; - tag->axis[1][i] = start->axis[1][i] * backLerp + end->axis[1][i] * frontLerp; - tag->axis[2][i] = start->axis[2][i] * backLerp + end->axis[2][i] * frontLerp; - } - VectorNormalize( tag->axis[0] ); - VectorNormalize( tag->axis[1] ); - VectorNormalize( tag->axis[2] ); - return qtrue; -} - - -/* -==================== -R_ModelBounds -==================== -*/ -void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) { - model_t *model; - - model = R_GetModelByHandle( handle ); - - if(model->type == MOD_BRUSH) { - VectorCopy( model->bmodel->bounds[0], mins ); - VectorCopy( model->bmodel->bounds[1], maxs ); - - return; - } else if (model->type == MOD_MESH) { - mdvModel_t *header; - mdvFrame_t *frame; - - header = model->mdv[0]; - frame = header->frames; - - VectorCopy( frame->bounds[0], mins ); - VectorCopy( frame->bounds[1], maxs ); - - return; - } else if (model->type == MOD_MD4) { - md4Header_t *header; - md4Frame_t *frame; - - header = (md4Header_t *)model->modelData; - frame = (md4Frame_t *) ((byte *)header + header->ofsFrames); - - VectorCopy( frame->bounds[0], mins ); - VectorCopy( frame->bounds[1], maxs ); - - return; -#ifdef RAVENMD4 - } else if (model->type == MOD_MDR) { - mdrHeader_t *header; - mdrFrame_t *frame; - - header = (mdrHeader_t *)model->modelData; - frame = (mdrFrame_t *) ((byte *)header + header->ofsFrames); - - VectorCopy( frame->bounds[0], mins ); - VectorCopy( frame->bounds[1], maxs ); - - return; -#endif - } else if(model->type == MOD_IQM) { - iqmData_t *iqmData; - - iqmData = model->modelData; - - if(iqmData->bounds) - { - VectorCopy(iqmData->bounds, mins); - VectorCopy(iqmData->bounds + 3, maxs); - return; - } - } - - VectorClear( mins ); - VectorClear( maxs ); -} diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c deleted file mode 100644 index 1f1bf747..00000000 --- a/code/renderergl2/tr_model_iqm.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2011 Thilo Schulz -Copyright (C) 2011 Matthias Bentrup - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "tr_local.h" - -#define LL(x) x=LittleLong(x) - -static qboolean IQM_CheckRange( iqmHeader_t *header, int offset, - int count,int size ) { - // return true if the range specified by offset, count and size - // doesn't fit into the file - return ( count <= 0 || - offset < 0 || - offset > header->filesize || - offset + count * size < 0 || - offset + count * size > header->filesize ); -} -// "multiply" 3x4 matrices, these are assumed to be the top 3 rows -// of a 4x4 matrix with the last row = (0 0 0 1) -static void Matrix34Multiply( float *a, float *b, float *out ) { - out[ 0] = a[0] * b[0] + a[1] * b[4] + a[ 2] * b[ 8]; - out[ 1] = a[0] * b[1] + a[1] * b[5] + a[ 2] * b[ 9]; - out[ 2] = a[0] * b[2] + a[1] * b[6] + a[ 2] * b[10]; - out[ 3] = a[0] * b[3] + a[1] * b[7] + a[ 2] * b[11] + a[ 3]; - out[ 4] = a[4] * b[0] + a[5] * b[4] + a[ 6] * b[ 8]; - out[ 5] = a[4] * b[1] + a[5] * b[5] + a[ 6] * b[ 9]; - out[ 6] = a[4] * b[2] + a[5] * b[6] + a[ 6] * b[10]; - out[ 7] = a[4] * b[3] + a[5] * b[7] + a[ 6] * b[11] + a[ 7]; - out[ 8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[ 8]; - out[ 9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[ 9]; - out[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10]; - out[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11]; -} -static void InterpolateMatrix( float *a, float *b, float lerp, float *mat ) { - float unLerp = 1.0f - lerp; - - mat[ 0] = a[ 0] * unLerp + b[ 0] * lerp; - mat[ 1] = a[ 1] * unLerp + b[ 1] * lerp; - mat[ 2] = a[ 2] * unLerp + b[ 2] * lerp; - mat[ 3] = a[ 3] * unLerp + b[ 3] * lerp; - mat[ 4] = a[ 4] * unLerp + b[ 4] * lerp; - mat[ 5] = a[ 5] * unLerp + b[ 5] * lerp; - mat[ 6] = a[ 6] * unLerp + b[ 6] * lerp; - mat[ 7] = a[ 7] * unLerp + b[ 7] * lerp; - mat[ 8] = a[ 8] * unLerp + b[ 8] * lerp; - mat[ 9] = a[ 9] * unLerp + b[ 9] * lerp; - mat[10] = a[10] * unLerp + b[10] * lerp; - mat[11] = a[11] * unLerp + b[11] * lerp; -} -static void JointToMatrix( vec4_t rot, vec3_t scale, vec3_t trans, - float *mat ) { - float xx = 2.0f * rot[0] * rot[0]; - float yy = 2.0f * rot[1] * rot[1]; - float zz = 2.0f * rot[2] * rot[2]; - float xy = 2.0f * rot[0] * rot[1]; - float xz = 2.0f * rot[0] * rot[2]; - float yz = 2.0f * rot[1] * rot[2]; - float wx = 2.0f * rot[3] * rot[0]; - float wy = 2.0f * rot[3] * rot[1]; - float wz = 2.0f * rot[3] * rot[2]; - - mat[ 0] = scale[0] * (1.0f - (yy + zz)); - mat[ 1] = scale[0] * (xy - wz); - mat[ 2] = scale[0] * (xz + wy); - mat[ 3] = trans[0]; - mat[ 4] = scale[1] * (xy + wz); - mat[ 5] = scale[1] * (1.0f - (xx + zz)); - mat[ 6] = scale[1] * (yz - wx); - mat[ 7] = trans[1]; - mat[ 8] = scale[2] * (xz - wy); - mat[ 9] = scale[2] * (yz + wx); - mat[10] = scale[2] * (1.0f - (xx + yy)); - mat[11] = trans[2]; -} -static void Matrix34Invert( float *inMat, float *outMat ) -{ - vec3_t trans; - float invSqrLen, *v; - - outMat[ 0] = inMat[ 0]; outMat[ 1] = inMat[ 4]; outMat[ 2] = inMat[ 8]; - outMat[ 4] = inMat[ 1]; outMat[ 5] = inMat[ 5]; outMat[ 6] = inMat[ 9]; - outMat[ 8] = inMat[ 2]; outMat[ 9] = inMat[ 6]; outMat[10] = inMat[10]; - - v = outMat + 0; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - v = outMat + 4; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - v = outMat + 8; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v); - - trans[0] = inMat[ 3]; - trans[1] = inMat[ 7]; - trans[2] = inMat[11]; - - outMat[ 3] = -DotProduct(outMat + 0, trans); - outMat[ 7] = -DotProduct(outMat + 4, trans); - outMat[11] = -DotProduct(outMat + 8, trans); -} - -/* -================= -R_LoadIQM - -Load an IQM model and compute the joint matrices for every frame. -================= -*/ -qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_name ) { - iqmHeader_t *header; - iqmVertexArray_t *vertexarray; - iqmTriangle_t *triangle; - iqmMesh_t *mesh; - iqmJoint_t *joint; - iqmPose_t *pose; - iqmBounds_t *bounds; - unsigned short *framedata; - char *str; - int i, j; - float jointMats[IQM_MAX_JOINTS * 2 * 12]; - float *mat; - size_t size, joint_names; - iqmData_t *iqmData; - srfIQModel_t *surface; - - if( filesize < sizeof(iqmHeader_t) ) { - return qfalse; - } - - header = (iqmHeader_t *)buffer; - if( Q_strncmp( header->magic, IQM_MAGIC, sizeof(header->magic) ) ) { - return qfalse; - } - - LL( header->version ); - if( header->version != IQM_VERSION ) { - ri.Printf(PRINT_WARNING, "R_LoadIQM: %s is a unsupported IQM version (%d), only version %d is supported.\n", - mod_name, header->version, IQM_VERSION); - return qfalse; - } - - LL( header->filesize ); - if( header->filesize > filesize || header->filesize > 16<<20 ) { - return qfalse; - } - - LL( header->flags ); - LL( header->num_text ); - LL( header->ofs_text ); - LL( header->num_meshes ); - LL( header->ofs_meshes ); - LL( header->num_vertexarrays ); - LL( header->num_vertexes ); - LL( header->ofs_vertexarrays ); - LL( header->num_triangles ); - LL( header->ofs_triangles ); - LL( header->ofs_adjacency ); - LL( header->num_joints ); - LL( header->ofs_joints ); - LL( header->num_poses ); - LL( header->ofs_poses ); - LL( header->num_anims ); - LL( header->ofs_anims ); - LL( header->num_frames ); - LL( header->num_framechannels ); - LL( header->ofs_frames ); - LL( header->ofs_bounds ); - LL( header->num_comment ); - LL( header->ofs_comment ); - LL( header->num_extensions ); - LL( header->ofs_extensions ); - - // check ioq3 joint limit - if ( header->num_joints > IQM_MAX_JOINTS ) { - ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %d joints (%d).\n", - mod_name, IQM_MAX_JOINTS, header->num_joints); - return qfalse; - } - - // check and swap vertex arrays - if( IQM_CheckRange( header, header->ofs_vertexarrays, - header->num_vertexarrays, - sizeof(iqmVertexArray_t) ) ) { - return qfalse; - } - vertexarray = (iqmVertexArray_t *)((byte *)header + header->ofs_vertexarrays); - for( i = 0; i < header->num_vertexarrays; i++, vertexarray++ ) { - int j, n, *intPtr; - - if( vertexarray->size <= 0 || vertexarray->size > 4 ) { - return qfalse; - } - - // total number of values - n = header->num_vertexes * vertexarray->size; - - switch( vertexarray->format ) { - case IQM_BYTE: - case IQM_UBYTE: - // 1 byte, no swapping necessary - if( IQM_CheckRange( header, vertexarray->offset, - n, sizeof(byte) ) ) { - return qfalse; - } - break; - case IQM_INT: - case IQM_UINT: - case IQM_FLOAT: - // 4-byte swap - if( IQM_CheckRange( header, vertexarray->offset, - n, sizeof(float) ) ) { - return qfalse; - } - intPtr = (int *)((byte *)header + vertexarray->offset); - for( j = 0; j < n; j++, intPtr++ ) { - LL( *intPtr ); - } - break; - default: - // not supported - return qfalse; - break; - } - - switch( vertexarray->type ) { - case IQM_POSITION: - case IQM_NORMAL: - if( vertexarray->format != IQM_FLOAT || - vertexarray->size != 3 ) { - return qfalse; - } - break; - case IQM_TANGENT: - if( vertexarray->format != IQM_FLOAT || - vertexarray->size != 4 ) { - return qfalse; - } - break; - case IQM_TEXCOORD: - if( vertexarray->format != IQM_FLOAT || - vertexarray->size != 2 ) { - return qfalse; - } - break; - case IQM_BLENDINDEXES: - case IQM_BLENDWEIGHTS: - if( vertexarray->format != IQM_UBYTE || - vertexarray->size != 4 ) { - return qfalse; - } - break; - case IQM_COLOR: - if( vertexarray->format != IQM_UBYTE || - vertexarray->size != 4 ) { - return qfalse; - } - break; - } - } - - // check and swap triangles - if( IQM_CheckRange( header, header->ofs_triangles, - header->num_triangles, sizeof(iqmTriangle_t) ) ) { - return qfalse; - } - triangle = (iqmTriangle_t *)((byte *)header + header->ofs_triangles); - for( i = 0; i < header->num_triangles; i++, triangle++ ) { - LL( triangle->vertex[0] ); - LL( triangle->vertex[1] ); - LL( triangle->vertex[2] ); - - if( triangle->vertex[0] > header->num_vertexes || - triangle->vertex[1] > header->num_vertexes || - triangle->vertex[2] > header->num_vertexes ) { - return qfalse; - } - } - - // check and swap meshes - if( IQM_CheckRange( header, header->ofs_meshes, - header->num_meshes, sizeof(iqmMesh_t) ) ) { - return qfalse; - } - mesh = (iqmMesh_t *)((byte *)header + header->ofs_meshes); - for( i = 0; i < header->num_meshes; i++, mesh++) { - LL( mesh->name ); - LL( mesh->material ); - LL( mesh->first_vertex ); - LL( mesh->num_vertexes ); - LL( mesh->first_triangle ); - LL( mesh->num_triangles ); - - // check ioq3 limits - if ( mesh->num_vertexes > SHADER_MAX_VERTEXES ) - { - ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %i verts on a surface (%i).\n", - mod_name, SHADER_MAX_VERTEXES, mesh->num_vertexes ); - return qfalse; - } - if ( mesh->num_triangles*3 > SHADER_MAX_INDEXES ) - { - ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %i triangles on a surface (%i).\n", - mod_name, SHADER_MAX_INDEXES / 3, mesh->num_triangles ); - return qfalse; - } - - if( mesh->first_vertex >= header->num_vertexes || - mesh->first_vertex + mesh->num_vertexes > header->num_vertexes || - mesh->first_triangle >= header->num_triangles || - mesh->first_triangle + mesh->num_triangles > header->num_triangles || - mesh->name >= header->num_text || - mesh->material >= header->num_text ) { - return qfalse; - } - } - - // check and swap joints - if( IQM_CheckRange( header, header->ofs_joints, - header->num_joints, sizeof(iqmJoint_t) ) ) { - return qfalse; - } - joint = (iqmJoint_t *)((byte *)header + header->ofs_joints); - joint_names = 0; - for( i = 0; i < header->num_joints; i++, joint++ ) { - LL( joint->name ); - LL( joint->parent ); - LL( joint->translate[0] ); - LL( joint->translate[1] ); - LL( joint->translate[2] ); - LL( joint->rotate[0] ); - LL( joint->rotate[1] ); - LL( joint->rotate[2] ); - LL( joint->rotate[3] ); - LL( joint->scale[0] ); - LL( joint->scale[1] ); - LL( joint->scale[2] ); - - if( joint->parent < -1 || - joint->parent >= (int)header->num_joints || - joint->name >= (int)header->num_text ) { - return qfalse; - } - joint_names += strlen( (char *)header + header->ofs_text + - joint->name ) + 1; - } - - // check and swap poses - if( header->num_poses != header->num_joints ) { - return qfalse; - } - if( IQM_CheckRange( header, header->ofs_poses, - header->num_poses, sizeof(iqmPose_t) ) ) { - return qfalse; - } - pose = (iqmPose_t *)((byte *)header + header->ofs_poses); - for( i = 0; i < header->num_poses; i++, pose++ ) { - LL( pose->parent ); - LL( pose->mask ); - LL( pose->channeloffset[0] ); - LL( pose->channeloffset[1] ); - LL( pose->channeloffset[2] ); - LL( pose->channeloffset[3] ); - LL( pose->channeloffset[4] ); - LL( pose->channeloffset[5] ); - LL( pose->channeloffset[6] ); - LL( pose->channeloffset[7] ); - LL( pose->channeloffset[8] ); - LL( pose->channeloffset[9] ); - LL( pose->channelscale[0] ); - LL( pose->channelscale[1] ); - LL( pose->channelscale[2] ); - LL( pose->channelscale[3] ); - LL( pose->channelscale[4] ); - LL( pose->channelscale[5] ); - LL( pose->channelscale[6] ); - LL( pose->channelscale[7] ); - LL( pose->channelscale[8] ); - LL( pose->channelscale[9] ); - } - - if (header->ofs_bounds) - { - // check and swap model bounds - if(IQM_CheckRange(header, header->ofs_bounds, - header->num_frames, sizeof(*bounds))) - { - return qfalse; - } - bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds); - for(i = 0; i < header->num_frames; i++) - { - LL(bounds->bbmin[0]); - LL(bounds->bbmin[1]); - LL(bounds->bbmin[2]); - LL(bounds->bbmax[0]); - LL(bounds->bbmax[1]); - LL(bounds->bbmax[2]); - - bounds++; - } - } - - // allocate the model and copy the data - size = sizeof(iqmData_t); - size += header->num_meshes * sizeof( srfIQModel_t ); - size += header->num_joints * header->num_frames * 12 * sizeof( float ); - if(header->ofs_bounds) - size += header->num_frames * 6 * sizeof(float); // model bounds - size += header->num_vertexes * 3 * sizeof(float); // positions - size += header->num_vertexes * 2 * sizeof(float); // texcoords - size += header->num_vertexes * 3 * sizeof(float); // normals - size += header->num_vertexes * 4 * sizeof(float); // tangents - size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes - size += header->num_vertexes * 4 * sizeof(byte); // blendWeights - size += header->num_vertexes * 4 * sizeof(byte); // colors - size += header->num_joints * sizeof(int); // parents - size += header->num_triangles * 3 * sizeof(int); // triangles - size += joint_names; // joint names - - mod->type = MOD_IQM; - iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); - mod->modelData = iqmData; - - // fill header - iqmData->num_vertexes = header->num_vertexes; - iqmData->num_triangles = header->num_triangles; - iqmData->num_frames = header->num_frames; - iqmData->num_surfaces = header->num_meshes; - iqmData->num_joints = header->num_joints; - iqmData->surfaces = (srfIQModel_t *)(iqmData + 1); - iqmData->poseMats = (float *) (iqmData->surfaces + iqmData->num_surfaces); - if(header->ofs_bounds) - { - iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames; - iqmData->positions = iqmData->bounds + 6 * header->num_frames; - } - else - iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames; - iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes; - iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes; - iqmData->tangents = iqmData->normals + 3 * header->num_vertexes; - iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes); - iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes; - iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes; - iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes); - iqmData->triangles = iqmData->jointParents + header->num_joints; - iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles); - - // calculate joint matrices and their inverses - // they are needed only until the pose matrices are calculated - mat = jointMats; - joint = (iqmJoint_t *)((byte *)header + header->ofs_joints); - for( i = 0; i < header->num_joints; i++, joint++ ) { - float baseFrame[12], invBaseFrame[12]; - - JointToMatrix( joint->rotate, joint->scale, joint->translate, baseFrame ); - Matrix34Invert( baseFrame, invBaseFrame ); - - if ( joint->parent >= 0 ) - { - Matrix34Multiply( jointMats + 2 * 12 * joint->parent, baseFrame, mat ); - mat += 12; - Matrix34Multiply( invBaseFrame, jointMats + 2 * 12 * joint->parent + 12, mat ); - mat += 12; - } - else - { - Com_Memcpy( mat, baseFrame, sizeof(baseFrame) ); - mat += 12; - Com_Memcpy( mat, invBaseFrame, sizeof(invBaseFrame) ); - mat += 12; - } - } - - // calculate pose matrices - framedata = (unsigned short *)((byte *)header + header->ofs_frames); - mat = iqmData->poseMats; - for( i = 0; i < header->num_frames; i++ ) { - pose = (iqmPose_t *)((byte *)header + header->ofs_poses); - for( j = 0; j < header->num_poses; j++, pose++ ) { - vec3_t translate; - vec4_t rotate; - vec3_t scale; - float mat1[12], mat2[12]; - - translate[0] = pose->channeloffset[0]; - if( pose->mask & 0x001) - translate[0] += *framedata++ * pose->channelscale[0]; - translate[1] = pose->channeloffset[1]; - if( pose->mask & 0x002) - translate[1] += *framedata++ * pose->channelscale[1]; - translate[2] = pose->channeloffset[2]; - if( pose->mask & 0x004) - translate[2] += *framedata++ * pose->channelscale[2]; - - rotate[0] = pose->channeloffset[3]; - if( pose->mask & 0x008) - rotate[0] += *framedata++ * pose->channelscale[3]; - rotate[1] = pose->channeloffset[4]; - if( pose->mask & 0x010) - rotate[1] += *framedata++ * pose->channelscale[4]; - rotate[2] = pose->channeloffset[5]; - if( pose->mask & 0x020) - rotate[2] += *framedata++ * pose->channelscale[5]; - rotate[3] = pose->channeloffset[6]; - if( pose->mask & 0x040) - rotate[3] += *framedata++ * pose->channelscale[6]; - - scale[0] = pose->channeloffset[7]; - if( pose->mask & 0x080) - scale[0] += *framedata++ * pose->channelscale[7]; - scale[1] = pose->channeloffset[8]; - if( pose->mask & 0x100) - scale[1] += *framedata++ * pose->channelscale[8]; - scale[2] = pose->channeloffset[9]; - if( pose->mask & 0x200) - scale[2] += *framedata++ * pose->channelscale[9]; - - // construct transformation matrix - JointToMatrix( rotate, scale, translate, mat1 ); - - if( pose->parent >= 0 ) { - Matrix34Multiply( jointMats + 12 * 2 * pose->parent, - mat1, mat2 ); - } else { - Com_Memcpy( mat2, mat1, sizeof(mat1) ); - } - - Matrix34Multiply( mat2, jointMats + 12 * (2 * j + 1), mat ); - mat += 12; - } - } - - // register shaders - // overwrite the material offset with the shader index - mesh = (iqmMesh_t *)((byte *)header + header->ofs_meshes); - surface = iqmData->surfaces; - str = (char *)header + header->ofs_text; - for( i = 0; i < header->num_meshes; i++, mesh++, surface++ ) { - surface->surfaceType = SF_IQM; - Q_strncpyz(surface->name, str + mesh->name, sizeof (surface->name)); - Q_strlwr(surface->name); // lowercase the surface name so skin compares are faster - surface->shader = R_FindShader( str + mesh->material, LIGHTMAP_NONE, qtrue ); - if( surface->shader->defaultShader ) - surface->shader = tr.defaultShader; - surface->data = iqmData; - surface->first_vertex = mesh->first_vertex; - surface->num_vertexes = mesh->num_vertexes; - surface->first_triangle = mesh->first_triangle; - surface->num_triangles = mesh->num_triangles; - } - - // copy vertexarrays and indexes - vertexarray = (iqmVertexArray_t *)((byte *)header + header->ofs_vertexarrays); - for( i = 0; i < header->num_vertexarrays; i++, vertexarray++ ) { - int n; - - // total number of values - n = header->num_vertexes * vertexarray->size; - - switch( vertexarray->type ) { - case IQM_POSITION: - Com_Memcpy( iqmData->positions, - (byte *)header + vertexarray->offset, - n * sizeof(float) ); - break; - case IQM_NORMAL: - Com_Memcpy( iqmData->normals, - (byte *)header + vertexarray->offset, - n * sizeof(float) ); - break; - case IQM_TANGENT: - Com_Memcpy( iqmData->tangents, - (byte *)header + vertexarray->offset, - n * sizeof(float) ); - break; - case IQM_TEXCOORD: - Com_Memcpy( iqmData->texcoords, - (byte *)header + vertexarray->offset, - n * sizeof(float) ); - break; - case IQM_BLENDINDEXES: - Com_Memcpy( iqmData->blendIndexes, - (byte *)header + vertexarray->offset, - n * sizeof(byte) ); - break; - case IQM_BLENDWEIGHTS: - Com_Memcpy( iqmData->blendWeights, - (byte *)header + vertexarray->offset, - n * sizeof(byte) ); - break; - case IQM_COLOR: - Com_Memcpy( iqmData->colors, - (byte *)header + vertexarray->offset, - n * sizeof(byte) ); - break; - } - } - - // copy joint parents - joint = (iqmJoint_t *)((byte *)header + header->ofs_joints); - for( i = 0; i < header->num_joints; i++, joint++ ) { - iqmData->jointParents[i] = joint->parent; - } - - // copy triangles - triangle = (iqmTriangle_t *)((byte *)header + header->ofs_triangles); - for( i = 0; i < header->num_triangles; i++, triangle++ ) { - iqmData->triangles[3*i+0] = triangle->vertex[0]; - iqmData->triangles[3*i+1] = triangle->vertex[1]; - iqmData->triangles[3*i+2] = triangle->vertex[2]; - } - - // copy joint names - str = iqmData->names; - joint = (iqmJoint_t *)((byte *)header + header->ofs_joints); - for( i = 0; i < header->num_joints; i++, joint++ ) { - char *name = (char *)header + header->ofs_text + - joint->name; - int len = strlen( name ) + 1; - Com_Memcpy( str, name, len ); - str += len; - } - - // copy model bounds - if(header->ofs_bounds) - { - mat = iqmData->bounds; - bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds); - for(i = 0; i < header->num_frames; i++) - { - mat[0] = bounds->bbmin[0]; - mat[1] = bounds->bbmin[1]; - mat[2] = bounds->bbmin[2]; - mat[3] = bounds->bbmax[0]; - mat[4] = bounds->bbmax[1]; - mat[5] = bounds->bbmax[2]; - - mat += 6; - bounds++; - } - } - - return qtrue; -} - -/* -============= -R_CullIQM -============= -*/ -static int R_CullIQM( iqmData_t *data, trRefEntity_t *ent ) { - vec3_t bounds[2]; - vec_t *oldBounds, *newBounds; - int i; - - if (!data->bounds) { - tr.pc.c_box_cull_md3_clip++; - return CULL_CLIP; - } - - // compute bounds pointers - oldBounds = data->bounds + 6*ent->e.oldframe; - newBounds = data->bounds + 6*ent->e.frame; - - // calculate a bounding box in the current coordinate system - for (i = 0 ; i < 3 ; i++) { - bounds[0][i] = oldBounds[i] < newBounds[i] ? oldBounds[i] : newBounds[i]; - bounds[1][i] = oldBounds[i+3] > newBounds[i+3] ? oldBounds[i+3] : newBounds[i+3]; - } - - 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; - } -} - -/* -================= -R_ComputeIQMFogNum - -================= -*/ -int R_ComputeIQMFogNum( iqmData_t *data, trRefEntity_t *ent ) { - int i, j; - fog_t *fog; - const vec_t *bounds; - const vec_t defaultBounds[6] = { -8, -8, -8, 8, 8, 8 }; - vec3_t diag, center; - vec3_t localOrigin; - vec_t radius; - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { - return 0; - } - - // FIXME: non-normalized axis issues - if (data->bounds) { - bounds = data->bounds + 6*ent->e.frame; - } else { - bounds = defaultBounds; - } - VectorSubtract( bounds+3, bounds, diag ); - VectorMA( bounds, 0.5f, diag, center ); - VectorAdd( ent->e.origin, center, localOrigin ); - radius = 0.5f * VectorLength( diag ); - - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { - fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( localOrigin[j] - radius >= fog->bounds[1][j] ) { - break; - } - if ( localOrigin[j] + radius <= fog->bounds[0][j] ) { - break; - } - } - if ( j == 3 ) { - return i; - } - } - - return 0; -} - -/* -================= -R_AddIQMSurfaces - -Add all surfaces of this model -================= -*/ -void R_AddIQMSurfaces( trRefEntity_t *ent ) { - iqmData_t *data; - srfIQModel_t *surface; - int i, j; - qboolean personalModel; - int cull; - int fogNum; - shader_t *shader; - skin_t *skin; - - data = tr.currentModel->modelData; - surface = data->surfaces; - - // don't add third_person objects if not in a portal - personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal; - - if ( ent->e.renderfx & RF_WRAP_FRAMES ) { - ent->e.frame %= data->num_frames; - ent->e.oldframe %= data->num_frames; - } - - // - // 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 >= data->num_frames) - || (ent->e.frame < 0) - || (ent->e.oldframe >= data->num_frames) - || (ent->e.oldframe < 0) ) { - ri.Printf( PRINT_DEVELOPER, "R_AddIQMSurfaces: 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; - } - - // - // cull the entire model if merged bounding box of both frames - // is outside the view frustum. - // - cull = R_CullIQM ( data, 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_ComputeIQMFogNum( data, ent ); - - for ( i = 0 ; i < data->num_surfaces ; i++ ) { - if(ent->e.customShader) - shader = R_GetShaderByHandle( ent->e.customShader ); - else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins) - { - skin = R_GetSkinByHandle(ent->e.customSkin); - shader = tr.defaultShader; - - for(j = 0; j < skin->numSurfaces; j++) - { - if (!strcmp(skin->surfaces[j]->name, surface->name)) - { - shader = skin->surfaces[j]->shader; - break; - } - } - } else { - shader = surface->shader; - } - - // 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_NOSHADOW | RF_DEPTHHACK ) ) - && shader->sort == SS_OPAQUE ) { - R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, 0, 0 ); - } - - // 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( (void *)surface, tr.projectionShadowShader, 0, 0, 0 ); - } - - if( !personalModel ) { - R_AddDrawSurf( (void *)surface, shader, fogNum, 0, 0 ); - } - - surface++; - } -} - - -static void ComputeJointMats( iqmData_t *data, int frame, int oldframe, - float backlerp, float *mat ) { - float *mat1, *mat2; - int *joint = data->jointParents; - int i; - - if ( oldframe == frame ) { - mat1 = data->poseMats + 12 * data->num_joints * frame; - for( i = 0; i < data->num_joints; i++, joint++ ) { - if( *joint >= 0 ) { - Matrix34Multiply( mat + 12 * *joint, - mat1 + 12*i, mat + 12*i ); - } else { - Com_Memcpy( mat + 12*i, mat1 + 12*i, 12 * sizeof(float) ); - } - } - } else { - mat1 = data->poseMats + 12 * data->num_joints * frame; - mat2 = data->poseMats + 12 * data->num_joints * oldframe; - - for( i = 0; i < data->num_joints; i++, joint++ ) { - if( *joint >= 0 ) { - float tmpMat[12]; - InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, - backlerp, tmpMat ); - Matrix34Multiply( mat + 12 * *joint, - tmpMat, mat + 12*i ); - - } else { - InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, - backlerp, mat ); - } - } - } -} - - -/* -================= -RB_AddIQMSurfaces - -Compute vertices for this model surface -================= -*/ -void RB_IQMSurfaceAnim( surfaceType_t *surface ) { - srfIQModel_t *surf = (srfIQModel_t *)surface; - iqmData_t *data = surf->data; - float jointMats[IQM_MAX_JOINTS * 12]; - int i; - - vec4_t *outXYZ = &tess.xyz[tess.numVertexes]; - vec4_t *outNormal = &tess.normal[tess.numVertexes]; - vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes]; - vec4_t *outColor = &tess.vertexColors[tess.numVertexes]; - - int frame = backEnd.currentEntity->e.frame % data->num_frames; - int oldframe = backEnd.currentEntity->e.oldframe % data->num_frames; - float backlerp = backEnd.currentEntity->e.backlerp; - - int *tri; - glIndex_t *ptr; - glIndex_t base; - - RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 ); - - // compute interpolated joint matrices - ComputeJointMats( data, frame, oldframe, backlerp, jointMats ); - - // transform vertexes and fill other data - for( i = 0; i < surf->num_vertexes; - i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) { - int j, k; - float vtxMat[12]; - float nrmMat[9]; - int vtx = i + surf->first_vertex; - - // compute the vertex matrix by blending the up to - // four blend weights - for( k = 0; k < 12; k++ ) - vtxMat[k] = data->blendWeights[4*vtx] - * jointMats[12*data->blendIndexes[4*vtx] + k]; - for( j = 1; j < 4; j++ ) { - if( data->blendWeights[4*vtx + j] <= 0 ) - break; - for( k = 0; k < 12; k++ ) - vtxMat[k] += data->blendWeights[4*vtx + j] - * jointMats[12*data->blendIndexes[4*vtx + j] + k]; - } - for( k = 0; k < 12; k++ ) - vtxMat[k] *= 1.0f / 255.0f; - - // compute the normal matrix as transpose of the adjoint - // of the vertex matrix - nrmMat[ 0] = vtxMat[ 5]*vtxMat[10] - vtxMat[ 6]*vtxMat[ 9]; - nrmMat[ 1] = vtxMat[ 6]*vtxMat[ 8] - vtxMat[ 4]*vtxMat[10]; - nrmMat[ 2] = vtxMat[ 4]*vtxMat[ 9] - vtxMat[ 5]*vtxMat[ 8]; - nrmMat[ 3] = vtxMat[ 2]*vtxMat[ 9] - vtxMat[ 1]*vtxMat[10]; - nrmMat[ 4] = vtxMat[ 0]*vtxMat[10] - vtxMat[ 2]*vtxMat[ 8]; - nrmMat[ 5] = vtxMat[ 1]*vtxMat[ 8] - vtxMat[ 0]*vtxMat[ 9]; - nrmMat[ 6] = vtxMat[ 1]*vtxMat[ 6] - vtxMat[ 2]*vtxMat[ 5]; - nrmMat[ 7] = vtxMat[ 2]*vtxMat[ 4] - vtxMat[ 0]*vtxMat[ 6]; - nrmMat[ 8] = vtxMat[ 0]*vtxMat[ 5] - vtxMat[ 1]*vtxMat[ 4]; - - (*outTexCoord)[0][0] = data->texcoords[2*vtx + 0]; - (*outTexCoord)[0][1] = data->texcoords[2*vtx + 1]; - (*outTexCoord)[1][0] = (*outTexCoord)[0][0]; - (*outTexCoord)[1][1] = (*outTexCoord)[0][1]; - - (*outXYZ)[0] = - vtxMat[ 0] * data->positions[3*vtx+0] + - vtxMat[ 1] * data->positions[3*vtx+1] + - vtxMat[ 2] * data->positions[3*vtx+2] + - vtxMat[ 3]; - (*outXYZ)[1] = - vtxMat[ 4] * data->positions[3*vtx+0] + - vtxMat[ 5] * data->positions[3*vtx+1] + - vtxMat[ 6] * data->positions[3*vtx+2] + - vtxMat[ 7]; - (*outXYZ)[2] = - vtxMat[ 8] * data->positions[3*vtx+0] + - vtxMat[ 9] * data->positions[3*vtx+1] + - vtxMat[10] * data->positions[3*vtx+2] + - vtxMat[11]; - (*outXYZ)[3] = 1.0f; - - (*outNormal)[0] = - nrmMat[ 0] * data->normals[3*vtx+0] + - nrmMat[ 1] * data->normals[3*vtx+1] + - nrmMat[ 2] * data->normals[3*vtx+2]; - (*outNormal)[1] = - nrmMat[ 3] * data->normals[3*vtx+0] + - nrmMat[ 4] * data->normals[3*vtx+1] + - nrmMat[ 5] * data->normals[3*vtx+2]; - (*outNormal)[2] = - nrmMat[ 6] * data->normals[3*vtx+0] + - nrmMat[ 7] * data->normals[3*vtx+1] + - nrmMat[ 8] * data->normals[3*vtx+2]; - (*outNormal)[3] = 0.0f; - - (*outColor)[0] = data->colors[4*vtx+0] / 255.0f; - (*outColor)[1] = data->colors[4*vtx+1] / 255.0f; - (*outColor)[2] = data->colors[4*vtx+2] / 255.0f; - (*outColor)[3] = data->colors[4*vtx+3] / 255.0f; - } - - tri = data->triangles + 3 * surf->first_triangle; - ptr = &tess.indexes[tess.numIndexes]; - base = tess.numVertexes; - - for( i = 0; i < surf->num_triangles; i++ ) { - *ptr++ = base + (*tri++ - surf->first_vertex); - *ptr++ = base + (*tri++ - surf->first_vertex); - *ptr++ = base + (*tri++ - surf->first_vertex); - } - - tess.numIndexes += 3 * surf->num_triangles; - tess.numVertexes += surf->num_vertexes; -} - -int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, - int startFrame, int endFrame, - float frac, const char *tagName ) { - float jointMats[IQM_MAX_JOINTS * 12]; - int joint; - char *names = data->names; - - // get joint number by reading the joint names - for( joint = 0; joint < data->num_joints; joint++ ) { - if( !strcmp( tagName, names ) ) - break; - names += strlen( names ) + 1; - } - if( joint >= data->num_joints ) { - AxisClear( tag->axis ); - VectorClear( tag->origin ); - return qfalse; - } - - ComputeJointMats( data, startFrame, endFrame, frac, jointMats ); - - tag->axis[0][0] = jointMats[12 * joint + 0]; - tag->axis[1][0] = jointMats[12 * joint + 1]; - tag->axis[2][0] = jointMats[12 * joint + 2]; - tag->origin[0] = jointMats[12 * joint + 3]; - tag->axis[0][1] = jointMats[12 * joint + 4]; - tag->axis[1][1] = jointMats[12 * joint + 5]; - tag->axis[2][1] = jointMats[12 * joint + 6]; - tag->origin[1] = jointMats[12 * joint + 7]; - tag->axis[0][2] = jointMats[12 * joint + 8]; - tag->axis[1][2] = jointMats[12 * joint + 9]; - tag->axis[2][2] = jointMats[12 * joint + 10]; - tag->origin[2] = jointMats[12 * joint + 11]; - - return qtrue; -} diff --git a/code/renderergl2/tr_postprocess.c b/code/renderergl2/tr_postprocess.c deleted file mode 100644 index 0cb162b3..00000000 --- a/code/renderergl2/tr_postprocess.c +++ /dev/null @@ -1,490 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2011 Andrei Drexler, Richard Allen, James Canete - -This file is part of Reaction source code. - -Reaction source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Reaction source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Reaction source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "tr_local.h" - -void RB_ToneMap(FBO_t *hdrFbo, int autoExposure) -{ - vec4i_t srcBox, dstBox; - vec4_t color; - static int lastFrameCount = 0; - - if (autoExposure) - { - if (lastFrameCount == 0 || tr.frameCount < lastFrameCount || tr.frameCount - lastFrameCount > 5) - { - // determine average log luminance - FBO_t *srcFbo, *dstFbo, *tmp; - int size = 256; - - lastFrameCount = tr.frameCount; - - VectorSet4(dstBox, 0, 0, size, size); - - srcFbo = hdrFbo; - dstFbo = tr.textureScratchFbo[0]; - FBO_Blit(srcFbo, NULL, NULL, dstFbo, dstBox, &tr.calclevels4xShader[0], NULL, 0); - - srcFbo = tr.textureScratchFbo[0]; - dstFbo = tr.textureScratchFbo[1]; - - // downscale to 1x1 texture - while (size > 1) - { - VectorSet4(srcBox, 0, 0, size, size); - //size >>= 2; - size >>= 1; - VectorSet4(dstBox, 0, 0, size, size); - - if (size == 1) - dstFbo = tr.targetLevelsFbo; - - //FBO_Blit(targetFbo, srcBox, NULL, tr.textureScratchFbo[nextScratch], dstBox, &tr.calclevels4xShader[1], NULL, 0); - FBO_FastBlit(srcFbo, srcBox, dstFbo, dstBox, GL_COLOR_BUFFER_BIT, GL_LINEAR); - - tmp = srcFbo; - srcFbo = dstFbo; - dstFbo = tmp; - } - } - - // blend with old log luminance for gradual change - VectorSet4(srcBox, 0, 0, 0, 0); - - color[0] = - color[1] = - color[2] = 1.0f; - if (glRefConfig.textureFloat) - color[3] = 0.03f; - else - color[3] = 0.1f; - - FBO_Blit(tr.targetLevelsFbo, srcBox, NULL, tr.calcLevelsFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); - } - - // tonemap - color[0] = - color[1] = - color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value); - color[3] = 1.0f; - - if (autoExposure) - GL_BindToTMU(tr.calcLevelsImage, TB_LEVELSMAP); - else - GL_BindToTMU(tr.fixedLevelsImage, TB_LEVELSMAP); - - FBO_Blit(hdrFbo, NULL, NULL, tr.screenScratchFbo, NULL, &tr.tonemapShader, color, 0); -} - - -void RB_BokehBlur(float blur) -{ -// vec4i_t srcBox, dstBox; - vec4_t color; - - blur *= 10.0f; - - if (blur < 0.004f) - return; - - if (glRefConfig.framebufferObject) - { - // bokeh blur - if (blur > 0.0f) - { - // create a quarter texture - FBO_Blit(tr.screenScratchFbo, NULL, NULL, tr.quarterFbo[0], NULL, NULL, NULL, 0); - } - -#ifndef HQ_BLUR - if (blur > 1.0f) - { - // create a 1/16th texture - FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, NULL, 0); - } -#endif - - if (blur > 0.0f && blur <= 1.0f) - { - // Crossfade original with quarter texture - VectorSet4(color, 1, 1, 1, blur); - - FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); - } -#ifndef HQ_BLUR - // ok blur, but can see some pixelization - else if (blur > 1.0f && blur <= 2.0f) - { - // crossfade quarter texture with 1/16th texture - FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, NULL, 0); - - VectorSet4(color, 1, 1, 1, blur - 1.0f); - - FBO_Blit(tr.textureScratchFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); - } - else if (blur > 2.0f) - { - // blur 1/16th texture then replace - int i; - - for (i = 0; i < 2; i++) - { - vec2_t blurTexScale; - float subblur; - - subblur = ((blur - 2.0f) / 2.0f) / 3.0f * (float)(i + 1); - - blurTexScale[0] = - blurTexScale[1] = subblur; - - color[0] = - color[1] = - color[2] = 0.5f; - color[3] = 1.0f; - - if (i != 0) - FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); - else - FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0); - } - - FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, tr.screenScratchFbo, NULL, &tr.textureColorShader, NULL, 0); - } -#else // higher quality blur, but slower - else if (blur > 1.0f) - { - // blur quarter texture then replace - int i; - - src = tr.quarterFbo[0]; - dst = tr.quarterFbo[1]; - - VectorSet4(color, 0.5f, 0.5f, 0.5f, 1); - - for (i = 0; i < 2; i++) - { - vec2_t blurTexScale; - float subblur; - - subblur = (blur - 1.0f) / 2.0f * (float)(i + 1); - - blurTexScale[0] = - blurTexScale[1] = subblur; - - color[0] = - color[1] = - color[2] = 1.0f; - if (i != 0) - color[3] = 1.0f; - else - color[3] = 0.5f; - - FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); - } - - FBO_Blit(tr.quarterFbo[1], NULL, NULL, tr.screenScratchFbo, NULL, &tr.textureColorShader, NULL, 0); - } -#endif - } -} - - -#ifdef REACTION -static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha) -{ - vec4i_t srcBox, dstBox; - vec4_t color; - const float inc = 1.f / passes; - const float mul = powf(stretch, inc); - float scale; - - { - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; - - alpha *= inc; - VectorSet4(color, alpha, alpha, alpha, 1.0f); - - VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); - VectorSet4(dstBox, x, y, w, h); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0); - - --passes; - scale = mul; - while (passes > 0) - { - float iscale = 1.f / scale; - float s0 = xcenter * (1.f - iscale); - float t0 = (1.0f - ycenter) * (1.f - iscale); - float s1 = iscale + s0; - float t1 = iscale + t0; - - srcBox[0] = s0 * srcFbo->width; - srcBox[1] = t0 * srcFbo->height; - srcBox[2] = (s1 - s0) * srcFbo->width; - srcBox[3] = (t1 - t0) * srcFbo->height; - - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - scale *= mul; - --passes; - } - } -} - - -static qboolean RB_UpdateSunFlareVis(void) -{ - GLuint sampleCount = 0; - if (!glRefConfig.occlusionQuery) - return qtrue; - - tr.sunFlareQueryIndex ^= 1; - if (!tr.sunFlareQueryActive[tr.sunFlareQueryIndex]) - return qtrue; - - /* debug code */ - if (0) - { - int iter; - for (iter=0 ; ; ++iter) - { - GLint available = 0; - qglGetQueryObjectivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - if (available) - break; - } - - ri.Printf(PRINT_DEVELOPER, "Waited %d iterations\n", iter); - } - - qglGetQueryObjectuivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_ARB, &sampleCount); - return sampleCount > 0; -} - -void RB_GodRays(void) -{ - vec4i_t srcBox, dstBox; - vec4_t color; - vec3_t dir; - float dot; - const float cutoff = 0.25f; - qboolean colorize = qtrue; - -// float w, h, w2, h2; - matrix_t mvp; - vec4_t pos, hpos; - - if (!backEnd.viewHasSunFlare) - return; - - VectorSubtract(backEnd.sunFlarePos, backEnd.viewParms.or.origin, dir); - VectorNormalize(dir); - - dot = DotProduct(dir, backEnd.viewParms.or.axis[0]); - if (dot < cutoff) - return; - - if (!RB_UpdateSunFlareVis()) - return; - - VectorCopy(backEnd.sunFlarePos, pos); - pos[3] = 1.f; - - // project sun point - Matrix16Multiply(backEnd.viewParms.projectionMatrix, backEnd.viewParms.world.modelMatrix, mvp); - Matrix16Transform(mvp, pos, hpos); - - // transform to UV coords - hpos[3] = 0.5f / hpos[3]; - - pos[0] = 0.5f + hpos[0] * hpos[3]; - pos[1] = 0.5f - hpos[1] * hpos[3]; - - // viewport dimensions - // JBravo: Apparently not used -/* w = glConfig.vidWidth; - h = glConfig.vidHeight; - w2 = glConfig.vidWidth / 2; - h2 = glConfig.vidHeight / 2; */ - - // initialize quarter buffers - { - float mul = 1.f; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; - - VectorSet4(color, mul, mul, mul, 1); - - // first, downsample the framebuffer - VectorSet4(srcBox, 0, 0, tr.godRaysFbo->width, tr.godRaysFbo->height); - VectorSet4(dstBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); - FBO_Blit(tr.godRaysFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, 0); - - if (colorize) - { - VectorSet4(srcBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); - FBO_Blit(tr.screenScratchFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, - GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); - } - } - - // radial blur passes, ping-ponging between the two quarter-size buffers - { - const float stretch_add = 2.f/3.f; - float stretch = 1.f + stretch_add; - int i; - for (i=0; i<2; ++i) - { - RB_RadialBlur(tr.quarterFbo[i&1], tr.quarterFbo[(~i) & 1], 5, stretch, 0.f, 0.f, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height, pos[0], pos[1], 1.125f); - stretch += stretch_add; - } - } - - // add result back on top of the main buffer - { - float mul = 1.f; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; - - VectorSet4(color, mul, mul, mul, 1); - - VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); - VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); - FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); - } -} -#endif - -static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean horizontal) -{ - float dx, dy; - float xmul, ymul; - float weights[3] = { - 0.227027027f, - 0.316216216f, - 0.070270270f, - }; - float offsets[3] = { - 0.f, - 1.3846153846f, - 3.2307692308f, - }; - - xmul = horizontal; - ymul = 1.f - xmul; - - xmul *= strength; - ymul *= strength; - - { - vec4i_t srcBox, dstBox; - vec4_t color; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; - - VectorSet4(color, weights[0], weights[0], weights[0], 1.0f); - VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); - VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0 ); - - VectorSet4(color, weights[1], weights[1], weights[1], 1.0f); - dx = offsets[1] * xmul; - dy = offsets[1] * ymul; - VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - VectorSet4(color, weights[2], weights[2], weights[2], 1.0f); - dx = offsets[2] * xmul; - dy = offsets[2] * ymul; - VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - } -} - -static void RB_HBlur(FBO_t *srcFbo, FBO_t *dstFbo, float strength) -{ - RB_BlurAxis(srcFbo, dstFbo, strength, qtrue); -} - -static void RB_VBlur(FBO_t *srcFbo, FBO_t *dstFbo, float strength) -{ - RB_BlurAxis(srcFbo, dstFbo, strength, qfalse); -} - -void RB_GaussianBlur(float blur) -{ - //float mul = 1.f; - float factor = Com_Clamp(0.f, 1.f, blur); - - if (factor <= 0.f) - return; - - { - vec4i_t srcBox, dstBox; - vec4_t color; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; - - VectorSet4(color, 1, 1, 1, 1); - - // first, downsample the framebuffer - VectorSet4(srcBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); - VectorSet4(dstBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); - FBO_Blit(tr.screenScratchFbo, srcBox, texScale, tr.quarterFbo[0], dstBox, &tr.textureColorShader, color, 0); - - VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); - VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); - FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, 0); - - // set the alpha channel - VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height); - VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); - qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, GLS_DEPTHTEST_DISABLE); - qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - // blur the tiny buffer horizontally and vertically - RB_HBlur(tr.textureScratchFbo[0], tr.textureScratchFbo[1], factor); - RB_VBlur(tr.textureScratchFbo[1], tr.textureScratchFbo[0], factor); - - // finally, merge back to framebuffer - VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); - VectorSet4(dstBox, 0, 0, tr.screenScratchFbo->width, tr.screenScratchFbo->height); - color[3] = factor; - FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); - } -} diff --git a/code/renderergl2/tr_postprocess.h b/code/renderergl2/tr_postprocess.h deleted file mode 100644 index 5575bfd2..00000000 --- a/code/renderergl2/tr_postprocess.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2011 Andrei Drexler, Richard Allen, James Canete - -This file is part of Reaction source code. - -Reaction source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Reaction source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Reaction source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#ifndef TR_POSTPROCESS_H -#define TR_POSTPROCESS_H - -#include "tr_fbo.h" - -void RB_ToneMap(FBO_t *hdrFbo, int autoExposure); -void RB_BokehBlur(float blur); -void RB_GodRays(void); -void RB_GaussianBlur(float blur); - -#endif \ No newline at end of file diff --git a/code/renderergl2/tr_scene.c b/code/renderergl2/tr_scene.c deleted file mode 100644 index 555bf171..00000000 --- a/code/renderergl2/tr_scene.c +++ /dev/null @@ -1,515 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -#include "tr_local.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; - - -/* -==================== -R_ToggleSmpFrame - -==================== -*/ -void R_ToggleSmpFrame( void ) { - if ( r_smp->integer ) { - // use the other buffers next frame, because another CPU - // may still be rendering into the current ones - tr.smpFrame ^= 1; - } else { - tr.smpFrame = 0; - } - - backEndData[tr.smpFrame]->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; -} - -/* -=========================================================================== - -DISCRETE POLYS - -=========================================================================== -*/ - -/* -===================== -R_AddPolygonSurfaces - -Adds all the scene's polys into this view's drawsurf list -===================== -*/ -void R_AddPolygonSurfaces( void ) { - int i; - shader_t *sh; - srfPoly_t *poly; -// JBravo: Fog fixes - int fogMask; - - tr.currentEntityNum = ENTITYNUM_WORLD; - tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - fogMask = -((tr.refdef.rdflags & RDF_NOFOG) == 0); - - for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) { - sh = R_GetShaderByHandle( poly->hShader ); - R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex & fogMask, qfalse, qfalse ); - } -} - -/* -===================== -RE_AddPolyToScene - -===================== -*/ -void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) { - srfPoly_t *poly; - int i, j; - int fogIndex; - fog_t *fog; - vec3_t bounds[2]; - - if ( !tr.registered ) { - return; - } - - if ( !hShader ) { - // This isn't a useful warning, and an hShader of zero isn't a null shader, it's - // the default shader. - //ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n"); - //return; - } - - for ( j = 0; j < numPolys; j++ ) { - 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, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n"); - return; - } - - poly = &backEndData[tr.smpFrame]->polys[r_numpolys]; - poly->surfaceType = SF_POLY; - poly->hShader = hShader; - poly->numVerts = numVerts; - poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts]; - - Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) ); - - if ( glConfig.hardwareType == GLHW_RAGEPRO ) { - poly->verts->modulate[0] = 255; - poly->verts->modulate[1] = 255; - poly->verts->modulate[2] = 255; - poly->verts->modulate[3] = 255; - } - // done. - r_numpolys++; - r_numpolyverts += numVerts; - - // if no world is loaded - if ( tr.world == NULL ) { - fogIndex = 0; - } - // see if it is in a fog volume - else if ( 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 ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) { - fog = &tr.world->fogs[fogIndex]; - if ( bounds[1][0] >= fog->bounds[0][0] - && bounds[1][1] >= fog->bounds[0][1] - && bounds[1][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] ) { - break; - } - } - if ( fogIndex == tr.world->numfogs ) { - fogIndex = 0; - } - } - poly->fogIndex = fogIndex; - } -} - - -//================================================================================= - - -/* -===================== -RE_AddRefEntityToScene - -===================== -*/ -void RE_AddRefEntityToScene( const refEntity_t *ent ) { -#ifdef REACTION - // JBravo: Mirrored models - vec3_t cross; -#endif - - if ( !tr.registered ) { - return; - } - if ( r_numentities >= MAX_ENTITIES ) { - ri.Printf(PRINT_DEVELOPER, "RE_AddRefEntityToScene: Dropping refEntity, reached MAX_ENTITIES\n"); - return; - } - if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) { - static qboolean firstTime = qtrue; - if (firstTime) { - firstTime = qfalse; - ri.Printf( PRINT_WARNING, "RE_AddRefEntityToScene passed a refEntity which has an origin with a NaN component\n"); - } - return; - } - if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) { - ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); - } - - backEndData[tr.smpFrame]->entities[r_numentities].e = *ent; - backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse; - -#ifdef REACTION - // JBravo: Mirrored models - CrossProduct(ent->axis[0], ent->axis[1], cross); - backEndData[tr.smpFrame]->entities[r_numentities].mirrored = (DotProduct(ent->axis[2], cross) < 0.f); -#endif - - r_numentities++; -} - - -/* -===================== -RE_AddDynamicLightToScene - -===================== -*/ -void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) { - dlight_t *dl; - - if ( !tr.registered ) { - return; - } - if ( r_numdlights >= MAX_DLIGHTS ) { - return; - } - if ( intensity <= 0 ) { - return; - } - // these cards don't have the correct blend mode - if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) { - return; - } - dl = &backEndData[tr.smpFrame]->dlights[r_numdlights++]; - VectorCopy (org, dl->origin); - dl->radius = intensity; - dl->color[0] = r; - dl->color[1] = g; - dl->color[2] = b; - dl->additive = additive; -} - -/* -===================== -RE_AddLightToScene - -===================== -*/ -void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) { - RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse ); -} - -/* -===================== -RE_AddAdditiveLightToScene - -===================== -*/ -void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) { - RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue ); -} - -/* -@@@@@@@@@@@@@@@@@@@@@ -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, -@@@@@@@@@@@@@@@@@@@@@ -*/ -void RE_RenderScene( const refdef_t *fd ) { - viewParms_t parms; - int startTime; - - if ( !tr.registered ) { - return; - } - GLimp_LogComment( "====== RE_RenderScene =====\n" ); - - if ( r_norefresh->integer ) { - return; - } - - startTime = ri.Milliseconds(); - - if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) { - ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel"); - } - - Com_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; - - 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.rdflags = fd->rdflags; - - // 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; - } - } - - tr.refdef.sunDir[3] = 0.0f; - tr.refdef.sunCol[3] = 1.0f; - tr.refdef.sunAmbCol[3] = 1.0f; - - VectorCopy(tr.sunDirection, tr.refdef.sunDir); - if ( (tr.refdef.rdflags & RDF_NOWORLDMODEL) || !(r_depthPrepass->value) ){ - tr.refdef.colorScale = 1.0f; - VectorSet(tr.refdef.sunCol, 0, 0, 0); - VectorSet(tr.refdef.sunAmbCol, 0, 0, 0); - } - else if (r_forceSun->integer == 1) - { - float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); - tr.refdef.colorScale = r_forceSunMapLightScale->value; - VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol); - VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol); - } - else - { - float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); - tr.refdef.colorScale = tr.mapLightScale; - VectorScale(tr.sunLight, scale, tr.refdef.sunCol); - VectorScale(tr.sunAmbient, scale, tr.refdef.sunAmbCol); - } - -//#ifdef REACTION - // Makro - copy exta info if present - if (fd->rdflags & RDF_EXTRA) { - const refdefex_t* extra = (const refdefex_t*) (fd+1); - - tr.refdef.blurFactor = extra->blurFactor; - - if (fd->rdflags & RDF_SUNLIGHT) - { - VectorCopy(extra->sunDir, tr.refdef.sunDir); - VectorCopy(extra->sunCol, tr.refdef.sunCol); - VectorCopy(extra->sunAmbCol, tr.refdef.sunAmbCol); - } - } - else - { - tr.refdef.blurFactor = 0.0f; - } -//#endif - - // derived info - - tr.refdef.floatTime = tr.refdef.time * 0.001f; - - tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; - tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs; - - tr.refdef.num_entities = r_numentities - r_firstSceneEntity; - tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity]; - - tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight; - tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight]; - - tr.refdef.numPolys = r_numpolys - r_firstScenePoly; - tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly]; - - tr.refdef.num_pshadows = 0; - tr.refdef.pshadows = &backEndData[tr.smpFrame]->pshadows[0]; - - // 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 || - glConfig.hardwareType == GLHW_PERMEDIA2 ) { - 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++; - - // SmileTheory: playing with shadow mapping - if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightMode->integer >= 2) - { - R_RenderDlightCubemaps(fd); - } - - /* playing with more shadows */ - if(!( fd->rdflags & RDF_NOWORLDMODEL ) && r_shadows->integer == 4) - { - R_RenderPshadowMaps(fd); - } - - // playing with even more shadows - if(!( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows)) - { - R_RenderSunShadowMaps(fd, 0); - R_RenderSunShadowMaps(fd, 1); - R_RenderSunShadowMaps(fd, 2); - } - - // 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 - // - Com_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; - parms.viewportHeight = tr.refdef.height; - parms.isPortal = qfalse; - - parms.fovX = tr.refdef.fov_x; - parms.fovY = tr.refdef.fov_y; - - parms.stereoFrame = tr.refdef.stereoFrame; - - if (glRefConfig.framebufferObject) - { - parms.targetFbo = tr.renderFbo; - } - - VectorCopy( fd->vieworg, parms.or.origin ); - VectorCopy( fd->viewaxis[0], parms.or.axis[0] ); - VectorCopy( fd->viewaxis[1], parms.or.axis[1] ); - VectorCopy( fd->viewaxis[2], parms.or.axis[2] ); - - VectorCopy( fd->vieworg, parms.pvsOrigin ); - - if(!( fd->rdflags & RDF_NOWORLDMODEL ) && r_depthPrepass->value && ((r_forceSun->integer) || tr.sunShadows)) - { - parms.flags = VPF_USESUNLIGHT; - } - - R_RenderView( &parms ); - - if(!( fd->rdflags & RDF_NOWORLDMODEL )) - R_AddPostProcessCmd(); - - // 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; -} diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c deleted file mode 100644 index e6f787c1..00000000 --- a/code/renderergl2/tr_shade.c +++ /dev/null @@ -1,1798 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_shade.c - -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include -#endif - -/* - - THIS ENTIRE FILE IS BACK END - - This file deals with applying shaders to surface data in the tess struct. -*/ - - -/* -================== -R_DrawElements - -================== -*/ - -void R_DrawElementsVBO( int numIndexes, int firstIndex ) -{ - if (glRefConfig.drawRangeElements) - qglDrawRangeElementsEXT(GL_TRIANGLES, 0, numIndexes, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE))); - else - qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE))); - -} - - -static void R_DrawMultiElementsVBO( int multiDrawPrimitives, const GLvoid **multiDrawFirstIndex, GLsizei *multiDrawNumIndexes ) -{ - if (glRefConfig.multiDrawArrays) - { - qglMultiDrawElementsEXT(GL_TRIANGLES, multiDrawNumIndexes, GL_INDEX_TYPE, multiDrawFirstIndex, multiDrawPrimitives); - } - else - { - int i; - - if (glRefConfig.drawRangeElements) - { - for (i = 0; i < multiDrawPrimitives; i++) - { - qglDrawRangeElementsEXT(GL_TRIANGLES, 0, multiDrawNumIndexes[i], multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]); - } - } - else - { - for (i = 0; i < multiDrawPrimitives; i++) - { - qglDrawElements(GL_TRIANGLES, multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]); - } - } - } -} - - -/* -============================================================= - -SURFACE SHADERS - -============================================================= -*/ - -shaderCommands_t tess; - - -/* -================= -R_BindAnimatedImageToTMU - -================= -*/ -static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) { - int index; - - if ( bundle->isVideoMap ) { - int oldtmu = glState.currenttmu; - GL_SelectTexture(tmu); - ri.CIN_RunCinematic(bundle->videoMapHandle); - ri.CIN_UploadCinematic(bundle->videoMapHandle); - GL_SelectTexture(oldtmu); - return; - } - - if ( bundle->numImageAnimations <= 1 ) { - GL_BindToTMU( bundle->image[0], tmu); - return; - } - - // it is necessary to do this messy calc to make sure animations line up - // exactly with waveforms of the same frequency - index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE); - index >>= FUNCTABLE_SIZE2; - - if ( index < 0 ) { - index = 0; // may happen with shader time offsets - } - index %= bundle->numImageAnimations; - - GL_BindToTMU( bundle->image[ index ], tmu ); -} - - -/* -================ -DrawTris - -Draws triangle outlines for debugging -================ -*/ -static void DrawTris (shaderCommands_t *input) { - GL_Bind( tr.whiteImage ); - - GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); - qglDepthRange( 0, 0 ); - - { - shaderProgram_t *sp = &tr.textureColorShader; - vec4_t color; - - GLSL_VertexAttribsState(ATTR_POSITION); - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - VectorSet4(color, 1, 1, 1, 1); - GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color); - - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - } - - qglDepthRange( 0, 1 ); -} - - -/* -================ -DrawNormals - -Draws vertex normals for debugging -================ -*/ -static void DrawNormals (shaderCommands_t *input) { - //FIXME: implement this -} - -/* -============== -RB_BeginSurface - -We must set some things up before beginning any tesselation, -because a surface may be forced to perform a RB_End due -to overflow. -============== -*/ -void RB_BeginSurface( shader_t *shader, int fogNum ) { - - shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader; - - tess.numIndexes = 0; - tess.firstIndex = 0; - tess.numVertexes = 0; - tess.multiDrawPrimitives = 0; - tess.shader = state; - tess.fogNum = fogNum; - tess.dlightBits = 0; // will be OR'd in by surface functions - tess.pshadowBits = 0; // will be OR'd in by surface functions - tess.xstages = state->stages; - tess.numPasses = state->numUnfoggedPasses; - tess.currentStageIteratorFunc = state->optimalStageIteratorFunc; - tess.useInternalVBO = qtrue; - - tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; - if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) { - tess.shaderTime = tess.shader->clampTime; - } - - if (backEnd.viewParms.flags & VPF_SHADOWMAP) - { - tess.currentStageIteratorFunc = RB_StageIteratorGeneric; - } -} - - - -extern float EvalWaveForm( const waveForm_t *wf ); -extern float EvalWaveFormClamped( const waveForm_t *wf ); - - -static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outmatrix) -{ - int tm; - float matrix[16], currentmatrix[16]; - textureBundle_t *bundle = &pStage->bundle[bundleNum]; - - Matrix16Identity(outmatrix); - Matrix16Identity(currentmatrix); - - for ( tm = 0; tm < bundle->numTexMods ; tm++ ) { - switch ( bundle->texMods[tm].type ) - { - - case TMOD_NONE: - tm = TR_MAX_TEXMODS; // break out of for loop - break; - - case TMOD_TURBULENT: - RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave, - matrix ); - outmatrix[12] = matrix[12]; - outmatrix[13] = matrix[13]; - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_ENTITY_TRANSLATE: - RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_SCROLL: - RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_SCALE: - RB_CalcScaleTexMatrix( bundle->texMods[tm].scale, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_STRETCH: - RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_TRANSFORM: - RB_CalcTransformTexMatrix( &bundle->texMods[tm], - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - case TMOD_ROTATE: - RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed, - matrix ); - Matrix16Multiply(matrix, currentmatrix, outmatrix); - Matrix16Copy(outmatrix, currentmatrix); - break; - - default: - ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'\n", bundle->texMods[tm].type, tess.shader->name ); - break; - } - } -} - - -static void ComputeDeformValues(int *deformGen, vec5_t deformParams) -{ - // u_DeformGen - *deformGen = DGEN_NONE; - if(!ShaderRequiresCPUDeforms(tess.shader)) - { - deformStage_t *ds; - - // only support the first one - ds = &tess.shader->deforms[0]; - - switch (ds->deformation) - { - case DEFORM_WAVE: - *deformGen = ds->deformationWave.func; - - deformParams[0] = ds->deformationWave.base; - deformParams[1] = ds->deformationWave.amplitude; - deformParams[2] = ds->deformationWave.phase; - deformParams[3] = ds->deformationWave.frequency; - deformParams[4] = ds->deformationSpread; - break; - - case DEFORM_BULGE: - *deformGen = DGEN_BULGE; - - deformParams[0] = 0; - deformParams[1] = ds->bulgeHeight; // amplitude - deformParams[2] = ds->bulgeWidth; // phase - deformParams[3] = ds->bulgeSpeed; // frequency - deformParams[4] = 0; - break; - - default: - break; - } - } -} - - -static void ProjectDlightTexture( void ) { - int l; - vec3_t origin; - float scale; - float radius; - int deformGen; - vec5_t deformParams; - - if ( !backEnd.refdef.num_dlights ) { - return; - } - - ComputeDeformValues(&deformGen, deformParams); - - for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { - dlight_t *dl; - shaderProgram_t *sp; - vec4_t vector; - - if ( !( tess.dlightBits & ( 1 << l ) ) ) { - continue; // this surface definately doesn't have any of this light - } - - dl = &backEnd.refdef.dlights[l]; - VectorCopy( dl->transformed, origin ); - radius = dl->radius; - scale = 1.0f / radius; - - sp = &tr.dlightallShader; - - backEnd.pc.c_dlightDraws++; - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - GLSL_SetUniformFloat(sp, DLIGHT_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, DLIGHT_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, DLIGHT_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, DLIGHT_UNIFORM_TIME, tess.shaderTime); - } - - vector[0] = dl->color[0]; - vector[1] = dl->color[1]; - vector[2] = dl->color[2]; - vector[3] = 1.0f; - GLSL_SetUniformVec4(sp, DLIGHT_UNIFORM_COLOR, vector); - - vector[0] = origin[0]; - vector[1] = origin[1]; - vector[2] = origin[2]; - vector[3] = scale; - GLSL_SetUniformVec4(sp, DLIGHT_UNIFORM_DLIGHTINFO, vector); - - GL_Bind( tr.dlightImage ); - - // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light - // where they aren't rendered - if ( dl->additive ) { - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - else { - GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - } - - if (tess.multiDrawPrimitives) - { - R_DrawMultiElementsVBO(tess.multiDrawPrimitives, (const GLvoid **)tess.multiDrawFirstIndex, tess.multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex); - } - - backEnd.pc.c_totalIndexes += tess.numIndexes; - backEnd.pc.c_dlightIndexes += tess.numIndexes; - } -} - - -static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor ) -{ - // - // rgbGen - // - switch ( pStage->rgbGen ) - { - case CGEN_IDENTITY: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_IDENTITY_LIGHTING: - baseColor[0] = - baseColor[1] = - baseColor[2] = tr.identityLight; - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_EXACT_VERTEX: - case CGEN_EXACT_VERTEX_LIT: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 0.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 1.0f; - break; - case CGEN_CONST: - baseColor[0] = pStage->constantColor[0] / 255.0f; - baseColor[1] = pStage->constantColor[1] / 255.0f; - baseColor[2] = pStage->constantColor[2] / 255.0f; - baseColor[3] = pStage->constantColor[3] / 255.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_VERTEX: - case CGEN_VERTEX_LIT: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 0.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = tr.identityLight; - vertColor[3] = 1.0f; - break; - case CGEN_ONE_MINUS_VERTEX: - baseColor[0] = - baseColor[1] = - baseColor[2] = tr.identityLight; - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = -tr.identityLight; - vertColor[3] = 0.0f; - break; - case CGEN_FOG: - { - fog_t *fog; - - fog = tr.world->fogs + tess.fogNum; - - baseColor[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; - baseColor[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; - baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; - baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; - } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_WAVEFORM: - baseColor[0] = - baseColor[1] = - baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave ); - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_ENTITY: - if (backEnd.currentEntity) - { - baseColor[0] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; - baseColor[1] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; - baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; - baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; - } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_ONE_MINUS_ENTITY: - if (backEnd.currentEntity) - { - baseColor[0] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f; - baseColor[1] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f; - baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f; - baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; - } - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - case CGEN_LIGHTING_DIFFUSE: - case CGEN_BAD: - baseColor[0] = - baseColor[1] = - baseColor[2] = - baseColor[3] = 1.0f; - - vertColor[0] = - vertColor[1] = - vertColor[2] = - vertColor[3] = 0.0f; - break; - } - - // - // alphaGen - // - switch ( pStage->alphaGen ) - { - case AGEN_SKIP: - break; - case AGEN_IDENTITY: - baseColor[3] = 1.0f; - vertColor[3] = 0.0f; - break; - case AGEN_CONST: - baseColor[3] = pStage->constantColor[3] / 255.0f; - vertColor[3] = 0.0f; - break; - case AGEN_WAVEFORM: - baseColor[3] = RB_CalcWaveAlphaSingle( &pStage->alphaWave ); - vertColor[3] = 0.0f; - break; - case AGEN_ENTITY: - if (backEnd.currentEntity) - { - baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; - } - vertColor[3] = 0.0f; - break; - case AGEN_ONE_MINUS_ENTITY: - if (backEnd.currentEntity) - { - baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f; - } - vertColor[3] = 0.0f; - break; - case AGEN_VERTEX: - baseColor[3] = 0.0f; - vertColor[3] = 1.0f; - break; - case AGEN_ONE_MINUS_VERTEX: - baseColor[3] = 1.0f; - vertColor[3] = -1.0f; - break; - case AGEN_LIGHTING_SPECULAR: - case AGEN_PORTAL: - case AGEN_FRESNEL: - // Done entirely in vertex program - baseColor[3] = 1.0f; - vertColor[3] = 0.0f; - break; - } - - // FIXME: find some way to implement this. -#if 0 - // if in greyscale rendering mode turn all color values into greyscale. - if(r_greyscale->integer) - { - int scale; - - for(i = 0; i < tess.numVertexes; i++) - { - scale = (tess.svars.colors[i][0] + tess.svars.colors[i][1] + tess.svars.colors[i][2]) / 3; - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } - } -#endif -} - - -static void ComputeFogValues(vec4_t fogDistanceVector, vec4_t fogDepthVector, float *eyeT) -{ - // from RB_CalcFogTexCoords() - fog_t *fog; - vec3_t local; - - if (!tess.fogNum) - return; - - fog = tr.world->fogs + tess.fogNum; - - VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local ); - fogDistanceVector[0] = -backEnd.or.modelMatrix[2]; - fogDistanceVector[1] = -backEnd.or.modelMatrix[6]; - fogDistanceVector[2] = -backEnd.or.modelMatrix[10]; - fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] ); - - // scale the fog vectors based on the fog's thickness - VectorScale4(fogDistanceVector, fog->tcScale, fogDistanceVector); - - // rotate the gradient vector for this orientation - if ( fog->hasSurface ) { - fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] + - fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2]; - fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] + - fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2]; - fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] + - fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2]; - fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface ); - - *eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3]; - } else { - *eyeT = 1; // non-surface fog always has eye inside - } -} - - -static void ComputeFogColorMask( shaderStage_t *pStage, vec4_t fogColorMask ) -{ - switch(pStage->adjustColorsForFog) - { - case ACFF_MODULATE_RGB: - fogColorMask[0] = - fogColorMask[1] = - fogColorMask[2] = 1.0f; - fogColorMask[3] = 0.0f; - break; - case ACFF_MODULATE_ALPHA: - fogColorMask[0] = - fogColorMask[1] = - fogColorMask[2] = 0.0f; - fogColorMask[3] = 1.0f; - break; - case ACFF_MODULATE_RGBA: - fogColorMask[0] = - fogColorMask[1] = - fogColorMask[2] = - fogColorMask[3] = 1.0f; - break; - default: - fogColorMask[0] = - fogColorMask[1] = - fogColorMask[2] = - fogColorMask[3] = 0.0f; - break; - } -} - - -static void ForwardDlight( void ) { - int l; - //vec3_t origin; - //float scale; - float radius; - - int deformGen; - vec5_t deformParams; - - vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - float eyeT = 0; - - shaderCommands_t *input = &tess; - shaderStage_t *pStage = tess.xstages[0]; - - if ( !backEnd.refdef.num_dlights ) { - return; - } - - ComputeDeformValues(&deformGen, deformParams); - - ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); - - for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { - dlight_t *dl; - shaderProgram_t *sp; - vec4_t vector; - matrix_t matrix; - - if ( !( tess.dlightBits & ( 1 << l ) ) ) { - continue; // this surface definately doesn't have any of this light - } - - dl = &backEnd.refdef.dlights[l]; - //VectorCopy( dl->transformed, origin ); - radius = dl->radius; - //scale = 1.0f / radius; - - //if (pStage->glslShaderGroup == tr.lightallShader) - { - int index = pStage->glslShaderIndex; - - index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP); - index |= LIGHTDEF_USE_LIGHT_VECTOR; - - sp = &tr.lightallShader[index]; - } - - backEnd.pc.c_lightallDraws++; - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime); - } - - if ( input->fogNum ) { - vec4_t fogColorMask; - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT); - - ComputeFogColorMask(pStage, fogColorMask); - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask); - } - - { - vec4_t baseColor; - vec4_t vertColor; - - ComputeShaderColors(pStage, baseColor, vertColor); - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor); - } - - if (pStage->alphaGen == AGEN_PORTAL) - { - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange); - } - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen); - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen); - - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, dl->color); - - VectorSet(vector, 0, 0, 0); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, vector); - - VectorCopy(dl->origin, vector); - vector[3] = 1.0f; - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vector); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, radius); - - GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo); - - // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light - // where they aren't rendered - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); - - if (pStage->bundle[TB_DIFFUSEMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); - - if (pStage->bundle[TB_NORMALMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); - - if (pStage->bundle[TB_SPECULARMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); - - if (r_dlightMode->integer >= 2) - { - GL_SelectTexture(TB_SHADOWMAP); - GL_BindCubemap(tr.shadowCubemaps[l]); - GL_SelectTexture(0); - } - - ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, matrix); - - // - // draw - // - - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - - backEnd.pc.c_totalIndexes += tess.numIndexes; - backEnd.pc.c_dlightIndexes += tess.numIndexes; - } -} - - -static void ForwardSunlight( void ) { -// int l; - //vec3_t origin; - //float scale; - int stage; - int stageGlState[2]; - qboolean alphaOverride = qfalse; - - int deformGen; - vec5_t deformParams; - - vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - float eyeT = 0; - - shaderCommands_t *input = &tess; - - ComputeDeformValues(&deformGen, deformParams); - - ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); - - // deal with vertex alpha blended surfaces - if (input->xstages[0] && input->xstages[1] && - (input->xstages[1]->alphaGen == AGEN_VERTEX || input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX)) - { - stageGlState[0] = input->xstages[0]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS); - - if (stageGlState[0] == 0 || stageGlState[0] == (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO)) - { - stageGlState[1] = input->xstages[1]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS); - - if (stageGlState[1] == (GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA)) - { - alphaOverride = qtrue; - stageGlState[0] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; - stageGlState[1] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; - } - else if (stageGlState[1] == (GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA)) - { - alphaOverride = qtrue; - stageGlState[0] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; - stageGlState[1] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; - } - } - } - - if (!alphaOverride) - { - stageGlState[0] = - stageGlState[1] = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; - } - - for ( stage = 0; stage < 2 /*MAX_SHADER_STAGES */; stage++ ) - { - shaderStage_t *pStage = input->xstages[stage]; - shaderProgram_t *sp; - //vec4_t vector; - matrix_t matrix; - - if ( !pStage ) - { - break; - } - - //VectorCopy( dl->transformed, origin ); - - //if (pStage->glslShaderGroup == tr.lightallShader) - { - int index = pStage->glslShaderIndex; - - index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP); - index |= LIGHTDEF_USE_LIGHT_VECTOR | LIGHTDEF_USE_SHADOWMAP; - - if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) - { - index |= LIGHTDEF_ENTITY; - } - - sp = &tr.lightallShader[index]; - } - - backEnd.pc.c_lightallDraws++; - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime); - } - - if ( input->fogNum ) { - vec4_t fogColorMask; - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT); - - ComputeFogColorMask(pStage, fogColorMask); - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask); - } - - { - vec4_t baseColor; - vec4_t vertColor; - - ComputeShaderColors(pStage, baseColor, vertColor); - - if (alphaOverride) - { - if (input->xstages[1]->alphaGen == AGEN_VERTEX) - { - baseColor[3] = 0.0f; - vertColor[3] = 1.0f; - } - else if (input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX) - { - baseColor[3] = 1.0f; - vertColor[3] = -1.0f; - } - } - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor); - } - - if (pStage->alphaGen == AGEN_PORTAL) - { - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange); - } - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen); - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen); - - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, backEnd.refdef.sunCol); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, backEnd.refdef.sunAmbCol); - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, backEnd.refdef.sunDir); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, 9999999999); - - GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo); - - GL_State( stageGlState[stage] ); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); - - if (pStage->bundle[TB_DIFFUSEMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); - - if (pStage->bundle[TB_NORMALMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); - - if (pStage->bundle[TB_SPECULARMAP].image[0]) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); - - /* - { - GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); - GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); - GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); - } - */ - GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP); - - ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, matrix); - - // - // draw - // - - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - - backEnd.pc.c_totalIndexes += tess.numIndexes; - backEnd.pc.c_dlightIndexes += tess.numIndexes; - } -} - - -static void ProjectPshadowVBOGLSL( void ) { - int l; - vec3_t origin; - float radius; - - int deformGen; - vec5_t deformParams; - - shaderCommands_t *input = &tess; - - if ( !backEnd.refdef.num_pshadows ) { - return; - } - - ComputeDeformValues(&deformGen, deformParams); - - for ( l = 0 ; l < backEnd.refdef.num_pshadows ; l++ ) { - pshadow_t *ps; - shaderProgram_t *sp; - vec4_t vector; - - if ( !( tess.pshadowBits & ( 1 << l ) ) ) { - continue; // this surface definately doesn't have any of this shadow - } - - ps = &backEnd.refdef.pshadows[l]; - VectorCopy( ps->lightOrigin, origin ); - radius = ps->lightRadius; - - sp = &tr.pshadowShader; - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - VectorCopy(origin, vector); - vector[3] = 1.0f; - GLSL_SetUniformVec4(sp, PSHADOW_UNIFORM_LIGHTORIGIN, vector); - - VectorScale(ps->lightViewAxis[0], 1.0f / ps->viewRadius, vector); - GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTFORWARD, vector); - - VectorScale(ps->lightViewAxis[1], 1.0f / ps->viewRadius, vector); - GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTRIGHT, vector); - - VectorScale(ps->lightViewAxis[2], 1.0f / ps->viewRadius, vector); - GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTUP, vector); - - GLSL_SetUniformFloat(sp, PSHADOW_UNIFORM_LIGHTRADIUS, radius); - - // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light - // where they aren't rendered - GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); - - GL_BindToTMU( tr.pshadowMaps[l], TB_DIFFUSEMAP ); - - // - // draw - // - - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - - backEnd.pc.c_totalIndexes += tess.numIndexes; - //backEnd.pc.c_dlightIndexes += tess.numIndexes; - } -} - - - -/* -=================== -RB_FogPass - -Blends a fog texture on top of everything else -=================== -*/ -static void RB_FogPass( void ) { - fog_t *fog; - vec4_t color; - vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - float eyeT = 0; - shaderProgram_t *sp = &tr.fogShader; - - int deformGen; - vec5_t deformParams; - - ComputeDeformValues(&deformGen, deformParams); - - backEnd.pc.c_fogDraws++; - - GLSL_BindProgram(sp); - - fog = tr.world->fogs + tess.fogNum; - - GLSL_SetUniformMatrix16(sp, FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, FOGPASS_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, FOGPASS_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_TIME, tess.shaderTime); - } - - color[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; - color[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; - color[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; - color[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; - GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_COLOR, color); - - ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); - - GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_FOGDISTANCE, fogDistanceVector); - GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_FOGDEPTH, fogDepthVector); - GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_FOGEYET, eyeT); - - if ( tess.shader->fogPass == FP_EQUAL ) { - GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); - } else { - GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - } - - if (tess.multiDrawPrimitives) - { - R_DrawMultiElementsVBO(tess.multiDrawPrimitives, (const GLvoid **)tess.multiDrawFirstIndex, tess.multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex); - } -} - - -static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input ) -{ - unsigned int vertexAttribs = input->shader->vertexAttribs; - - if(glState.vertexAttribsInterpolation > 0.0f) - { - vertexAttribs |= ATTR_POSITION2; - if (vertexAttribs & ATTR_NORMAL) - { - vertexAttribs |= ATTR_NORMAL2; -#ifdef USE_VERT_TANGENT_SPACE - vertexAttribs |= ATTR_TANGENT2; - vertexAttribs |= ATTR_BITANGENT2; -#endif - } - } - - return vertexAttribs; -} - -static void RB_IterateStagesGeneric( shaderCommands_t *input ) -{ - int stage; - matrix_t matrix; - - vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - float eyeT = 0; - - int deformGen; - vec5_t deformParams; - - ComputeDeformValues(&deformGen, deformParams); - - ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); - - for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) - { - shaderStage_t *pStage = input->xstages[stage]; - shaderProgram_t *sp; - - if ( !pStage ) - { - break; - } - - if (backEnd.depthFill) - { - if (pStage->glslShaderGroup) - { - int index = 0; - - if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) - { - index |= LIGHTDEF_ENTITY; - } - - sp = &pStage->glslShaderGroup[index]; - } - else - { - int shaderAttribs = 0; - - if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader)) - { - shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; - } - - if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) - { - shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; - } - - sp = &tr.genericShader[shaderAttribs]; - } - } - else if (pStage->glslShaderGroup) - { - int index = pStage->glslShaderIndex; - - if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) - { - index |= LIGHTDEF_ENTITY; - } - - if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP) - { - index = LIGHTDEF_USE_LIGHTMAP; - } - - sp = &pStage->glslShaderGroup[index]; - - if (pStage->glslShaderGroup == tr.lightallShader) - { - backEnd.pc.c_lightallDraws++; - } - } - else - { - sp = GLSL_GetGenericShaderProgram(stage); - - backEnd.pc.c_genericDraws++; - } - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime); - } - - if ( input->fogNum ) { - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT); - } - - GL_State( pStage->stateBits ); - - { - vec4_t baseColor; - vec4_t vertColor; - qboolean tint = qtrue; - int stage2; - - ComputeShaderColors(pStage, baseColor, vertColor); - - for ( stage2 = stage + 1; stage2 < MAX_SHADER_STAGES; stage2++ ) - { - shaderStage_t *pStage2 = input->xstages[stage2]; - unsigned int srcBlendBits; //, dstBlendBits; - - if ( !pStage2 ) - { - break; - } - - srcBlendBits = pStage2->stateBits & GLS_SRCBLEND_BITS; - // dstBlendBits = pStage2->stateBits & GLS_DSTBLEND_BITS; - - if (srcBlendBits == GLS_SRCBLEND_DST_COLOR) - { - tint = qfalse; - break; - } - } - - if (!((tr.sunShadows || r_forceSun->integer) && tess.shader->sort <= SS_OPAQUE - && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader)) - { - tint = qfalse; - } - - if (tint) - { - // use vectorscale to only scale first three values, not alpha - VectorScale(baseColor, backEnd.refdef.colorScale, baseColor); - VectorScale(vertColor, backEnd.refdef.colorScale, vertColor); - } - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor); - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor); - } - - if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) - { - vec4_t vec; - - VectorScale(backEnd.currentEntity->ambientLight, 1.0f / 255.0f, vec); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, vec); - - VectorScale(backEnd.currentEntity->directedLight, 1.0f / 255.0f, vec); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, vec); - - VectorCopy(backEnd.currentEntity->lightDir, vec); - vec[3] = 0.0f; - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vec); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, 999999.0f); - } - - if (pStage->alphaGen == AGEN_PORTAL) - { - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange); - } - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen); - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen); - - if ( input->fogNum ) - { - vec4_t fogColorMask; - - ComputeFogColorMask(pStage, fogColorMask); - - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask); - } - - ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, matrix); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, pStage->bundle[0].tcGen); - if (pStage->bundle[0].tcGen == TCGEN_VECTOR) - { - vec3_t vec; - - VectorCopy(pStage->bundle[0].tcGenVectors[0], vec); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_TCGEN0VECTOR0, vec); - VectorCopy(pStage->bundle[0].tcGenVectors[1], vec); - GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_TCGEN0VECTOR1, vec); - } - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); - - GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo); - - //GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale); - - // - // do multitexture - // - if ( backEnd.depthFill ) - { - if (!(pStage->stateBits & GLS_ATEST_BITS)) - GL_BindToTMU( tr.whiteImage, 0 ); - else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) - R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP ); - } - else if ( pStage->glslShaderGroup ) - { - int i; - - if ((r_lightmap->integer == 1 || r_lightmap->integer == 2) && pStage->bundle[TB_LIGHTMAP].image[0]) - { - for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) - { - if (i == TB_LIGHTMAP) - { - R_BindAnimatedImageToTMU( &pStage->bundle[i], i); - } - else if (pStage->bundle[i].image[0]) - { - GL_BindToTMU( tr.whiteImage, i); - } - } - } - else if (r_lightmap->integer == 3 && pStage->bundle[TB_DELUXEMAP].image[0]) - { - for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) - { - if (i == TB_LIGHTMAP) - { - R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); - } - else if (pStage->bundle[i].image[0]) - { - GL_BindToTMU( tr.whiteImage, i); - } - } - } - else - { - for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) - { - if (pStage->bundle[i].image[0]) - { - R_BindAnimatedImageToTMU( &pStage->bundle[i], i); - } - } - } - } - else if ( pStage->bundle[1].image[0] != 0 ) - { - R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); - - // - // lightmap/secondary pass - // - if ( r_lightmap->integer ) { - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, GL_REPLACE); - } else { - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, tess.shader->multitextureEnv); - } - - R_BindAnimatedImageToTMU( &pStage->bundle[1], 1 ); - } - else - { - // - // set state - // - if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) - { - GL_BindToTMU( tr.whiteImage, 0 ); - } - else - R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, 0); - } - - // - // draw - // - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - - // allow skipping out to show just lightmaps during development - if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) - { - break; - } - - if (backEnd.depthFill) - break; - } -} - - -static void RB_RenderShadowmap( shaderCommands_t *input ) -{ - int deformGen; - vec5_t deformParams; - - ComputeDeformValues(&deformGen, deformParams); - - { - shaderProgram_t *sp = &tr.shadowmapShader; - - vec4_t vector; - - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); - - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); - - GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen); - if (deformGen != DGEN_NONE) - { - GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime); - } - - VectorCopy(backEnd.viewParms.or.origin, vector); - vector[3] = 1.0f; - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vector); - GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, backEnd.viewParms.zFar); - - GL_State( 0 ); - - // - // do multitexture - // - //if ( pStage->glslShaderGroup ) - { - // - // draw - // - - if (input->multiDrawPrimitives) - { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, (const GLvoid **)input->multiDrawFirstIndex, input->multiDrawNumIndexes); - } - else - { - R_DrawElementsVBO(input->numIndexes, input->firstIndex); - } - } - } -} - - - -/* -** RB_StageIteratorGeneric -*/ -void RB_StageIteratorGeneric( void ) -{ - shaderCommands_t *input; - unsigned int vertexAttribs = 0; - - input = &tess; - - if (!input->numVertexes || !input->numIndexes) - { - return; - } - - if (tess.useInternalVBO) - { - RB_DeformTessGeometry(); - } - - vertexAttribs = RB_CalcShaderVertexAttribs( input ); - - if (tess.useInternalVBO) - { - RB_UpdateVBOs(vertexAttribs); - } - else - { - backEnd.pc.c_staticVboDraws++; - } - - // - // log this call - // - if ( r_logFile->integer ) - { - // don't just call LogComment, or we will get - // a call to va() every frame! - GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) ); - } - - // - // set face culling appropriately - // - if ((backEnd.viewParms.flags & VPF_DEPTHSHADOW)) - { - //GL_Cull( CT_TWO_SIDED ); - - if (input->shader->cullType == CT_TWO_SIDED) - GL_Cull( CT_TWO_SIDED ); - else if (input->shader->cullType == CT_FRONT_SIDED) - GL_Cull( CT_BACK_SIDED ); - else - GL_Cull( CT_FRONT_SIDED ); - - } - else - GL_Cull( input->shader->cullType ); - - // set polygon offset if necessary - if ( input->shader->polygonOffset ) - { - qglEnable( GL_POLYGON_OFFSET_FILL ); - qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); - } - - // - // Set vertex attribs and pointers - // - GLSL_VertexAttribsState(vertexAttribs); - - // - // render depth if in depthfill mode - // - if (backEnd.depthFill) - { - RB_IterateStagesGeneric( input ); - - // - // reset polygon offset - // - if ( input->shader->polygonOffset ) - { - qglDisable( GL_POLYGON_OFFSET_FILL ); - } - - return; - } - - // - // render shadowmap if in shadowmap mode - // - if (backEnd.viewParms.flags & VPF_SHADOWMAP) - { - if ( input->shader->sort == SS_OPAQUE ) - { - RB_RenderShadowmap( input ); - } - // - // reset polygon offset - // - if ( input->shader->polygonOffset ) - { - qglDisable( GL_POLYGON_OFFSET_FILL ); - } - - return; - } - - // - // - // call shader function - // - RB_IterateStagesGeneric( input ); - - // - // pshadows! - // - if ( tess.pshadowBits && tess.shader->sort <= SS_OPAQUE - && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { - ProjectPshadowVBOGLSL(); - } - - - // - // now do any dynamic lighting needed - // - if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE - && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { - if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader - && (tess.xstages[0]->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && r_dlightMode->integer) - { - ForwardDlight(); - } - else - { - ProjectDlightTexture(); - } - } - - if ((backEnd.viewParms.flags & VPF_USESUNLIGHT) && tess.shader->sort <= SS_OPAQUE - //if ((tr.sunShadows || r_forceSunlight->value > 0.0f) && tess.shader->sort <= SS_OPAQUE - && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader) { - ForwardSunlight(); - } - - // - // now do fog - // - if ( tess.fogNum && tess.shader->fogPass ) { - RB_FogPass(); - } - - // - // reset polygon offset - // - if ( input->shader->polygonOffset ) - { - qglDisable( GL_POLYGON_OFFSET_FILL ); - } -} - - -/* -** RB_EndSurface -*/ -void RB_EndSurface( void ) { - shaderCommands_t *input; - - input = &tess; - - if (input->numIndexes == 0 || input->numVertexes == 0) { - return; - } - - if (input->indexes[SHADER_MAX_INDEXES-1] != 0) { - ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit"); - } - if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) { - ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit"); - } - - if ( tess.shader == tr.shadowShader ) { - RB_ShadowTessEnd(); - return; - } - - // for debugging of sort order issues, stop rendering after a given sort value - if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) { - return; - } - - // - // update performance counters - // - backEnd.pc.c_shaders++; - backEnd.pc.c_vertexes += tess.numVertexes; - backEnd.pc.c_indexes += tess.numIndexes; - backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses; - - // - // call off to shader specific tess end function - // - tess.currentStageIteratorFunc(); - - // - // draw debugging stuff - // - if ( r_showtris->integer ) { - DrawTris (input); - } - if ( r_shownormals->integer ) { - DrawNormals (input); - } - // clear shader so we can tell we don't have any unclosed surfaces - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; - tess.multiDrawPrimitives = 0; - - GLimp_LogComment( "----------\n" ); -} diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c deleted file mode 100644 index 9421f646..00000000 --- a/code/renderergl2/tr_shade_calc.c +++ /dev/null @@ -1,1339 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_shade_calc.c - -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include -#endif - - -#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ ri.ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude)) - -static float *TableForFunc( genFunc_t func ) -{ - switch ( func ) - { - case GF_SIN: - return tr.sinTable; - case GF_TRIANGLE: - return tr.triangleTable; - case GF_SQUARE: - return tr.squareTable; - case GF_SAWTOOTH: - return tr.sawToothTable; - case GF_INVERSE_SAWTOOTH: - return tr.inverseSawToothTable; - case GF_NONE: - default: - break; - } - - ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'", func, tess.shader->name ); - return NULL; -} - -/* -** EvalWaveForm -** -** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly -*/ -static float EvalWaveForm( const waveForm_t *wf ) -{ - float *table; - - table = TableForFunc( wf->func ); - - return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency ); -} - -static float EvalWaveFormClamped( const waveForm_t *wf ) -{ - float glow = EvalWaveForm( wf ); - - if ( glow < 0 ) - { - return 0; - } - - if ( glow > 1 ) - { - return 1; - } - - return glow; -} - -/* -** RB_CalcStretchTexCoords -*/ -void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st ) -{ - float p; - texModInfo_t tmi; - - p = 1.0f / EvalWaveForm( wf ); - - tmi.matrix[0][0] = p; - tmi.matrix[1][0] = 0; - tmi.translate[0] = 0.5f - 0.5f * p; - - tmi.matrix[0][1] = 0; - tmi.matrix[1][1] = p; - tmi.translate[1] = 0.5f - 0.5f * p; - - RB_CalcTransformTexCoords( &tmi, st ); -} - -void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix ) -{ - float p; - texModInfo_t tmi; - - p = 1.0f / EvalWaveForm( wf ); - - tmi.matrix[0][0] = p; - tmi.matrix[1][0] = 0; - tmi.translate[0] = 0.5f - 0.5f * p; - - tmi.matrix[0][1] = 0; - tmi.matrix[1][1] = p; - tmi.translate[1] = 0.5f - 0.5f * p; - - RB_CalcTransformTexMatrix( &tmi, matrix ); -} - -/* -==================================================================== - -DEFORMATIONS - -==================================================================== -*/ - -/* -======================== -RB_CalcDeformVertexes - -======================== -*/ -void RB_CalcDeformVertexes( deformStage_t *ds ) -{ - int i; - vec3_t offset; - float scale; - float *xyz = ( float * ) tess.xyz; - float *normal = ( float * ) tess.normal; - float *table; - - if ( ds->deformationWave.frequency == 0 ) - { - scale = EvalWaveForm( &ds->deformationWave ); - - for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) - { - VectorScale( normal, scale, offset ); - - xyz[0] += offset[0]; - xyz[1] += offset[1]; - xyz[2] += offset[2]; - } - } - else - { - table = TableForFunc( ds->deformationWave.func ); - - for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) - { - float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread; - - scale = WAVEVALUE( table, ds->deformationWave.base, - ds->deformationWave.amplitude, - ds->deformationWave.phase + off, - ds->deformationWave.frequency ); - - VectorScale( normal, scale, offset ); - - xyz[0] += offset[0]; - xyz[1] += offset[1]; - xyz[2] += offset[2]; - } - } -} - -/* -========================= -RB_CalcDeformNormals - -Wiggle the normals for wavy environment mapping -========================= -*/ -void RB_CalcDeformNormals( deformStage_t *ds ) { - int i; - float scale; - float *xyz = ( float * ) tess.xyz; - float *normal = ( float * ) tess.normal; - - for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) { - scale = 0.98f; - scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, - tess.shaderTime * ds->deformationWave.frequency ); - normal[ 0 ] += ds->deformationWave.amplitude * scale; - - scale = 0.98f; - scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, - tess.shaderTime * ds->deformationWave.frequency ); - normal[ 1 ] += ds->deformationWave.amplitude * scale; - - scale = 0.98f; - scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, - tess.shaderTime * ds->deformationWave.frequency ); - normal[ 2 ] += ds->deformationWave.amplitude * scale; - - VectorNormalizeFast( normal ); - } -} - -/* -======================== -RB_CalcBulgeVertexes - -======================== -*/ -void RB_CalcBulgeVertexes( deformStage_t *ds ) { - int i; - const float *st = ( const float * ) tess.texCoords[0]; - float *xyz = ( float * ) tess.xyz; - float *normal = ( float * ) tess.normal; - float now; - - now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f; - - for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) { - int off; - float scale; - - off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now ); - - scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight; - - xyz[0] += normal[0] * scale; - xyz[1] += normal[1] * scale; - xyz[2] += normal[2] * scale; - } -} - - -/* -====================== -RB_CalcMoveVertexes - -A deformation that can move an entire surface along a wave path -====================== -*/ -void RB_CalcMoveVertexes( deformStage_t *ds ) { - int i; - float *xyz; - float *table; - float scale; - vec3_t offset; - - table = TableForFunc( ds->deformationWave.func ); - - scale = WAVEVALUE( table, ds->deformationWave.base, - ds->deformationWave.amplitude, - ds->deformationWave.phase, - ds->deformationWave.frequency ); - - VectorScale( ds->moveVector, scale, offset ); - - xyz = ( float * ) tess.xyz; - for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) { - VectorAdd( xyz, offset, xyz ); - } -} - - -/* -============= -DeformText - -Change a polygon into a bunch of text polygons -============= -*/ -void DeformText( const char *text ) { - int i; - vec3_t origin, width, height; - int len; - int ch; - float color[4]; - float bottom, top; - vec3_t mid; - - height[0] = 0; - height[1] = 0; - height[2] = -1; - CrossProduct( tess.normal[0], height, width ); - - // find the midpoint of the box - VectorClear( mid ); - bottom = 999999; - top = -999999; - for ( i = 0 ; i < 4 ; i++ ) { - VectorAdd( tess.xyz[i], mid, mid ); - if ( tess.xyz[i][2] < bottom ) { - bottom = tess.xyz[i][2]; - } - if ( tess.xyz[i][2] > top ) { - top = tess.xyz[i][2]; - } - } - VectorScale( mid, 0.25f, origin ); - - // determine the individual character size - height[0] = 0; - height[1] = 0; - height[2] = ( top - bottom ) * 0.5f; - - VectorScale( width, height[2] * -0.75f, width ); - - // determine the starting position - len = strlen( text ); - VectorMA( origin, (len-1), width, origin ); - - // clear the shader indexes - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; - - color[0] = color[1] = color[2] = color[3] = 1.0f; - - // draw each character - for ( i = 0 ; i < len ; i++ ) { - ch = text[i]; - ch &= 255; - - if ( ch != ' ' ) { - int row, col; - float frow, fcol, size; - - row = ch>>4; - col = ch&15; - - frow = row*0.0625f; - fcol = col*0.0625f; - size = 0.0625f; - - RB_AddQuadStampExt( origin, width, height, color, fcol, frow, fcol + size, frow + size ); - } - VectorMA( origin, -2, width, origin ); - } -} - -/* -================== -GlobalVectorToLocal -================== -*/ -static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) { - out[0] = DotProduct( in, backEnd.or.axis[0] ); - out[1] = DotProduct( in, backEnd.or.axis[1] ); - out[2] = DotProduct( in, backEnd.or.axis[2] ); -} - -/* -===================== -AutospriteDeform - -Assuming all the triangles for this shader are independant -quads, rebuild them as forward facing sprites -===================== -*/ -static void AutospriteDeform( void ) { - int i; - int oldVerts; - float *xyz; - vec3_t mid, delta; - float radius; - vec3_t left, up; - vec3_t leftDir, upDir; - - if ( tess.numVertexes & 3 ) { - ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count\n", tess.shader->name ); - } - if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) { - ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count\n", tess.shader->name ); - } - - oldVerts = tess.numVertexes; - tess.numVertexes = 0; - tess.numIndexes = 0; - tess.firstIndex = 0; - - if ( backEnd.currentEntity != &tr.worldEntity ) { - GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir ); - GlobalVectorToLocal( backEnd.viewParms.or.axis[2], upDir ); - } else { - VectorCopy( backEnd.viewParms.or.axis[1], leftDir ); - VectorCopy( backEnd.viewParms.or.axis[2], upDir ); - } - - for ( i = 0 ; i < oldVerts ; i+=4 ) { - // find the midpoint - xyz = tess.xyz[i]; - - mid[0] = 0.25f * (xyz[0] + xyz[4] + xyz[8] + xyz[12]); - mid[1] = 0.25f * (xyz[1] + xyz[5] + xyz[9] + xyz[13]); - mid[2] = 0.25f * (xyz[2] + xyz[6] + xyz[10] + xyz[14]); - - VectorSubtract( xyz, mid, delta ); - radius = VectorLength( delta ) * 0.707f; // / sqrt(2) - - VectorScale( leftDir, radius, left ); - VectorScale( upDir, radius, up ); - - if ( backEnd.viewParms.isMirror ) { - VectorSubtract( vec3_origin, left, left ); - } - - // compensate for scale in the axes if necessary - if ( backEnd.currentEntity->e.nonNormalizedAxes ) { - float axisLength; - axisLength = VectorLength( backEnd.currentEntity->e.axis[0] ); - if ( !axisLength ) { - axisLength = 0; - } else { - axisLength = 1.0f / axisLength; - } - VectorScale(left, axisLength, left); - VectorScale(up, axisLength, up); - } - - RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] ); - } -} - - -/* -===================== -Autosprite2Deform - -Autosprite2 will pivot a rectangular quad along the center of its long axis -===================== -*/ -int edgeVerts[6][2] = { - { 0, 1 }, - { 0, 2 }, - { 0, 3 }, - { 1, 2 }, - { 1, 3 }, - { 2, 3 } -}; - -static void Autosprite2Deform( void ) { - int i, j, k; - int indexes; - float *xyz; - vec3_t forward; - - if ( tess.numVertexes & 3 ) { - ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd vertex count", tess.shader->name ); - } - if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) { - ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count", tess.shader->name ); - } - - if ( backEnd.currentEntity != &tr.worldEntity ) { - GlobalVectorToLocal( backEnd.viewParms.or.axis[0], forward ); - } else { - VectorCopy( backEnd.viewParms.or.axis[0], forward ); - } - - // this is a lot of work for two triangles... - // we could precalculate a lot of it is an issue, but it would mess up - // the shader abstraction - for ( i = 0, indexes = 0 ; i < tess.numVertexes ; i+=4, indexes+=6 ) { - float lengths[2]; - int nums[2]; - vec3_t mid[2]; - vec3_t major, minor; - float *v1, *v2; - - // find the midpoint - xyz = tess.xyz[i]; - - // identify the two shortest edges - nums[0] = nums[1] = 0; - lengths[0] = lengths[1] = 999999; - - for ( j = 0 ; j < 6 ; j++ ) { - float l; - vec3_t temp; - - v1 = xyz + 4 * edgeVerts[j][0]; - v2 = xyz + 4 * edgeVerts[j][1]; - - VectorSubtract( v1, v2, temp ); - - l = DotProduct( temp, temp ); - if ( l < lengths[0] ) { - nums[1] = nums[0]; - lengths[1] = lengths[0]; - nums[0] = j; - lengths[0] = l; - } else if ( l < lengths[1] ) { - nums[1] = j; - lengths[1] = l; - } - } - - for ( j = 0 ; j < 2 ; j++ ) { - v1 = xyz + 4 * edgeVerts[nums[j]][0]; - v2 = xyz + 4 * edgeVerts[nums[j]][1]; - - mid[j][0] = 0.5f * (v1[0] + v2[0]); - mid[j][1] = 0.5f * (v1[1] + v2[1]); - mid[j][2] = 0.5f * (v1[2] + v2[2]); - } - - // find the vector of the major axis - VectorSubtract( mid[1], mid[0], major ); - - // cross this with the view direction to get minor axis - CrossProduct( major, forward, minor ); - VectorNormalize( minor ); - - // re-project the points - for ( j = 0 ; j < 2 ; j++ ) { - float l; - - v1 = xyz + 4 * edgeVerts[nums[j]][0]; - v2 = xyz + 4 * edgeVerts[nums[j]][1]; - - l = 0.5 * sqrt( lengths[j] ); - - // we need to see which direction this edge - // is used to determine direction of projection - for ( k = 0 ; k < 5 ; k++ ) { - if ( tess.indexes[ indexes + k ] == i + edgeVerts[nums[j]][0] - && tess.indexes[ indexes + k + 1 ] == i + edgeVerts[nums[j]][1] ) { - break; - } - } - - if ( k == 5 ) { - VectorMA( mid[j], l, minor, v1 ); - VectorMA( mid[j], -l, minor, v2 ); - } else { - VectorMA( mid[j], -l, minor, v1 ); - VectorMA( mid[j], l, minor, v2 ); - } - } - } -} - - -/* -===================== -RB_DeformTessGeometry - -===================== -*/ -void RB_DeformTessGeometry( void ) { - int i; - deformStage_t *ds; - - if(!ShaderRequiresCPUDeforms(tess.shader)) - { - // we don't need the following CPU deforms - return; - } - - for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) { - ds = &tess.shader->deforms[ i ]; - - switch ( ds->deformation ) { - case DEFORM_NONE: - break; - case DEFORM_NORMALS: - RB_CalcDeformNormals( ds ); - break; - case DEFORM_WAVE: - RB_CalcDeformVertexes( ds ); - break; - case DEFORM_BULGE: - RB_CalcBulgeVertexes( ds ); - break; - case DEFORM_MOVE: - RB_CalcMoveVertexes( ds ); - break; - case DEFORM_PROJECTION_SHADOW: - RB_ProjectionShadowDeform(); - break; - case DEFORM_AUTOSPRITE: - AutospriteDeform(); - break; - case DEFORM_AUTOSPRITE2: - Autosprite2Deform(); - break; - case DEFORM_TEXT0: - case DEFORM_TEXT1: - case DEFORM_TEXT2: - case DEFORM_TEXT3: - case DEFORM_TEXT4: - case DEFORM_TEXT5: - case DEFORM_TEXT6: - case DEFORM_TEXT7: - DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] ); - break; - } - } -} - -/* -==================================================================== - -COLORS - -==================================================================== -*/ - - -/* -** RB_CalcColorFromEntity -*/ -void RB_CalcColorFromEntity( unsigned char *dstColors ) -{ - int i; - int *pColors = ( int * ) dstColors; - int c; - - if ( !backEnd.currentEntity ) - return; - - c = * ( int * ) backEnd.currentEntity->e.shaderRGBA; - - for ( i = 0; i < tess.numVertexes; i++, pColors++ ) - { - *pColors = c; - } -} - -/* -** RB_CalcColorFromOneMinusEntity -*/ -void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) -{ - int i; - int *pColors = ( int * ) dstColors; - unsigned char invModulate[4]; - int c; - - if ( !backEnd.currentEntity ) - return; - - invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0]; - invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1]; - invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2]; - invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it - - c = * ( int * ) invModulate; - - for ( i = 0; i < tess.numVertexes; i++, pColors++ ) - { - *pColors = c; - } -} - -/* -** RB_CalcAlphaFromEntity -*/ -void RB_CalcAlphaFromEntity( unsigned char *dstColors ) -{ - int i; - - if ( !backEnd.currentEntity ) - return; - - dstColors += 3; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - *dstColors = backEnd.currentEntity->e.shaderRGBA[3]; - } -} - -/* -** RB_CalcAlphaFromOneMinusEntity -*/ -void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ) -{ - int i; - - if ( !backEnd.currentEntity ) - return; - - dstColors += 3; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - *dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3]; - } -} - -/* -** RB_CalcWaveColorSingle -*/ -float RB_CalcWaveColorSingle( const waveForm_t *wf ) -{ - float glow; - - if ( wf->func == GF_NOISE ) { - glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude; - } else { - glow = EvalWaveForm( wf ) * tr.identityLight; - } - - if ( glow < 0 ) { - glow = 0; - } - else if ( glow > 1 ) { - glow = 1; - } - - return glow; -} - -/* -** RB_CalcWaveColor -*/ -void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ) -{ - int i; - int v; - float glow; - int *colors = ( int * ) dstColors; - byte color[4]; - - glow = RB_CalcWaveColorSingle( wf ); - - v = ri.ftol(255 * glow); - color[0] = color[1] = color[2] = v; - color[3] = 255; - v = *(int *)color; - - for ( i = 0; i < tess.numVertexes; i++, colors++ ) { - *colors = v; - } -} - -/* -** RB_CalcWaveAlphaSingle -*/ -float RB_CalcWaveAlphaSingle( const waveForm_t *wf ) -{ - return EvalWaveFormClamped( wf ); -} - -/* -** RB_CalcWaveAlpha -*/ -void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors ) -{ - int i; - int v; - float glow; - - glow = EvalWaveFormClamped( wf ); - - v = 255 * glow; - - for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 ) - { - dstColors[3] = v; - } -} - -/* -** RB_CalcModulateColorsByFog -*/ -void RB_CalcModulateColorsByFog( unsigned char *colors ) { - int i; - float texCoords[SHADER_MAX_VERTEXES][2]; - - // calculate texcoords so we can derive density - // this is not wasted, because it would only have - // been previously called if the surface was opaque - RB_CalcFogTexCoords( texCoords[0] ); - - for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { - float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); - colors[0] *= f; - colors[1] *= f; - colors[2] *= f; - } -} - -/* -** RB_CalcModulateAlphasByFog -*/ -void RB_CalcModulateAlphasByFog( unsigned char *colors ) { - int i; - float texCoords[SHADER_MAX_VERTEXES][2]; - - // calculate texcoords so we can derive density - // this is not wasted, because it would only have - // been previously called if the surface was opaque - RB_CalcFogTexCoords( texCoords[0] ); - - for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { - float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); - colors[3] *= f; - } -} - -/* -** RB_CalcModulateRGBAsByFog -*/ -void RB_CalcModulateRGBAsByFog( unsigned char *colors ) { - int i; - float texCoords[SHADER_MAX_VERTEXES][2]; - - // calculate texcoords so we can derive density - // this is not wasted, because it would only have - // been previously called if the surface was opaque - RB_CalcFogTexCoords( texCoords[0] ); - - for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) { - float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] ); - colors[0] *= f; - colors[1] *= f; - colors[2] *= f; - colors[3] *= f; - } -} - - -/* -==================================================================== - -TEX COORDS - -==================================================================== -*/ - -/* -======================== -RB_CalcFogTexCoords - -To do the clipped fog plane really correctly, we should use -projected textures, but I don't trust the drivers and it -doesn't fit our shader data. -======================== -*/ -void RB_CalcFogTexCoords( float *st ) { - int i; - float *v; - float s, t; - float eyeT; - qboolean eyeOutside; - fog_t *fog; - vec3_t local; - vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; - - fog = tr.world->fogs + tess.fogNum; - - // all fogging distance is based on world Z units - VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local ); - fogDistanceVector[0] = -backEnd.or.modelMatrix[2]; - fogDistanceVector[1] = -backEnd.or.modelMatrix[6]; - fogDistanceVector[2] = -backEnd.or.modelMatrix[10]; - fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] ); - - // scale the fog vectors based on the fog's thickness - fogDistanceVector[0] *= fog->tcScale; - fogDistanceVector[1] *= fog->tcScale; - fogDistanceVector[2] *= fog->tcScale; - fogDistanceVector[3] *= fog->tcScale; - - // rotate the gradient vector for this orientation - if ( fog->hasSurface ) { - fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] + - fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2]; - fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] + - fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2]; - fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] + - fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2]; - fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface ); - - eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3]; - } else { - eyeT = 1; // non-surface fog always has eye inside - } - - // see if the viewpoint is outside - // this is needed for clipping distance even for constant fog - - if ( eyeT < 0 ) { - eyeOutside = qtrue; - } else { - eyeOutside = qfalse; - } - - fogDistanceVector[3] += 1.0/512; - - // calculate density for each point - for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) { - // calculate the length in fog - s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3]; - t = DotProduct( v, fogDepthVector ) + fogDepthVector[3]; - - // partially clipped fogs use the T axis - if ( eyeOutside ) { - if ( t < 1.0 ) { - t = 1.0/32; // point is outside, so no fogging - } else { - t = 1.0/32 + 30.0/32 * t / ( t - eyeT ); // cut the distance at the fog plane - } - } else { - if ( t < 0 ) { - t = 1.0/32; // point is outside, so no fogging - } else { - t = 31.0/32; - } - } - - st[0] = s; - st[1] = t; - st += 2; - } -} - - - -/* -** RB_CalcEnvironmentTexCoords -*/ -void RB_CalcEnvironmentTexCoords( float *st ) -{ - int i; - float *v, *normal; - vec3_t viewer, reflected; - float d; - - v = tess.xyz[0]; - normal = tess.normal[0]; - - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) - { - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - VectorNormalizeFast (viewer); - - d = DotProduct (normal, viewer); - - reflected[0] = normal[0]*2*d - viewer[0]; - reflected[1] = normal[1]*2*d - viewer[1]; - reflected[2] = normal[2]*2*d - viewer[2]; - - st[0] = 0.5 + reflected[1] * 0.5; - st[1] = 0.5 - reflected[2] * 0.5; - } -} - -/* -** RB_CalcTurbulentTexCoords -*/ -void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st ) -{ - int i; - float now; - - now = ( wf->phase + tess.shaderTime * wf->frequency ); - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - float s = st[0]; - float t = st[1]; - - st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; - st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude; - } -} - -void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix ) -{ - float now; - - now = ( wf->phase + tess.shaderTime * wf->frequency ); - - // bit of a hack here, hide amplitude and now in the matrix - // the vertex program will extract them and perform a turbulent pass last if it's nonzero - - matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude; - matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; -} - -/* -** RB_CalcScaleTexCoords -*/ -void RB_CalcScaleTexCoords( const float scale[2], float *st ) -{ - int i; - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - st[0] *= scale[0]; - st[1] *= scale[1]; - } -} - -void RB_CalcScaleTexMatrix( const float scale[2], float *matrix ) -{ - matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f; - matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; -} - -/* -** RB_CalcScrollTexCoords -*/ -void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st ) -{ - int i; - float timeScale = tess.shaderTime; - float adjustedScrollS, adjustedScrollT; - - adjustedScrollS = scrollSpeed[0] * timeScale; - adjustedScrollT = scrollSpeed[1] * timeScale; - - // clamp so coordinates don't continuously get larger, causing problems - // with hardware limits - adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); - adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - st[0] += adjustedScrollS; - st[1] += adjustedScrollT; - } -} - -void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix ) -{ - float timeScale = tess.shaderTime; - float adjustedScrollS, adjustedScrollT; - - adjustedScrollS = scrollSpeed[0] * timeScale; - adjustedScrollT = scrollSpeed[1] * timeScale; - - // clamp so coordinates don't continuously get larger, causing problems - // with hardware limits - adjustedScrollS = adjustedScrollS - floor( adjustedScrollS ); - adjustedScrollT = adjustedScrollT - floor( adjustedScrollT ); - - - matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f; - matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; -} - -/* -** RB_CalcTransformTexCoords -*/ -void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st ) -{ - int i; - - for ( i = 0; i < tess.numVertexes; i++, st += 2 ) - { - float s = st[0]; - float t = st[1]; - - st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0]; - st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1]; - } -} - -void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix ) -{ - matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f; - matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f; - matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f; - matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f; -} - -/* -** RB_CalcRotateTexCoords -*/ -void RB_CalcRotateTexCoords( float degsPerSecond, float *st ) -{ - float timeScale = tess.shaderTime; - float degs; - int index; - float sinValue, cosValue; - texModInfo_t tmi; - - degs = -degsPerSecond * timeScale; - index = degs * ( FUNCTABLE_SIZE / 360.0f ); - - sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; - cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; - - tmi.matrix[0][0] = cosValue; - tmi.matrix[1][0] = -sinValue; - tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; - - tmi.matrix[0][1] = sinValue; - tmi.matrix[1][1] = cosValue; - tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; - - RB_CalcTransformTexCoords( &tmi, st ); -} - -void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix ) -{ - float timeScale = tess.shaderTime; - float degs; - int index; - float sinValue, cosValue; - texModInfo_t tmi; - - degs = -degsPerSecond * timeScale; - index = degs * ( FUNCTABLE_SIZE / 360.0f ); - - sinValue = tr.sinTable[ index & FUNCTABLE_MASK ]; - cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ]; - - tmi.matrix[0][0] = cosValue; - tmi.matrix[1][0] = -sinValue; - tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue; - - tmi.matrix[0][1] = sinValue; - tmi.matrix[1][1] = cosValue; - tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue; - - RB_CalcTransformTexMatrix( &tmi, matrix ); -} -/* -** RB_CalcSpecularAlpha -** -** Calculates specular coefficient and places it in the alpha channel -*/ -vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically - -void RB_CalcSpecularAlpha( unsigned char *alphas ) { - int i; - float *v, *normal; - vec3_t viewer, reflected; - float l, d; - int b; - vec3_t lightDir; - int numVertexes; - - v = tess.xyz[0]; - normal = tess.normal[0]; - - alphas += 3; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) { - float ilength; - - VectorSubtract( lightOrigin, v, lightDir ); -// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) ); - VectorNormalizeFast( lightDir ); - - // calculate the specular color - d = DotProduct (normal, lightDir); -// d *= ilength; - - // we don't optimize for the d < 0 case since this tends to - // cause visual artifacts such as faceted "snapping" - reflected[0] = normal[0]*2*d - lightDir[0]; - reflected[1] = normal[1]*2*d - lightDir[1]; - reflected[2] = normal[2]*2*d - lightDir[2]; - - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - ilength = Q_rsqrt( DotProduct( viewer, viewer ) ); - l = DotProduct (reflected, viewer); - l *= ilength; - - if (l < 0) { - b = 0; - } else { - l = l*l; - l = l*l; - b = l * 255; - if (b > 255) { - b = 255; - } - } - - *alphas = b; - } -} - -/* -** RB_CalcDiffuseColor -** -** The basic vertex lighting calc -*/ -#if idppc_altivec -static void RB_CalcDiffuseColor_altivec( unsigned char *colors ) -{ - int i; - float *v, *normal; - trRefEntity_t *ent; - int ambientLightInt; - vec3_t lightDir; - int numVertexes; - vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff); - vector float ambientLightVec; - vector float directedLightVec; - vector float lightDirVec; - vector float normalVec0, normalVec1; - vector float incomingVec0, incomingVec1, incomingVec2; - vector float zero, jVec; - vector signed int jVecInt; - vector signed short jVecShort; - vector unsigned char jVecChar, normalPerm; - ent = backEnd.currentEntity; - ambientLightInt = ent->ambientLightInt; - // A lot of this could be simplified if we made sure - // entities light info was 16-byte aligned. - jVecChar = vec_lvsl(0, ent->ambientLight); - ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight); - jVec = vec_ld(11, (vector float *)ent->ambientLight); - ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar); - - jVecChar = vec_lvsl(0, ent->directedLight); - directedLightVec = vec_ld(0,(vector float *)ent->directedLight); - jVec = vec_ld(11,(vector float *)ent->directedLight); - directedLightVec = vec_perm(directedLightVec,jVec,jVecChar); - - jVecChar = vec_lvsl(0, ent->lightDir); - lightDirVec = vec_ld(0,(vector float *)ent->lightDir); - jVec = vec_ld(11,(vector float *)ent->lightDir); - lightDirVec = vec_perm(lightDirVec,jVec,jVecChar); - - zero = (vector float)vec_splat_s8(0); - VectorCopy( ent->lightDir, lightDir ); - - v = tess.xyz[0]; - normal = tess.normal[0]; - - normalPerm = vec_lvsl(0,normal); - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - normalVec0 = vec_ld(0,(vector float *)normal); - normalVec1 = vec_ld(11,(vector float *)normal); - normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm); - incomingVec0 = vec_madd(normalVec0, lightDirVec, zero); - incomingVec1 = vec_sld(incomingVec0,incomingVec0,4); - incomingVec2 = vec_add(incomingVec0,incomingVec1); - incomingVec1 = vec_sld(incomingVec1,incomingVec1,4); - incomingVec2 = vec_add(incomingVec2,incomingVec1); - incomingVec0 = vec_splat(incomingVec2,0); - incomingVec0 = vec_max(incomingVec0,zero); - normalPerm = vec_lvsl(12,normal); - jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec); - jVecInt = vec_cts(jVec,0); // RGBx - jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx - jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx - jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 - vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color - } -} -#endif - -static void RB_CalcDiffuseColor_scalar( unsigned char *colors ) -{ - int i, j; - float *v, *normal; - float incoming; - trRefEntity_t *ent; - int ambientLightInt; - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - int numVertexes; - ent = backEnd.currentEntity; - ambientLightInt = ent->ambientLightInt; - VectorCopy( ent->ambientLight, ambientLight ); - VectorCopy( ent->directedLight, directedLight ); - VectorCopy( ent->lightDir, lightDir ); - - v = tess.xyz[0]; - normal = tess.normal[0]; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - incoming = DotProduct (normal, lightDir); - if ( incoming <= 0 ) { - *(int *)&colors[i*4] = ambientLightInt; - continue; - } - j = ri.ftol(ambientLight[0] + incoming * directedLight[0]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+0] = j; - - j = ri.ftol(ambientLight[1] + incoming * directedLight[1]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+1] = j; - - j = ri.ftol(ambientLight[2] + incoming * directedLight[2]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+2] = j; - - colors[i*4+3] = 255; - } -} - -void RB_CalcDiffuseColor( unsigned char *colors ) -{ -#if idppc_altivec - if (com_altivec->integer) { - // must be in a seperate function or G3 systems will crash. - RB_CalcDiffuseColor_altivec( colors ); - return; - } -#endif - RB_CalcDiffuseColor_scalar( colors ); -} - - - - - diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c deleted file mode 100644 index 97cb138d..00000000 --- a/code/renderergl2/tr_shader.c +++ /dev/null @@ -1,3710 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "tr_local.h" - -// tr_shader.c -- this file deals with the parsing and definition of shaders - -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 shader_t shader; -static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS]; - -#define FILE_HASH_SIZE 1024 -static shader_t* hashTable[FILE_HASH_SIZE]; - -#define MAX_SHADERTEXT_HASH 2048 -static char **shaderTextHashTable[MAX_SHADERTEXT_HASH]; - -/* -================ -return a hash value for the filename -================ -*/ -#ifdef __GNUCC__ - #warning TODO: check if long is ok here -#endif -static long generateHashValue( const char *fname, const int size ) { - int i; - long hash; - char letter; - - hash = 0; - i = 0; - while (fname[i] != '\0') { - letter = tolower(fname[i]); - if (letter =='.') break; // don't include extension - if (letter =='\\') letter = '/'; // damn path names - if (letter == PATH_SEP) letter = '/'; // damn path names - hash+=(long)(letter)*(i+119); - i++; - } - hash = (hash ^ (hash >> 10) ^ (hash >> 20)); - hash &= (size-1); - return hash; -} - -void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) { - char strippedName[MAX_QPATH]; - int hash; - shader_t *sh, *sh2; - qhandle_t h; - - sh = R_FindShaderByName( shaderName ); - if (sh == NULL || sh == tr.defaultShader) { - h = RE_RegisterShaderLightMap(shaderName, 0); - sh = R_GetShaderByHandle(h); - } - if (sh == NULL || sh == tr.defaultShader) { - ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName ); - return; - } - - sh2 = R_FindShaderByName( newShaderName ); - if (sh2 == NULL || sh2 == tr.defaultShader) { - h = RE_RegisterShaderLightMap(newShaderName, 0); - sh2 = R_GetShaderByHandle(h); - } - - if (sh2 == NULL || sh2 == tr.defaultShader) { - ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName ); - return; - } - - // remap all the shaders with the given name - // even tho they might have different lightmaps - COM_StripExtension(shaderName, strippedName, sizeof(strippedName)); - hash = generateHashValue(strippedName, FILE_HASH_SIZE); - for (sh = hashTable[hash]; sh; sh = sh->next) { - if (Q_stricmp(sh->name, strippedName) == 0) { - if (sh != sh2) { - sh->remappedShader = sh2; - } else { - sh->remappedShader = NULL; - } - } - } - if (timeOffset) { - sh2->timeOffset = atof(timeOffset); - } -} - -/* -=============== -ParseVector -=============== -*/ -static qboolean ParseVector( char **text, int count, float *v ) { - char *token; - int i; - - // FIXME: spaces are currently required after parens, should change parseext... - token = COM_ParseExt( text, qfalse ); - if ( strcmp( token, "(" ) ) { - ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name ); - return qfalse; - } - - for ( i = 0 ; i < count ; i++ ) { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) { - ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name ); - return qfalse; - } - v[i] = atof( token ); - } - - token = COM_ParseExt( text, qfalse ); - if ( strcmp( token, ")" ) ) { - ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name ); - return qfalse; - } - - return qtrue; -} - - -/* -=============== -NameToAFunc -=============== -*/ -static unsigned NameToAFunc( const char *funcname ) -{ - if ( !Q_stricmp( funcname, "GT0" ) ) - { - return GLS_ATEST_GT_0; - } - else if ( !Q_stricmp( funcname, "LT128" ) ) - { - return GLS_ATEST_LT_80; - } - else if ( !Q_stricmp( funcname, "GE128" ) ) - { - return GLS_ATEST_GE_80; - } - - ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name ); - return 0; -} - - -/* -=============== -NameToSrcBlendMode -=============== -*/ -static int NameToSrcBlendMode( const char *name ) -{ - if ( !Q_stricmp( name, "GL_ONE" ) ) - { - return GLS_SRCBLEND_ONE; - } - else if ( !Q_stricmp( name, "GL_ZERO" ) ) - { - return GLS_SRCBLEND_ZERO; - } - else if ( !Q_stricmp( name, "GL_DST_COLOR" ) ) - { - return GLS_SRCBLEND_DST_COLOR; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) ) - { - return GLS_SRCBLEND_ONE_MINUS_DST_COLOR; - } - else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) - { - return GLS_SRCBLEND_SRC_ALPHA; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) - { - return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA; - } - else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) - { - return GLS_SRCBLEND_DST_ALPHA; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) - { - return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA; - } - else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) ) - { - return GLS_SRCBLEND_ALPHA_SATURATE; - } - - ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name ); - return GLS_SRCBLEND_ONE; -} - -/* -=============== -NameToDstBlendMode -=============== -*/ -static int NameToDstBlendMode( const char *name ) -{ - if ( !Q_stricmp( name, "GL_ONE" ) ) - { - return GLS_DSTBLEND_ONE; - } - else if ( !Q_stricmp( name, "GL_ZERO" ) ) - { - return GLS_DSTBLEND_ZERO; - } - else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) ) - { - return GLS_DSTBLEND_SRC_ALPHA; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) ) - { - return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - } - else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) ) - { - return GLS_DSTBLEND_DST_ALPHA; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) ) - { - return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA; - } - else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) ) - { - return GLS_DSTBLEND_SRC_COLOR; - } - else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) ) - { - return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR; - } - - ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name ); - return GLS_DSTBLEND_ONE; -} - -/* -=============== -NameToGenFunc -=============== -*/ -static genFunc_t NameToGenFunc( const char *funcname ) -{ - if ( !Q_stricmp( funcname, "sin" ) ) - { - return GF_SIN; - } - else if ( !Q_stricmp( funcname, "square" ) ) - { - return GF_SQUARE; - } - else if ( !Q_stricmp( funcname, "triangle" ) ) - { - return GF_TRIANGLE; - } - else if ( !Q_stricmp( funcname, "sawtooth" ) ) - { - return GF_SAWTOOTH; - } - else if ( !Q_stricmp( funcname, "inversesawtooth" ) ) - { - return GF_INVERSE_SAWTOOTH; - } - else if ( !Q_stricmp( funcname, "noise" ) ) - { - return GF_NOISE; - } - - ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name ); - return GF_SIN; -} - - -/* -=================== -ParseWaveForm -=================== -*/ -static void ParseWaveForm( char **text, waveForm_t *wave ) -{ - char *token; - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); - return; - } - wave->func = NameToGenFunc( token ); - - // BASE, AMP, PHASE, FREQ - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); - return; - } - wave->base = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); - return; - } - wave->amplitude = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); - return; - } - wave->phase = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name ); - return; - } - wave->frequency = atof( token ); -} - - -/* -=================== -ParseTexMod -=================== -*/ -static void ParseTexMod( char *_text, shaderStage_t *stage ) -{ - const char *token; - char **text = &_text; - texModInfo_t *tmi; - - if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) { - ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'", shader.name ); - return; - } - - tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods]; - stage->bundle[0].numTexMods++; - - token = COM_ParseExt( text, qfalse ); - - // - // turb - // - if ( !Q_stricmp( token, "turb" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.base = atof( token ); - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); - return; - } - tmi->wave.amplitude = atof( token ); - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); - return; - } - tmi->wave.phase = atof( token ); - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name ); - return; - } - tmi->wave.frequency = atof( token ); - - tmi->type = TMOD_TURBULENT; - } - // - // scale - // - else if ( !Q_stricmp( token, "scale" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name ); - return; - } - tmi->scale[0] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name ); - return; - } - tmi->scale[1] = atof( token ); - tmi->type = TMOD_SCALE; - } - // - // scroll - // - else if ( !Q_stricmp( token, "scroll" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name ); - return; - } - tmi->scroll[0] = atof( token ); - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name ); - return; - } - tmi->scroll[1] = atof( token ); - tmi->type = TMOD_SCROLL; - } - // - // stretch - // - else if ( !Q_stricmp( token, "stretch" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.func = NameToGenFunc( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.base = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.amplitude = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.phase = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name ); - return; - } - tmi->wave.frequency = atof( token ); - - tmi->type = TMOD_STRETCH; - } - // - // transform - // - else if ( !Q_stricmp( token, "transform" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->matrix[0][0] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->matrix[0][1] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->matrix[1][0] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->matrix[1][1] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->translate[0] = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name ); - return; - } - tmi->translate[1] = atof( token ); - - tmi->type = TMOD_TRANSFORM; - } - // - // rotate - // - else if ( !Q_stricmp( token, "rotate" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name ); - return; - } - tmi->rotateSpeed = atof( token ); - tmi->type = TMOD_ROTATE; - } - // - // entityTranslate - // - else if ( !Q_stricmp( token, "entityTranslate" ) ) - { - tmi->type = TMOD_ENTITY_TRANSLATE; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name ); - } -} - - -/* -=================== -ParseStage -=================== -*/ -static qboolean ParseStage( shaderStage_t *stage, char **text ) -{ - char *token; - int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0; - qboolean depthMaskExplicit = qfalse; - - stage->active = qtrue; - - while ( 1 ) - { - token = COM_ParseExt( text, qtrue ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" ); - return qfalse; - } - - if ( token[0] == '}' ) - { - break; - } - // - // map - // - else if ( !Q_stricmp( token, "map" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if ( !Q_stricmp( token, "$whiteimage" ) ) - { - stage->bundle[0].image[0] = tr.whiteImage; - continue; - } - else if ( !Q_stricmp( token, "$lightmap" ) ) - { - stage->bundle[0].isLightmap = qtrue; - if ( shader.lightmapIndex < 0 ) { - stage->bundle[0].image[0] = tr.whiteImage; - } else { - stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; - } - continue; - } - else if ( !Q_stricmp( token, "$deluxemap" ) ) - { - if (!tr.worldDeluxeMapping) - { - ri.Printf( PRINT_WARNING, "WARNING: shader '%s' wants a deluxe map in a map compiled without them\n", shader.name ); - return qfalse; - } - - stage->bundle[0].isLightmap = qtrue; - if ( shader.lightmapIndex < 0 ) { - stage->bundle[0].image[0] = tr.whiteImage; - } else { - stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex]; - } - continue; - } - else - { - imgType_t type = IMGTYPE_COLORALPHA; - imgFlags_t flags = IMGFLAG_NONE; - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP) - { - type = IMGTYPE_NORMAL; - flags |= IMGFLAG_NOLIGHTSCALE; - - if (stage->type == ST_NORMALPARALLAXMAP) - type = IMGTYPE_NORMALHEIGHT; - } - else - { - if (r_genNormalMaps->integer) - flags |= IMGFLAG_GENNORMALMAP; - - if (r_srgb->integer) - flags |= IMGFLAG_SRGB; - } - - stage->bundle[0].image[0] = R_FindImageFile( token, type, flags ); - - if ( !stage->bundle[0].image[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - } - } - // - // clampmap - // - else if ( !Q_stricmp( token, "clampmap" ) ) - { - imgType_t type = IMGTYPE_COLORALPHA; - imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_SRGB; - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP) - { - type = IMGTYPE_NORMAL; - flags |= IMGFLAG_NOLIGHTSCALE; - - if (stage->type == ST_NORMALPARALLAXMAP) - type = IMGTYPE_NORMALHEIGHT; - } - else - { - if (r_genNormalMaps->integer) - flags |= IMGFLAG_GENNORMALMAP; - - if (r_srgb->integer) - flags |= IMGFLAG_SRGB; - } - - - stage->bundle[0].image[0] = R_FindImageFile( token, type, flags ); - if ( !stage->bundle[0].image[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - } - // - // animMap .... - // - else if ( !Q_stricmp( token, "animMap" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - stage->bundle[0].imageAnimationSpeed = atof( token ); - - // parse up to MAX_IMAGE_ANIMATIONS animations - while ( 1 ) { - int num; - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) { - break; - } - num = stage->bundle[0].numImageAnimations; - if ( num < MAX_IMAGE_ANIMATIONS ) { - imgFlags_t flags = IMGFLAG_SRGB; - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); - if ( !stage->bundle[0].image[num] ) - { - ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - stage->bundle[0].numImageAnimations++; - } - } - } - else if ( !Q_stricmp( token, "videoMap" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); - if (stage->bundle[0].videoMapHandle != -1) { - stage->bundle[0].isVideoMap = qtrue; - stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle]; - } - } - // - // alphafunc - // - else if ( !Q_stricmp( token, "alphaFunc" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - atestBits = NameToAFunc( token ); - } - // - // depthFunc - // - else if ( !Q_stricmp( token, "depthfunc" ) ) - { - token = COM_ParseExt( text, qfalse ); - - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if ( !Q_stricmp( token, "lequal" ) ) - { - depthFuncBits = 0; - } - else if ( !Q_stricmp( token, "equal" ) ) - { - depthFuncBits = GLS_DEPTHFUNC_EQUAL; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // detail - // - else if ( !Q_stricmp( token, "detail" ) ) - { - stage->isDetail = qtrue; - } - // - // blendfunc - // or blendfunc - // - else if ( !Q_stricmp( token, "blendfunc" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); - continue; - } - // check for "simple" blends first - if ( !Q_stricmp( token, "add" ) ) { - blendSrcBits = GLS_SRCBLEND_ONE; - blendDstBits = GLS_DSTBLEND_ONE; - } else if ( !Q_stricmp( token, "filter" ) ) { - blendSrcBits = GLS_SRCBLEND_DST_COLOR; - blendDstBits = GLS_DSTBLEND_ZERO; - } else if ( !Q_stricmp( token, "blend" ) ) { - blendSrcBits = GLS_SRCBLEND_SRC_ALPHA; - blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - } else { - // complex double blends - blendSrcBits = NameToSrcBlendMode( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); - continue; - } - blendDstBits = NameToDstBlendMode( token ); - } - - // clear depth mask for blended surfaces - if ( !depthMaskExplicit ) - { - depthMaskBits = 0; - } - } - // - // stage - // - else if(!Q_stricmp(token, "stage")) - { - token = COM_ParseExt(text, qfalse); - if(token[0] == 0) - { - ri.Printf(PRINT_WARNING, "WARNING: missing parameters for stage in shader '%s'\n", shader.name); - continue; - } - - if(!Q_stricmp(token, "diffuseMap")) - { - stage->type = ST_DIFFUSEMAP; - } - else if(!Q_stricmp(token, "normalMap") || !Q_stricmp(token, "bumpMap")) - { - stage->type = ST_NORMALMAP; - } - else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap")) - { - if (r_parallaxMapping->integer) - stage->type = ST_NORMALPARALLAXMAP; - else - stage->type = ST_NORMALMAP; - } - else if(!Q_stricmp(token, "specularMap")) - { - stage->type = ST_SPECULARMAP; - stage->materialInfo[0] = 0.04f; - stage->materialInfo[1] = 256.0f; - } - else - { - ri.Printf(PRINT_WARNING, "WARNING: unknown stage parameter '%s' in shader '%s'\n", token, shader.name); - continue; - } - } - // - // specularReflectance - // - else if (!Q_stricmp(token, "specularreflectance")) - { - token = COM_ParseExt(text, qfalse); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name ); - continue; - } - stage->materialInfo[0] = atof( token ); - } - // - // specularExponent - // - else if (!Q_stricmp(token, "specularexponent")) - { - token = COM_ParseExt(text, qfalse); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular exponent in shader '%s'\n", shader.name ); - continue; - } - stage->materialInfo[1] = atof( token ); - } - // - // rgbGen - // - else if ( !Q_stricmp( token, "rgbGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "wave" ) ) - { - ParseWaveForm( text, &stage->rgbWave ); - stage->rgbGen = CGEN_WAVEFORM; - } - else if ( !Q_stricmp( token, "const" ) ) - { - vec3_t color; - - ParseVector( text, 3, color ); - stage->constantColor[0] = 255 * color[0]; - stage->constantColor[1] = 255 * color[1]; - stage->constantColor[2] = 255 * color[2]; - - stage->rgbGen = CGEN_CONST; - } - else if ( !Q_stricmp( token, "identity" ) ) - { - stage->rgbGen = CGEN_IDENTITY; - } - else if ( !Q_stricmp( token, "identityLighting" ) ) - { - stage->rgbGen = CGEN_IDENTITY_LIGHTING; - } - else if ( !Q_stricmp( token, "entity" ) ) - { - stage->rgbGen = CGEN_ENTITY; - } - else if ( !Q_stricmp( token, "oneMinusEntity" ) ) - { - stage->rgbGen = CGEN_ONE_MINUS_ENTITY; - } - else if ( !Q_stricmp( token, "vertex" ) ) - { - stage->rgbGen = CGEN_VERTEX; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "exactVertex" ) ) - { - stage->rgbGen = CGEN_EXACT_VERTEX; - } - else if ( !Q_stricmp( token, "vertexLit" ) ) - { - stage->rgbGen = CGEN_VERTEX_LIT; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "exactVertexLit" ) ) - { - stage->rgbGen = CGEN_EXACT_VERTEX_LIT; - } - else if ( !Q_stricmp( token, "lightingDiffuse" ) ) - { - stage->rgbGen = CGEN_LIGHTING_DIFFUSE; - } - else if ( !Q_stricmp( token, "oneMinusVertex" ) ) - { - stage->rgbGen = CGEN_ONE_MINUS_VERTEX; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // alphaGen - // - else if ( !Q_stricmp( token, "alphaGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "wave" ) ) - { - ParseWaveForm( text, &stage->alphaWave ); - stage->alphaGen = AGEN_WAVEFORM; - } - else if ( !Q_stricmp( token, "const" ) ) - { - token = COM_ParseExt( text, qfalse ); - stage->constantColor[3] = 255 * atof( token ); - stage->alphaGen = AGEN_CONST; - } - else if ( !Q_stricmp( token, "identity" ) ) - { - stage->alphaGen = AGEN_IDENTITY; - } - else if ( !Q_stricmp( token, "entity" ) ) - { - stage->alphaGen = AGEN_ENTITY; - } - else if ( !Q_stricmp( token, "oneMinusEntity" ) ) - { - stage->alphaGen = AGEN_ONE_MINUS_ENTITY; - } - else if ( !Q_stricmp( token, "vertex" ) ) - { - stage->alphaGen = AGEN_VERTEX; - } - else if ( !Q_stricmp( token, "lightingSpecular" ) ) - { - stage->alphaGen = AGEN_LIGHTING_SPECULAR; - } - else if ( !Q_stricmp( token, "oneMinusVertex" ) ) - { - stage->alphaGen = AGEN_ONE_MINUS_VERTEX; - } - else if ( !Q_stricmp( token, "portal" ) ) - { - stage->alphaGen = AGEN_PORTAL; - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - shader.portalRange = 256; - ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name ); - } - else - { - shader.portalRange = atof( token ); - } - } - else if ( !Q_stricmp( token, "fresnel" ) ) - { - stage->alphaGen = AGEN_FRESNEL; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // tcGen - // - else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "environment" ) ) - { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; - } - else if ( !Q_stricmp( token, "lightmap" ) ) - { - stage->bundle[0].tcGen = TCGEN_LIGHTMAP; - } - else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) ) - { - stage->bundle[0].tcGen = TCGEN_TEXTURE; - } - else if ( !Q_stricmp( token, "vector" ) ) - { - ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] ); - ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] ); - - stage->bundle[0].tcGen = TCGEN_VECTOR; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name ); - } - } - // - // tcMod <...> - // - else if ( !Q_stricmp( token, "tcMod" ) ) - { - char buffer[1024] = ""; - - while ( 1 ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - break; - strcat( buffer, token ); - strcat( buffer, " " ); - } - - ParseTexMod( buffer, stage ); - - continue; - } - // - // depthmask - // - else if ( !Q_stricmp( token, "depthwrite" ) ) - { - depthMaskBits = GLS_DEPTHMASK_TRUE; - depthMaskExplicit = qtrue; - - continue; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - } - - // - // if cgen isn't explicitly specified, use either identity or identitylighting - // - if ( stage->rgbGen == CGEN_BAD ) { - if ( blendSrcBits == 0 || - blendSrcBits == GLS_SRCBLEND_ONE || - blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) { - stage->rgbGen = CGEN_IDENTITY_LIGHTING; - } else { - stage->rgbGen = CGEN_IDENTITY; - } - } - - - // - // implicitly assume that a GL_ONE GL_ZERO blend mask disables blending - // - if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && - ( blendDstBits == GLS_DSTBLEND_ZERO ) ) - { - blendDstBits = blendSrcBits = 0; - depthMaskBits = GLS_DEPTHMASK_TRUE; - } - - // decide which agens we can skip - if ( stage->alphaGen == AGEN_IDENTITY ) { - if ( stage->rgbGen == CGEN_IDENTITY - || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) { - stage->alphaGen = AGEN_SKIP; - } - } - - // - // compute state bits - // - stage->stateBits = depthMaskBits | - blendSrcBits | blendDstBits | - atestBits | - depthFuncBits; - - return qtrue; -} - -/* -=============== -ParseDeform - -deformVertexes wave -deformVertexes normal -deformVertexes move -deformVertexes bulge -deformVertexes projectionShadow -deformVertexes autoSprite -deformVertexes autoSprite2 -deformVertexes text[0-7] -=============== -*/ -static void ParseDeform( char **text ) { - char *token; - deformStage_t *ds; - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name ); - return; - } - - if ( shader.numDeforms == MAX_SHADER_DEFORMS ) { - ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name ); - return; - } - - ds = &shader.deforms[ shader.numDeforms ]; - shader.numDeforms++; - - if ( !Q_stricmp( token, "projectionShadow" ) ) { - ds->deformation = DEFORM_PROJECTION_SHADOW; - return; - } - - if ( !Q_stricmp( token, "autosprite" ) ) { - ds->deformation = DEFORM_AUTOSPRITE; - return; - } - - if ( !Q_stricmp( token, "autosprite2" ) ) { - ds->deformation = DEFORM_AUTOSPRITE2; - return; - } - - if ( !Q_stricmpn( token, "text", 4 ) ) { - int n; - - n = token[4] - '0'; - if ( n < 0 || n > 7 ) { - n = 0; - } - ds->deformation = DEFORM_TEXT0 + n; - return; - } - - if ( !Q_stricmp( token, "bulge" ) ) { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); - return; - } - ds->bulgeWidth = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); - return; - } - ds->bulgeHeight = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name ); - return; - } - ds->bulgeSpeed = atof( token ); - - ds->deformation = DEFORM_BULGE; - return; - } - - if ( !Q_stricmp( token, "wave" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); - return; - } - - if ( atof( token ) != 0 ) - { - ds->deformationSpread = 1.0f / atof( token ); - } - else - { - ds->deformationSpread = 100.0f; - ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name ); - } - - ParseWaveForm( text, &ds->deformationWave ); - ds->deformation = DEFORM_WAVE; - return; - } - - if ( !Q_stricmp( token, "normal" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); - return; - } - ds->deformationWave.amplitude = atof( token ); - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); - return; - } - ds->deformationWave.frequency = atof( token ); - - ds->deformation = DEFORM_NORMALS; - return; - } - - if ( !Q_stricmp( token, "move" ) ) { - int i; - - for ( i = 0 ; i < 3 ; i++ ) { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name ); - return; - } - ds->moveVector[i] = atof( token ); - } - - ParseWaveForm( text, &ds->deformationWave ); - ds->deformation = DEFORM_MOVE; - return; - } - - ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name ); -} - - -/* -=============== -ParseSkyParms - -skyParms -=============== -*/ -static void ParseSkyParms( char **text ) { - char *token; - static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; - char pathname[MAX_QPATH]; - int i; - - // outerbox - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); - return; - } - if ( strcmp( token, "-" ) ) { - for (i=0 ; i<6 ; i++) { - Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" - , token, suf[i] ); - shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE ); - - if ( !shader.sky.outerbox[i] ) { - shader.sky.outerbox[i] = tr.defaultImage; - } - } - } - - // cloudheight - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); - return; - } - shader.sky.cloudHeight = atof( token ); - if ( !shader.sky.cloudHeight ) { - shader.sky.cloudHeight = 512; - } - R_InitSkyTexCoords( shader.sky.cloudHeight ); - - - // innerbox - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); - return; - } - if ( strcmp( token, "-" ) ) { - for (i=0 ; i<6 ; i++) { - Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga" - , token, suf[i] ); - shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP ); - if ( !shader.sky.innerbox[i] ) { - shader.sky.innerbox[i] = tr.defaultImage; - } - } - } - - shader.isSky = qtrue; -} - - -/* -================= -ParseSort -================= -*/ -void ParseSort( char **text ) { - char *token; - - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name ); - return; - } - - if ( !Q_stricmp( token, "portal" ) ) { - shader.sort = SS_PORTAL; - } else if ( !Q_stricmp( token, "sky" ) ) { - shader.sort = SS_ENVIRONMENT; - } else if ( !Q_stricmp( token, "opaque" ) ) { - shader.sort = SS_OPAQUE; - }else if ( !Q_stricmp( token, "decal" ) ) { - shader.sort = SS_DECAL; - } else if ( !Q_stricmp( token, "seeThrough" ) ) { - shader.sort = SS_SEE_THROUGH; - } else if ( !Q_stricmp( token, "banner" ) ) { - shader.sort = SS_BANNER; - } else if ( !Q_stricmp( token, "additive" ) ) { - shader.sort = SS_BLEND1; - } else if ( !Q_stricmp( token, "nearest" ) ) { - shader.sort = SS_NEAREST; - } else if ( !Q_stricmp( token, "underwater" ) ) { - shader.sort = SS_UNDERWATER; - } else { - shader.sort = atof( token ); - } -} - - - -// this table is also present in q3map - -typedef struct { - char *name; - int clearSolid, surfaceFlags, contents; -} infoParm_t; - -infoParm_t infoParms[] = { - // server relevant contents - {"water", 1, 0, CONTENTS_WATER }, - {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging - {"lava", 1, 0, CONTENTS_LAVA }, // very damaging - {"playerclip", 1, 0, CONTENTS_PLAYERCLIP }, - {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP }, - {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc) - {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag - - // utility relevant attributes - {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes - {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces - {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp - {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas - {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas - {"clusterportal", 1,0, CONTENTS_CLUSTERPORTAL }, // for bots - {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots - - {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering - {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map - {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it - {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis - {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter - - // server attributes - {"slick", 0, SURF_SLICK, 0 }, - {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks - {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode - {"ladder", 0, SURF_LADDER, 0 }, - {"nodamage", 0, SURF_NODAMAGE, 0 }, - {"metalsteps", 0, SURF_METALSTEPS,0 }, - {"flesh", 0, SURF_FLESH, 0 }, - {"nosteps", 0, SURF_NOSTEPS, 0 }, - - // drawsurf attributes - {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap) - {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes - {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap - {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights - {"dust", 0, SURF_DUST, 0} // leave a dust trail when walking on this surface -}; - - -/* -=============== -ParseSurfaceParm - -surfaceparm -=============== -*/ -static void ParseSurfaceParm( char **text ) { - char *token; - int numInfoParms = ARRAY_LEN( infoParms ); - int i; - - token = COM_ParseExt( text, qfalse ); - for ( i = 0 ; i < numInfoParms ; i++ ) { - if ( !Q_stricmp( token, infoParms[i].name ) ) { - shader.surfaceFlags |= infoParms[i].surfaceFlags; - shader.contentFlags |= infoParms[i].contents; -#if 0 - if ( infoParms[i].clearSolid ) { - si->contents &= ~CONTENTS_SOLID; - } -#endif - break; - } - } -} - -/* -================= -ParseShader - -The current text pointer is at the explicit text definition of the -shader. Parse it into the global shader variable. Later functions -will optimize it. -================= -*/ -static qboolean ParseShader( char **text ) -{ - char *token; - int s; - - s = 0; - - token = COM_ParseExt( text, qtrue ); - if ( token[0] != '{' ) - { - ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name ); - return qfalse; - } - - while ( 1 ) - { - token = COM_ParseExt( text, qtrue ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name ); - return qfalse; - } - - // end of shader definition - if ( token[0] == '}' ) - { - break; - } - // stage definition - else if ( token[0] == '{' ) - { - if ( s >= MAX_SHADER_STAGES ) { - ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name ); - return qfalse; - } - - if ( !ParseStage( &stages[s], text ) ) - { - return qfalse; - } - stages[s].active = qtrue; - s++; - - continue; - } - // skip stuff that only the QuakeEdRadient needs - else if ( !Q_stricmpn( token, "qer", 3 ) ) { - SkipRestOfLine( text ); - continue; - } - // sun parms - else if ( !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) || !Q_stricmp( token, "q3gl2_sun" ) ) { - float a, b; - qboolean isGL2Sun = qfalse; - - if (!Q_stricmp( token, "q3gl2_sun" ) && r_sunShadows->integer ) - { - isGL2Sun = qtrue; - tr.sunShadows = qtrue; - } - - token = COM_ParseExt( text, qfalse ); - tr.sunLight[0] = atof( token ); - token = COM_ParseExt( text, qfalse ); - tr.sunLight[1] = atof( token ); - token = COM_ParseExt( text, qfalse ); - tr.sunLight[2] = atof( token ); - - VectorNormalize( tr.sunLight ); - - token = COM_ParseExt( text, qfalse ); - a = atof( token ); - VectorScale( tr.sunLight, a, tr.sunLight); - - VectorSet( tr.sunAmbient, 0.0f, 0.0f, 0.0f); - - token = COM_ParseExt( text, qfalse ); - a = atof( token ); - a = a / 180 * M_PI; - - token = COM_ParseExt( text, qfalse ); - b = atof( token ); - b = b / 180 * M_PI; - - tr.sunDirection[0] = cos( a ) * cos( b ); - tr.sunDirection[1] = sin( a ) * cos( b ); - tr.sunDirection[2] = sin( b ); - - if (isGL2Sun) - { - token = COM_ParseExt( text, qfalse ); - tr.mapLightScale = atof(token); - - token = COM_ParseExt( text, qfalse ); - VectorScale( tr.sunLight, atof(token), tr.sunAmbient ); - } - - SkipRestOfLine( text ); - } - else if ( !Q_stricmp( token, "deformVertexes" ) ) { - ParseDeform( text ); - continue; - } - else if ( !Q_stricmp( token, "tesssize" ) ) { - SkipRestOfLine( text ); - continue; - } - else if ( !Q_stricmp( token, "clampTime" ) ) { - token = COM_ParseExt( text, qfalse ); - if (token[0]) { - shader.clampTime = atof(token); - } - } - // skip stuff that only the q3map needs - else if ( !Q_stricmpn( token, "q3map", 5 ) ) { - SkipRestOfLine( text ); - continue; - } - // skip stuff that only q3map or the server needs - else if ( !Q_stricmp( token, "surfaceParm" ) ) { - ParseSurfaceParm( text ); - continue; - } - // no mip maps - else if ( !Q_stricmp( token, "nomipmaps" ) ) - { - shader.noMipMaps = qtrue; - shader.noPicMip = qtrue; - continue; - } - // no picmip adjustment - else if ( !Q_stricmp( token, "nopicmip" ) ) - { - shader.noPicMip = qtrue; - continue; - } - // polygonOffset - else if ( !Q_stricmp( token, "polygonOffset" ) ) - { - shader.polygonOffset = qtrue; - continue; - } - // entityMergable, allowing sprite surfaces from multiple entities - // to be merged into one batch. This is a savings for smoke - // puffs and blood, but can't be used for anything where the - // shader calcs (not the surface function) reference the entity color or scroll - else if ( !Q_stricmp( token, "entityMergable" ) ) - { - shader.entityMergable = qtrue; - continue; - } - // fogParms - else if ( !Q_stricmp( token, "fogParms" ) ) - { - if ( !ParseVector( text, 3, shader.fogParms.color ) ) { - return qfalse; - } - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name ); - continue; - } - shader.fogParms.depthForOpaque = atof( token ); - - // skip any old gradient directions - SkipRestOfLine( text ); - continue; - } - // portal - else if ( !Q_stricmp(token, "portal") ) - { - shader.sort = SS_PORTAL; - shader.isPortal = qtrue; - continue; - } - // skyparms - else if ( !Q_stricmp( token, "skyparms" ) ) - { - ParseSkyParms( text ); - continue; - } - // light determines flaring in q3map, not needed here - else if ( !Q_stricmp(token, "light") ) - { - token = COM_ParseExt( text, qfalse ); - continue; - } - // cull - else if ( !Q_stricmp( token, "cull") ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) ) - { - shader.cullType = CT_TWO_SIDED; - } - else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) ) - { - shader.cullType = CT_BACK_SIDED; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name ); - } - continue; - } - // sort - else if ( !Q_stricmp( token, "sort" ) ) - { - ParseSort( text ); - continue; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name ); - return qfalse; - } - } - - // - // ignore shaders that don't have any stages, unless it is a sky or fog - // - if ( s == 0 && !shader.isSky && !(shader.contentFlags & CONTENTS_FOG ) ) { - return qfalse; - } - - shader.explicitlyDefined = qtrue; - - return qtrue; -} - -/* -======================================================================================== - -SHADER OPTIMIZATION AND FOGGING - -======================================================================================== -*/ - -/* -=================== -ComputeStageIteratorFunc - -See if we can use on of the simple fastpath stage functions, -otherwise set to the generic stage function -=================== -*/ -static void ComputeStageIteratorFunc( void ) -{ - shader.optimalStageIteratorFunc = RB_StageIteratorGeneric; - - // - // see if this should go into the sky path - // - if ( shader.isSky ) - { - shader.optimalStageIteratorFunc = RB_StageIteratorSky; - return; - } -} - -/* -=================== -ComputeVertexAttribs - -Check which vertex attributes we only need, so we -don't need to submit/copy all of them. -=================== -*/ -static void ComputeVertexAttribs(void) -{ - int i, stage; - - // dlights always need ATTR_NORMAL - shader.vertexAttribs = ATTR_POSITION | ATTR_NORMAL; - - // portals always need normals, for SurfIsOffscreen() - if (shader.isPortal) - { - shader.vertexAttribs |= ATTR_NORMAL; - } - - if (shader.defaultShader) - { - shader.vertexAttribs |= ATTR_TEXCOORD; - return; - } - - if(shader.numDeforms) - { - for ( i = 0; i < shader.numDeforms; i++) - { - deformStage_t *ds = &shader.deforms[i]; - - switch (ds->deformation) - { - case DEFORM_BULGE: - shader.vertexAttribs |= ATTR_NORMAL | ATTR_TEXCOORD; - break; - - case DEFORM_AUTOSPRITE: - shader.vertexAttribs |= ATTR_NORMAL | ATTR_COLOR; - break; - - case DEFORM_WAVE: - case DEFORM_NORMALS: - case DEFORM_TEXT0: - case DEFORM_TEXT1: - case DEFORM_TEXT2: - case DEFORM_TEXT3: - case DEFORM_TEXT4: - case DEFORM_TEXT5: - case DEFORM_TEXT6: - case DEFORM_TEXT7: - shader.vertexAttribs |= ATTR_NORMAL; - break; - - default: - case DEFORM_NONE: - case DEFORM_MOVE: - case DEFORM_PROJECTION_SHADOW: - case DEFORM_AUTOSPRITE2: - break; - } - } - } - - for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) - { - shaderStage_t *pStage = &stages[stage]; - - if ( !pStage->active ) - { - break; - } - - if (pStage->glslShaderGroup == tr.lightallShader) - { - shader.vertexAttribs |= ATTR_NORMAL; - -#ifdef USE_VERT_TANGENT_SPACE - if (pStage->glslShaderIndex & LIGHTDEF_USE_NORMALMAP) - { - shader.vertexAttribs |= ATTR_BITANGENT | ATTR_TANGENT; - } -#endif - - switch (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) - { - case LIGHTDEF_USE_LIGHTMAP: - case LIGHTDEF_USE_LIGHT_VERTEX: - shader.vertexAttribs |= ATTR_LIGHTDIRECTION; - break; - default: - break; - } - } - - for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) - { - if ( pStage->bundle[i].image[0] == 0 ) - { - continue; - } - - switch(pStage->bundle[i].tcGen) - { - case TCGEN_TEXTURE: - shader.vertexAttribs |= ATTR_TEXCOORD; - break; - case TCGEN_LIGHTMAP: - shader.vertexAttribs |= ATTR_LIGHTCOORD; - break; - case TCGEN_ENVIRONMENT_MAPPED: - shader.vertexAttribs |= ATTR_NORMAL; - break; - - default: - break; - } - } - - switch(pStage->rgbGen) - { - case CGEN_EXACT_VERTEX: - case CGEN_VERTEX: - case CGEN_EXACT_VERTEX_LIT: - case CGEN_VERTEX_LIT: - case CGEN_ONE_MINUS_VERTEX: - shader.vertexAttribs |= ATTR_COLOR; - break; - - case CGEN_LIGHTING_DIFFUSE: - shader.vertexAttribs |= ATTR_NORMAL; - break; - - default: - break; - } - - switch(pStage->alphaGen) - { - case AGEN_LIGHTING_SPECULAR: - case AGEN_FRESNEL: - shader.vertexAttribs |= ATTR_NORMAL; - break; - - case AGEN_VERTEX: - case AGEN_ONE_MINUS_VERTEX: - shader.vertexAttribs |= ATTR_COLOR; - break; - - default: - break; - } - } -} - -typedef struct { - int blendA; - int blendB; - - int multitextureEnv; - int multitextureBlend; -} collapse_t; - -static collapse_t collapse[] = { - { 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, 0 }, - - { 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, 0 }, - - { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, - GL_ADD, 0 }, - - { GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, - GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE }, -#if 0 - { 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA, - GL_DECAL, 0 }, -#endif - { -1 } -}; - -/* -================ -CollapseMultitexture - -Attempt to combine two stages into a single multitexture stage -FIXME: I think modulated add + modulated add collapses incorrectly -================= -*/ -static qboolean CollapseMultitexture( void ) { - int abits, bbits; - int i; - textureBundle_t tmpBundle; - - if ( !qglActiveTextureARB ) { - return qfalse; - } - - // make sure both stages are active - if ( !stages[0].active || !stages[1].active ) { - return qfalse; - } - - // on voodoo2, don't combine different tmus - if ( glConfig.driverType == GLDRV_VOODOO ) { - if ( stages[0].bundle[0].image[0]->TMU == - stages[1].bundle[0].image[0]->TMU ) { - return qfalse; - } - } - - abits = stages[0].stateBits; - bbits = stages[1].stateBits; - - // make sure that both stages have identical state other than blend modes - if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) != - ( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) { - return qfalse; - } - - abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - - // search for a valid multitexture blend function - for ( i = 0; collapse[i].blendA != -1 ; i++ ) { - if ( abits == collapse[i].blendA - && bbits == collapse[i].blendB ) { - break; - } - } - - // nothing found - if ( collapse[i].blendA == -1 ) { - return qfalse; - } - - // GL_ADD is a separate extension - if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) { - return qfalse; - } - - // make sure waveforms have identical parameters - if ( ( stages[0].rgbGen != stages[1].rgbGen ) || - ( stages[0].alphaGen != stages[1].alphaGen ) ) { - return qfalse; - } - - // an add collapse can only have identity colors - if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) { - return qfalse; - } - - if ( stages[0].rgbGen == CGEN_WAVEFORM ) - { - if ( memcmp( &stages[0].rgbWave, - &stages[1].rgbWave, - sizeof( stages[0].rgbWave ) ) ) - { - return qfalse; - } - } - if ( stages[0].alphaGen == AGEN_WAVEFORM ) - { - if ( memcmp( &stages[0].alphaWave, - &stages[1].alphaWave, - sizeof( stages[0].alphaWave ) ) ) - { - return qfalse; - } - } - - - // make sure that lightmaps are in bundle 1 for 3dfx - if ( stages[0].bundle[0].isLightmap ) - { - tmpBundle = stages[0].bundle[0]; - stages[0].bundle[0] = stages[1].bundle[0]; - stages[0].bundle[1] = tmpBundle; - } - else - { - stages[0].bundle[1] = stages[1].bundle[0]; - } - - // set the new blend state bits - shader.multitextureEnv = collapse[i].multitextureEnv; - stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - stages[0].stateBits |= collapse[i].multitextureBlend; - - // - // move down subsequent shaders - // - memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) ); - Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) ); - - return qtrue; -} - -static void CollapseStagesToLightall(shaderStage_t *diffuse, - shaderStage_t *normal, shaderStage_t *specular, shaderStage_t *lightmap, - qboolean useLightVector, qboolean useLightVertex, qboolean parallax, qboolean environment) -{ - int defs = 0; - - //ri.Printf(PRINT_ALL, "shader %s has diffuse %s", shader.name, diffuse->bundle[0].image[0]->imgName); - - // reuse diffuse, mark others inactive - diffuse->type = ST_GLSL; - - if (lightmap) - { - //ri.Printf(PRINT_ALL, ", lightmap"); - diffuse->bundle[TB_LIGHTMAP] = lightmap->bundle[0]; - defs |= LIGHTDEF_USE_LIGHTMAP; - } - else if (useLightVector) - { - defs |= LIGHTDEF_USE_LIGHT_VECTOR; - } - else if (useLightVertex) - { - defs |= LIGHTDEF_USE_LIGHT_VERTEX; - } - - if (r_deluxeMapping->integer && tr.worldDeluxeMapping && lightmap) - { - //ri.Printf(PRINT_ALL, ", deluxemap"); - diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0]; - diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex]; - defs |= LIGHTDEF_USE_DELUXEMAP; - } - - if (r_normalMapping->integer) - { - image_t *diffuseImg; - if (normal) - { - //ri.Printf(PRINT_ALL, ", normalmap %s", normal->bundle[0].image[0]->imgName); - diffuse->bundle[TB_NORMALMAP] = normal->bundle[0]; - defs |= LIGHTDEF_USE_NORMALMAP; - if (parallax && r_parallaxMapping->integer) - defs |= LIGHTDEF_USE_PARALLAXMAP; - } - else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0])) - { - char normalName[MAX_QPATH]; - image_t *normalImg; - imgFlags_t normalFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE; - - COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH); - Q_strcat(normalName, MAX_QPATH, "_n"); - - normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags); - - if (normalImg) - { - diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0]; - diffuse->bundle[TB_NORMALMAP].image[0] = normalImg; - - defs |= LIGHTDEF_USE_NORMALMAP; - if (parallax && r_parallaxMapping->integer) - defs |= LIGHTDEF_USE_PARALLAXMAP; - } - } - } - - if (r_specularMapping->integer) - { - if (specular) - { - //ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName); - diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0]; - diffuse->materialInfo[0] = specular->materialInfo[0]; - diffuse->materialInfo[1] = specular->materialInfo[1]; - defs |= LIGHTDEF_USE_SPECULARMAP; - } - } - - if (environment) - { - defs |= LIGHTDEF_TCGEN_ENVIRONMENT; - } - - //ri.Printf(PRINT_ALL, ".\n"); - - diffuse->glslShaderGroup = tr.lightallShader; - diffuse->glslShaderIndex = defs; -} - - -static qboolean CollapseStagesToGLSL(void) -{ - int i, j, numStages; - qboolean skip = qfalse; - - // skip shaders with deforms - if (shader.numDeforms != 0) - { - skip = qtrue; - } - - if (!skip) - { - // if 2+ stages and first stage is lightmap, switch them - // this makes it easier for the later bits to process - if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active) - { - int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - - if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) - || blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) - { - int stateBits0 = stages[0].stateBits; - int stateBits1 = stages[1].stateBits; - shaderStage_t swapStage; - - swapStage = stages[0]; - stages[0] = stages[1]; - stages[1] = swapStage; - - stages[0].stateBits = stateBits0; - stages[1].stateBits = stateBits1; - } - } - } - - if (!skip) - { - // scan for shaders that aren't supported - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - shaderStage_t *pStage = &stages[i]; - - if (!pStage->active) - continue; - - if (pStage->adjustColorsForFog) - { - skip = qtrue; - break; - } - - if (pStage->bundle[0].isLightmap) - { - int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - - if (blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) - && blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) - { - skip = qtrue; - break; - } - } - - switch(pStage->bundle[0].tcGen) - { - case TCGEN_TEXTURE: - case TCGEN_LIGHTMAP: - case TCGEN_ENVIRONMENT_MAPPED: - break; - default: - skip = qtrue; - break; - } - - switch(pStage->alphaGen) - { - case AGEN_LIGHTING_SPECULAR: - case AGEN_PORTAL: - case AGEN_FRESNEL: - skip = qtrue; - break; - default: - break; - } - } - } - - if (!skip) - { - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - shaderStage_t *pStage = &stages[i]; - shaderStage_t *diffuse, *normal, *specular, *lightmap; - qboolean parallax, environment, diffuselit, vertexlit; - - if (!pStage->active) - continue; - - // skip normal and specular maps - if (pStage->type != ST_COLORMAP) - continue; - - // skip lightmaps - if (pStage->bundle[0].isLightmap) - continue; - - diffuse = pStage; - normal = NULL; - parallax = qfalse; - specular = NULL; - lightmap = NULL; - - // we have a diffuse map, find matching normal, specular, and lightmap - for (j = i + 1; j < MAX_SHADER_STAGES; j++) - { - shaderStage_t *pStage2 = &stages[j]; - - if (!pStage2->active) - continue; - - switch(pStage2->type) - { - case ST_NORMALMAP: - if (!normal) - { - normal = pStage2; - } - break; - - case ST_NORMALPARALLAXMAP: - if (!normal) - { - normal = pStage2; - parallax = qtrue; - } - break; - - case ST_SPECULARMAP: - if (!specular) - { - specular = pStage2; - } - break; - - case ST_COLORMAP: - if (pStage2->bundle[0].isLightmap) - { - lightmap = pStage2; - } - break; - - default: - break; - } - } - - environment = qfalse; - if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED) - { - environment = qtrue; - } - - diffuselit = qfalse; - if (diffuse->rgbGen == CGEN_LIGHTING_DIFFUSE) - { - diffuselit = qtrue; - } - - vertexlit = qfalse; - if (diffuse->rgbGen == CGEN_VERTEX_LIT || diffuse->rgbGen == CGEN_EXACT_VERTEX_LIT) - { - vertexlit = qtrue; - } - - CollapseStagesToLightall(diffuse, normal, specular, lightmap, diffuselit, vertexlit, parallax, environment); - } - - // deactivate lightmap stages - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - shaderStage_t *pStage = &stages[i]; - - if (!pStage->active) - continue; - - if (pStage->bundle[0].isLightmap) - { - pStage->active = qfalse; - } - } - } - - // deactivate normal and specular stages - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - shaderStage_t *pStage = &stages[i]; - - if (!pStage->active) - continue; - - if (pStage->type == ST_NORMALMAP) - { - pStage->active = qfalse; - } - - if (pStage->type == ST_NORMALPARALLAXMAP) - { - pStage->active = qfalse; - } - - if (pStage->type == ST_SPECULARMAP) - { - pStage->active = qfalse; - } - } - - // remove inactive stages - numStages = 0; - for (i = 0; i < MAX_SHADER_STAGES; i++) - { - if (!stages[i].active) - continue; - - if (i == numStages) - { - numStages++; - continue; - } - - stages[numStages] = stages[i]; - stages[i].active = qfalse; - numStages++; - } - - if (numStages == i && i >= 2 && CollapseMultitexture()) - numStages--; - - return numStages; -} - -/* -============= - -FixRenderCommandList -https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493 -Arnout: this is a nasty issue. Shaders can be registered after drawsurfaces are generated -but before the frame is rendered. This will, for the duration of one frame, cause drawsurfaces -to be rendered with bad shaders. To fix this, need to go through all render commands and fix -sortedIndex. -============== -*/ -static void FixRenderCommandList( int newShader ) { - renderCommandList_t *cmdList = &backEndData[tr.smpFrame]->commands; - - if( cmdList ) { - const void *curCmd = cmdList->cmds; - - while ( 1 ) { - curCmd = PADP(curCmd, sizeof(void *)); - - switch ( *(const int *)curCmd ) { - case RC_SET_COLOR: - { - const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd; - curCmd = (const void *)(sc_cmd + 1); - break; - } - case RC_STRETCH_PIC: - { - const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd; - curCmd = (const void *)(sp_cmd + 1); - break; - } - case RC_DRAW_SURFS: - { - int i; - drawSurf_t *drawSurf; - shader_t *shader; - int fogNum; - int entityNum; - int dlightMap; - int pshadowMap; - int sortedIndex; - const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd; - - for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) { - R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap ); - sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1)); - if( sortedIndex >= newShader ) { - sortedIndex++; - drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | ( (int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap; - } - } - curCmd = (const void *)(ds_cmd + 1); - break; - } - case RC_DRAW_BUFFER: - { - const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd; - curCmd = (const void *)(db_cmd + 1); - break; - } - case RC_SWAP_BUFFERS: - { - const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd; - curCmd = (const void *)(sb_cmd + 1); - break; - } - case RC_END_OF_LIST: - default: - return; - } - } - } -} - -/* -============== -SortNewShader - -Positions the most recently created shader in the tr.sortedShaders[] -array so that the shader->sort key is sorted reletive to the other -shaders. - -Sets shader->sortedIndex -============== -*/ -static void SortNewShader( void ) { - int i; - float sort; - shader_t *newShader; - - newShader = tr.shaders[ tr.numShaders - 1 ]; - sort = newShader->sort; - - for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) { - if ( tr.sortedShaders[ i ]->sort <= sort ) { - break; - } - tr.sortedShaders[i+1] = tr.sortedShaders[i]; - tr.sortedShaders[i+1]->sortedIndex++; - } - - // Arnout: fix rendercommandlist - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493 - FixRenderCommandList( i+1 ); - - newShader->sortedIndex = i+1; - tr.sortedShaders[i+1] = newShader; -} - - -/* -==================== -GeneratePermanentShader -==================== -*/ -static shader_t *GeneratePermanentShader( void ) { - shader_t *newShader; - int i, b; - int size, hash; - - if ( tr.numShaders == MAX_SHADERS ) { - ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n"); - return tr.defaultShader; - } - - newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low ); - - *newShader = shader; - - if ( shader.sort <= SS_OPAQUE ) { - newShader->fogPass = FP_EQUAL; - } else if ( shader.contentFlags & CONTENTS_FOG ) { - newShader->fogPass = FP_LE; - } - - tr.shaders[ tr.numShaders ] = newShader; - newShader->index = tr.numShaders; - - tr.sortedShaders[ tr.numShaders ] = newShader; - newShader->sortedIndex = tr.numShaders; - - tr.numShaders++; - - for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) { - if ( !stages[i].active ) { - break; - } - newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low ); - *newShader->stages[i] = stages[i]; - - for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) { - size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t ); - newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low ); - Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size ); - } - } - - SortNewShader(); - - hash = generateHashValue(newShader->name, FILE_HASH_SIZE); - newShader->next = hashTable[hash]; - hashTable[hash] = newShader; - - return newShader; -} - -/* -================= -VertexLightingCollapse - -If vertex lighting is enabled, only render a single -pass, trying to guess which is the correct one to best aproximate -what it is supposed to look like. -================= -*/ -static void VertexLightingCollapse( void ) { - int stage; - shaderStage_t *bestStage; - int bestImageRank; - int rank; - - // if we aren't opaque, just use the first pass - if ( shader.sort == SS_OPAQUE ) { - - // pick the best texture for the single pass - bestStage = &stages[0]; - bestImageRank = -999999; - - for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { - shaderStage_t *pStage = &stages[stage]; - - if ( !pStage->active ) { - break; - } - rank = 0; - - if ( pStage->bundle[0].isLightmap ) { - rank -= 100; - } - if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) { - rank -= 5; - } - if ( pStage->bundle[0].numTexMods ) { - rank -= 5; - } - if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) { - rank -= 3; - } - - if ( rank > bestImageRank ) { - bestImageRank = rank; - bestStage = pStage; - } - } - - stages[0].bundle[0] = bestStage->bundle[0]; - stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - stages[0].stateBits |= GLS_DEPTHMASK_TRUE; - if ( shader.lightmapIndex == LIGHTMAP_NONE ) { - stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; - } else { - stages[0].rgbGen = CGEN_EXACT_VERTEX; - } - stages[0].alphaGen = AGEN_SKIP; - } else { - // don't use a lightmap (tesla coils) - if ( stages[0].bundle[0].isLightmap ) { - stages[0] = stages[1]; - } - - // if we were in a cross-fade cgen, hack it to normal - if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) { - stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; - } - if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH ) - && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) { - stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; - } - if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH ) - && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) { - stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; - } - } - - for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) { - shaderStage_t *pStage = &stages[stage]; - - if ( !pStage->active ) { - break; - } - - Com_Memset( pStage, 0, sizeof( *pStage ) ); - } -} - -/* -========================= -FinishShader - -Returns a freshly allocated shader with all the needed info -from the current global working shader -========================= -*/ -static shader_t *FinishShader( void ) { - int stage; - qboolean hasLightmapStage; - qboolean vertexLightmap; - - hasLightmapStage = qfalse; - vertexLightmap = qfalse; - - // - // set sky stuff appropriate - // - if ( shader.isSky ) { - shader.sort = SS_ENVIRONMENT; - } - - // - // set polygon offset - // - if ( shader.polygonOffset && !shader.sort ) { - shader.sort = SS_DECAL; - } - - // - // set appropriate stage information - // - for ( stage = 0; stage < MAX_SHADER_STAGES; ) { - shaderStage_t *pStage = &stages[stage]; - - if ( !pStage->active ) { - break; - } - - // check for a missing texture - if ( !pStage->bundle[0].image[0] ) { - ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name ); - pStage->active = qfalse; - stage++; - continue; - } - - // - // ditch this stage if it's detail and detail textures are disabled - // - if ( pStage->isDetail && !r_detailTextures->integer ) - { - int index; - - for(index = stage + 1; index < MAX_SHADER_STAGES; index++) - { - if(!stages[index].active) - break; - } - - if(index < MAX_SHADER_STAGES) - memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage)); - else - { - if(stage + 1 < MAX_SHADER_STAGES) - memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage - 1)); - - Com_Memset(&stages[index - 1], 0, sizeof(*stages)); - } - - continue; - } - - // - // default texture coordinate generation - // - if ( pStage->bundle[0].isLightmap ) { - if ( pStage->bundle[0].tcGen == TCGEN_BAD ) { - pStage->bundle[0].tcGen = TCGEN_LIGHTMAP; - } - hasLightmapStage = qtrue; - } else { - if ( pStage->bundle[0].tcGen == TCGEN_BAD ) { - pStage->bundle[0].tcGen = TCGEN_TEXTURE; - } - } - - - // not a true lightmap but we want to leave existing - // behaviour in place and not print out a warning - //if (pStage->rgbGen == CGEN_VERTEX) { - // vertexLightmap = qtrue; - //} - - - - // - // determine sort order and fog color adjustment - // - if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) && - ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) { - int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS; - int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS; - - // fog color adjustment only works for blend modes that have a contribution - // that aproaches 0 as the modulate values aproach 0 -- - // GL_ONE, GL_ONE - // GL_ZERO, GL_ONE_MINUS_SRC_COLOR - // GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA - - // modulate, additive - if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) || - ( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) { - pStage->adjustColorsForFog = ACFF_MODULATE_RGB; - } - // strict blend - else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) - { - pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA; - } - // premultiplied alpha - else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) ) - { - pStage->adjustColorsForFog = ACFF_MODULATE_RGBA; - } else { - // we can't adjust this one correctly, so it won't be exactly correct in fog - } - - // don't screw with sort order if this is a portal or environment - if ( !shader.sort ) { - // see through item, like a grill or grate - if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) { - shader.sort = SS_SEE_THROUGH; - } else { - shader.sort = SS_BLEND0; - } - } - } - - stage++; - } - - // there are times when you will need to manually apply a sort to - // opaque alpha tested shaders that have later blend passes - if ( !shader.sort ) { - shader.sort = SS_OPAQUE; - } - - // - // if we are in r_vertexLight mode, never use a lightmap texture - // - if ( stage > 1 && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) { - VertexLightingCollapse(); - stage = 1; - hasLightmapStage = qfalse; - } - - // - // look for multitexture potential - // - stage = CollapseStagesToGLSL(); - - if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) { - if (vertexLightmap) { - ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name ); - } else { - ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name ); - // Don't set this, it will just add duplicate shaders to the hash - //shader.lightmapIndex = LIGHTMAP_NONE; - } - } - - - // - // compute number of passes - // - shader.numUnfoggedPasses = stage; - - // fogonly shaders don't have any normal passes - if (stage == 0 && !shader.isSky) - shader.sort = SS_FOG; - - // determine which stage iterator function is appropriate - ComputeStageIteratorFunc(); - - // determine which vertex attributes this shader needs - ComputeVertexAttribs(); - - return GeneratePermanentShader(); -} - -//======================================================================================== - -/* -==================== -FindShaderInShaderText - -Scans the combined text description of all the shader files for -the given shader name. - -return NULL if not found - -If found, it will return a valid shader -===================== -*/ -static char *FindShaderInShaderText( const char *shadername ) { - - char *token, *p; - - int i, hash; - - hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH); - - if(shaderTextHashTable[hash]) - { - for (i = 0; shaderTextHashTable[hash][i]; i++) - { - p = shaderTextHashTable[hash][i]; - token = COM_ParseExt(&p, qtrue); - - if(!Q_stricmp(token, shadername)) - return p; - } - } - - p = s_shaderText; - - if ( !p ) { - return NULL; - } - - // look for label - while ( 1 ) { - token = COM_ParseExt( &p, qtrue ); - if ( token[0] == 0 ) { - break; - } - - if ( !Q_stricmp( token, shadername ) ) { - return p; - } - else { - // skip the definition - SkipBracedSection( &p ); - } - } - - return NULL; -} - - -/* -================== -R_FindShaderByName - -Will always return a valid shader, but it might be the -default shader if the real one can't be found. -================== -*/ -shader_t *R_FindShaderByName( const char *name ) { - char strippedName[MAX_QPATH]; - int hash; - shader_t *sh; - - if ( (name==NULL) || (name[0] == 0) ) { - return tr.defaultShader; - } - - COM_StripExtension(name, strippedName, sizeof(strippedName)); - - hash = generateHashValue(strippedName, FILE_HASH_SIZE); - - // - // see if the shader is already loaded - // - for (sh=hashTable[hash]; sh; sh=sh->next) { - // NOTE: if there was no shader or image available with the name strippedName - // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we - // have to check all default shaders otherwise for every call to R_FindShader - // with that same strippedName a new default shader is created. - if (Q_stricmp(sh->name, strippedName) == 0) { - // match found - return sh; - } - } - - return tr.defaultShader; -} - - -/* -=============== -R_FindShader - -Will always return a valid shader, but it might be the -default shader if the real one can't be found. - -In the interest of not requiring an explicit shader text entry to -be defined for every single image used in the game, three default -shader behaviors can be auto-created for any image: - -If lightmapIndex == LIGHTMAP_NONE, then the image will have -dynamic diffuse lighting applied to it, as apropriate for most -entity skin surfaces. - -If lightmapIndex == LIGHTMAP_2D, then the image will be used -for 2D rendering unless an explicit shader is found - -If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use -the vertex rgba modulate values, as apropriate for misc_model -pre-lit surfaces. - -Other lightmapIndex values will have a lightmap stage created -and src*dest blending applied with the texture, as apropriate for -most world construction surfaces. - -=============== -*/ -shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { - char strippedName[MAX_QPATH]; - int i, hash; - char *shaderText; - image_t *image; - shader_t *sh; - - if ( name[0] == 0 ) { - return tr.defaultShader; - } - - // use (fullbright) vertex lighting if the bsp file doesn't have - // lightmaps - if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) { - lightmapIndex = LIGHTMAP_BY_VERTEX; - } else if ( lightmapIndex < LIGHTMAP_2D ) { - // negative lightmap indexes cause stray pointers (think tr.lightmaps[lightmapIndex]) - ri.Printf( PRINT_WARNING, "WARNING: shader '%s' has invalid lightmap index of %d\n", name, lightmapIndex ); - lightmapIndex = LIGHTMAP_BY_VERTEX; - } - - COM_StripExtension(name, strippedName, sizeof(strippedName)); - - hash = generateHashValue(strippedName, FILE_HASH_SIZE); - - // - // see if the shader is already loaded - // - for (sh = hashTable[hash]; sh; sh = sh->next) { - // NOTE: if there was no shader or image available with the name strippedName - // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we - // have to check all default shaders otherwise for every call to R_FindShader - // with that same strippedName a new default shader is created. - if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) && - !Q_stricmp(sh->name, strippedName)) { - // match found - return sh; - } - } - - // make sure the render thread is stopped, because we are probably - // going to have to upload an image - if (r_smp->integer) { - R_SyncRenderThread(); - } - - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, strippedName, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - } - - // - // attempt to define shader from an explicit parameter file - // - shaderText = FindShaderInShaderText( strippedName ); - if ( shaderText ) { - // enable this when building a pak file to get a global list - // of all explicit shaders - if ( r_printShaders->integer ) { - ri.Printf( PRINT_ALL, "*SHADER* %s\n", name ); - } - - if ( !ParseShader( &shaderText ) ) { - // had errors, so use default shader - shader.defaultShader = qtrue; - } - sh = FinishShader(); - return sh; - } - - - // - // if not defined in the in-memory shader descriptions, - // look for a single supported image file - // - { - imgFlags_t flags; - - flags = IMGFLAG_NONE; - - if (r_srgb->integer) - flags |= IMGFLAG_SRGB; - - if (mipRawImage) - { - flags |= IMGFLAG_MIPMAP | IMGFLAG_PICMIP; - - if (r_genNormalMaps->integer) - flags |= IMGFLAG_GENNORMALMAP; - } - else - { - flags |= IMGFLAG_CLAMPTOEDGE; - } - - image = R_FindImageFile( name, IMGTYPE_COLORALPHA, flags ); - if ( !image ) { - ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name ); - shader.defaultShader = qtrue; - return FinishShader(); - } - } - - // - // create the default shading commands - // - if ( shader.lightmapIndex == LIGHTMAP_NONE ) { - // dynamic colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) { - // explicit colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_EXACT_VERTEX; - stages[0].alphaGen = AGEN_SKIP; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_2D ) { - // GUI elements - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_VERTEX; - stages[0].alphaGen = AGEN_VERTEX; - stages[0].stateBits = GLS_DEPTHTEST_DISABLE | - GLS_SRCBLEND_SRC_ALPHA | - GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) { - // fullbright level - stages[0].bundle[0].image[0] = tr.whiteImage; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; - stages[0].stateBits = GLS_DEFAULT; - - stages[1].bundle[0].image[0] = image; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY; - stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; - } else { - // two pass lightmap - stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; - stages[0].bundle[0].isLightmap = qtrue; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation - // for identitylight - stages[0].stateBits = GLS_DEFAULT; - - stages[1].bundle[0].image[0] = image; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY; - stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; - } - - return FinishShader(); -} - - -qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) { - int i, hash; - shader_t *sh; - - hash = generateHashValue(name, FILE_HASH_SIZE); - - // probably not necessary since this function - // only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D - // but better safe than sorry. - if ( lightmapIndex >= tr.numLightmaps ) { - lightmapIndex = LIGHTMAP_WHITEIMAGE; - } - - // - // see if the shader is already loaded - // - for (sh=hashTable[hash]; sh; sh=sh->next) { - // NOTE: if there was no shader or image available with the name strippedName - // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we - // have to check all default shaders otherwise for every call to R_FindShader - // with that same strippedName a new default shader is created. - if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) && - // index by name - !Q_stricmp(sh->name, name)) { - // match found - return sh->index; - } - } - - // make sure the render thread is stopped, because we are probably - // going to have to upload an image - if (r_smp->integer) { - R_SyncRenderThread(); - } - - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, name, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - } - - // - // create the default shading commands - // - if ( shader.lightmapIndex == LIGHTMAP_NONE ) { - // dynamic colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) { - // explicit colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_EXACT_VERTEX; - stages[0].alphaGen = AGEN_SKIP; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_2D ) { - // GUI elements - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_VERTEX; - stages[0].alphaGen = AGEN_VERTEX; - stages[0].stateBits = GLS_DEPTHTEST_DISABLE | - GLS_SRCBLEND_SRC_ALPHA | - GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) { - // fullbright level - stages[0].bundle[0].image[0] = tr.whiteImage; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY_LIGHTING; - stages[0].stateBits = GLS_DEFAULT; - - stages[1].bundle[0].image[0] = image; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY; - stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; - } else { - // two pass lightmap - stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; - stages[0].bundle[0].isLightmap = qtrue; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation - // for identitylight - stages[0].stateBits = GLS_DEFAULT; - - stages[1].bundle[0].image[0] = image; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY; - stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; - } - - sh = FinishShader(); - return sh->index; -} - - -/* -==================== -RE_RegisterShader - -This is the exported shader entry point for the rest of the system -It will always return an index that will be valid. - -This should really only be used for explicit shaders, because there is no -way to ask for different implicit lighting modes (vertex, lightmap, etc) -==================== -*/ -qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) { - shader_t *sh; - - if ( strlen( name ) >= MAX_QPATH ) { - ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" ); - return 0; - } - - sh = R_FindShader( name, lightmapIndex, qtrue ); - - // we want to return 0 if the shader failed to - // load for some reason, but R_FindShader should - // still keep a name allocated for it, so if - // something calls RE_RegisterShader again with - // the same name, we don't try looking for it again - if ( sh->defaultShader ) { - return 0; - } - - return sh->index; -} - - -/* -==================== -RE_RegisterShader - -This is the exported shader entry point for the rest of the system -It will always return an index that will be valid. - -This should really only be used for explicit shaders, because there is no -way to ask for different implicit lighting modes (vertex, lightmap, etc) -==================== -*/ -qhandle_t RE_RegisterShader( const char *name ) { - shader_t *sh; - - if ( strlen( name ) >= MAX_QPATH ) { - ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" ); - return 0; - } - - sh = R_FindShader( name, LIGHTMAP_2D, qtrue ); - - // we want to return 0 if the shader failed to - // load for some reason, but R_FindShader should - // still keep a name allocated for it, so if - // something calls RE_RegisterShader again with - // the same name, we don't try looking for it again - if ( sh->defaultShader ) { - return 0; - } - - return sh->index; -} - - -/* -==================== -RE_RegisterShaderNoMip - -For menu graphics that should never be picmiped -==================== -*/ -qhandle_t RE_RegisterShaderNoMip( const char *name ) { - shader_t *sh; - - if ( strlen( name ) >= MAX_QPATH ) { - ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" ); - return 0; - } - - sh = R_FindShader( name, LIGHTMAP_2D, qfalse ); - - // we want to return 0 if the shader failed to - // load for some reason, but R_FindShader should - // still keep a name allocated for it, so if - // something calls RE_RegisterShader again with - // the same name, we don't try looking for it again - if ( sh->defaultShader ) { - return 0; - } - - return sh->index; -} - -/* -==================== -R_GetShaderByHandle - -When a handle is passed in by another module, this range checks -it and returns a valid (possibly default) shader_t to be used internally. -==================== -*/ -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; - } - if ( hShader >= tr.numShaders ) { - ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader ); - return tr.defaultShader; - } - return tr.shaders[hShader]; -} - -/* -=============== -R_ShaderList_f - -Dump information on all valid shaders to the console -A second parameter will cause it to print in sorted order -=============== -*/ -void R_ShaderList_f (void) { - int i; - int count; - shader_t *shader; - - ri.Printf (PRINT_ALL, "-----------------------\n"); - - count = 0; - for ( i = 0 ; i < tr.numShaders ; i++ ) { - if ( ri.Cmd_Argc() > 1 ) { - shader = tr.sortedShaders[i]; - } else { - shader = tr.shaders[i]; - } - - ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses ); - - if (shader->lightmapIndex >= 0 ) { - ri.Printf (PRINT_ALL, "L "); - } else { - ri.Printf (PRINT_ALL, " "); - } - if ( shader->multitextureEnv == GL_ADD ) { - ri.Printf( PRINT_ALL, "MT(a) " ); - } else if ( shader->multitextureEnv == GL_MODULATE ) { - ri.Printf( PRINT_ALL, "MT(m) " ); - } else if ( shader->multitextureEnv == GL_DECAL ) { - ri.Printf( PRINT_ALL, "MT(d) " ); - } else { - ri.Printf( PRINT_ALL, " " ); - } - if ( shader->explicitlyDefined ) { - ri.Printf( PRINT_ALL, "E " ); - } else { - ri.Printf( PRINT_ALL, " " ); - } - - if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) { - ri.Printf( PRINT_ALL, "gen " ); - } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) { - ri.Printf( PRINT_ALL, "sky " ); - } else { - ri.Printf( PRINT_ALL, " " ); - } - - if ( shader->defaultShader ) { - ri.Printf (PRINT_ALL, ": %s (DEFAULTED)\n", shader->name); - } else { - ri.Printf (PRINT_ALL, ": %s\n", shader->name); - } - count++; - } - ri.Printf (PRINT_ALL, "%i total shaders\n", count); - ri.Printf (PRINT_ALL, "------------------\n"); -} - -/* -==================== -ScanAndLoadShaderFiles - -Finds and loads all .shader files, combining them into -a single large text block that can be scanned for shader names -===================== -*/ -#define MAX_SHADER_FILES 4096 -static void ScanAndLoadShaderFiles( void ) -{ - char **shaderFiles; - char *buffers[MAX_SHADER_FILES]; - char *p; - int numShaderFiles; - int i; - char *oldp, *token, *hashMem, *textEnd; - int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size; - - long sum = 0, summand; - // scan for shader files - shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles ); - - if ( !shaderFiles || !numShaderFiles ) - { - ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" ); - return; - } - - if ( numShaderFiles > MAX_SHADER_FILES ) { - numShaderFiles = MAX_SHADER_FILES; - } - - // load and parse shader files - for ( i = 0; i < numShaderFiles; i++ ) - { - char filename[MAX_QPATH]; - - // look for a .mtr file first - { - char *ext; - Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] ); - if ( (ext = strrchr(filename, '.')) ) - { - strcpy(ext, ".mtr"); - } - - if ( ri.FS_ReadFile( filename, NULL ) <= 0 ) - { - Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] ); - } - } - - ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename ); - summand = ri.FS_ReadFile( filename, (void **)&buffers[i] ); - - if ( !buffers[i] ) - ri.Error( ERR_DROP, "Couldn't load %s", filename ); - - // Do a simple check on the shader structure in that file to make sure one bad shader file cannot fuck up all other shaders. - p = buffers[i]; - while(1) - { - token = COM_ParseExt(&p, qtrue); - - if(!*token) - break; - - oldp = p; - - token = COM_ParseExt(&p, qtrue); - if(token[0] != '{' && token[1] != '\0') - { - ri.Printf(PRINT_WARNING, "WARNING: Bad shader file %s has incorrect syntax.\n", filename); - ri.FS_FreeFile(buffers[i]); - buffers[i] = NULL; - break; - } - - SkipBracedSection(&oldp); - p = oldp; - } - - - if (buffers[i]) - sum += summand; - } - - // build single large buffer - s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low ); - s_shaderText[ 0 ] = '\0'; - textEnd = s_shaderText; - - // free in reverse order, so the temp files are all dumped - for ( i = numShaderFiles - 1; i >= 0 ; i-- ) - { - if ( !buffers[i] ) - continue; - - strcat( textEnd, buffers[i] ); - strcat( textEnd, "\n" ); - textEnd += strlen( textEnd ); - ri.FS_FreeFile( buffers[i] ); - } - - COM_Compress( s_shaderText ); - - // free up memory - ri.FS_FreeFileList( shaderFiles ); - - Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes)); - size = 0; - - p = s_shaderText; - // look for shader names - while ( 1 ) { - token = COM_ParseExt( &p, qtrue ); - if ( token[0] == 0 ) { - break; - } - - hash = generateHashValue(token, MAX_SHADERTEXT_HASH); - shaderTextHashTableSizes[hash]++; - size++; - SkipBracedSection(&p); - } - - size += MAX_SHADERTEXT_HASH; - - hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low ); - - for (i = 0; i < MAX_SHADERTEXT_HASH; i++) { - shaderTextHashTable[i] = (char **) hashMem; - hashMem = ((char *) hashMem) + ((shaderTextHashTableSizes[i] + 1) * sizeof(char *)); - } - - Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes)); - - p = s_shaderText; - // look for shader names - while ( 1 ) { - oldp = p; - token = COM_ParseExt( &p, qtrue ); - if ( token[0] == 0 ) { - break; - } - - hash = generateHashValue(token, MAX_SHADERTEXT_HASH); - shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp; - - SkipBracedSection(&p); - } - - return; - -} - - -/* -==================== -CreateInternalShaders -==================== -*/ -static void CreateInternalShaders( void ) { - tr.numShaders = 0; - - // init the default shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - - Q_strncpyz( shader.name, "", sizeof( shader.name ) ); - - shader.lightmapIndex = LIGHTMAP_NONE; - stages[0].bundle[0].image[0] = tr.defaultImage; - stages[0].active = qtrue; - stages[0].stateBits = GLS_DEFAULT; - tr.defaultShader = FinishShader(); - - // shadow shader is just a marker - Q_strncpyz( shader.name, "", sizeof( shader.name ) ); - shader.sort = SS_STENCIL_SHADOW; - tr.shadowShader = FinishShader(); -} - -static void CreateExternalShaders( void ) { - tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue ); - tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); - - // Hack to make fogging work correctly on flares. Fog colors are calculated - // in tr_flare.c already. - if(!tr.flareShader->defaultShader) - { - int index; - - for(index = 0; index < tr.flareShader->numUnfoggedPasses; index++) - { - tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE; - tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE; - } - } - - tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); -} - -/* -================== -R_InitShaders -================== -*/ -void R_InitShaders( void ) { - ri.Printf( PRINT_ALL, "Initializing Shaders\n" ); - - Com_Memset(hashTable, 0, sizeof(hashTable)); - - CreateInternalShaders(); - - ScanAndLoadShaderFiles(); - - CreateExternalShaders(); -} diff --git a/code/renderergl2/tr_shadows.c b/code/renderergl2/tr_shadows.c deleted file mode 100644 index f412b00d..00000000 --- a/code/renderergl2/tr_shadows.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#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] - -*/ - -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]; - -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; - -#if 0 - int numTris; - - // dumb way -- render every triangle's edges - numTris = tess.numIndexes / 3; - - for ( i = 0 ; i < numTris ; i++ ) { - int i1, i2, i3; - - if ( !facing[i] ) { - continue; - } - - i1 = tess.indexes[ i*3 + 0 ]; - i2 = tess.indexes[ i*3 + 1 ]; - i3 = tess.indexes[ i*3 + 2 ]; - - qglBegin( GL_TRIANGLE_STRIP ); - qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); - qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); - qglVertex3fv( tess.xyz[ i3 ] ); - qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); - qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); - qglEnd(); - } -#else - int c, c2; - int j, k; - int i2; - int c_edges, c_rejected; - int hit[2]; - - // 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 - c_edges = 0; - c_rejected = 0; - - for ( i = 0 ; i < tess.numVertexes ; i++ ) { - c = numEdgeDefs[ i ]; - for ( j = 0 ; j < c ; j++ ) { - if ( !edgeDefs[ i ][ j ].facing ) { - continue; - } - - 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 ] == 0 ) { - 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 -} - -/* -================= -RB_ShadowTessEnd - -triangleFromEdge[ v1 ][ v2 ] - - - set triangle from edge( v1, v2, tri ) - if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) { - } -================= -*/ -void RB_ShadowTessEnd( void ) { - int i; - int numTris; - vec3_t lightDir; - GLboolean rgba[4]; - - // 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; - } - - 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] ); - } - - // decide which triangles face the light - Com_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 ]; - - VectorSubtract( v2, v1, d1 ); - VectorSubtract( v3, v1, d2 ); - CrossProduct( d1, d2, normal ); - - d = DotProduct( normal, lightDir ); - 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 ] ); - } - - // draw the silhouette edges - - GL_Bind( tr.whiteImage ); - qglEnable( GL_CULL_FACE ); - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - qglColor3f( 0.2f, 0.2f, 0.2f ); - - // don't write to the color buffer - qglGetBooleanv(GL_COLOR_WRITEMASK, rgba); - qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - - qglEnable( GL_STENCIL_TEST ); - qglStencilFunc( GL_ALWAYS, 1, 255 ); - - // 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 ); - - R_RenderShadowEdges(); - } else { - qglCullFace( GL_BACK ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - - R_RenderShadowEdges(); - - qglCullFace( GL_FRONT ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - - R_RenderShadowEdges(); - } - - - // reenable writing to the color buffer - qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]); -} - - -/* -================= -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; - } - qglEnable( GL_STENCIL_TEST ); - qglStencilFunc( GL_NOTEQUAL, 0, 255 ); - - qglDisable (GL_CLIP_PLANE0); - qglDisable (GL_CULL_FACE); - - GL_Bind( tr.whiteImage ); - - 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 ); - - qglBegin( GL_QUADS ); - qglVertex3f( -100, 100, -10 ); - qglVertex3f( 100, 100, -10 ); - qglVertex3f( 100, -100, -10 ); - qglVertex3f( -100, -100, -10 ); - qglEnd (); - - qglColor4f(1,1,1,1); - qglDisable( GL_STENCIL_TEST ); -} - - -/* -================= -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.or.axis[0][2]; - ground[1] = backEnd.or.axis[1][2]; - ground[2] = backEnd.or.axis[2][2]; - - groundDist = backEnd.or.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; - } -} diff --git a/code/renderergl2/tr_sky.c b/code/renderergl2/tr_sky.c deleted file mode 100644 index c06dcb52..00000000 --- a/code/renderergl2/tr_sky.c +++ /dev/null @@ -1,955 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_sky.c -#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 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 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) - ri.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 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 ; inumIndexes; i += 3 ) - { - for (j = 0 ; j < 3 ; j++) - { - VectorSubtract( input->xyz[input->indexes[i+j]], - backEnd.viewParms.or.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 int sky_texorder[6] = {0,2,1,3,4,5}; -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; - int firstVertex = tess.numVertexes; - //int firstIndex = tess.numIndexes; - vec4_t color; - - //tess.numVertexes = 0; - //tess.numIndexes = 0; - tess.firstIndex = tess.numIndexes; - - GL_Bind( image ); - GL_Cull( CT_TWO_SIDED ); - - 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++ ) - { - tess.xyz[tess.numVertexes][0] = s_skyPoints[t][s][0]; - tess.xyz[tess.numVertexes][1] = s_skyPoints[t][s][1]; - tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2]; - tess.xyz[tess.numVertexes][3] = 1.0; - - 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) - { - ri.Error(ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySideVBO()\n"); - } - } - } - - for ( t = 0; t < maxs[1] - mins[1]; t++ ) - { - for ( s = 0; s < maxs[0] - mins[0]; s++ ) - { - if (tess.numIndexes + 6 >= SHADER_MAX_INDEXES) - { - ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()\n"); - } - - tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; - - tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; - tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; - } - } - - // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); -/* - { - shaderProgram_t *sp = &tr.textureColorShader; - - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - color[0] = - color[1] = - color[2] = tr.identityLight; - color[3] = 1.0f; - GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color); - } -*/ - { - shaderProgram_t *sp = &tr.lightallShader[0]; - matrix_t matrix; - - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - color[0] = - color[1] = - color[2] = tr.identityLight; - color[3] = 1.0f; - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, color); - - color[0] = - color[1] = - color[2] = - color[3] = 0.0f; - GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, color); - - Matrix16Identity(matrix); - GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, matrix); - } - - R_DrawElementsVBO(tess.numIndexes - tess.firstIndex, tess.firstIndex); - - //qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(GL_INDEX_TYPE))); - - //R_BindNullVBO(); - //R_BindNullIBO(); - - tess.numIndexes = tess.firstIndex; - tess.numVertexes = firstVertex; - tess.firstIndex = 0; -} - -static void DrawSkyBox( shader_t *shader ) -{ - int i; - - sky_min = 0; - sky_max = 1; - - Com_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[sky_texorder[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.or.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 ) - { - ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()" ); - } - } - } - - // 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 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] = ri.ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS); - sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS); - sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS); - sky_maxs_subd[1] = ri.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, ( stage == 0 ) ); - } -} - -/* -** R_BuildCloudData -*/ -void R_BuildCloudData( shaderCommands_t *input ) -{ - int i; - shader_t *shader; - - shader = input->shader; - - assert( shader->isSky ); - - 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; - tess.firstIndex = 0; - - if ( shader->sky.cloudHeight ) - { - for ( i = 0; i < MAX_SHADER_STAGES; i++ ) - { - if ( !tess.xstages[i] ) { - break; - } - FillCloudBox( 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 = 4096; - 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 = Q_acos( v[0] ); - tRad = Q_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.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - { - // FIXME: this could be a lot cleaner - matrix_t trans, product; - - Matrix16Translation( backEnd.viewParms.or.origin, trans ); - Matrix16Multiply( backEnd.viewParms.world.modelMatrix, trans, product ); - GL_SetModelviewMatrix( product ); - } - - 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] = 1.0f; - tess.vertexColors[tess.numVertexes][1] = 1.0f; - tess.vertexColors[tess.numVertexes][2] = 1.0f; - 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] = 1.0f; - tess.vertexColors[tess.numVertexes][1] = 1.0f; - tess.vertexColors[tess.numVertexes][2] = 1.0f; - 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] = 1.0f; - tess.vertexColors[tess.numVertexes][1] = 1.0f; - tess.vertexColors[tess.numVertexes][2] = 1.0f; - 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] = 1.0f; - tess.vertexColors[tess.numVertexes][1] = 1.0f; - tess.vertexColors[tess.numVertexes][2] = 1.0f; - 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; - } - - // 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 ) { - matrix_t oldmodelview; - - GL_State( 0 ); - //qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); - - { - // FIXME: this could be a lot cleaner - matrix_t trans, product; - - Matrix16Copy( glState.modelview, oldmodelview ); - Matrix16Translation( backEnd.viewParms.or.origin, trans ); - Matrix16Multiply( glState.modelview, trans, product ); - GL_SetModelviewMatrix( product ); - - } - - DrawSkyBox( tess.shader ); - - GL_SetModelviewMatrix( oldmodelview ); - } - - // 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; -} - - - - - diff --git a/code/renderergl2/tr_subs.c b/code/renderergl2/tr_subs.c deleted file mode 100644 index 6f490128..00000000 --- a/code/renderergl2/tr_subs.c +++ /dev/null @@ -1,48 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2010 James Canete (use.less01@gmail.com) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_subs.c - 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); -} diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c deleted file mode 100644 index 1e5a32b1..00000000 --- a/code/renderergl2/tr_surface.c +++ /dev/null @@ -1,1690 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_surf.c -#include "tr_local.h" -#if idppc_altivec && !defined(MACOS_X) -#include -#endif - -/* - - THIS ENTIRE FILE IS BACK END - -backEnd.currentEntity will be valid. - -Tess_Begin has already been called for the surface's shader. - -The modelview matrix will be set. - -It is safe to actually issue drawing commands here if you don't want to -use the shader system. -*/ - - -//============================================================================ - - -/* -============== -RB_CheckOverflow -============== -*/ -void RB_CheckOverflow( int verts, int indexes ) { - if (tess.numVertexes + verts < SHADER_MAX_VERTEXES - && tess.numIndexes + indexes < SHADER_MAX_INDEXES) { - return; - } - - RB_EndSurface(); - - if ( verts >= SHADER_MAX_VERTEXES ) { - ri.Error(ERR_DROP, "RB_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES ); - } - if ( indexes >= SHADER_MAX_INDEXES ) { - ri.Error(ERR_DROP, "RB_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES ); - } - - RB_BeginSurface(tess.shader, tess.fogNum ); -} - -void RB_CheckVBOandIBO(VBO_t *vbo, IBO_t *ibo) -{ - if (!(vbo == glState.currentVBO && ibo == glState.currentIBO) || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES) - { - RB_EndSurface(); - RB_BeginSurface(tess.shader, tess.fogNum); - - R_BindVBO(vbo); - R_BindIBO(ibo); - } - - if (vbo != tess.vbo && ibo != tess.ibo) - tess.useInternalVBO = qfalse; -} - - -/* -============== -RB_AddQuadStampExt -============== -*/ -void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) { - vec3_t normal; - int ndx; - - RB_CHECKOVERFLOW( 4, 6 ); - - ndx = tess.numVertexes; - - // triangle indexes for a simple quad - tess.indexes[ tess.numIndexes ] = ndx; - tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; - tess.indexes[ tess.numIndexes + 2 ] = ndx + 3; - - tess.indexes[ tess.numIndexes + 3 ] = ndx + 3; - tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; - tess.indexes[ tess.numIndexes + 5 ] = ndx + 2; - - tess.xyz[ndx][0] = origin[0] + left[0] + up[0]; - tess.xyz[ndx][1] = origin[1] + left[1] + up[1]; - tess.xyz[ndx][2] = origin[2] + left[2] + up[2]; - - tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0]; - tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1]; - tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2]; - - tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0]; - tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1]; - tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2]; - - tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0]; - tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1]; - tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2]; - - - // constant normal all the way around - VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal ); - - tess.normal[ndx][0] = tess.normal[ndx+1][0] = tess.normal[ndx+2][0] = tess.normal[ndx+3][0] = normal[0]; - tess.normal[ndx][1] = tess.normal[ndx+1][1] = tess.normal[ndx+2][1] = tess.normal[ndx+3][1] = normal[1]; - tess.normal[ndx][2] = tess.normal[ndx+1][2] = tess.normal[ndx+2][2] = tess.normal[ndx+3][2] = normal[2]; - - // standard square texture coordinates - tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1; - tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1; - - tess.texCoords[ndx+1][0][0] = tess.texCoords[ndx+1][1][0] = s2; - tess.texCoords[ndx+1][0][1] = tess.texCoords[ndx+1][1][1] = t1; - - tess.texCoords[ndx+2][0][0] = tess.texCoords[ndx+2][1][0] = s2; - tess.texCoords[ndx+2][0][1] = tess.texCoords[ndx+2][1][1] = t2; - - tess.texCoords[ndx+3][0][0] = tess.texCoords[ndx+3][1][0] = s1; - tess.texCoords[ndx+3][0][1] = tess.texCoords[ndx+3][1][1] = t2; - - // constant color all the way around - // should this be identity and let the shader specify from entity? - tess.vertexColors[ndx][0] = color[0]; - tess.vertexColors[ndx][1] = color[1]; - tess.vertexColors[ndx][2] = color[2]; - tess.vertexColors[ndx][3] = color[3]; - - tess.vertexColors[ndx+1][0] = color[0]; - tess.vertexColors[ndx+1][1] = color[1]; - tess.vertexColors[ndx+1][2] = color[2]; - tess.vertexColors[ndx+1][3] = color[3]; - - tess.vertexColors[ndx+2][0] = color[0]; - tess.vertexColors[ndx+2][1] = color[1]; - tess.vertexColors[ndx+2][2] = color[2]; - tess.vertexColors[ndx+2][3] = color[3]; - - tess.vertexColors[ndx+3][0] = color[0]; - tess.vertexColors[ndx+3][1] = color[1]; - tess.vertexColors[ndx+3][2] = color[2]; - tess.vertexColors[ndx+3][3] = color[3]; - - tess.numVertexes += 4; - tess.numIndexes += 6; -} - -/* -============== -RB_AddQuadStamp -============== -*/ -void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, float color[4] ) { - RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 ); -} - - -/* -============== -RB_InstantQuad - -based on Tess_InstantQuad from xreal -============== -*/ -void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4]) -{ - GLimp_LogComment("--- RB_InstantQuad2 ---\n"); - - tess.numVertexes = 0; - tess.numIndexes = 0; - tess.firstIndex = 0; - - VectorCopy4(quadVerts[0], tess.xyz[tess.numVertexes]); - VectorCopy2(texCoords[0], tess.texCoords[tess.numVertexes][0]); - tess.numVertexes++; - - VectorCopy4(quadVerts[1], tess.xyz[tess.numVertexes]); - VectorCopy2(texCoords[1], tess.texCoords[tess.numVertexes][0]); - tess.numVertexes++; - - VectorCopy4(quadVerts[2], tess.xyz[tess.numVertexes]); - VectorCopy2(texCoords[2], tess.texCoords[tess.numVertexes][0]); - tess.numVertexes++; - - VectorCopy4(quadVerts[3], tess.xyz[tess.numVertexes]); - VectorCopy2(texCoords[3], tess.texCoords[tess.numVertexes][0]); - 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_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); - - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); - - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex); - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; -} - - -void RB_InstantQuad(vec4_t quadVerts[4]) -{ - vec4_t color; - vec2_t texCoords[4]; - vec2_t invTexRes; - - VectorSet4(color, 1, 1, 1, 1); - - texCoords[0][0] = 0; - texCoords[0][1] = 0; - - texCoords[1][0] = 1; - texCoords[1][1] = 0; - - texCoords[2][0] = 1; - texCoords[2][1] = 1; - - texCoords[3][0] = 0; - texCoords[3][1] = 1; - - invTexRes[0] = 1.0f / 256.0f; - invTexRes[1] = 1.0f / 256.0f; - - GLSL_BindProgram(&tr.textureColorShader); - - GLSL_SetUniformMatrix16(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - GLSL_SetUniformVec4(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, color); - GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_INVTEXRES, invTexRes); - GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, tr.autoExposureMinMax); - - RB_InstantQuad2(quadVerts, texCoords); //, color, &tr.textureColorShader, invTexRes); -} - - -/* -============== -RB_SurfaceSprite -============== -*/ -static void RB_SurfaceSprite( void ) { - vec3_t left, up; - float radius; - float colors[4]; - trRefEntity_t *ent = backEnd.currentEntity; - - // calculate the xyz locations for the four corners - radius = ent->e.radius; - if ( ent->e.rotation == 0 ) { - VectorScale( backEnd.viewParms.or.axis[1], radius, left ); - VectorScale( backEnd.viewParms.or.axis[2], radius, up ); - } else { - float s, c; - float ang; - - ang = M_PI * ent->e.rotation / 180; - s = sin( ang ); - c = cos( ang ); - - VectorScale( backEnd.viewParms.or.axis[1], c * radius, left ); - VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left ); - - VectorScale( backEnd.viewParms.or.axis[2], c * radius, up ); - VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up ); - } - if ( backEnd.viewParms.isMirror ) { - VectorSubtract( vec3_origin, left, left ); - } - -#ifdef REACTION - if (ent->e.renderfx & RF_SUNFLARE) - { - if (backEnd.viewHasSunFlare) - { - ri.Printf(PRINT_WARNING, "Multiple sun flares not supported\n"); - return; - } - if (R_CullPointAndRadiusEx(ent->e.origin, ent->e.radius, backEnd.viewParms.frustum, ARRAY_LEN(backEnd.viewParms.frustum)) == CULL_OUT) - return; - colors[0] = colors[1] = colors[2] = colors[3] = ent->e.shaderRGBA[glRefConfig.framebufferObject] / 255.0f; - if (colors[0] == 0) - return; - backEnd.viewHasSunFlare = qtrue; - backEnd.frameHasSunFlare = qtrue; - } - else -#endif - { - VectorScale4(ent->e.shaderRGBA, 1.0f / 255.0f, colors); - } - - RB_AddQuadStamp( ent->e.origin, left, up, colors ); -} - - -/* -============= -RB_SurfacePolychain -============= -*/ -static void RB_SurfacePolychain( srfPoly_t *p ) { - int i; - int numv; - - RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) ); - - // fan triangles into the tess array - numv = tess.numVertexes; - for ( i = 0; i < p->numVerts; i++ ) { - VectorCopy( p->verts[i].xyz, tess.xyz[numv] ); - tess.texCoords[numv][0][0] = p->verts[i].st[0]; - tess.texCoords[numv][0][1] = p->verts[i].st[1]; - tess.vertexColors[numv][0] = p->verts[ i ].modulate[0] / 255.0f; - tess.vertexColors[numv][1] = p->verts[ i ].modulate[1] / 255.0f; - tess.vertexColors[numv][2] = p->verts[ i ].modulate[2] / 255.0f; - tess.vertexColors[numv][3] = p->verts[ i ].modulate[3] / 255.0f; - - numv++; - } - - // generate fan indexes into the tess array - for ( i = 0; i < p->numVerts-2; i++ ) { - tess.indexes[tess.numIndexes + 0] = tess.numVertexes; - tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1; - tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2; - tess.numIndexes += 3; - } - - tess.numVertexes = numv; -} - -static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits, int pshadowBits) -{ - int i; - srfTriangle_t *tri; - srfVert_t *dv; - float *xyz, *normal, *texCoords, *lightCoords, *lightdir; -#ifdef USE_VERT_TANGENT_SPACE - float *tangent, *bitangent; -#endif - glIndex_t *index; - float *color; - - RB_CheckVBOandIBO(tess.vbo, tess.ibo); - - RB_CHECKOVERFLOW( numVerts, numTriangles * 3 ); - - tri = triangles; - index = &tess.indexes[ tess.numIndexes ]; - for ( i = 0 ; i < numTriangles ; i++, tri++ ) { - *index++ = tess.numVertexes + tri->indexes[0]; - *index++ = tess.numVertexes + tri->indexes[1]; - *index++ = tess.numVertexes + tri->indexes[2]; - } - tess.numIndexes += numTriangles * 3; - - if ( tess.shader->vertexAttribs & ATTR_POSITION ) - { - dv = verts; - xyz = tess.xyz[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, xyz+=4 ) - VectorCopy(dv->xyz, xyz); - } - - if ( tess.shader->vertexAttribs & ATTR_NORMAL ) - { - dv = verts; - normal = tess.normal[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 ) - VectorCopy(dv->normal, normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - if ( tess.shader->vertexAttribs & ATTR_TANGENT ) - { - dv = verts; - tangent = tess.tangent[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 ) - VectorCopy(dv->tangent, tangent); - } - - if ( tess.shader->vertexAttribs & ATTR_BITANGENT ) - { - dv = verts; - bitangent = tess.bitangent[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, bitangent+=4 ) - VectorCopy(dv->bitangent, bitangent); - } -#endif - - if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) - { - dv = verts; - texCoords = tess.texCoords[ tess.numVertexes ][0]; - for ( i = 0 ; i < numVerts ; i++, dv++, texCoords+=4 ) - VectorCopy2(dv->st, texCoords); - } - - if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD ) - { - dv = verts; - lightCoords = tess.texCoords[ tess.numVertexes ][1]; - for ( i = 0 ; i < numVerts ; i++, dv++, lightCoords+=4 ) - VectorCopy2(dv->lightmap, lightCoords); - } - - if ( tess.shader->vertexAttribs & ATTR_COLOR ) - { - dv = verts; - color = tess.vertexColors[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, color+=4 ) - VectorCopy4(dv->vertexColors, color); - } - - if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) - { - dv = verts; - lightdir = tess.lightdir[ tess.numVertexes ]; - for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 ) - VectorCopy(dv->lightdir, lightdir); - } - -#if 0 // nothing even uses vertex dlightbits - for ( i = 0 ; i < numVerts ; i++ ) { - tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits; - } -#endif - - tess.dlightBits |= dlightBits; - tess.pshadowBits |= pshadowBits; - - tess.numVertexes += numVerts; -} - -static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int dlightBits, int pshadowBits, qboolean shaderCheck) -{ - int i, mergeForward, mergeBack; - GLvoid *firstIndexOffset, *lastIndexOffset; - - if (!vbo || !ibo) - { - return qfalse; - } - - if (shaderCheck && !(!ShaderRequiresCPUDeforms(tess.shader) && !tess.shader->isSky && !tess.shader->isPortal)) - { - return qfalse; - } - - RB_CheckVBOandIBO(vbo, ibo); - - tess.dlightBits |= dlightBits; - tess.pshadowBits |= pshadowBits; - - // merge this into any existing multidraw primitives - mergeForward = -1; - mergeBack = -1; - firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)); - lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(GL_INDEX_TYPE)); - - if (r_mergeMultidraws->integer) - { - i = 0; - - if (r_mergeMultidraws->integer == 1) - { - // lazy merge, only check the last primitive - if (tess.multiDrawPrimitives) - { - i = tess.multiDrawPrimitives - 1; - } - } - - for (; i < tess.multiDrawPrimitives; i++) - { - if (tess.multiDrawLastIndex[i] == firstIndexOffset) - { - mergeBack = i; - } - - if (lastIndexOffset == tess.multiDrawFirstIndex[i]) - { - mergeForward = i; - } - } - } - - if (mergeBack != -1 && mergeForward == -1) - { - tess.multiDrawNumIndexes[mergeBack] += numIndexes; - tess.multiDrawLastIndex[mergeBack] = (byte *)tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack] * sizeof(GL_INDEX_TYPE); - backEnd.pc.c_multidrawsMerged++; - } - else if (mergeBack == -1 && mergeForward != -1) - { - tess.multiDrawNumIndexes[mergeForward] += numIndexes; - tess.multiDrawFirstIndex[mergeForward] = firstIndexOffset; - tess.multiDrawLastIndex[mergeForward] = (byte *)tess.multiDrawFirstIndex[mergeForward] + tess.multiDrawNumIndexes[mergeForward] * sizeof(GL_INDEX_TYPE); - backEnd.pc.c_multidrawsMerged++; - } - else if (mergeBack != -1 && mergeForward != -1) - { - tess.multiDrawNumIndexes[mergeBack] += numIndexes + tess.multiDrawNumIndexes[mergeForward]; - tess.multiDrawLastIndex[mergeBack] = (byte *)tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack] * sizeof(GL_INDEX_TYPE); - tess.multiDrawPrimitives--; - - if (mergeForward != tess.multiDrawPrimitives) - { - tess.multiDrawNumIndexes[mergeForward] = tess.multiDrawNumIndexes[tess.multiDrawPrimitives]; - tess.multiDrawFirstIndex[mergeForward] = tess.multiDrawFirstIndex[tess.multiDrawPrimitives]; - } - backEnd.pc.c_multidrawsMerged += 2; - } - else if (mergeBack == -1 && mergeForward == -1) - { - tess.multiDrawNumIndexes[tess.multiDrawPrimitives] = numIndexes; - tess.multiDrawFirstIndex[tess.multiDrawPrimitives] = firstIndexOffset; - tess.multiDrawLastIndex[tess.multiDrawPrimitives] = lastIndexOffset; - tess.multiDrawPrimitives++; - } - - backEnd.pc.c_multidraws++; - - tess.numIndexes += numIndexes; - tess.numVertexes += numVerts; - - return qtrue; -} - -/* -============= -RB_SurfaceTriangles -============= -*/ -static void RB_SurfaceTriangles( srfTriangles_t *srf ) { - if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) ) - { - return; - } - - RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame]); -} - - - -/* -============== -RB_SurfaceBeam -============== -*/ -static void RB_SurfaceBeam( void ) -{ -#define NUM_BEAM_SEGS 6 - refEntity_t *e; - int i; - vec3_t perpvec; - vec3_t direction, normalized_direction; - vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; - vec3_t oldorigin, origin; - - e = &backEnd.currentEntity->e; - - oldorigin[0] = e->oldorigin[0]; - oldorigin[1] = e->oldorigin[1]; - oldorigin[2] = e->oldorigin[2]; - - origin[0] = e->origin[0]; - origin[1] = e->origin[1]; - origin[2] = e->origin[2]; - - normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; - normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; - normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; - - if ( VectorNormalize( normalized_direction ) == 0 ) - return; - - PerpendicularVector( perpvec, normalized_direction ); - - VectorScale( perpvec, 4, perpvec ); - - for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) - { - RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); -// VectorAdd( start_points[i], origin, start_points[i] ); - VectorAdd( start_points[i], direction, end_points[i] ); - } - - GL_Bind( tr.whiteImage ); - - GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - - // FIXME: Quake3 doesn't use this, so I never tested it - tess.numVertexes = 0; - tess.numIndexes = 0; - tess.firstIndex = 0; - - for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { - VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); - VectorCopy(end_points [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); - } - - for ( i = 0; i < NUM_BEAM_SEGS; i++ ) { - tess.indexes[tess.numIndexes++] = i * 2; - tess.indexes[tess.numIndexes++] = (i + 1) * 2; - tess.indexes[tess.numIndexes++] = 1 + i * 2; - - tess.indexes[tess.numIndexes++] = 1 + i * 2; - tess.indexes[tess.numIndexes++] = (i + 1) * 2; - tess.indexes[tess.numIndexes++] = 1 + (i + 1) * 2; - } - - // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION); - - { - shaderProgram_t *sp = &tr.textureColorShader; - vec4_t color; - - GLSL_VertexAttribsState(ATTR_POSITION); - GLSL_BindProgram(sp); - - GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); - - color[0] = 1.0f; - color[1] = 0.0f; - color[2] = 0.0f; - color[3] = 1.0f; - GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color); - } - - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex); - - tess.numIndexes = 0; - tess.numVertexes = 0; - tess.firstIndex = 0; -} - -//================================================================================ - -static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth ) -{ - float spanWidth2; - int vbase; - float t = len / 256.0f; - - vbase = tess.numVertexes; - - spanWidth2 = -spanWidth; - - // FIXME: use quad stamp? - VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25 / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25 / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25 / 255.0f; - tess.numVertexes++; - - VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); - - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = t; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - tess.indexes[tess.numIndexes++] = vbase; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 2; - - tess.indexes[tess.numIndexes++] = vbase + 2; - tess.indexes[tess.numIndexes++] = vbase + 1; - tess.indexes[tess.numIndexes++] = vbase + 3; -} - -static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up ) -{ - int i; - vec3_t pos[4]; - vec3_t v; - int spanWidth = r_railWidth->integer; - float c, s; - float scale; - - if ( numSegs > 1 ) - numSegs--; - if ( !numSegs ) - return; - - scale = 0.25; - - for ( i = 0; i < 4; i++ ) - { - c = cos( DEG2RAD( 45 + i * 90 ) ); - s = sin( DEG2RAD( 45 + i * 90 ) ); - v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth; - v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth; - v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth; - VectorAdd( start, v, pos[i] ); - - if ( numSegs > 1 ) - { - // offset by 1 segment if we're doing a long distance shot - VectorAdd( pos[i], dir, pos[i] ); - } - } - - for ( i = 0; i < numSegs; i++ ) - { - int j; - - RB_CHECKOVERFLOW( 4, 6 ); - - for ( j = 0; j < 4; j++ ) - { - VectorCopy( pos[j], tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = ( j < 2 ); - tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 ); - tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f; - tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f; - tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f; - tess.numVertexes++; - - VectorAdd( pos[j], dir, pos[j] ); - } - - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1; - tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2; - } -} - -/* -** RB_SurfaceRailRinges -*/ -static void RB_SurfaceRailRings( void ) { - refEntity_t *e; - int numSegs; - int len; - vec3_t vec; - vec3_t right, up; - vec3_t start, end; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - MakeNormalVectors( vec, right, up ); - numSegs = ( len ) / r_railSegmentLength->value; - if ( numSegs <= 0 ) { - numSegs = 1; - } - - VectorScale( vec, r_railSegmentLength->value, vec ); - - DoRailDiscs( numSegs, start, vec, right, up ); -} - -/* -** RB_SurfaceRailCore -*/ -static void RB_SurfaceRailCore( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, start ); - VectorCopy( e->origin, end ); - - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - DoRailCore( start, end, right, len, r_railCoreWidth->integer ); -} - -/* -** RB_SurfaceLightningBolt -*/ -static void RB_SurfaceLightningBolt( void ) { - refEntity_t *e; - int len; - vec3_t right; - vec3_t vec; - vec3_t start, end; - vec3_t v1, v2; - int i; - - e = &backEnd.currentEntity->e; - - VectorCopy( e->oldorigin, end ); - VectorCopy( e->origin, start ); - - // compute variables - VectorSubtract( end, start, vec ); - len = VectorNormalize( vec ); - - // compute side vector - VectorSubtract( start, backEnd.viewParms.or.origin, v1 ); - VectorNormalize( v1 ); - VectorSubtract( end, backEnd.viewParms.or.origin, v2 ); - VectorNormalize( v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - for ( i = 0 ; i < 4 ; i++ ) { - vec3_t temp; - - DoRailCore( start, end, right, len, 8 ); - RotatePointAroundVector( temp, vec, right, 45 ); - VectorCopy( temp, right ); - } -} - -/* -** VectorArrayNormalize -* -* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0) -* This means that we don't have to worry about zero length or enormously long vectors. -*/ -static void VectorArrayNormalize(vec4_t *normals, unsigned int count) -{ -// assert(count); - -#if idppc - { - register float half = 0.5; - register float one = 1.0; - float *components = (float *)normals; - - // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, - // runs *much* faster than calling sqrt(). We'll use a single Newton-Raphson - // refinement step to get a little more precision. This seems to yeild results - // that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5). - // (That is, for the given input range of about 0.6 to 2.0). - do { - float x, y, z; - float B, y0, y1; - - x = components[0]; - y = components[1]; - z = components[2]; - components += 4; - B = x*x + y*y + z*z; - -#ifdef __GNUC__ - asm("frsqrte %0,%1" : "=f" (y0) : "f" (B)); -#else - y0 = __frsqrte(B); -#endif - y1 = y0 + half*y0*(one - B*y0*y0); - - x = x * y1; - y = y * y1; - components[-4] = x; - z = z * y1; - components[-3] = y; - components[-2] = z; - } while(count--); - } -#else // No assembly version for this architecture, or C_ONLY defined - // given the input, it's safe to call VectorNormalizeFast - while (count--) { - VectorNormalizeFast(normals[0]); - normals++; - } -#endif - -} - - - -/* -** LerpMeshVertexes -*/ -#if idppc_altivec -static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp) -{ - short *oldXyz, *newXyz, *oldNormals, *newNormals; - float *outXyz, *outNormal; - float oldXyzScale QALIGN(16); - float newXyzScale QALIGN(16); - float oldNormalScale QALIGN(16); - float newNormalScale QALIGN(16); - int vertNum; - unsigned lat, lng; - int numVerts; - - outXyz = tess.xyz[tess.numVertexes]; - outNormal = tess.normal[tess.numVertexes]; - - newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) - + (backEnd.currentEntity->e.frame * surf->numVerts * 4); - newNormals = newXyz + 3; - - newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); - newNormalScale = 1.0 - backlerp; - - numVerts = surf->numVerts; - - if ( backlerp == 0 ) { - vector signed short newNormalsVec0; - vector signed short newNormalsVec1; - vector signed int newNormalsIntVec; - vector float newNormalsFloatVec; - vector float newXyzScaleVec; - vector unsigned char newNormalsLoadPermute; - vector unsigned char newNormalsStorePermute; - vector float zero; - - newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec); - newXyzScaleVec = *(vector float *)&newXyzScale; - newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute); - newXyzScaleVec = vec_splat(newXyzScaleVec,0); - newNormalsLoadPermute = vec_lvsl(0,newXyz); - newNormalsStorePermute = vec_lvsr(0,outXyz); - zero = (vector float)vec_splat_s8(0); - // - // just copy the vertexes - // - for (vertNum=0 ; vertNum < numVerts ; vertNum++, - newXyz += 4, newNormals += 4, - outXyz += 4, outNormal += 4) - { - newNormalsLoadPermute = vec_lvsl(0,newXyz); - newNormalsStorePermute = vec_lvsr(0,outXyz); - newNormalsVec0 = vec_ld(0,newXyz); - newNormalsVec1 = vec_ld(16,newXyz); - newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute); - newNormalsIntVec = vec_unpackh(newNormalsVec0); - newNormalsFloatVec = vec_ctf(newNormalsIntVec,0); - newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero); - newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute); - //outXyz[0] = newXyz[0] * newXyzScale; - //outXyz[1] = newXyz[1] * newXyzScale; - //outXyz[2] = newXyz[2] * newXyzScale; - - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - 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 ) - - outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - - vec_ste(newNormalsFloatVec,0,outXyz); - vec_ste(newNormalsFloatVec,4,outXyz); - vec_ste(newNormalsFloatVec,8,outXyz); - } - } else { - // - // interpolate and copy the vertex and normal - // - oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) - + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4); - oldNormals = oldXyz + 3; - - oldXyzScale = MD3_XYZ_SCALE * backlerp; - oldNormalScale = backlerp; - - for (vertNum=0 ; vertNum < numVerts ; vertNum++, - oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, - outXyz += 4, outNormal += 4) - { - vec3_t uncompressedOldNormal, uncompressedNewNormal; - - // interpolate the xyz - outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; - outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale; - outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; - - // FIXME: interpolate lat/long instead? - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - lat *= 4; - lng *= 4; - uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - - lat = ( oldNormals[0] >> 8 ) & 0xff; - lng = ( oldNormals[0] & 0xff ); - lat *= 4; - lng *= 4; - - uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - - outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale; - outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale; - outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale; - -// VectorNormalize (outNormal); - } - VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts); - } -} -#endif - -static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp) -{ -#if 0 - short *oldXyz, *newXyz, *oldNormals, *newNormals; - float *outXyz, *outNormal; - float oldXyzScale, newXyzScale; - float oldNormalScale, newNormalScale; - int vertNum; - unsigned lat, lng; - int numVerts; - - outXyz = tess.xyz[tess.numVertexes]; - outNormal = tess.normal[tess.numVertexes]; - - newXyz = (short *)((byte *)surf + surf->ofsXyzNormals) - + (backEnd.currentEntity->e.frame * surf->numVerts * 4); - newNormals = newXyz + 3; - - newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); - newNormalScale = 1.0 - backlerp; - - numVerts = surf->numVerts; - - if ( backlerp == 0 ) { - // - // just copy the vertexes - // - for (vertNum=0 ; vertNum < numVerts ; vertNum++, - newXyz += 4, newNormals += 4, - outXyz += 4, outNormal += 4) - { - - outXyz[0] = newXyz[0] * newXyzScale; - outXyz[1] = newXyz[1] * newXyzScale; - outXyz[2] = newXyz[2] * newXyzScale; - - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - 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 ) - - outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - } - } else { - // - // interpolate and copy the vertex and normal - // - oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals) - + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4); - oldNormals = oldXyz + 3; - - oldXyzScale = MD3_XYZ_SCALE * backlerp; - oldNormalScale = backlerp; - - for (vertNum=0 ; vertNum < numVerts ; vertNum++, - oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, - outXyz += 4, outNormal += 4) - { - vec3_t uncompressedOldNormal, uncompressedNewNormal; - - // interpolate the xyz - outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; - outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale; - outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; - - // FIXME: interpolate lat/long instead? - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - lat *= 4; - lng *= 4; - uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - - lat = ( oldNormals[0] >> 8 ) & 0xff; - lng = ( oldNormals[0] & 0xff ); - lat *= 4; - lng *= 4; - - uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng]; - uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK]; - - outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale; - outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale; - outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale; - -// VectorNormalize (outNormal); - } - VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts); - } -#endif - float *outXyz, *outNormal; - mdvVertex_t *newVerts; - int vertNum; - - newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts; - - outXyz = tess.xyz[tess.numVertexes]; - outNormal = tess.normal[tess.numVertexes]; - - if (backlerp == 0) - { - // - // just copy the vertexes - // - - for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++) - { - VectorCopy(newVerts->xyz, outXyz); - VectorCopy(newVerts->normal, outNormal); - newVerts++; - outXyz += 4; - outNormal += 4; - } - } - else - { - // - // interpolate and copy the vertex and normal - // - - mdvVertex_t *oldVerts; - - oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts; - - for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++) - { - VectorLerp(newVerts->xyz, oldVerts->xyz, backlerp, outXyz); - VectorLerp(newVerts->normal, oldVerts->normal, backlerp, outNormal); - //VectorNormalize(outNormal); - newVerts++; - oldVerts++; - outXyz += 4; - outNormal += 4; - } - VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], surf->numVerts); - } - -} - -static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp) -{ -#if 0 -#if idppc_altivec - if (com_altivec->integer) { - // must be in a seperate function or G3 systems will crash. - LerpMeshVertexes_altivec( surf, backlerp ); - return; - } -#endif // idppc_altivec -#endif - LerpMeshVertexes_scalar( surf, backlerp ); -} - - -/* -============= -RB_SurfaceMesh -============= -*/ -static void RB_SurfaceMesh(mdvSurface_t *surface) { - int j; - float backlerp; - srfTriangle_t *triangles; - mdvSt_t *texCoords; - int indexes; - int Bob, Doug; - int numVerts; - - if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) { - backlerp = 0; - } else { - backlerp = backEnd.currentEntity->e.backlerp; - } - - RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 ); - - LerpMeshVertexes (surface, backlerp); - - triangles = surface->triangles; - indexes = surface->numTriangles * 3; - Bob = tess.numIndexes; - Doug = tess.numVertexes; - for (j = 0 ; j < surface->numTriangles ; j++) { - tess.indexes[Bob + j*3 + 0] = Doug + triangles[j].indexes[0]; - tess.indexes[Bob + j*3 + 1] = Doug + triangles[j].indexes[1]; - tess.indexes[Bob + j*3 + 2] = Doug + triangles[j].indexes[2]; - } - tess.numIndexes += indexes; - - texCoords = surface->st; - - numVerts = surface->numVerts; - for ( j = 0; j < numVerts; j++ ) { - tess.texCoords[Doug + j][0][0] = texCoords[j].st[0]; - tess.texCoords[Doug + j][0][1] = texCoords[j].st[1]; - // FIXME: fill in lightmapST for completeness? - } - - tess.numVertexes += surface->numVerts; - -} - - -/* -============== -RB_SurfaceFace -============== -*/ -static void RB_SurfaceFace( srfSurfaceFace_t *srf ) { - if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) ) - { - return; - } - - RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles, srf->triangles, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame]); -} - - -static float LodErrorForVolume( vec3_t local, float radius ) { - vec3_t world; - float d; - - // never let it go negative - if ( r_lodCurveError->value < 0 ) { - return 0; - } - - world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] + - local[2] * backEnd.or.axis[2][0] + backEnd.or.origin[0]; - world[1] = local[0] * backEnd.or.axis[0][1] + local[1] * backEnd.or.axis[1][1] + - local[2] * backEnd.or.axis[2][1] + backEnd.or.origin[1]; - world[2] = local[0] * backEnd.or.axis[0][2] + local[1] * backEnd.or.axis[1][2] + - local[2] * backEnd.or.axis[2][2] + backEnd.or.origin[2]; - - VectorSubtract( world, backEnd.viewParms.or.origin, world ); - d = DotProduct( world, backEnd.viewParms.or.axis[0] ); - - if ( d < 0 ) { - d = -d; - } - d -= radius; - if ( d < 1 ) { - d = 1; - } - - return r_lodCurveError->value / d; -} - -/* -============= -RB_SurfaceGrid - -Just copy the grid of points and triangulate -============= -*/ -static void RB_SurfaceGrid( srfGridMesh_t *srf ) { - int i, j; - float *xyz; - float *texCoords, *lightCoords; - float *normal; -#ifdef USE_VERT_TANGENT_SPACE - float *tangent, *bitangent; -#endif - float *color, *lightdir; - srfVert_t *dv; - int rows, irows, vrows; - int used; - int widthTable[MAX_GRID_SIZE]; - int heightTable[MAX_GRID_SIZE]; - float lodError; - int lodWidth, lodHeight; - int numVertexes; - int dlightBits; - int pshadowBits; - //int *vDlightBits; - - if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qtrue ) ) - { - return; - } - - dlightBits = srf->dlightBits[backEnd.smpFrame]; - tess.dlightBits |= dlightBits; - - pshadowBits = srf->pshadowBits[backEnd.smpFrame]; - tess.pshadowBits |= pshadowBits; - - // determine the allowable discrepance - lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius ); - - // determine which rows and columns of the subdivision - // we are actually going to use - widthTable[0] = 0; - lodWidth = 1; - for ( i = 1 ; i < srf->width-1 ; i++ ) { - if ( srf->widthLodError[i] <= lodError ) { - widthTable[lodWidth] = i; - lodWidth++; - } - } - widthTable[lodWidth] = srf->width-1; - lodWidth++; - - heightTable[0] = 0; - lodHeight = 1; - for ( i = 1 ; i < srf->height-1 ; i++ ) { - if ( srf->heightLodError[i] <= lodError ) { - heightTable[lodHeight] = i; - lodHeight++; - } - } - heightTable[lodHeight] = srf->height-1; - lodHeight++; - - - // very large grids may have more points or indexes than can be fit - // in the tess structure, so we may have to issue it in multiple passes - - used = 0; - while ( used < lodHeight - 1 ) { - // see how many rows of both verts and indexes we can add without overflowing - do { - vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth; - irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 ); - - // if we don't have enough space for at least one strip, flush the buffer - if ( vrows < 2 || irows < 1 ) { - RB_EndSurface(); - RB_BeginSurface(tess.shader, tess.fogNum ); - } else { - break; - } - } while ( 1 ); - - rows = irows; - if ( vrows < irows + 1 ) { - rows = vrows - 1; - } - if ( used + rows > lodHeight ) { - rows = lodHeight - used; - } - - numVertexes = tess.numVertexes; - - xyz = tess.xyz[numVertexes]; - normal = tess.normal[numVertexes]; -#ifdef USE_VERT_TANGENT_SPACE - tangent = tess.tangent[numVertexes]; - bitangent = tess.bitangent[numVertexes]; -#endif - texCoords = tess.texCoords[numVertexes][0]; - lightCoords = tess.texCoords[numVertexes][1]; - color = tess.vertexColors[numVertexes]; - lightdir = tess.lightdir[numVertexes]; - //vDlightBits = &tess.vertexDlightBits[numVertexes]; - - for ( i = 0 ; i < rows ; i++ ) { - for ( j = 0 ; j < lodWidth ; j++ ) { - dv = srf->verts + heightTable[ used + i ] * srf->width - + widthTable[ j ]; - - if ( tess.shader->vertexAttribs & ATTR_POSITION ) - { - VectorCopy(dv->xyz, xyz); - xyz += 4; - } - - if ( tess.shader->vertexAttribs & ATTR_NORMAL ) - { - VectorCopy(dv->normal, normal); - normal += 4; - } - -#ifdef USE_VERT_TANGENT_SPACE - if ( tess.shader->vertexAttribs & ATTR_TANGENT ) - { - VectorCopy(dv->tangent, tangent); - tangent += 4; - } - - if ( tess.shader->vertexAttribs & ATTR_BITANGENT ) - { - VectorCopy(dv->bitangent, bitangent); - bitangent += 4; - } -#endif - if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) - { - VectorCopy2(dv->st, texCoords); - texCoords += 4; - } - - if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD ) - { - VectorCopy2(dv->lightmap, lightCoords); - lightCoords += 4; - } - - if ( tess.shader->vertexAttribs & ATTR_COLOR ) - { - VectorCopy4(dv->vertexColors, color); - color += 4; - } - - if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) - { - VectorCopy(dv->lightdir, lightdir); - lightdir += 4; - } - - //*vDlightBits++ = dlightBits; - } - } - - - // add the indexes - { - int numIndexes; - int w, h; - - h = rows - 1; - w = lodWidth - 1; - numIndexes = tess.numIndexes; - for (i = 0 ; i < h ; i++) { - for (j = 0 ; j < w ; j++) { - int v1, v2, v3, v4; - - // vertex order to be reckognized as tristrips - v1 = numVertexes + i*lodWidth + j + 1; - v2 = v1 - 1; - v3 = v2 + lodWidth; - v4 = v3 + 1; - - tess.indexes[numIndexes] = v2; - tess.indexes[numIndexes+1] = v3; - tess.indexes[numIndexes+2] = v1; - - tess.indexes[numIndexes+3] = v1; - tess.indexes[numIndexes+4] = v3; - tess.indexes[numIndexes+5] = v4; - numIndexes += 6; - } - } - - tess.numIndexes = numIndexes; - } - - tess.numVertexes += rows * lodWidth; - - used += rows - 1; - } -} - - -/* -=========================================================================== - -NULL MODEL - -=========================================================================== -*/ - -/* -=================== -RB_SurfaceAxis - -Draws x/y/z lines from the origin for orientation debugging -=================== -*/ -static void RB_SurfaceAxis( void ) { - // FIXME: implement this -#if 0 - GL_Bind( tr.whiteImage ); - qglLineWidth( 3 ); - qglBegin( GL_LINES ); - qglColor3f( 1,0,0 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 16,0,0 ); - qglColor3f( 0,1,0 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 0,16,0 ); - qglColor3f( 0,0,1 ); - qglVertex3f( 0,0,0 ); - qglVertex3f( 0,0,16 ); - qglEnd(); - qglLineWidth( 1 ); -#endif -} - -//=========================================================================== - -/* -==================== -RB_SurfaceEntity - -Entities that have a single procedurally generated surface -==================== -*/ -static void RB_SurfaceEntity( surfaceType_t *surfType ) { - switch( backEnd.currentEntity->e.reType ) { - case RT_SPRITE: - RB_SurfaceSprite(); - break; - case RT_BEAM: - RB_SurfaceBeam(); - break; - case RT_RAIL_CORE: - RB_SurfaceRailCore(); - break; - case RT_RAIL_RINGS: - RB_SurfaceRailRings(); - break; - case RT_LIGHTNING: - RB_SurfaceLightningBolt(); - break; - default: - RB_SurfaceAxis(); - break; - } - return; -} - -static void RB_SurfaceBad( surfaceType_t *surfType ) { - ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" ); -} - -static void RB_SurfaceFlare(srfFlare_t *surf) -{ - if (r_flares->integer) - RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); -} - -static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf) -{ - RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->dlightBits[backEnd.smpFrame], srf->pshadowBits[backEnd.smpFrame], qfalse ); -} - -void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) -{ - //mdvModel_t *mdvModel; - //mdvSurface_t *mdvSurface; - refEntity_t *refEnt; - - GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n"); - - if(!surface->vbo || !surface->ibo) - return; - - //RB_CheckVBOandIBO(surface->vbo, surface->ibo); - RB_EndSurface(); - RB_BeginSurface(tess.shader, tess.fogNum); - - R_BindVBO(surface->vbo); - R_BindIBO(surface->ibo); - - tess.useInternalVBO = qfalse; - - tess.numIndexes += surface->numIndexes; - tess.numVertexes += surface->numVerts; - - //mdvModel = surface->mdvModel; - //mdvSurface = surface->mdvSurface; - - refEnt = &backEnd.currentEntity->e; - - if(refEnt->oldframe == refEnt->frame) - { - glState.vertexAttribsInterpolation = 0; - } - else - { - glState.vertexAttribsInterpolation = refEnt->backlerp; - } - - glState.vertexAttribsOldFrame = refEnt->oldframe; - glState.vertexAttribsNewFrame = refEnt->frame; - - RB_EndSurface(); - - // So we don't lerp surfaces that shouldn't be lerped - glState.vertexAttribsInterpolation = 0; -} - -static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { - // all apropriate state must be set in RB_BeginSurface - // this isn't implemented yet... - qglCallList( surf->listNum ); -} - -static void RB_SurfaceSkip( void *surf ) { -} - - -void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { - (void(*)(void*))RB_SurfaceBad, // SF_BAD, - (void(*)(void*))RB_SurfaceSkip, // SF_SKIP, - (void(*)(void*))RB_SurfaceFace, // SF_FACE, - (void(*)(void*))RB_SurfaceGrid, // SF_GRID, - (void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES, - (void(*)(void*))RB_SurfacePolychain, // SF_POLY, - (void(*)(void*))RB_SurfaceMesh, // SF_MDV, - (void(*)(void*))RB_SurfaceAnim, // SF_MD4, -#ifdef RAVENMD4 - (void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR, -#endif - (void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM, - (void(*)(void*))RB_SurfaceFlare, // SF_FLARE, - (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY - (void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST - (void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH, - (void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH -}; diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c deleted file mode 100644 index 4b39369d..00000000 --- a/code/renderergl2/tr_vbo.c +++ /dev/null @@ -1,932 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2007-2009 Robert Beckebans - -This file is part of XreaL source code. - -XreaL source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -XreaL source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with XreaL source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// tr_vbo.c -#include "tr_local.h" - -/* -============ -R_CreateVBO -============ -*/ -VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage) -{ - VBO_t *vbo; - int glUsage; - - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long\n", name); - } - - if ( tr.numVBOs == MAX_VBOS ) { - ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit\n"); - } - - // make sure the render thread is stopped - R_SyncRenderThread(); - - vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); - tr.numVBOs++; - - memset(vbo, 0, sizeof(*vbo)); - - Q_strncpyz(vbo->name, name, sizeof(vbo->name)); - - vbo->vertexesSize = vertexesSize; - - qglGenBuffersARB(1, &vbo->vertexesVBO); - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage); - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - - glState.currentVBO = NULL; - - GL_CheckErrors(); - - return vbo; -} - -/* -============ -R_CreateVBO2 -============ -*/ -VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage) -{ - VBO_t *vbo; - int i; - - byte *data; - int dataSize; - int dataOfs; - - int glUsage; - - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(!numVertexes) - return NULL; - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long\n", name); - } - - if ( tr.numVBOs == MAX_VBOS ) { - ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit\n"); - } - - // make sure the render thread is stopped - R_SyncRenderThread(); - - vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); - tr.numVBOs++; - - memset(vbo, 0, sizeof(*vbo)); - - Q_strncpyz(vbo->name, name, sizeof(vbo->name)); - - if (usage == VBO_USAGE_STATIC) - { - // since these vertex attributes are never altered, interleave them - vbo->ofs_xyz = 0; - dataSize = sizeof(verts[0].xyz); - - if(stateBits & ATTR_NORMAL) - { - vbo->ofs_normal = dataSize; - dataSize += sizeof(verts[0].normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(stateBits & ATTR_TANGENT) - { - vbo->ofs_tangent = dataSize; - dataSize += sizeof(verts[0].tangent); - } - - if(stateBits & ATTR_BITANGENT) - { - vbo->ofs_bitangent = dataSize; - dataSize += sizeof(verts[0].bitangent); - } -#endif - - if(stateBits & ATTR_TEXCOORD) - { - vbo->ofs_st = dataSize; - dataSize += sizeof(verts[0].st); - } - - if(stateBits & ATTR_LIGHTCOORD) - { - vbo->ofs_lightmap = dataSize; - dataSize += sizeof(verts[0].lightmap); - } - - if(stateBits & ATTR_COLOR) - { - vbo->ofs_vertexcolor = dataSize; - dataSize += sizeof(verts[0].vertexColors); - } - - if(stateBits & ATTR_LIGHTDIRECTION) - { - vbo->ofs_lightdir = dataSize; - dataSize += sizeof(verts[0].lightdir); - } - - vbo->stride_xyz = dataSize; - vbo->stride_normal = dataSize; -#ifdef USE_VERT_TANGENT_SPACE - vbo->stride_tangent = dataSize; - vbo->stride_bitangent = dataSize; -#endif - vbo->stride_st = dataSize; - vbo->stride_lightmap = dataSize; - vbo->stride_vertexcolor = dataSize; - vbo->stride_lightdir = dataSize; - - // create VBO - dataSize *= numVertexes; - data = ri.Hunk_AllocateTempMemory(dataSize); - dataOfs = 0; - - //ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, - //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); - - for (i = 0; i < numVertexes; i++) - { - // xyz - memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); - dataOfs += sizeof(verts[i].xyz); - - // normal - if(stateBits & ATTR_NORMAL) - { - memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal)); - dataOfs += sizeof(verts[i].normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - // tangent - if(stateBits & ATTR_TANGENT) - { - memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent)); - dataOfs += sizeof(verts[i].tangent); - } - - // bitangent - if(stateBits & ATTR_BITANGENT) - { - memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent)); - dataOfs += sizeof(verts[i].bitangent); - } -#endif - - // vertex texcoords - if(stateBits & ATTR_TEXCOORD) - { - memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); - dataOfs += sizeof(verts[i].st); - } - - // feed vertex lightmap texcoords - if(stateBits & ATTR_LIGHTCOORD) - { - memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); - dataOfs += sizeof(verts[i].lightmap); - } - - // feed vertex colors - if(stateBits & ATTR_COLOR) - { - memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); - dataOfs += sizeof(verts[i].vertexColors); - } - - // feed vertex light directions - if(stateBits & ATTR_LIGHTDIRECTION) - { - memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); - dataOfs += sizeof(verts[i].lightdir); - } - } - } - else - { - // since these vertex attributes may be changed, put them in flat arrays - dataSize = sizeof(verts[0].xyz); - - if(stateBits & ATTR_NORMAL) - { - dataSize += sizeof(verts[0].normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(stateBits & ATTR_TANGENT) - { - dataSize += sizeof(verts[0].tangent); - } - - if(stateBits & ATTR_BITANGENT) - { - dataSize += sizeof(verts[0].bitangent); - } -#endif - - if(stateBits & ATTR_TEXCOORD) - { - dataSize += sizeof(verts[0].st); - } - - if(stateBits & ATTR_LIGHTCOORD) - { - dataSize += sizeof(verts[0].lightmap); - } - - if(stateBits & ATTR_COLOR) - { - dataSize += sizeof(verts[0].vertexColors); - } - - if(stateBits & ATTR_LIGHTDIRECTION) - { - dataSize += sizeof(verts[0].lightdir); - } - - // create VBO - dataSize *= numVertexes; - data = ri.Hunk_AllocateTempMemory(dataSize); - dataOfs = 0; - - vbo->ofs_xyz = 0; - vbo->ofs_normal = 0; -#ifdef USE_VERT_TANGENT_SPACE - vbo->ofs_tangent = 0; - vbo->ofs_bitangent = 0; -#endif - vbo->ofs_st = 0; - vbo->ofs_lightmap = 0; - vbo->ofs_vertexcolor = 0; - vbo->ofs_lightdir = 0; - - vbo->stride_xyz = sizeof(verts[0].xyz); - vbo->stride_normal = sizeof(verts[0].normal); -#ifdef USE_VERT_TANGENT_SPACE - vbo->stride_tangent = sizeof(verts[0].tangent); - vbo->stride_bitangent = sizeof(verts[0].bitangent); -#endif - vbo->stride_vertexcolor = sizeof(verts[0].vertexColors); - vbo->stride_st = sizeof(verts[0].st); - vbo->stride_lightmap = sizeof(verts[0].lightmap); - vbo->stride_lightdir = sizeof(verts[0].lightdir); - - //ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, - //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); - - // xyz - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); - dataOfs += sizeof(verts[i].xyz); - } - - // normal - if(stateBits & ATTR_NORMAL) - { - vbo->ofs_normal = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal)); - dataOfs += sizeof(verts[i].normal); - } - } - -#ifdef USE_VERT_TANGENT_SPACE - // tangent - if(stateBits & ATTR_TANGENT) - { - vbo->ofs_tangent = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent)); - dataOfs += sizeof(verts[i].tangent); - } - } - - // bitangent - if(stateBits & ATTR_BITANGENT) - { - vbo->ofs_bitangent = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent)); - dataOfs += sizeof(verts[i].bitangent); - } - } -#endif - - // vertex texcoords - if(stateBits & ATTR_TEXCOORD) - { - vbo->ofs_st = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); - dataOfs += sizeof(verts[i].st); - } - } - - // feed vertex lightmap texcoords - if(stateBits & ATTR_LIGHTCOORD) - { - vbo->ofs_lightmap = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); - dataOfs += sizeof(verts[i].lightmap); - } - } - - // feed vertex colors - if(stateBits & ATTR_COLOR) - { - vbo->ofs_vertexcolor = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); - dataOfs += sizeof(verts[i].vertexColors); - } - } - - // feed vertex lightdirs - if(stateBits & ATTR_LIGHTDIRECTION) - { - vbo->ofs_lightdir = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); - dataOfs += sizeof(verts[i].lightdir); - } - } - } - - - vbo->vertexesSize = dataSize; - - qglGenBuffersARB(1, &vbo->vertexesVBO); - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage); - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - - glState.currentVBO = NULL; - - GL_CheckErrors(); - - ri.Hunk_FreeTempMemory(data); - - return vbo; -} - - -/* -============ -R_CreateIBO -============ -*/ -IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage) -{ - IBO_t *ibo; - int glUsage; - - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long\n", name); - } - - if ( tr.numIBOs == MAX_IBOS ) { - ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit\n"); - } - - // make sure the render thread is stopped - R_SyncRenderThread(); - - ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - tr.numIBOs++; - - Q_strncpyz(ibo->name, name, sizeof(ibo->name)); - - ibo->indexesSize = indexesSize; - - qglGenBuffersARB(1, &ibo->indexesVBO); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - - glState.currentIBO = NULL; - - GL_CheckErrors(); - - return ibo; -} - -/* -============ -R_CreateIBO2 -============ -*/ -IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage) -{ - IBO_t *ibo; - int i, j; - - byte *indexes; - int indexesSize; - int indexesOfs; - - srfTriangle_t *tri; - glIndex_t index; - int glUsage; - - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(!numTriangles) - return NULL; - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long\n", name); - } - - if ( tr.numIBOs == MAX_IBOS ) { - ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit\n"); - } - - // make sure the render thread is stopped - R_SyncRenderThread(); - - ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - tr.numIBOs++; - - Q_strncpyz(ibo->name, name, sizeof(ibo->name)); - - indexesSize = numTriangles * 3 * sizeof(int); - indexes = ri.Hunk_AllocateTempMemory(indexesSize); - indexesOfs = 0; - - for(i = 0, tri = triangles; i < numTriangles; i++, tri++) - { - for(j = 0; j < 3; j++) - { - index = tri->indexes[j]; - memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t)); - indexesOfs += sizeof(glIndex_t); - } - } - - ibo->indexesSize = indexesSize; - - qglGenBuffersARB(1, &ibo->indexesVBO); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - - glState.currentIBO = NULL; - - GL_CheckErrors(); - - ri.Hunk_FreeTempMemory(indexes); - - return ibo; -} - -/* -============ -R_BindVBO -============ -*/ -void R_BindVBO(VBO_t * vbo) -{ - if(!vbo) - { - //R_BindNullVBO(); - ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo"); - return; - } - - if(r_logFile->integer) - { - // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name)); - } - - if(glState.currentVBO != vbo) - { - glState.currentVBO = vbo; - glState.vertexAttribPointersSet = 0; - - glState.vertexAttribsInterpolation = 0; - glState.vertexAttribsOldFrame = 0; - glState.vertexAttribsNewFrame = 0; - - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); - - backEnd.pc.c_vboVertexBuffers++; - } -} - -/* -============ -R_BindNullVBO -============ -*/ -void R_BindNullVBO(void) -{ - GLimp_LogComment("--- R_BindNullVBO ---\n"); - - if(glState.currentVBO) - { - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - glState.currentVBO = NULL; - } - - GL_CheckErrors(); -} - -/* -============ -R_BindIBO -============ -*/ -void R_BindIBO(IBO_t * ibo) -{ - if(!ibo) - { - //R_BindNullIBO(); - ri.Error(ERR_DROP, "R_BindIBO: NULL ibo"); - return; - } - - if(r_logFile->integer) - { - // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- R_BindIBO( %s ) ---\n", ibo->name)); - } - - if(glState.currentIBO != ibo) - { - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - - glState.currentIBO = ibo; - - backEnd.pc.c_vboIndexBuffers++; - } -} - -/* -============ -R_BindNullIBO -============ -*/ -void R_BindNullIBO(void) -{ - GLimp_LogComment("--- R_BindNullIBO ---\n"); - - if(glState.currentIBO) - { - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - glState.currentIBO = NULL; - glState.vertexAttribPointersSet = 0; - } -} - -/* -============ -R_InitVBOs -============ -*/ -void R_InitVBOs(void) -{ - int dataSize; - int offset; - - ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n"); - - tr.numVBOs = 0; - tr.numIBOs = 0; - - dataSize = sizeof(tess.xyz[0]); - dataSize += sizeof(tess.normal[0]); -#ifdef USE_VERT_TANGENT_SPACE - dataSize += sizeof(tess.tangent[0]); - dataSize += sizeof(tess.bitangent[0]); -#endif - dataSize += sizeof(tess.vertexColors[0]); - dataSize += sizeof(tess.texCoords[0][0]) * 2; - dataSize += sizeof(tess.lightdir[0]); - dataSize *= SHADER_MAX_VERTEXES; - - tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC); - - offset = 0; - - tess.vbo->ofs_xyz = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; - tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; -#ifdef USE_VERT_TANGENT_SPACE - tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; - tess.vbo->ofs_bitangent = offset; offset += sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES; -#endif - // these next two are actually interleaved - tess.vbo->ofs_st = offset; - tess.vbo->ofs_lightmap = offset + sizeof(tess.texCoords[0][0]); - offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; - - tess.vbo->ofs_vertexcolor = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; - tess.vbo->ofs_lightdir = offset; - - tess.vbo->stride_xyz = sizeof(tess.xyz[0]); - tess.vbo->stride_normal = sizeof(tess.normal[0]); -#ifdef USE_VERT_TANGENT_SPACE - tess.vbo->stride_tangent = sizeof(tess.tangent[0]); - tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]); -#endif - tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]); - tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2; - tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2; - tess.vbo->stride_lightdir = sizeof(tess.lightdir[0]); - - dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES; - - tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC); - - R_BindNullVBO(); - R_BindNullIBO(); - - GL_CheckErrors(); -} - -/* -============ -R_ShutdownVBOs -============ -*/ -void R_ShutdownVBOs(void) -{ - int i; - VBO_t *vbo; - IBO_t *ibo; - - ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n"); - - R_BindNullVBO(); - R_BindNullIBO(); - - - for(i = 0; i < tr.numVBOs; i++) - { - vbo = tr.vbos[i]; - - if(vbo->vertexesVBO) - { - qglDeleteBuffersARB(1, &vbo->vertexesVBO); - } - - //ri.Free(vbo); - } - - for(i = 0; i < tr.numIBOs; i++) - { - ibo = tr.ibos[i]; - - if(ibo->indexesVBO) - { - qglDeleteBuffersARB(1, &ibo->indexesVBO); - } - - //ri.Free(ibo); - } - - tr.numVBOs = 0; - tr.numIBOs = 0; -} - -/* -============ -R_VBOList_f -============ -*/ -void R_VBOList_f(void) -{ - int i; - VBO_t *vbo; - IBO_t *ibo; - int vertexesSize = 0; - int indexesSize = 0; - - ri.Printf(PRINT_ALL, " size name\n"); - ri.Printf(PRINT_ALL, "----------------------------------------------------------\n"); - - for(i = 0; i < tr.numVBOs; i++) - { - vbo = tr.vbos[i]; - - ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024), - (vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name); - - vertexesSize += vbo->vertexesSize; - } - - for(i = 0; i < tr.numIBOs; i++) - { - ibo = tr.ibos[i]; - - ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024), - (ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name); - - indexesSize += ibo->indexesSize; - } - - ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs); - ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024), - (vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); - - ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs); - ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024), - (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); -} - - -/* -============== -RB_UpdateVBOs - -Adapted from Tess_UpdateVBOs from xreal - -Tr3B: update the default VBO to replace the client side vertex arrays -============== -*/ -void RB_UpdateVBOs(unsigned int attribBits) -{ - GLimp_LogComment("--- RB_UpdateVBOs ---\n"); - - backEnd.pc.c_dynamicVboDraws++; - - // update the default VBO - if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES) - { - R_BindVBO(tess.vbo); - - if(attribBits & ATTR_BITS) - { - if(attribBits & ATTR_POSITION) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); - } - - if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD) - { - // these are interleaved, so we update both if either need it - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); - } - - if(attribBits & ATTR_NORMAL) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(attribBits & ATTR_TANGENT) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); - } - - if(attribBits & ATTR_BITANGENT) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent); - } -#endif - - if(attribBits & ATTR_COLOR) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); - } - - if(attribBits & ATTR_LIGHTDIRECTION) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); - } - } - else - { - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); -#ifdef USE_VERT_TANGENT_SPACE - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent); -#endif - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); - } - - } - - // update the default IBO - if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) - { - R_BindIBO(tess.ibo); - - qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); - } -} diff --git a/code/renderergl2/tr_world.c b/code/renderergl2/tr_world.c deleted file mode 100644 index 8f0f26b3..00000000 --- a/code/renderergl2/tr_world.c +++ /dev/null @@ -1,851 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "tr_local.h" - - - -/* -================ -R_CullSurface - -Tries to cull surfaces before they are lighted or -added to the sorting list. -================ -*/ -static qboolean R_CullSurface( msurface_t *surf ) { - if ( r_nocull->integer || surf->cullinfo.type == CULLINFO_NONE) { - return qfalse; - } - - if (surf->cullinfo.type & CULLINFO_PLANE) - { - // Only true for SF_FACE, so treat like its own function - float d; - cullType_t ct; - - if ( !r_facePlaneCull->integer ) { - return qfalse; - } - - ct = surf->shader->cullType; - - if (ct == CT_TWO_SIDED) - { - return qfalse; - } - - // don't cull for depth shadow - /* - if ( tr.viewParms.flags & VPF_DEPTHSHADOW ) - { - return qfalse; - } - */ - - // shadowmaps draw back surfaces - if ( tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW) ) - { - if (ct == CT_FRONT_SIDED) - { - ct = CT_BACK_SIDED; - } - else - { - ct = CT_FRONT_SIDED; - } - } - - // do proper cull for orthographic projection - if (tr.viewParms.flags & VPF_ORTHOGRAPHIC) { - d = DotProduct(tr.viewParms.or.axis[0], surf->cullinfo.plane.normal); - if ( ct == CT_FRONT_SIDED ) { - if (d > 0) - return qtrue; - } else { - if (d < 0) - return qtrue; - } - return qfalse; - } - - d = DotProduct (tr.or.viewOrigin, surf->cullinfo.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 ( ct == CT_FRONT_SIDED ) { - if ( d < surf->cullinfo.plane.dist - 8 ) { - return qtrue; - } - } else { - if ( d > surf->cullinfo.plane.dist + 8 ) { - return qtrue; - } - } - - return qfalse; - } - - if (surf->cullinfo.type & CULLINFO_SPHERE) - { - int sphereCull; - - if ( tr.currentEntityNum != ENTITYNUM_WORLD ) { - sphereCull = R_CullLocalPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius ); - } else { - sphereCull = R_CullPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius ); - } - - if ( sphereCull == CULL_OUT ) - { - return qtrue; - } - - if ( sphereCull == CULL_IN ) - { - return qfalse; - } - } - - if (surf->cullinfo.type & CULLINFO_BOX) - { - int boxCull; - - if ( tr.currentEntityNum != ENTITYNUM_WORLD ) { - boxCull = R_CullLocalBox( surf->cullinfo.bounds ); - } else { - boxCull = R_CullBox( surf->cullinfo.bounds ); - } - - if ( boxCull == CULL_OUT ) - { - return qtrue; - } - - if ( boxCull == CULL_IN ) - { - return qfalse; - } - } - - return qfalse; -} - - -/* -==================== -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 ) { - float d; - int i; - dlight_t *dl; - - if ( surf->cullinfo.type & CULLINFO_PLANE ) - { - int i; - for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { - if ( ! ( dlightBits & ( 1 << i ) ) ) { - continue; - } - dl = &tr.refdef.dlights[i]; - d = DotProduct( dl->origin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist; - if ( d < -dl->radius || d > dl->radius ) { - // dlight doesn't reach the plane - dlightBits &= ~( 1 << i ); - } - } - } - - if ( surf->cullinfo.type & CULLINFO_BOX ) - { - 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 > surf->cullinfo.bounds[1][0] - || dl->origin[0] + dl->radius < surf->cullinfo.bounds[0][0] - || dl->origin[1] - dl->radius > surf->cullinfo.bounds[1][1] - || dl->origin[1] + dl->radius < surf->cullinfo.bounds[0][1] - || dl->origin[2] - dl->radius > surf->cullinfo.bounds[1][2] - || dl->origin[2] + dl->radius < surf->cullinfo.bounds[0][2] ) { - // dlight doesn't reach the bounds - dlightBits &= ~( 1 << i ); - } - } - } - - if ( surf->cullinfo.type & CULLINFO_SPHERE ) - { - for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) { - if ( ! ( dlightBits & ( 1 << i ) ) ) { - continue; - } - dl = &tr.refdef.dlights[i]; - if (!SpheresIntersect(dl->origin, dl->radius, surf->cullinfo.localOrigin, surf->cullinfo.radius)) - { - // dlight doesn't reach the bounds - dlightBits &= ~( 1 << i ); - } - } - } - - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits; - } else if ( *surf->data == SF_VBO_MESH ) { - ((srfVBOMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = dlightBits; - } else { - dlightBits = 0; - } - - if ( dlightBits ) { - tr.pc.c_dlightSurfaces++; - } - - return dlightBits; -} - -/* -==================== -R_PshadowSurface - -Just like R_DlightSurface, cull any we can -==================== -*/ -static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) { - float d; - int i; - pshadow_t *ps; - - if ( surf->cullinfo.type & CULLINFO_PLANE ) - { - int i; - for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) { - if ( ! ( pshadowBits & ( 1 << i ) ) ) { - continue; - } - ps = &tr.refdef.pshadows[i]; - d = DotProduct( ps->lightOrigin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist; - if ( d < -ps->lightRadius || d > ps->lightRadius ) { - // pshadow doesn't reach the plane - pshadowBits &= ~( 1 << i ); - } - } - } - - if ( surf->cullinfo.type & CULLINFO_BOX ) - { - for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) { - if ( ! ( pshadowBits & ( 1 << i ) ) ) { - continue; - } - ps = &tr.refdef.pshadows[i]; - if ( ps->lightOrigin[0] - ps->lightRadius > surf->cullinfo.bounds[1][0] - || ps->lightOrigin[0] + ps->lightRadius < surf->cullinfo.bounds[0][0] - || ps->lightOrigin[1] - ps->lightRadius > surf->cullinfo.bounds[1][1] - || ps->lightOrigin[1] + ps->lightRadius < surf->cullinfo.bounds[0][1] - || ps->lightOrigin[2] - ps->lightRadius > surf->cullinfo.bounds[1][2] - || ps->lightOrigin[2] + ps->lightRadius < surf->cullinfo.bounds[0][2] - || BoxOnPlaneSide(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1], &ps->cullPlane) == 2 ) { - // pshadow doesn't reach the bounds - pshadowBits &= ~( 1 << i ); - } - } - } - - if ( surf->cullinfo.type & CULLINFO_SPHERE ) - { - for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) { - if ( ! ( pshadowBits & ( 1 << i ) ) ) { - continue; - } - ps = &tr.refdef.pshadows[i]; - if (!SpheresIntersect(ps->viewOrigin, ps->viewRadius, surf->cullinfo.localOrigin, surf->cullinfo.radius) - || DotProduct( surf->cullinfo.localOrigin, ps->cullPlane.normal ) - ps->cullPlane.dist < -surf->cullinfo.radius) - { - // pshadow doesn't reach the bounds - pshadowBits &= ~( 1 << i ); - } - } - } - - if ( *surf->data == SF_FACE ) { - ((srfSurfaceFace_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits; - } else if ( *surf->data == SF_GRID ) { - ((srfGridMesh_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits; - } else if ( *surf->data == SF_TRIANGLES ) { - ((srfTriangles_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits; - } else if ( *surf->data == SF_VBO_MESH ) { - ((srfVBOMesh_t *)surf->data)->pshadowBits[ tr.smpFrame ] = pshadowBits; - } else { - pshadowBits = 0; - } - - if ( pshadowBits ) { - //tr.pc.c_dlightSurfaces++; - } - - return pshadowBits; -} - - -/* -====================== -R_AddWorldSurface -====================== -*/ -static void R_AddWorldSurface( msurface_t *surf, int dlightBits, int pshadowBits ) { - // FIXME: bmodel fog? - - // try to cull before dlighting or adding - if ( R_CullSurface( surf ) ) { - return; - } - - // check for dlighting - if ( dlightBits ) { - dlightBits = R_DlightSurface( surf, dlightBits ); - dlightBits = ( dlightBits != 0 ); - } - - // check for pshadows - /*if ( pshadowBits ) */{ - pshadowBits = R_PshadowSurface( surf, pshadowBits); - pshadowBits = ( pshadowBits != 0 ); - } - - R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits, pshadowBits ); -} - -/* -============================================================= - - 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; - } - - R_SetupEntityLighting( &tr.refdef, ent ); - R_DlightBmodel( bmodel ); - - for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { - int surf = bmodel->firstSurface + i; - - if (tr.world->surfacesViewCount[surf] != tr.viewCount) - { - tr.world->surfacesViewCount[surf] = tr.viewCount; - R_AddWorldSurface( tr.world->surfaces + surf, tr.currentEntity->needDlights, 0 ); - } - } -} - - -/* -============================================================= - - WORLD MODEL - -============================================================= -*/ - - -/* -================ -R_RecursiveWorldNode -================ -*/ -static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits, int pshadowBits ) { - - do { - int newDlights[2]; - unsigned int newPShadows[2]; - - // if the node wasn't marked as potentially visible, exit - // pvs is skipped for depth shadows - if (!(tr.viewParms.flags & VPF_DEPTHSHADOW) && node->visCounts[tr.visIndex] != tr.visCounts[tr.visIndex]) { - 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 ) { - 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; - } - - // node is just a decision point, so go down both sides - // since we don't care about sort orders, just go positive to negative - - // determine which dlights are needed - 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 ); - } - } - } - } - - newPShadows[0] = 0; - newPShadows[1] = 0; - if ( pshadowBits ) { - int i; - - for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) { - pshadow_t *shadow; - float dist; - - if ( pshadowBits & ( 1 << i ) ) { - shadow = &tr.refdef.pshadows[i]; - dist = DotProduct( shadow->lightOrigin, node->plane->normal ) - node->plane->dist; - - if ( dist > -shadow->lightRadius ) { - newPShadows[0] |= ( 1 << i ); - } - if ( dist < shadow->lightRadius ) { - newPShadows[1] |= ( 1 << i ); - } - } - } - } - - // recurse down the children, front side first - R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0], newPShadows[0] ); - - // tail recurse - node = node->children[1]; - dlightBits = newDlights[1]; - pshadowBits = newPShadows[1]; - } while ( 1 ); - - { - // leaf node, so add mark surfaces - int c; - int surf, *view; - - 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 merged and unmerged surfaces - if (tr.world->viewSurfaces) - view = tr.world->viewSurfaces + node->firstmarksurface; - else - view = tr.world->marksurfaces + node->firstmarksurface; - - c = node->nummarksurfaces; - while (c--) { - // just mark it as visible, so we don't jump out of the cache derefencing the surface - surf = *view; - if (surf < 0) - { - if (tr.world->mergedSurfacesViewCount[-surf - 1] != tr.viewCount) - { - tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount; - tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits; - tr.world->mergedSurfacesPshadowBits[-surf - 1] = pshadowBits; - } - else - { - tr.world->mergedSurfacesDlightBits[-surf - 1] |= dlightBits; - tr.world->mergedSurfacesPshadowBits[-surf - 1] |= pshadowBits; - } - } - else - { - if (tr.world->surfacesViewCount[surf] != tr.viewCount) - { - tr.world->surfacesViewCount[surf] = tr.viewCount; - tr.world->surfacesDlightBits[surf] = dlightBits; - tr.world->surfacesPshadowBits[surf] = pshadowBits; - } - else - { - tr.world->surfacesDlightBits[surf] |= dlightBits; - tr.world->surfacesPshadowBits[surf] |= pshadowBits; - } - } - view++; - } - } - -} - - -/* -=============== -R_PointInLeaf -=============== -*/ -static mnode_t *R_PointInLeaf( const vec3_t p ) { - mnode_t *node; - float d; - cplane_t *plane; - - if ( !tr.world ) { - ri.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( const vec3_t p1, const vec3_t p2 ) { - mnode_t *leaf; - byte *vis; - - leaf = R_PointInLeaf( p1 ); - vis = ri.CM_ClusterPVS( leaf->cluster ); // why not R_ClusterPVS ?? - 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 - - for(i = 0; i < MAX_VISCOUNTS; i++) - { - if(tr.visClusters[i] == cluster) - { - //tr.visIndex = i; - break; - } - } - - // if r_showcluster was just turned on, remark everything - if(i != MAX_VISCOUNTS && !tr.refdef.areamaskModified && !r_showcluster->modified)// && !r_dynamicBspOcclusionCulling->modified) - { - if(tr.visClusters[i] != tr.visClusters[tr.visIndex] && r_showcluster->integer) - { - ri.Printf(PRINT_ALL, "found cluster:%i area:%i index:%i\n", cluster, leaf->area, i); - } - tr.visIndex = i; - return; - } - - // if the areamask was modified, invalidate all visclusters - // this caused doors to open into undrawn areas - if (tr.refdef.areamaskModified) - { - memset(tr.visClusters, -2, sizeof(tr.visClusters)); - } - - tr.visIndex = (tr.visIndex + 1) % MAX_VISCOUNTS; - tr.visCounts[tr.visIndex]++; - tr.visClusters[tr.visIndex] = cluster; - - 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 ); - } - } - - // set all nodes to visible if there is no vis - // this caused some levels to simply not render - if (r_novis->integer || !tr.world->vis || tr.visClusters[tr.visIndex] == -1) { - for (i=0 ; inumnodes ; i++) { - if (tr.world->nodes[i].contents != CONTENTS_SOLID) { - tr.world->nodes[i].visCounts[tr.visIndex] = tr.visCounts[tr.visIndex]; - } - } - return; - } - - vis = R_ClusterPVS(tr.visClusters[tr.visIndex]); - - for (i=0,leaf=tr.world->nodes ; inumnodes ; 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->visCounts[tr.visIndex] == tr.visCounts[tr.visIndex]) - break; - parent->visCounts[tr.visIndex] = tr.visCounts[tr.visIndex]; - 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 = ENTITYNUM_WORLD; - tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT; - - // determine which leaves are in the PVS / areamask - if (!(tr.viewParms.flags & VPF_DEPTHSHADOW)) - R_MarkLeaves (); - - // clear out the visible min/max - ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] ); - - // perform frustum culling and flag all the potentially visible surfaces - if ( tr.refdef.num_dlights > 32 ) { - tr.refdef.num_dlights = 32 ; - } - - if ( tr.refdef.num_pshadows > 32 ) { - tr.refdef.num_pshadows = 32 ; - } - - if ( tr.viewParms.flags & VPF_DEPTHSHADOW ) - { - R_RecursiveWorldNode( tr.world->nodes, 31, 0, 0); - } - else if ( !(tr.viewParms.flags & VPF_SHADOWMAP) ) - { - R_RecursiveWorldNode( tr.world->nodes, 15, ( 1 << tr.refdef.num_dlights ) - 1, ( 1 << tr.refdef.num_pshadows ) - 1 ); - } - else - { - R_RecursiveWorldNode( tr.world->nodes, 31, ( 1 << tr.refdef.num_dlights ) - 1, 0 ); - } - - // now add all the potentially visible surfaces - // also mask invisible dlights for next frame - { - int i; - - tr.refdef.dlightMask = 0; - - for (i = 0; i < tr.world->numWorldSurfaces; i++) - { - if (tr.world->surfacesViewCount[i] != tr.viewCount) - continue; - - R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i], tr.world->surfacesPshadowBits[i] ); - tr.refdef.dlightMask |= tr.world->surfacesDlightBits[i]; - } - for (i = 0; i < tr.world->numMergedSurfaces; i++) - { - if (tr.world->mergedSurfacesViewCount[i] != tr.viewCount) - continue; - - R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i], tr.world->mergedSurfacesPshadowBits[i] ); - tr.refdef.dlightMask |= tr.world->mergedSurfacesDlightBits[i]; - } - - tr.refdef.dlightMask = ~tr.refdef.dlightMask; - } -}